Compare commits

...

54 Commits

Author SHA1 Message Date
LorenzoM 29138a8a0b Tolti commenti inutili e sistemata interfaccia 2022-01-21 12:50:34 +01:00
LorenzoM 99b503a637 Migliorie vm additivo 2022-01-20 13:09:53 +01:00
LorenzoM acad826499 CorrettiErrori/LineeDiTest 2022-01-18 18:09:21 +01:00
LorenzoM 2f4d75b958 Correzioni/UtensileSferico/NB:CiSonoLineePerTest 2022-01-18 13:07:48 +01:00
LorenzoM 7e2bf848a9 Correzione errori vm 2022-01-14 18:05:04 +01:00
LorenzoM 4f62467320 Corretti errori vm additivo 2022-01-14 17:54:51 +01:00
LorenzoM 78d4d79cbf Aggiunto utensile additivo generico 2022-01-14 13:19:06 +01:00
LorenzoM 1c8ee6a332 Correzione errori vm additivo 2022-01-13 17:55:39 +01:00
LorenzoM e4b5e4c0a9 Correzioni vmill 2022-01-12 17:26:54 +01:00
LorenzoM 6f60e2d711 Correzione errori vmill additivo 2022-01-11 16:51:54 +01:00
LorenzoM 20a9efaebb Modifiche vm additivo 2022-01-10 18:27:41 +01:00
LorenzoM fd9a6a9847 Merge commit '8710115634c9be74c0a8ead37b0bb32144f84b96' into TempForVmill 2022-01-10 10:17:58 +01:00
LorenzoM c773b8829e Correzione errori 2022-01-10 10:00:38 +01:00
DarioS 8710115634 EgtGeomKernel :
- inserita opzione in compilazioni 64bit per evitare Warning su verifica riferimenti non nulli.
2022-01-09 15:49:58 +01:00
DarioS 4056be90d9 EgtGeomKernel 2.4a3 :
- modifiche a IntersLineBox e IntersPlaneBox
- adattamenti conseguenti.
2022-01-09 15:17:00 +01:00
DarioS 77640f3a6f EgtGeomKernel :
- migliorie a RemoveTJunctions di SurfTriMesh.
2022-01-07 17:13:16 +01:00
DarioS 9b11212d07 EgtGeomKernel 2.4a2 :
- in TriMesh eliminata ResetFaceting e UpdateFaceting ora cerca di ricostruire facce con indice come le eventuali precedenti
- in Trimesh SimplifyFacets cerca di conservare l'identificativo di faccia nei nuovi triangoli
- in Trimesh aggiunta funzione Repair e migliorata SimplifyFacets
- in Trimesh al termine di CutWithOtherSurf si cerca di regolarizzare il risultato.
2022-01-07 10:00:19 +01:00
LorenzoM 2ea8812f52 Recuperato da branch LorenzoM file VolZmap + tool 2022-01-05 18:29:08 +01:00
LorenzoM e2ae42a045 prova 2022-01-05 17:46:51 +01:00
DarioS 41d76f0c3f EgtGeomKernel 2.4a1 :
- migliorie alle booleane delle superfici trimesh.
2022-01-04 08:03:15 +01:00
DarioS d2b77833fd EgtGeomKernel 2.3l3 :
- altre modifiche per triangolazioni.
2021-12-23 15:44:49 +01:00
LorenzoM 9ac1a56535 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2021-12-23 09:23:38 +01:00
LorenzoM 9aca1f1e25 Migliorie trimesh 2021-12-23 09:22:25 +01:00
DarioS e3c10e9bd3 EgtGeomKernel 2.3l2 :
- aggiunta triangolazione mediante earcut di mapbox
- piccola modifica a calcoli preliminari per triangolazione standard.
2021-12-18 22:50:02 +01:00
LorenzoM e84a34917a Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2021-12-07 10:04:33 +01:00
LorenzoM 009328b31b Migliorie operazioni booleane e intersezione triangoli 2021-12-07 09:43:59 +01:00
DarioS ca83aaa249 EgtGeomKernel 2.3l1 :
- in IntersTriaTria aggiunto riconoscimento triangoli coincidenti
- in IntersTriaTria aggiunta distinzione tra intersezione sovrapposta equiversa e controversa.
2021-12-06 16:47:36 +01:00
DarioS 6cdfdf6db8 EgtGeomKernel 2.3k6 :
- dopo tagli e tagli generalizzati lunghezza minima per SimplfyFacets portata da 500 a 5000 per evitare problemi di adiacenza non trovata tra facce.
2021-11-25 14:47:03 +01:00
DarioS 6628b1ee24 EgtGeomKernel 2.3k5 :
- correzione in RemoveTriangle di TriMesh (controllo validità indice vertice).
2021-11-22 22:56:13 +01:00
DarioS 2d70d27d85 EgtGeomKernel 2.3k4 :
- piccole modifiche estetiche e cambio versione.
2021-11-14 12:32:28 +01:00
LorenzoM 63d62fcc92 Gestione tagli piccoli 2021-11-10 15:39:33 +01:00
LorenzoM b4303d0e0d Gestione dei triangoli giacenti sui rettangoli 2021-11-09 10:53:32 +01:00
DarioS 9369447886 EgtGeomKernel :
- altre migliorie a GeneralizedCut di SurfTriMesh.
2021-11-07 17:17:54 +01:00
DarioS dca713b240 EgtGeomKernel 2.3k3 :
- modifiche per GeneralizedCut di SurfTriMesh
- Cut e GeneralizedCut di SurfTriMesh spostati in nuovo sorgente SurfTriMeshCuts.cpp.
2021-11-07 12:57:53 +01:00
DarioS aa82c82ddc EgtGeomKernel 2.3k2 :
- corretta SurfTriMesh::SimplifyFacets.
2021-11-04 10:03:35 +01:00
DarioS 8a6dbf044e EgtGeomKernel :
- piccole modifiche in Cut e GeneralizedCut per eseguire il più possibile SimplfyFacet.
2021-11-03 13:30:26 +01:00
DarioS 76d009ddbe EgtGeomKernel 2.3k1 :
- corretto offset di segmenti di retta singoli con estrusione
- modifiche per calcolo taglio superfici TriMesh
- modifiche a funzione SimplifyFacets di superfici TriMesh.
2021-11-02 08:19:11 +01:00
LorenzoM 6deff01b6e Modifiche generalized cut 2021-10-29 17:17:51 +02:00
LorenzoM e79bb117d2 Pulizia codice simplify facet 2021-10-27 17:53:12 +02:00
LorenzoM 2ea4b59b9b Aggiunta funzione FimplifyFacets in TriMesh 2021-10-26 18:11:58 +02:00
DarioS 6e9465247f EgtGeomKernel 2.3j1 :
- diemnticato un file.
2021-10-24 18:00:00 +02:00
DarioS 1d1fb41212 EgtGeomKernel 2.3j :
- modifiche a SurfTriMesh::Cut (più semplice abilitare calcolo con facce invece di triangoli)
- ora CurveClassification (di Regioni e Curve) ricevono anche il parametro dMinLen.
2021-10-24 17:57:53 +02:00
DarioS add949b6a6 EgtGeomKernel :
- tentativo abortito di velocizzare Silhouette di superfici.
2021-10-04 09:01:36 +02:00
DarioS 4731df3702 EgtGeomKernel 2.3i2 :
- modificata completamente SurfTriMesh::GetSilhouette ora richiede un parametro per la tolleranza nel calcolo (diminuita sensibilità a problemi topologici)
- aggiunta funzione GetSurfFlatRegionFromTriangle.
2021-09-26 16:27:31 +02:00
DarioS e7d0b00e0f EgtGeomKernel :
- correzione a Zmap per calcolo grafica a triangoli.
2021-09-13 16:47:15 +02:00
DarioS 641708a5fa EgtGeomKernel 2.3i1 :
- in Regioni se richiesto offset praticamente nullo non si fa alcunché.
2021-09-13 15:48:36 +02:00
DarioS f5b11a61a0 EgtGeomKernel 2.3h3 :
- correzione crezione regioni da curve chiuse (contorni esterni che si intersecano e diventano in parte anche contorni interni).
2021-08-26 10:38:41 +02:00
DarioS a4cc43dadb EgtGeomKernel 2.3h2 :
- OffsetCurve ora gestisce anche il caso di curve piane con estrusione inclinata fino a 60gradi dalla normale del piano (l'offest si basa su un ellisse).
2021-08-25 15:03:56 +02:00
DarioS 334ce10018 EgtGeomKernel :
- ricompilazione.
2021-08-20 15:18:54 +02:00
DarioS 3d233597f3 EgtGeomKernel :
- a SurfTriMesh::DoSewing aggiunto parametro opzionale double dTol.
2021-08-01 17:12:07 +02:00
DarioS a5fad89380 EgtGeomKernel 2.3h1 :
- piccole migliorie suggerite da clang-cl.
2021-08-01 10:50:15 +02:00
DarioS d0f9c2fff5 EgtGeomKernel :
- piccole modifiche di stile.
2021-07-27 15:20:38 +02:00
DarioS 038142a6d7 EgtGeomKernel 2.3g3 :
- aggiustamenti e ricompilazione per seconda proprietà temporanea degli oggetti geometrici.
2021-07-21 16:44:28 +02:00
LorenzoM 26424252f9 Aggiunta una seconda tempProp a oggetti vari 2021-07-21 12:50:58 +02:00
61 changed files with 8536 additions and 3047 deletions
+2 -2
View File
@@ -13,8 +13,8 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "\EgtDev\Include\EGkBBox3d.h"
#include "\EgtDev\Include\EGkFrame3d.h"
#include "/EgtDev/Include/EGkBBox3d.h"
#include "/EgtDev/Include/EGkFrame3d.h"
#include <algorithm>
using namespace std ;
+5 -2
View File
@@ -59,8 +59,10 @@ class ArcApproxer
//----------------------------------------------------------------------------
CurveArc::CurveArc( void)
: m_nStatus( TO_VERIFY), m_PtCen(), m_VtN(), m_VtS(), m_dRad(),
m_dAngCenDeg(), m_dDeltaN(), m_VtExtr(), m_dThick(), m_nTempProp()
m_dAngCenDeg(), m_dDeltaN(), m_VtExtr(), m_dThick()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -578,7 +580,8 @@ CurveArc::CopyFrom( const CurveArc& caSrc)
return true ;
m_VtExtr = caSrc.m_VtExtr ;
m_dThick = caSrc.m_dThick ;
m_nTempProp = caSrc.m_nTempProp ;
m_nTempProp[0] = caSrc.m_nTempProp[0] ;
m_nTempProp[1] = caSrc.m_nTempProp[1] ;
return Set( caSrc.m_PtCen, caSrc.m_VtN, caSrc.m_dRad,
caSrc.m_VtS, caSrc.m_dAngCenDeg, caSrc.m_dDeltaN) ;
}
+6 -5
View File
@@ -49,10 +49,11 @@ class CurveArc : public ICurveArc, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // ICurve
bool IsSimple( void) const override
@@ -211,7 +212,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
double m_dDeltaN ; // variazione di quota lungo VtN della fine rispetto all'inizio
Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN)
double m_dThick ; // spessore
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
//-----------------------------------------------------------------------------
+5 -2
View File
@@ -45,8 +45,10 @@ GEOOBJ_REGISTER( CRV_BEZIER, NGE_C_BEZ, CurveBezier) ;
//----------------------------------------------------------------------------
CurveBezier::CurveBezier( void)
: m_nStatus( TO_VERIFY), m_nDeg(), m_bRat( false), m_dParSing( -2),
m_VtExtr(), m_dThick(), m_nTempProp()
m_VtExtr(), m_dThick()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -283,7 +285,8 @@ CurveBezier::CopyFrom( const CurveBezier& cbSrc)
m_vWeCtrl = cbSrc.m_vWeCtrl ;
m_VtExtr = cbSrc.m_VtExtr ;
m_dThick = cbSrc.m_dThick ;
m_nTempProp = cbSrc.m_nTempProp ;
m_nTempProp[0] = cbSrc.m_nTempProp[0] ;
m_nTempProp[1] = cbSrc.m_nTempProp[1] ;
return true ;
}
+6 -5
View File
@@ -51,10 +51,11 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // ICurve
bool IsSimple( void) const override { return true ; }
@@ -189,7 +190,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN)
double m_dThick ; // spessore
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
//-----------------------------------------------------------------------------
+17 -11
View File
@@ -30,6 +30,7 @@
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <algorithm>
@@ -40,8 +41,10 @@ GEOOBJ_REGISTER( CRV_COMPO, NGE_C_CMP, CurveComposite) ;
//----------------------------------------------------------------------------
CurveComposite::CurveComposite( void)
: m_nStatus( TO_VERIFY), m_VtExtr(), m_dThick(), m_ptStart(), m_nTempProp(), m_Iter( m_CrvSmplS.end())
: m_nStatus( TO_VERIFY), m_VtExtr(), m_dThick(), m_ptStart(), m_Iter( m_CrvSmplS.end())
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -63,7 +66,8 @@ CurveComposite::Clear( void)
m_VtExtr = V_NULL ;
m_dThick = 0 ;
m_ptStart = ORIG ;
m_nTempProp = 0 ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
m_Iter = m_CrvSmplS.end() ;
// imposto ricalcolo della grafica
@@ -541,7 +545,8 @@ CurveComposite::CopyFrom( const CurveComposite& ccSrc)
Clear() ;
m_VtExtr = ccSrc.m_VtExtr ;
m_dThick = ccSrc.m_dThick ;
m_nTempProp = ccSrc.m_nTempProp ;
m_nTempProp[0] = ccSrc.m_nTempProp[0] ;
m_nTempProp[1] = ccSrc.m_nTempProp[1] ;
for ( auto& pCrv : ccSrc.m_CrvSmplS) {
if ( ! AddCurve( *pCrv))
return false ;
@@ -558,7 +563,8 @@ CurveComposite::RelocateFrom( CurveComposite& ccSrc)
Clear() ;
m_VtExtr = ccSrc.m_VtExtr ;
m_dThick = ccSrc.m_dThick ;
m_nTempProp = ccSrc.m_nTempProp ;
m_nTempProp[0] = ccSrc.m_nTempProp[0] ;
m_nTempProp[1] = ccSrc.m_nTempProp[1] ;
for ( ICurve* pCrv = ccSrc.RemoveFirstOrLastCurve( false) ;
pCrv != nullptr ;
pCrv = ccSrc.RemoveFirstOrLastCurve( false)) {
@@ -1316,8 +1322,8 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P
// se lineare con lato obbligato...
if ( nType == APL_LEFT || nType == APL_LEFT_CONVEX ||
nType == APL_RIGHT || nType == APL_RIGHT_CONVEX) {
// prima approssimazione lineare a 10 * Epsilon
if ( ! ApproxWithLines( 10 * EPS_SMALL, dAngTolDeg, APL_SPECIAL, PL))
// prima approssimazione lineare alla tolleranza minima del programma
if ( ! ApproxWithLines( EPS_SMALL, dAngTolDeg, APL_SPECIAL, PL))
return false ;
// eliminazione dei punti in tolleranza andando solo dalla parte ammessa
Vector3d vtExtr = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ;
@@ -3129,7 +3135,7 @@ CurveComposite::RemoveUndercutOnY( double dLinTol, double dAngTolDeg)
pSfrCut->Translate( b3Box.GetMin() - Point3d( 10 * EPS_SMALL, dLen, 0)) ;
// calcolo la classificazione della curva rispetto alla regione
CRVCVECTOR ccClass ;
if ( ! pSfrCut->GetCurveClassification( *pOutLoop, ccClass))
if ( ! pSfrCut->GetCurveClassification( *pOutLoop, EPS_SMALL, ccClass))
return false ;
// determino gli intervalli di curva da conservare
Intervals inOk ;
@@ -3243,7 +3249,7 @@ CurveComposite::IsACircle( double dLinTol, Point3d& ptCen, Vector3d& vtN, double
//----------------------------------------------------------------------------
bool
CurveComposite::SetCurveTempProp( int nCrv, int nProp)
CurveComposite::SetCurveTempProp( int nCrv, int nProp, int nPropNum)
{
// la curva deve essere validata
if ( m_nStatus != OK)
@@ -3252,13 +3258,13 @@ CurveComposite::SetCurveTempProp( int nCrv, int nProp)
if ( nCrv < 0 || nCrv >= int( m_CrvSmplS.size()))
return false ;
// eseguo assegnazione
m_CrvSmplS[nCrv]->SetTempProp( nProp) ;
m_CrvSmplS[nCrv]->SetTempProp( nProp, nPropNum) ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::GetCurveTempProp( int nCrv, int& nProp) const
CurveComposite::GetCurveTempProp( int nCrv, int& nProp, int nPropNum) const
{
// la curva deve essere validata
if ( m_nStatus != OK)
@@ -3267,6 +3273,6 @@ CurveComposite::GetCurveTempProp( int nCrv, int& nProp) const
if ( nCrv < 0 || nCrv >= int( m_CrvSmplS.size()))
return false ;
// eseguo recupero
nProp = m_CrvSmplS[nCrv]->GetTempProp() ;
nProp = m_CrvSmplS[nCrv]->GetTempProp( nPropNum) ;
return true ;
}
+8 -7
View File
@@ -50,10 +50,11 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // ICurve
bool IsSimple( void) const override
@@ -158,8 +159,8 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool IsAPoint( void) const override ;
bool IsALine( double dLinTol, Point3d& ptStart, Point3d& ptEnd) const override ;
bool IsACircle( double dLinTol, Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const override ;
bool SetCurveTempProp( int nCrv, int nProp) override ;
bool GetCurveTempProp( int nCrv, int& nProp) const override ;
bool SetCurveTempProp( int nCrv, int nProp, int nPropNum = 0) override ;
bool GetCurveTempProp( int nCrv, int& nProp, int nPropNum = 0) const override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
@@ -202,7 +203,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN)
double m_dThick ; // spessore
Point3d m_ptStart ; // punto iniziale per composita vuota per Add di linee o archi
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
mutable PCSD_CONST_ITER m_Iter ; // iteratore
} ;
+5 -2
View File
@@ -29,8 +29,10 @@ GEOOBJ_REGISTER( CRV_LINE, NGE_C_LIN, CurveLine) ;
//----------------------------------------------------------------------------
CurveLine::CurveLine( void)
: m_nStatus( TO_VERIFY), m_PtStart(), m_PtEnd(), m_VtExtr(), m_dThick(), m_nTempProp()
: m_nStatus( TO_VERIFY), m_PtStart(), m_PtEnd(), m_VtExtr(), m_dThick()
{
m_nTempProp[0] = 0 ;
m_nTempProp[0] = 0 ;
}
//----------------------------------------------------------------------------
@@ -123,7 +125,8 @@ CurveLine::CopyFrom( const CurveLine& clSrc)
return true ;
m_VtExtr = clSrc.m_VtExtr ;
m_dThick = clSrc.m_dThick ;
m_nTempProp = clSrc.m_nTempProp ;
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
return Set( clSrc.m_PtStart, clSrc.m_PtEnd) ;
}
+6 -5
View File
@@ -49,10 +49,11 @@ class CurveLine : public ICurveLine, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // ICurve
bool IsSimple( void) const override
@@ -164,7 +165,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW
Point3d m_PtEnd ; // punto finale
Vector3d m_VtExtr ; // vettore estrusione
double m_dThick ; // spessore
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
//-----------------------------------------------------------------------------
+10 -11
View File
@@ -23,33 +23,30 @@
bool
CalcMinDistPointPolyLine( const Point3d& ptP, PolyLine& PL, double dLinTol, MDCVECTOR& vApproxMin)
{
double dSqDist ;
double dPar ;
double dUIni ;
double dUFin ;
Point3d ptIni ;
Point3d ptFin ;
double dMinDist ;
double dSqMinDist ;
MinDistCalc approxMin ;
vApproxMin.reserve( 4) ;
vApproxMin.clear() ;
bool bFound = false ;
bool bOnEnd = false ;
vApproxMin.reserve( 4) ;
vApproxMin.clear() ;
double dUIni, dUFin ;
Point3d ptIni, ptFin ;
double dMinDist, dSqMinDist ;
for ( bool bLine = PL.GetFirstULine( &dUIni, &ptIni, &dUFin, &ptFin) ;
bLine ;
bLine = PL.GetNextULine( &dUIni, &ptIni, &dUFin, &ptFin)) {
// calcolo la distanza del punto dal segmento
DistPointLine dstPtLn( ptP, ptIni, ptFin) ;
double dSqDist ;
if ( ! dstPtLn.GetSqDist( dSqDist))
continue ;
// altro punto con la stessa minima distanza già trovata
if ( bFound && abs( dSqDist - dSqMinDist) < 2 * dMinDist * dLinTol) {
// salvo i dati nella struttura
MinDistCalc approxMin ;
approxMin.dDist = dMinDist ;
dstPtLn.GetMinDistPoint( approxMin.ptQ) ;
double dPar ;
dstPtLn.GetParamAtMinDistPoint( dPar) ;
approxMin.dPar = ( 1 - dPar) * dUIni + dPar * dUFin ;
approxMin.dParMin = dUIni ;
@@ -66,8 +63,10 @@ CalcMinDistPointPolyLine( const Point3d& ptP, PolyLine& PL, double dLinTol, MDCV
dSqMinDist = dSqDist ;
dMinDist = sqrt( dSqMinDist) ;
// salvo i dati nella struttura
MinDistCalc approxMin ;
approxMin.dDist = dMinDist ;
dstPtLn.GetMinDistPoint( approxMin.ptQ) ;
double dPar ;
dstPtLn.GetParamAtMinDistPoint( dPar) ;
approxMin.dPar = ( 1 - dPar) * dUIni + dPar * dUFin ;
approxMin.dParMin = dUIni ;
BIN
View File
Binary file not shown.
+11 -8
View File
@@ -51,7 +51,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>ClangCL</PlatformToolset>
@@ -86,6 +86,7 @@
<OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
<IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
<IncludePath>C:\;$(IncludePath)</IncludePath>
<EnableClangTidyCodeAnalysis>false</EnableClangTidyCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetName>$(ProjectName)R$(PlatformArchitecture)</TargetName>
@@ -101,6 +102,7 @@
<OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
<IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
<IncludePath>C:\;$(IncludePath)</IncludePath>
<EnableClangTidyCodeAnalysis>false</EnableClangTidyCodeAnalysis>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -149,6 +151,7 @@ copy $(TargetPath) \EgtProg\DllD32</Command>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -237,10 +240,11 @@ copy $(TargetPath) \EgtProg\Dll32</Command>
<OmitFramePointers>true</OmitFramePointers>
<FloatingPointModel>Precise</FloatingPointModel>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
<WholeProgramOptimization>false</WholeProgramOptimization>
<DebugInformationFormat>None</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -364,12 +368,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="IntersCurveCurve.cpp" />
<ClCompile Include="IntersLineArc.cpp" />
<ClCompile Include="IntersLineLine.cpp" />
<ClCompile Include="IntersLinePlane.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="IntersLinePlane.cpp" />
<ClCompile Include="IntersLineSurfTm.cpp" />
<ClCompile Include="IntersLineTria.cpp" />
<ClCompile Include="Intervals.cpp" />
@@ -395,6 +394,8 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="SurfFlatRegionBooleans.cpp" />
<ClCompile Include="SurfFlatRegionOffset.cpp" />
<ClCompile Include="SurfTriMeshBooleans.cpp" />
<ClCompile Include="SurfTriMeshCuts.cpp" />
<ClCompile Include="SurfTriMeshUtilities.cpp" />
<ClCompile Include="TextureData.cpp" />
<ClCompile Include="Tool.cpp" />
<ClCompile Include="UserObjDefault.cpp" />
@@ -560,6 +561,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="DistPointCrvComposite.h" />
<ClInclude Include="DistPointLine.h" />
<ClInclude Include="DllMain.h" />
<ClInclude Include="earcut.hpp" />
<ClInclude Include="ExtDimension.h" />
<ClInclude Include="ExtText.h" />
<ClInclude Include="FontAux.h" />
@@ -588,6 +590,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="IntersArcArc.h" />
<ClInclude Include="IntersCrvCompoCrvCompo.h" />
<ClInclude Include="IntersLineArc.h" />
<ClInclude Include="IntersLineBox.h" />
<ClInclude Include="IntersLineLine.h" />
<ClInclude Include="IntersLineSurfStd.h" />
<ClInclude Include="IntersLineTria.h" />
+12
View File
@@ -453,6 +453,12 @@
<ClCompile Include="CDeRectPrismoidTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
</ClCompile>
<ClCompile Include="SurfTriMeshUtilities.cpp">
<Filter>File di origine\Geo</Filter>
</ClCompile>
<ClCompile Include="SurfTriMeshCuts.cpp">
<Filter>File di origine\Geo</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@@ -1076,6 +1082,12 @@
<ClInclude Include="CDeRectPrismoidTria.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="earcut.hpp">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="IntersLineBox.h">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc">
+4 -1
View File
@@ -49,6 +49,8 @@ ExtDimension::ExtDimension( void)
: m_dExtLineLen( STD_EXTLINELEN), m_dArrowLen( STD_ARROWLEN), m_dTextDist( STD_TEXTDIST),
m_bLenIsMM( true), m_nDecDigit( STD_DECDIGIT), m_sFont( STD_FONT), m_dTextHeight( STD_TEXTHEIGHT)
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -186,7 +188,8 @@ ExtDimension::CopyFrom( const ExtDimension& clSrc)
m_nDecDigit = clSrc.m_nDecDigit ;
m_sFont = clSrc.m_sFont ;
m_dTextHeight = clSrc.m_dTextHeight ;
m_nTempProp = clSrc.m_nTempProp ;
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
return true ;
}
+6 -5
View File
@@ -50,10 +50,11 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // IExtDimension
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -148,5 +149,5 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
int m_nDecDigit ; // numero di cifre decimali
std::string m_sFont ; // font del testo
double m_dTextHeight ; // altezza del testo
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
+5 -2
View File
@@ -35,8 +35,10 @@ GEOOBJ_REGISTER( EXT_TEXT, NGE_E_TXT, ExtText) ;
//----------------------------------------------------------------------------
ExtText::ExtText( void)
: m_pSTM( nullptr), m_bNoSTM( false), m_ptP(), m_vtN( 0, 0, 1), m_vtD( 1, 0, 0), m_sFont(),
m_nWeight( 400), m_bItalic( false), m_dHeight( 10), m_dRatio( 1), m_dAddAdvance( 0), m_nTempProp()
m_nWeight( 400), m_bItalic( false), m_dHeight( 10), m_dRatio( 1), m_dAddAdvance( 0)
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -184,7 +186,8 @@ ExtText::CopyFrom( const ExtText& clSrc)
m_dRatio = clSrc.m_dRatio ;
m_dAddAdvance = clSrc.m_dAddAdvance ;
m_nInsPos = clSrc.m_nInsPos ;
m_nTempProp = clSrc.m_nTempProp ;
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
return true ;
}
+6 -5
View File
@@ -50,10 +50,11 @@ class ExtText : public IExtText, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // IExtText
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -143,5 +144,5 @@ class ExtText : public IExtText, public IGeoObjRW
double m_dRatio ; // rapporto tra larghezza e altezza
double m_dAddAdvance ; // avanzamento addizionale tra caratteri
int m_nInsPos ; // posizione del punto di inserimento rispetto al testo
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
+118 -118
View File
@@ -57,7 +57,7 @@
using namespace std ;
//----------------------------------------------------------------------------
// Per Id di entità
// Per Id di entità
static const int ID_NO = -99 ;
// Per tipo di costruzione di poligono
static const int POLYG_INSCR = 1 ;
@@ -189,7 +189,7 @@ GdbExecutor::Execute( const string& sCmd1, const string& sCmd2, const STRVECTOR&
LOG_ERROR( GetEGkLogger(), "Error : null GeomDb in GdbExecutor.")
return ER_ERR ;
}
// verifico validità CmdParser
// verifico validità CmdParser
if ( m_pParser == nullptr) {
LOG_ERROR( GetEGkLogger(), "Error : null CmdParser in GdbExecutor.")
return ER_ERR ;
@@ -218,7 +218,7 @@ GdbExecutor::ExecuteGroup( const string& sCmd2, const STRVECTOR& vsParams)
// 2 o 3 parametri : Id, Id del padre[, Frame]
if ( vsParams.size() != 2 && vsParams.size() != 3)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -236,7 +236,7 @@ GdbExecutor::ExecuteGroup( const string& sCmd2, const STRVECTOR& vsParams)
// 3 parametri : Id, Id del padre, Orig
if ( vsParams.size() != 3)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -253,7 +253,7 @@ GdbExecutor::ExecuteGroup( const string& sCmd2, const STRVECTOR& vsParams)
// creo il gruppo
int nIdDest = GetIdParam( vsParams[0], true) ;
int nIdNew = m_pGDB->AddGroup( nIdDest, GetIdParam( vsParams[1]), frFrame) ;
// se IdDest da calcolare, può essere una variabili a cui cambiare il valore
// se IdDest da calcolare, può essere una variabili a cui cambiare il valore
if ( nIdDest == GDB_ID_NULL)
m_pParser->SetVariable( vsParams[0], nIdNew) ;
@@ -270,7 +270,7 @@ GdbExecutor::ExecutePoint( const string& sCmd2, const STRVECTOR& vsParams)
// 3 parametri : Id, IdParent e punto
if ( vsParams.size() != 3)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frPnt ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frPnt))
return false ;
@@ -289,7 +289,7 @@ GdbExecutor::ExecutePoint( const string& sCmd2, const STRVECTOR& vsParams)
// 4 : Id, IdParent, ptP, vtV
if ( vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frPnt ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frPnt))
return false ;
@@ -351,7 +351,7 @@ GdbExecutor::VectorMake( const STRVECTOR& vsParams)
// 3 o 4 parametri : Id, IdParent, Vettore [, ScaleFactor]
if ( vsParams.size() != 3 && vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect))
return false ;
@@ -378,7 +378,7 @@ GdbExecutor::VectorFromSpherical( const STRVECTOR& vsParams)
// 5 parametri : Id, IdParent, dLen, dAngVertDeg, dAngOrizzDeg
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect))
return false ;
@@ -386,7 +386,7 @@ GdbExecutor::VectorFromSpherical( const STRVECTOR& vsParams)
double dLen ;
if ( ! GetLengthParam( vsParams[2], dLen))
return false ;
// recupero l'angolo in verticale (non c'è metodo generale)
// recupero l'angolo in verticale (non c'è metodo generale)
double dAngVertDeg ;
if ( ! FromString( vsParams[3], dAngVertDeg))
return false ;
@@ -410,7 +410,7 @@ GdbExecutor::VectorCrossProduct( const STRVECTOR& vsParams)
// 4 o 5 parametri : Id, IdParent, vtV1, vtV2 [, bNorm]
if ( vsParams.size() != 4 && vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect))
return false ;
@@ -444,7 +444,7 @@ GdbExecutor::VectorDifference( const STRVECTOR& vsParams)
// 4 o 5 parametri : Id, IdParent, ptP1, ptP2 [, bNorm]
if ( vsParams.size() != 4 && vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect))
return false ;
@@ -478,7 +478,7 @@ GdbExecutor::VectorBaseVector( const STRVECTOR& vsParams)
// 4 o 5 parametri : Id, IdParent, PtBase, Vettore [, ScaleFactor]
if ( vsParams.size() != 4 && vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect))
return false ;
@@ -512,7 +512,7 @@ GdbExecutor::VectorModifyBase( const STRVECTOR& vsParams)
return false ;
// indice dell'oggetto
int nId = GetIdParam( vsParams[0]) ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGlobFrame( nId, frVect))
return false ;
@@ -537,7 +537,7 @@ GdbExecutor::ExecuteFrame( const string& sCmd2, const STRVECTOR& vsParams)
// 3 parametri : Id, ParentId, Frame
if ( vsParams.size() != 3)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -557,7 +557,7 @@ GdbExecutor::ExecuteFrame( const string& sCmd2, const STRVECTOR& vsParams)
// 5 parametri : Id, ParentId, ptOrig, ptOnX, ptNearY
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -579,7 +579,7 @@ GdbExecutor::ExecuteFrame( const string& sCmd2, const STRVECTOR& vsParams)
// 4 parametri
if ( vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -634,7 +634,7 @@ GdbExecutor::CurveLineMake( const STRVECTOR& vsParams)
// 4 parametri : Id, IdParent, ptStart, ptEnd
if ( vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -664,7 +664,7 @@ GdbExecutor::CurveLineVersorLength( const STRVECTOR& vsParams)
// 5 parametri : Id, IdParent, ptStart, vtDir, dLen
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -698,7 +698,7 @@ GdbExecutor::CurveLineDirLength( const STRVECTOR& vsParams)
// 5 parametri : Id, IdParent, ptStart, dAngDeg, dLen
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -863,7 +863,7 @@ GdbExecutor::CurveLineMinPointCurve( const STRVECTOR& vsParams)
// porto il punto nel riferimento della curva
Point3d ptSloc = ptStart ;
ptSloc.LocToLoc( frPoint, frCurve) ;
// recupero eventuale parametro per discriminare tra più soluzioni
// recupero eventuale parametro per discriminare tra più soluzioni
double dNearParam ;
if ( vsParams.size() < 5 || ! FromString( vsParams[4], dNearParam))
dNearParam = 0 ;
@@ -962,7 +962,7 @@ GdbExecutor::CurveCircleMake( const STRVECTOR& vsParams)
// 5 parametri
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -996,7 +996,7 @@ GdbExecutor::CurveCirclePlaneXY( const STRVECTOR& vsParams)
// 4 parametri
if ( vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1026,7 +1026,7 @@ GdbExecutor::CurveArcMake( const STRVECTOR& vsParams)
// 8 parametri
if ( vsParams.size() != 8)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1072,7 +1072,7 @@ GdbExecutor::CurveArcPlaneXY( const STRVECTOR& vsParams)
// 7 parametri
if ( vsParams.size() != 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1114,7 +1114,7 @@ GdbExecutor::CurveArcCircle3P( const STRVECTOR& vsParams, bool bCirc)
// 5 parametri : Id, ParentId, ptP0, ptP1, ptP2
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1148,7 +1148,7 @@ GdbExecutor::CurveArc2PDi( const STRVECTOR& vsParams)
// 5 parametri : Id, ParentId, ptPi, ptPf, dDiri
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1164,7 +1164,7 @@ GdbExecutor::CurveArc2PDi( const STRVECTOR& vsParams)
double dDirI ;
if ( ! GetDirParam( vsParams[4], frRef, dDirI))
return false ;
// calcolo l'arco (in casi particolari può essere una retta)
// calcolo l'arco (in casi particolari può essere una retta)
ICurve* pCurve = GetArc2PD( ptPi, ptPf, dDirI) ;
if ( pCurve == nullptr)
return false ;
@@ -1179,7 +1179,7 @@ GdbExecutor::CurveArc2PRS( const STRVECTOR& vsParams)
// 5 o 6 parametri : Id, ParentId, ptPi, ptPf, dRad[, CCW/CW]
if ( vsParams.size() != 5 && vsParams.size() != 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1217,7 +1217,7 @@ GdbExecutor::CurveArcC2P( const STRVECTOR& vsParams)
// 5 parametri : Id, ParentId, ptCen, ptPi, ptNearPf
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1251,7 +1251,7 @@ GdbExecutor::CurveCircleCenterTgArc( const STRVECTOR& vsParams)
// 5 parametri : Id, ParentId, ptCen, IdArc, ptNear
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frDest ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest))
return false ;
@@ -1297,7 +1297,7 @@ GdbExecutor::CurveArcCenterTgArcP( const STRVECTOR& vsParams)
// 6 parametri : Id, ParentId, ptCen, IdArc, ptNearTg, ptNearEnd
if ( vsParams.size() != 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frDest ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest))
return false ;
@@ -1349,7 +1349,7 @@ GdbExecutor::CurveArcPDiTgArc( const STRVECTOR& vsParams)
// 6 parametri : Id, ParentId, ptStart, dirStart, IdArc, ptNear
if ( vsParams.size() != 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frDest ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest))
return false ;
@@ -1382,7 +1382,7 @@ GdbExecutor::CurveArcPDiTgArc( const STRVECTOR& vsParams)
return false ;
Point3d ptNtloc = ptNear ;
ptNtloc.LocToLoc( frDest, frTgArc) ;
// calcolo l'arco (in casi particolari può essere una linea)
// calcolo l'arco (in casi particolari può essere una linea)
ICurve* pCurve = GetArcPntDirTgCurve( ptSloc, FromPolar( 1, dDirI), *pTgArc, ptNtloc, Z_AX) ;
if ( pCurve == nullptr)
return false ;
@@ -1521,7 +1521,7 @@ GdbExecutor::ExecuteCurveBez( const string& sCmd2, const STRVECTOR& vsParams)
// inizializzo la curva di Bezier
if ( ! pCrvBez->Init( nDeg, false))
return false ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1547,7 +1547,7 @@ GdbExecutor::ExecuteCurveBez( const string& sCmd2, const STRVECTOR& vsParams)
// inizializzo la curva di Bezier
if ( ! pCrvBez->Init( nDeg, true))
return false ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1949,7 +1949,7 @@ GdbExecutor::CurveCompoFromPolygon( const STRVECTOR& vsParams, int nType)
int nNumLati ;
if ( ! FromString( vsParams[2], nNumLati))
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1994,7 +1994,7 @@ GdbExecutor::CurveCompoFromBiarc( const STRVECTOR& vsParams)
// 6 o 7 parametri : Id, IdParent, ptP1, Dir1, ptP2, Dir2 [, Par]
if ( vsParams.size() != 6 && vsParams.size() != 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -2074,7 +2074,7 @@ GdbExecutor::CurveCompoExtractCurve( const STRVECTOR& vsParams, bool bEndOrStart
Frame3d frSou ;
if ( ! m_pGDB->GetGlobFrame( nIdCCompo, frSou))
return false ;
// estraggo la opportuna entità
// estraggo la opportuna entità
PtrOwner<ICurve> pCrv( pCrvCompo->RemoveFirstOrLastCurve( bEndOrStart)) ;
// se 1 solo parametro -> cancellazione
if ( vsParams.size() == 1)
@@ -2161,7 +2161,7 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams)
else if ( sCmd2 == "COMP" || sCmd2 == "DOCOMPACTING") {
return SurfTriMeshDoCompacting( vsParams) ;
}
// se unione di due o più superfici per cucitura
// se unione di due o più superfici per cucitura
else if ( sCmd2 == "SEW" || sCmd2 == "DOSEWING") {
return SurfTriMeshDoSewing( vsParams) ;
}
@@ -2395,7 +2395,7 @@ GdbExecutor::SurfTriMeshByExtrusion( const STRVECTOR& vsParams)
CurveLocal CrvLoc( m_pGDB, nCrvId, frDest) ;
if ( CrvLoc.Get() == nullptr)
return false ;
// recupero il vettore di estrusione (già in locale)
// recupero il vettore di estrusione (già in locale)
Vector3d vtExtr ;
if ( ! GetVectorParam( vsParams[3], frDest, vtExtr))
return false ;
@@ -2471,7 +2471,7 @@ GdbExecutor::SurfTriMeshByScrewing( bool bMove, const STRVECTOR& vsParams)
// recupero la tolleranza lineare
if ( vsParams.size() == 7)
FromString( vsParams[6], dLinTol) ;
// non c'é movimento lungo l'asse
// non c'é movimento lungo l'asse
}
// recupero il riferimento del gruppo destinazione
Frame3d frDest ;
@@ -2642,7 +2642,7 @@ GdbExecutor::SurfTrimeshClonePart( const STRVECTOR& vsParams)
// Parametri : IdNew, IdOld, IdParent, nPart
if ( vsParams.size() != 4)
return false ;
// Recupero il riferimento in cui è immerso
// Recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[2]), frRef))
return false ;
@@ -2785,7 +2785,7 @@ GdbExecutor::VolZmapCreate( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptO, dLengthX, dLengthY, dLengthZ, dPrec [, bTriDexel]
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -2829,7 +2829,7 @@ GdbExecutor::VolZmapCreateFromFlatRegion( const STRVECTOR& vsParams)
// parametri : Id, IdParent, idCurv, dPrec, dLengthZ [, bTriDexel]
if ( vsParams.size() < 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -2867,7 +2867,7 @@ GdbExecutor::VolZmapCreateFromTriMesh( const STRVECTOR& vsParams)
// parametri : Id, IdParent, idSurf, dPrec, bFlag
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -2900,7 +2900,7 @@ GdbExecutor::VolZmapMilling( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptPs, ptPe, vtVs, vtVe, dLinTol, dAngTolDeg (dLinTol e dAngTol sono per lavo con gen tool), bType
if ( vsParams.size() != 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3019,7 +3019,7 @@ bool GdbExecutor::VolZmapDeepnessMeasure( const STRVECTOR& vsParams) {
VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ;
if ( pZmap == nullptr)
return false ;
// recupero il riferimento in cui è immerso lo Zmap
// recupero il riferimento in cui è immerso lo Zmap
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3051,7 +3051,7 @@ GdbExecutor::VolZmapBBoxZmapIntersection( const STRVECTOR& vsParams)
VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ;
if ( pZmap == nullptr)
return false ;
// recupero il riferimento in cui è immerso lo Zmap
// recupero il riferimento in cui è immerso lo Zmap
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3096,7 +3096,7 @@ GdbExecutor::VolZmapBBoxZmapIntersection( const STRVECTOR& vsParams)
// VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ;
// if ( pZmap == nullptr)
// return false ;
// // recupero il riferimento in cui è immerso lo Zmap
// // recupero il riferimento in cui è immerso lo Zmap
// Frame3d frRef ;
// if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
// return false ;
@@ -3143,7 +3143,7 @@ GdbExecutor::VolZmapBBoxZmapIntersection( const STRVECTOR& vsParams)
// VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ;
// if ( pZmap == nullptr)
// return false;
// // recupero il riferimento in cui è immerso lo Zmap
// // recupero il riferimento in cui è immerso lo Zmap
// Frame3d frRef ;
// if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
// return false ;
@@ -3213,7 +3213,7 @@ GdbExecutor::LineDiscInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptDisc, ptLine, vtDisc, vtLine, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3281,7 +3281,7 @@ GdbExecutor::RayDiscInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptDisc, ptLine, vtDisc, vtLine, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3349,7 +3349,7 @@ GdbExecutor::SegmentDiscInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptDisc, ptLine, vtDisc, vtLine, dRad, dLen
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3421,7 +3421,7 @@ GdbExecutor::LineSphereInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptC, ptP, vtV, dRad
if ( vsParams.size() < 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3472,7 +3472,7 @@ GdbExecutor::RaySphereInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptC, ptP, vtV, dRad
if ( vsParams.size() < 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3530,7 +3530,7 @@ GdbExecutor::SegmentSphereInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptC, ptP, vtV, dRad, dLen
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3594,7 +3594,7 @@ GdbExecutor::LineSemiSphereInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3651,7 +3651,7 @@ GdbExecutor::RaySemiSphereInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3714,7 +3714,7 @@ GdbExecutor::SegmentSemiSphereInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad, dLen
if ( vsParams.size() < 8)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3783,7 +3783,7 @@ GdbExecutor::LinCompSemiSphereInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad, dLen, nLinType
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3854,7 +3854,7 @@ GdbExecutor::LineInfiniteCylinderInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3923,7 +3923,7 @@ GdbExecutor::RayInfiniteCylinderInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3992,7 +3992,7 @@ GdbExecutor::SegmentInfiniteCylinderInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad, dLen
if ( vsParams.size() < 8)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4064,7 +4064,7 @@ GdbExecutor::SegmentCylinderInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad, dCylHeigth, dLen
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4140,7 +4140,7 @@ GdbExecutor::SegmentConeInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptVCone, ptLine, vtCone, vtLine, dRad, dCylHeigth, dLen
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4221,7 +4221,7 @@ GdbExecutor::LineTruncateConeInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4303,7 +4303,7 @@ GdbExecutor::RayTruncateConeInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4384,7 +4384,7 @@ GdbExecutor::SegmentTruncateConeInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth
if ( vsParams.size() < 10)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4469,7 +4469,7 @@ GdbExecutor::LineTorusInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad,
if ( vsParams.size() < 8)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4584,7 +4584,7 @@ GdbExecutor::RayTorusInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad,
if ( vsParams.size() < 8)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4734,7 +4734,7 @@ GdbExecutor::SegmentTorusInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, dSgLen
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4903,7 +4903,7 @@ GdbExecutor::LinCompTorusPartInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, dSgLen, nLinType
if ( vsParams.size() < 10)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -5124,7 +5124,7 @@ GdbExecutor::ExecuteDistPointTrimesh( const std::string& sCmd2, const STRVECTOR&
// parametri : Id, IdMovedTria, IdParent, ptP, idSurf
if ( vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -5228,7 +5228,7 @@ GdbExecutor::TextSimple( const STRVECTOR& vsParams)
// parametri : Id, ParentId, Text, Point, AngDeg, H
if ( vsParams.size() != 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -5266,7 +5266,7 @@ GdbExecutor::TextComplete( const STRVECTOR& vsParams)
// parametri : Id, ParentId, Text, Point, AngDeg, Font, W, Italic, H, Rat, AddAdv, PosIns
if ( vsParams.size() != 12)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -5486,7 +5486,7 @@ GdbExecutor::AddGeoObj( const string& sId, const string& sIdParent, IGeoObj* pGe
// creo il gruppo
int nId = GetIdParam( sId, true) ;
int nIdNew = m_pGDB->AddGeoObj( nId, GetIdParam( sIdParent), pGeoObj) ;
// se nId da calcolare, può essere una variabile a cui cambiare il valore
// se nId da calcolare, può essere una variabile a cui cambiare il valore
if ( nId == GDB_ID_NULL)
m_pParser->SetVariable( sId, nIdNew) ;
@@ -5600,9 +5600,9 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
// ci deve essere almeno un parametro
if ( vsParams.size() < 1)
return false ;
// recupero l'indice dell'entità indicata dal primo parametro
// recupero l'indice dell'entità indicata dal primo parametro
int nIdEnt = GetIdParam( vsParams[0]) ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frEnt ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt, frEnt))
return false ;
@@ -5623,7 +5623,7 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
return false ;
}
}
// se entità geometrica
// se entità geometrica
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGDB->GetGeoObj( nIdEnt)) != nullptr) {
// se curva
@@ -5659,7 +5659,7 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
return false ;
return vtV.LocToLoc( frEnt, frVect) ;
}
case 'N' : // versore direzione nel punto più vicino a punto dato
case 'N' : // versore direzione nel punto più vicino a punto dato
{
// secondo parametro : punto di riferimento
Point3d ptRef ;
@@ -5669,7 +5669,7 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
ICurve::Side nSide = ICurve::FROM_MINUS ;
if ( vsParams.size() >= 3 && vsParams[2] == "+")
nSide = ICurve::FROM_PLUS ;
// calcolo il parametro del punto della curva più vicino al punto di riferimento
// calcolo il parametro del punto della curva più vicino al punto di riferimento
DistPointCurve dstPC( ptRef, *pCrv) ;
int nFlag ;
double dU ;
@@ -5723,7 +5723,7 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
}
return false ;
}
// altrimenti nome di vettore già nel DB
// altrimenti nome di vettore già nel DB
else {
int nIdEnt = GetIdParam( sParam) ;
const IGeoVector3d* pV ;
@@ -5742,7 +5742,7 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
bool
GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d& ptP)
{
// se insieme di 2 o 3 coordinate (considerate già nel riferimento frPnt)
// se insieme di 2 o 3 coordinate (considerate già nel riferimento frPnt)
if ( sParam[0] == '(') {
// divido in parti
STRVECTOR vsParams ;
@@ -5766,7 +5766,7 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
else
return false ;
}
// se altrimenti punto predefinito ORIG (considerato già nel riferimento frPnt)
// se altrimenti punto predefinito ORIG (considerato già nel riferimento frPnt)
else if ( sParam == "ORIG") {
ptP = ORIG ;
return true ;
@@ -5784,9 +5784,9 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
// ci deve essere almeno un parametro
if ( vsParams.size() < 1)
return false ;
// recupero l'indice dell'entità indicata dal primo parametro
// recupero l'indice dell'entità indicata dal primo parametro
int nIdEnt = GetIdParam( vsParams[0]) ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frEnt ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt, frEnt))
return false ;
@@ -5801,7 +5801,7 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
return false ;
}
}
// se entità geometrica
// se entità geometrica
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGDB->GetGeoObj( nIdEnt)) != nullptr) {
// se curva
@@ -5835,13 +5835,13 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
return false ;
return ptP.LocToLoc( frEnt, frPnt) ;
}
case 'N' : // punto più vicino a punto dato
case 'N' : // punto più vicino a punto dato
{
// secondo parametro : punto di riferimento
Point3d ptRef ;
if ( vsParams.size() < 2 || ! GetPointParam( vsParams[1], frEnt, ptRef))
return false ;
// calcolo il punto della curva più vicino al punto di riferimento
// calcolo il punto della curva più vicino al punto di riferimento
DistPointCurve dstPC( ptRef, *pCrv) ;
int nFlag ;
if ( ! dstPC.GetMinDistPoint( 0, ptP, nFlag))
@@ -5859,11 +5859,11 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
const ICurve* pCrv2 = GetCurve( pGObj2) ;
if ( pCrv2 == nullptr)
return false ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frEnt2 ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt2, frEnt2))
return false ;
// se il riferimento è diverso da quello della prima entità, devo trasformarla
// se il riferimento è diverso da quello della prima entità, devo trasformarla
PtrOwner<ICurve> pcrvTrans( nullptr) ;
if ( ! AreSameFrame( frEnt, frEnt2)) {
pcrvTrans.Set( pCrv2->Clone()) ;
@@ -5876,7 +5876,7 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
Point3d ptRef ;
if ( vsParams.size() >= 3 && ! GetPointParam( vsParams[2], frEnt, ptRef))
return false ;
// calcolo il punto di intersezione sulla prima curva più vicino al punto di riferimento
// calcolo il punto di intersezione sulla prima curva più vicino al punto di riferimento
IntersCurveCurve intCC( *pCrv, *pCrv2, true) ;
if ( ! intCC.GetIntersPointNearTo( 0, ptRef, ptP))
return false ;
@@ -5938,7 +5938,7 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
}
return false ;
}
// altrimenti nome di punto già nel DB
// altrimenti nome di punto già nel DB
else {
int nIdEnt = GetIdParam( sParam) ;
const IGeoPoint3d* pPt ;
@@ -6015,7 +6015,7 @@ GdbExecutor::GetPointWParam( const string& sParam, const Frame3d& frPnt, Point3d
FromString( vsParams[1], ptP.y) &&
FromString( vsParams[2], dW)) ;
}
// se 2 parti, nome di punto predefinito, punto notevole o già nel DB e un peso
// se 2 parti, nome di punto predefinito, punto notevole o già nel DB e un peso
else if ( vsParams.size() == 2) {
// recupero il punto
if ( ! GetPointParam( vsParams[0], frPnt, ptP))
@@ -6065,7 +6065,7 @@ GdbExecutor::GetLengthParam( const string& sParam, double& dLen)
// ci deve essere almeno un parametro
if ( vsParams.size() < 1)
return false ;
// recupero l'entità indicata dal primo parametro
// recupero l'entità indicata dal primo parametro
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGDB->GetGeoObj( GetIdParam( vsParams[0]))) == nullptr)
return false ;
@@ -6088,7 +6088,7 @@ GdbExecutor::GetLengthParam( const string& sParam, double& dLen)
// ci deve essere almeno un parametro
if ( vsParams.size() < 1)
return false ;
// recupero l'entità indicata dal primo parametro
// recupero l'entità indicata dal primo parametro
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGDB->GetGeoObj( GetIdParam( vsParams[0]))) == nullptr)
return false ;
@@ -6124,12 +6124,12 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
// ci deve essere almeno un parametro
if ( vsParams.size() < 1)
return false ;
// recupero l'entità indicata dal primo parametro
// recupero l'entità indicata dal primo parametro
int nIdEnt = GetIdParam( vsParams[0]) ;
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGDB->GetGeoObj( nIdEnt)) == nullptr)
return false ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frEnt ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt, frEnt))
return false ;
@@ -6143,7 +6143,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
if ( ! pCrv->GetStartDir( vtDir) || ! vtDir.LocToLoc( frEnt, frDir))
return false ;
vtDir.ToSpherical( nullptr, nullptr, &dDir) ;
// se esiste un secondo parametro è un offset di rotazione
// se esiste un secondo parametro è un offset di rotazione
if ( vsParams.size() >= 2) {
double dOffsetDeg = 0 ;
FromString( vsParams[1], dOffsetDeg) ;
@@ -6154,7 +6154,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
if ( ! pCrv->GetEndDir( vtDir) || ! vtDir.LocToLoc( frEnt, frDir))
return false ;
vtDir.ToSpherical( nullptr, nullptr, &dDir) ;
// se esiste un secondo parametro è un offset di rotazione
// se esiste un secondo parametro è un offset di rotazione
if ( vsParams.size() >= 2) {
double dOffsetDeg = 0 ;
FromString( vsParams[1], dOffsetDeg) ;
@@ -6165,7 +6165,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
if ( ! pCrv->GetMidDir( vtDir) || ! vtDir.LocToLoc( frEnt, frDir))
return false ;
vtDir.ToSpherical( nullptr, nullptr, &dDir) ;
// se esiste un secondo parametro è un offset di rotazione
// se esiste un secondo parametro è un offset di rotazione
if ( vsParams.size() >= 2) {
double dOffsetDeg = 0 ;
FromString( vsParams[1], dOffsetDeg) ;
@@ -6196,7 +6196,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
}
return true ;
}
case 'N' : // versore direzione nel punto più vicino a punto dato
case 'N' : // versore direzione nel punto più vicino a punto dato
{
// secondo parametro : punto di riferimento
Point3d ptRef ;
@@ -6206,7 +6206,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
ICurve::Side nSide = ICurve::FROM_MINUS ;
if ( vsParams.size() >= 3 && vsParams[2] == "+")
nSide = ICurve::FROM_PLUS ;
// calcolo il parametro del punto della curva più vicino al punto di riferimento
// calcolo il parametro del punto della curva più vicino al punto di riferimento
DistPointCurve dstPC( ptRef, *pCrv) ;
int nFlag ;
double dU ;
@@ -6236,7 +6236,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
Vector3d vtDir = pGVect->GetVector() ;
vtDir.LocToLoc( frEnt, frDir) ;
vtDir.ToSpherical( nullptr, nullptr, &dDir) ;
// se esiste un secondo parametro è un offset di rotazione
// se esiste un secondo parametro è un offset di rotazione
if ( vsParams.size() >= 2) {
double dOffsetDeg = 0 ;
FromString( vsParams[1], dOffsetDeg) ;
@@ -6294,7 +6294,7 @@ GdbExecutor::GetFrameParam( const string& sParam, const Frame3d& frRef, Frame3d&
STRVECTOR::iterator Iter ;
for ( Iter = vsParams.begin() ; Iter != vsParams.end() ; ++Iter)
Trim( (*Iter), " \t\r\n") ;
// se c'è un parametro è l'origine
// se c'è un parametro è l'origine
Point3d ptOrig ;
if ( vsParams.size() >= 1) {
if ( ! GetPointParam( vsParams[0], frRef, ptOrig))
@@ -6325,11 +6325,11 @@ GdbExecutor::GetFrameParam( const string& sParam, const Frame3d& frRef, Frame3d&
}
return true ;
}
// altrimenti nome di gruppo o di frame già nel DB
// altrimenti nome di gruppo o di frame già nel DB
else {
// identificativo
int nIdEnt = GetIdParam( sParam) ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frEnt ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt, frEnt))
return false ;
@@ -6337,7 +6337,7 @@ GdbExecutor::GetFrameParam( const string& sParam, const Frame3d& frRef, Frame3d&
if ( m_pGDB->GetGroupFrame( nIdEnt, frF)) {
return frF.LocToLoc( frEnt, frRef) ;
}
// altrimenti entità geometrica
// altrimenti entità geometrica
else {
// verifico se riferimento
const IGeoFrame3d* pFr ;
@@ -6393,7 +6393,7 @@ GdbExecutor::GetColorParam( const string& sParam, bool& bByParent, Color& cCol)
// ci deve essere un parametro
if ( vsParams.size() != 1)
return false ;
// recupero il colore dell'entità indicata dal parametro
// recupero il colore dell'entità indicata dal parametro
bByParent = false ;
return m_pGDB->GetCalcMaterial( GetIdParam( vsParams[0]), cCol) ;
}
@@ -6427,7 +6427,7 @@ GdbExecutor::GetMaterialParam( const string& sParam, bool& bByParent, int& nMat)
// ci deve essere un parametro
if ( vsParams.size() != 1)
return false ;
// recupero il materiale dell'entità indicata dal parametro
// recupero il materiale dell'entità indicata dal parametro
bByParent = false ;
return ( m_pGDB->GetCalcMaterial( GetIdParam( vsParams[0]), nMat) && nMat != GDB_MT_COLOR) ;
}
@@ -6975,7 +6975,7 @@ GdbExecutor::ExecuteCopy( const string& sCmd2, const STRVECTOR& vsParams)
nIdNew = m_pGDB->CopyGlob( GetIdParam( vsParams[0]), nIdDest, GetIdParam( vsParams[2]), nSonBeforeAfter) ;
else
nIdNew = m_pGDB->Copy( GetIdParam( vsParams[0]), nIdDest, GetIdParam( vsParams[2]), nSonBeforeAfter) ;
// se IdDest da calcolare, può essere una variabile a cui cambiare il valore
// se IdDest da calcolare, può essere una variabile a cui cambiare il valore
if ( nIdDest == GDB_ID_NULL)
m_pParser->SetVariable( vsParams[1], nIdNew) ;
@@ -7647,7 +7647,7 @@ GdbExecutor::CurveCopyBySplitClass( const STRVECTOR& vsParams)
IntersCurveCurve intCC( *pCrv, *pCloCrv, true) ;
// recupero la classificazione della prima curva
CRVCVECTOR ccClass ;
if ( ! intCC.GetCurveClassification( 0, ccClass))
if ( ! intCC.GetCurveClassification( 0, EPS_SMALL, ccClass))
return false ;
// recupero gli indici dei gruppi destinazione e i loro riferimenti
const int N_GRP = 4 ;
@@ -7877,7 +7877,7 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams)
// devono essere 6 parametri : IdText, IdGroup, IdEnt1, IdEnt2, ptText, hText
if ( vsParams.size() != 6)
return false ;
// recupero l'indice delle entità
// recupero l'indice delle entità
int nIdEnt1 = GetIdParam( vsParams[2]) ;
int nIdEnt2 = GetIdParam( vsParams[3]) ;
// verifico siano due curve
@@ -7894,7 +7894,7 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams)
Frame3d frEnt2 ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt2, frEnt2))
return false ;
// se i riferimenti sono diversi, porto la seconda entità nel riferimento della prima
// se i riferimenti sono diversi, porto la seconda entità nel riferimento della prima
PtrOwner<ICurve> pcrvTrans ;
if ( ! AreSameFrame( frEnt1, frEnt2)) {
pcrvTrans.Set( pCrv2->Clone()) ;
@@ -7953,7 +7953,7 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams)
}
}
}
// recupero il riferimento in cui è immerso il testo
// recupero il riferimento in cui è immerso il testo
Frame3d frText ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frText))
return false ;
@@ -8090,7 +8090,7 @@ bool
GdbExecutor::OutGroupTsc( int nId, int nFlag, int nLev)
{
m_OutTsc.Remark( "Start Group ---") ;
// emetto dati gruppo ( se non è radice)
// emetto dati gruppo ( se non è radice)
if ( nId > GDB_ID_ROOT) {
Frame3d frFrame ;
if ( ( nLev == 0 && m_pGDB->GetGroupGlobFrame( nId, frFrame)) ||
@@ -8113,7 +8113,7 @@ GdbExecutor::OutGroupTsc( int nId, int nFlag, int nLev)
}
}
}
// emetto entità gruppo
// emetto entità gruppo
m_OutTsc.Remark( "Entities :") ;
GdbIterator Iter( m_pGDB) ;
bool bNext = Iter.GoToFirstInGroup( nId) ;
+3 -2
View File
@@ -32,8 +32,9 @@ using namespace std ;
//----------------------------------------------------------------------------
GdbObj::GdbObj( void)
: m_nId( GDB_ID_NULL), m_pAttribs( nullptr), m_pTxrData( nullptr), m_pUserObj( nullptr),
m_pSelPrev( nullptr), m_pSelNext( nullptr),
m_pGDB( nullptr), m_pNext( nullptr), m_pPrev( nullptr), m_pParent( nullptr)
m_pGDB( nullptr), m_pNext( nullptr), m_pPrev( nullptr), m_pParent( nullptr),
m_pSelNext( nullptr), m_pSelPrev( nullptr)
{
}
+5 -2
View File
@@ -29,8 +29,10 @@ GEOOBJ_REGISTER( GEO_FRAME3D, NGE_G_FRM, GeoFrame3d) ;
//----------------------------------------------------------------------------
GeoFrame3d::GeoFrame3d( void)
: m_frF(), m_nTempProp()
: m_frF()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -114,7 +116,8 @@ GeoFrame3d::CopyFrom( const GeoFrame3d& gfSrc)
{
if ( &gfSrc == this)
return true ;
m_nTempProp = gfSrc.m_nTempProp ;
m_nTempProp[0] = gfSrc.m_nTempProp[0] ;
m_nTempProp[1] = gfSrc.m_nTempProp[1] ;
return Set( gfSrc.m_frF) ;
}
+6 -5
View File
@@ -57,10 +57,11 @@ class GeoFrame3d : public IGeoFrame3d, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // IGeoFrame3d
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -95,5 +96,5 @@ class GeoFrame3d : public IGeoFrame3d, public IGeoObjRW
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
Frame3d m_frF ; // oggetto
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
+5 -2
View File
@@ -28,8 +28,10 @@ GEOOBJ_REGISTER( GEO_PNT3D, NGE_G_PNT, GeoPoint3d) ;
//----------------------------------------------------------------------------
GeoPoint3d::GeoPoint3d( void)
: m_ptP(), m_nTempProp()
: m_ptP()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -82,7 +84,8 @@ GeoPoint3d::CopyFrom( const GeoPoint3d& clSrc)
{
if ( &clSrc == this)
return true ;
m_nTempProp = clSrc.m_nTempProp ;
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
return Set( clSrc.m_ptP) ;
}
+6 -5
View File
@@ -57,10 +57,11 @@ class GeoPoint3d : public IGeoPoint3d, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // IGeoPoint3d
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -89,5 +90,5 @@ class GeoPoint3d : public IGeoPoint3d, public IGeoObjRW
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
Point3d m_ptP ; // oggetto
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
+5 -2
View File
@@ -29,8 +29,10 @@ GEOOBJ_REGISTER( GEO_VECT3D, NGE_G_VEC, GeoVector3d) ;
//----------------------------------------------------------------------------
GeoVector3d::GeoVector3d( void)
: m_vtV(), m_nTempProp()
: m_vtV()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -98,7 +100,8 @@ GeoVector3d::CopyFrom( const GeoVector3d& clSrc)
{
if ( &clSrc == this)
return true ;
m_nTempProp = clSrc.m_nTempProp ;
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
return Set( clSrc.m_vtV, clSrc.m_ptBase) ;
}
+6 -5
View File
@@ -65,10 +65,11 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // IGeoVector3d
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -104,5 +105,5 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
Vector3d m_vtV ; // oggetto
Point3d m_ptBase ; // punto base da cui tracciare il vettore
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
-1
View File
@@ -684,7 +684,6 @@ HashGrids3d::Update( void)
double dSize = 0 ;
Obj.box.GetDiameter( dSize) ;
double dCellSpan = pGrid->GetCellSpan() ;
if ( dSize >= dCellSpan || dSize < ( dCellSpan / hierarchyFactor)) {
pGrid->Remove( Obj) ;
addGrid( Obj) ;
+10 -8
View File
@@ -391,7 +391,7 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
//----------------------------------------------------------------------------
bool
IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR& ccClass)
{
// pulisco vettore classificazioni
ccClass.clear() ;
@@ -407,7 +407,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
return false ;
// se esiste almeno una intersezione
if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[0], m_Info, ccClass) ;
return CalcCurveClassification( m_pCurve[0], m_Info, dLenMin, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna
else
return CalcCurveInOrOut( m_pCurve[0], m_pCurve[1], ccClass) ;
@@ -424,7 +424,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
SwapInfoAB( InfoTmp, 1) ;
// se esiste almeno una intersezione
if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[1], InfoTmp, ccClass) ;
return CalcCurveClassification( m_pCurve[1], InfoTmp, dLenMin, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna
else
return CalcCurveInOrOut( m_pCurve[1], m_pCurve[0], ccClass) ;
@@ -461,7 +461,7 @@ IntersCurveCurve::SwapInfoAB( ICCIVECTOR& Info, int IndCrvOrd)
//----------------------------------------------------------------------------
bool
IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTOR& Info, CRVCVECTOR& ccClass)
IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTOR& Info, double dLenMin, CRVCVECTOR& ccClass)
{
// numero intersezioni
int nNumInters = int( Info.size()) ;
@@ -471,6 +471,8 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
double dStartPar, dEndPar ;
if ( pCurve == nullptr || ! pCurve->GetDomain( dStartPar, dEndPar))
return false ;
// limito lunghezza minima
dLenMin = max( dLenMin, EPS_ZERO) ;
// elimino intersezioni senza attraversamento che giacciono in intervalli di sovrapposizione
ICCIVECTOR InfoCorr ;
InfoCorr.reserve( Info.size()) ;
@@ -527,7 +529,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
for ( int i = 0 ; i < nNumInters ; ++ i) {
// se è definito un tratto precedente
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].IciA[0].dU, dLenU) ;
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > EPS_SMALL) {
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
// verifico che la definizione sul tratto sia omogenea e valida
int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ;
if ( ( nLastTy != ICCT_NULL && nPrevTy != nLastTy) ||
@@ -562,7 +564,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
}
}
// eventuale tratto finale rimasto
if ( dCurrPar < dEndPar - EPS_PARAM && dEndLen - dCurrLen > EPS_SMALL) {
if ( dCurrPar < dEndPar - EPS_PARAM && dEndLen - dCurrLen > dLenMin) {
// verifico che la definizione sul tratto sia valida
if ( nLastTy == ICCT_NULL || nLastTy == ICCT_ON)
return false ;
@@ -673,7 +675,7 @@ IntersCurveCurve::GetRegionCurveClassification( void)
{
// classifico la prima curva rispetto alla seconda
CRVCVECTOR ccClass ;
if ( ! GetCurveClassification( 0, ccClass))
if ( ! GetCurveClassification( 0, EPS_SMALL, ccClass))
return CCREGC_NULL ;
// derivo la classificazione delle curve come regioni
bool bIn = false ;
@@ -710,7 +712,7 @@ IntersCurveCurve::GetRegionCurveClassification( void)
if ( bOnP)
return CCREGC_IN2 ;
CRVCVECTOR ccClass2 ;
if ( ! GetCurveClassification( 1, ccClass2) || ccClass2.empty())
if ( ! GetCurveClassification( 1, EPS_SMALL, ccClass2) || ccClass2.empty())
return CCREGC_NULL ;
if ( ccClass2[0].nClass == CRVC_OUT)
return CCREGC_OUT ;
+127 -108
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2020-2020
// EgalTech 2020-2022
//----------------------------------------------------------------------------
// File : IntersLineBox.cpp Data : 07.05.20 Versione : 2.2e1
// File : IntersLineBox.cpp Data : 08.01.22 Versione : 2.4a3
// Contenuto : Implementazione della intersezione linea/box.
//
//
@@ -13,13 +13,77 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "SurfTriMesh.h"
#include "IntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include <algorithm>
using namespace std ;
//----------------------------------------------------------------------------
// Linea e box allineato assi devono essere nel medesimo sistema di riferimento.
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
const Point3d& ptMin, const Point3d& ptMax,
double& dU1, double& dU2)
{
// Verifico il versore
if ( vtL.IsSmall())
return false ;
// Verifico gli estremi del box
if ( ptMin.x > ptMax.x + EPS_SMALL ||
ptMin.y > ptMax.y + EPS_SMALL ||
ptMin.z > ptMax.z + EPS_SMALL)
return false ;
// Casi di intersezione impossibile
if ( abs( vtL.x) < EPS_ZERO && ( ptL.x < ptMin.x - EPS_SMALL || ptL.x > ptMax.x + EPS_SMALL))
return false ;
if ( abs( vtL.y) < EPS_ZERO && ( ptL.y < ptMin.y - EPS_SMALL || ptL.y > ptMax.y + EPS_SMALL))
return false ;
if ( abs( vtL.z) < EPS_ZERO && ( ptL.z < ptMin.z - EPS_SMALL || ptL.z > ptMax.z + EPS_SMALL))
return false ;
// Parametri degli estremi della retta
dU1 = -INFINITO ;
dU2 = INFINITO ;
// Confronto con piani YZ (perpendicolari ad asse X)
if ( vtL.x > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.x - ptL.x) / vtL.x) ;
dU2 = min( dU2, ( ptMax.x - ptL.x) / vtL.x) ;
}
else if ( vtL.x < -EPS_ZERO) {
dU1 = max( dU1, ( ptMax.x - ptL.x) / vtL.x) ;
dU2 = min( dU2, ( ptMin.x - ptL.x) / vtL.x) ;
}
// Confronto con piani ZX (perpendicolari ad asse Y)
if ( vtL.y > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.y - ptL.y) / vtL.y) ;
dU2 = min( dU2, ( ptMax.y - ptL.y) / vtL.y) ;
}
else if ( vtL.y < -EPS_ZERO) {
dU1 = max( dU1, ( ptMax.y - ptL.y) / vtL.y) ;
dU2 = min( dU2, ( ptMin.y - ptL.y) / vtL.y) ;
}
// Confronto con piani XY (perpendicolari ad asse Z)
if ( vtL.z > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.z - ptL.z) / vtL.z) ;
dU2 = min( dU2, ( ptMax.z - ptL.z) / vtL.z) ;
}
else if ( vtL.z < -EPS_ZERO){
dU1 = max( dU1, ( ptMax.z - ptL.z) / vtL.z) ;
dU2 = min( dU2, ( ptMin.z - ptL.z) / vtL.z) ;
}
return ( dU2 >= dU1) ;
}
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptL1, const Point3d& ptL2, const BBox3d& b3Box, INTDBLVECTOR& vInters, bool bFinite)
@@ -38,114 +102,69 @@ bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3d& b3Box, INTDBLVECTOR& vInters, bool bFinite)
{
// Recupero i dati del Box
Point3d ptMin ;
double dDimX, dDimY, dDimZ ;
if ( ! b3Box.GetMinDim( ptMin, dDimX, dDimY, dDimZ))
Point3d ptMin, ptMax ;
if ( ! b3Box.GetMinMax( ptMin, ptMax))
return false ;
// Contorno di base
PolyLine PL ;
PL.AddUPoint( 0, ptMin) ;
PL.AddUPoint( 1, ptMin + Vector3d( dDimX, 0, 0)) ;
PL.AddUPoint( 2, ptMin + Vector3d( dDimX, dDimY, 0)) ;
PL.AddUPoint( 3, ptMin + Vector3d( 0, dDimY, 0)) ;
PL.Close() ;
// Vettore altezza
Vector3d vtExtr( 0, 0, dDimZ) ;
// Creo la superficie trimesh equivalente
SurfTriMesh Stm ;
if ( ! Stm.CreateByExtrusion( PL, vtExtr))
return false ;
SurfTriMesh StmBot ;
if ( ! StmBot.CreateByFlatContour( PL))
return false ;
StmBot.Invert() ;
SurfTriMesh StmTop ;
if ( ! StmTop.CreateByFlatContour( PL))
return false ;
StmTop.Translate( vtExtr) ;
if ( ! Stm.DoSewing( StmBot) || ! Stm.DoSewing( StmTop))
return false ;
// Calcolo l'intersezione
ILSIVECTOR vInfo ;
if ( ! IntersLineSurfTm( ptL, vtL, dLen, Stm, vInfo, bFinite))
return false ;
// ciclo sulle intersezioni
double dUcurr = -INFINITO ;
for ( const auto& Info : vInfo) {
// se intersezione puntuale
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
int nFlag = ILBT_TOUCH ;
if ( Info.dCosDN > EPS_ZERO)
nFlag = ILBT_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = ILBT_IN ;
vInters.emplace_back( nFlag, Info.dU) ;
dUcurr = Info.dU ;
// Pulisco vettore intersezioni
vInters.clear() ;
// Eseguo intersezione della linea completa
double dU1, dU2 ;
bool bInters = IntersLineBox( ptL, vtL, b3Box.GetMin(), b3Box.GetMax(), dU1, dU2) ;
// Se non c'è intersezione
if ( ! bInters || ( bFinite && ( dU1 > dLen + EPS_SMALL || dU2 < -EPS_SMALL)))
return true ;
// Se le due intersezioni coincidono
if ( ( dU2 - dU1) < EPS_SMALL) {
double dU = ( dU1 + dU2) / 2 ;
if ( ! bFinite) {
vInters.emplace_back( ILBT_TOUCH, dU) ;
}
// se altrimenti intersezione con coincidenza
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
if ( Info.dU > dUcurr - EPS_SMALL)
vInters.emplace_back( ILBT_TG_INI, Info.dU) ;
vInters.emplace_back( ILBT_TG_FIN, Info.dU2) ;
dUcurr = Info.dU2 ;
else {
if ( dU > - EPS_SMALL && dU < dLen + EPS_SMALL)
vInters.emplace_back( ILBT_TOUCH, Clamp( dU, 0., dLen)) ;
}
}
// elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) {
// intersezione precedente
size_t i = j - 1 ;
// se sono dello stesso tipo, elimino una delle due
if ( vInters[i].first == vInters[j].first) {
// se entranti elimino la prima
if ( vInters[i].first == ILBT_IN || vInters[i].first == ILBT_TG_INI)
vInters.erase( vInters.begin() + i) ;
// altrimenti la seconda
else
vInters.erase( vInters.begin() + j) ;
if ( i > 0)
-- j ;
continue ;
}
// se hanno lo stesso parametro
else if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
if ( ( vInters[i].first == ILBT_IN && vInters[j].first == ILBT_OUT) ||
( vInters[i].first == ILBT_OUT && vInters[j].first == ILBT_IN)) {
vInters[i].first = ILBT_TOUCH ;
vInters.erase( vInters.begin() + j) ;
if ( i > 0)
-- j ;
continue ;
}
// se prima puntuale e l'altra inizio o fine di coincidenza, elimino la prima
else if ( ( vInters[i].first == ILBT_IN || vInters[i].first == ILBT_OUT || vInters[i].first == ILBT_TOUCH) &&
( vInters[j].first == ILBT_TG_INI || vInters[j].first == ILBT_TG_FIN)) {
vInters.erase( vInters.begin() + i) ;
if ( i > 0)
-- j ;
continue ;
}
// se prima inizio o fine di coincidenza e l'altra puntuale, elimino la seconda
else if ( ( vInters[i].first == ILBT_TG_INI || vInters[i].first == ILBT_TG_FIN) &&
( vInters[j].first == ILBT_IN || vInters[j].first == ILBT_OUT || vInters[j].first == ILBT_TOUCH)) {
vInters.erase( vInters.begin() + j) ;
if ( i > 0)
-- j ;
continue ;
}
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
else if ( ( vInters[i].first == ILBT_TG_FIN && vInters[j].first == ILBT_TG_INI) ||
( vInters[i].first == ILBT_TG_INI && vInters[j].first == ILBT_TG_FIN)) {
vInters.erase( vInters.begin() + j) ;
vInters.erase( vInters.begin() + i) ;
if ( i > 0)
-- j ;
continue ;
}
}
// passo alla successiva
++ j ;
return true ;
}
// Se sono due intersezioni con la linea giacente su una faccia del box
if ( ( abs( vtL.x) < EPS_ZERO && ( abs( ptL.x - ptMin.x) < EPS_SMALL || abs( ptL.x - ptMax.x) < EPS_SMALL)) ||
( abs( vtL.y) < EPS_ZERO && ( abs( ptL.y - ptMin.y) < EPS_SMALL || abs( ptL.y - ptMax.y) < EPS_SMALL)) ||
( abs( vtL.z) < EPS_ZERO && ( abs( ptL.z - ptMin.z) < EPS_SMALL || abs( ptL.z - ptMax.z) < EPS_SMALL))) {
if ( ! bFinite) {
vInters.emplace_back( ILBT_TG_INI, dU1) ;
vInters.emplace_back( ILBT_TG_FIN, dU2) ;
}
else {
if ( dU1 > dLen - EPS_SMALL)
vInters.emplace_back( ILBT_IN, dLen) ;
else if ( dU2 < EPS_SMALL)
vInters.emplace_back( ILBT_OUT, 0) ;
else {
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ;
}
}
return true ;
}
// Altrimenti sono due intersezioni con attraversamento
if ( ! bFinite) {
vInters.emplace_back( ILBT_IN, dU1) ;
vInters.emplace_back( ILBT_OUT, dU2) ;
}
else {
if ( dU1 > dLen - EPS_SMALL)
vInters.emplace_back( ILBT_IN, dLen) ;
else if ( dU2 < EPS_SMALL)
vInters.emplace_back( ILBT_OUT, 0) ;
else {
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
}
}
return true ;
}
+34
View File
@@ -0,0 +1,34 @@
//----------------------------------------------------------------------------
// EgalTech 2022-2022
//----------------------------------------------------------------------------
// File : IntersLineBox.h Data : 08.01.22 Versione : 2.4a3
// Contenuto : Dichiarazione delle funzioni base per intersezione linea/box.
//
//
//
// Modifiche : 08.01.22 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EGkPoint3d.h"
//----------------------------------------------------------------------------
// Linea e box allineato agli assi sono nel medesimo riferimento.
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
const Point3d& ptMin, const Point3d& ptMax,
double& dU1, double& dU2) ;
//----------------------------------------------------------------------------
inline bool
TestIntersLineBox( const Point3d& ptL, const Vector3d& vtL,
const Point3d& ptMin, const Point3d& ptMax)
{
double dU1, dU2 ;
return IntersLineBox( ptL, vtL, ptMin, ptMax, dU1, dU2) ;
}
+3 -56
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2017-2018
// EgalTech 2017-2022
//----------------------------------------------------------------------------
// File : IntersLineSurfStd.cpp Data : 03.12.18 Versione : 1.9l1
// File : IntersLineSurfStd.cpp Data : 08.01.22 Versione : 2.4a3
// Contenuto : Implementazione delle funzioni di intersezione
// componente lineare e superficie standard.
//
@@ -13,6 +13,7 @@
#include "stdafx.h"
#include "IntersLineSurfStd.h"
#include "IntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h"
@@ -21,60 +22,6 @@
using namespace std ;
//----------------------------------------------------------------------------
// Punti e vettore devono essere espressi nel medesimo sistema di riferimento.
// Il box è allineato con gli assi di questo sistema di riferimento.
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptP, const Vector3d& vtV,
const Point3d& ptMin, const Point3d& ptMax, double& dU1, double& dU2)
{
// Casi di intersezione impossibile
if ( abs( vtV.x) < EPS_ZERO && ( ptP.x < ptMin.x - EPS_SMALL || ptP.x > ptMax.x + EPS_SMALL))
return false ;
if ( abs( vtV.y) < EPS_ZERO && ( ptP.y < ptMin.y - EPS_SMALL || ptP.y > ptMax.y + EPS_SMALL))
return false ;
if ( abs( vtV.z) < EPS_ZERO && ( ptP.z < ptMin.z - EPS_SMALL || ptP.z > ptMax.z + EPS_SMALL))
return false ;
// Inizializzo parametri intersezioni
dU1 = -INFINITO ;
dU2 = INFINITO ;
// Confronto con piani YZ (perpendicolari ad asse X)
if ( vtV.x > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.x - ptP.x) / vtV.x) ;
dU2 = min( dU2, ( ptMax.x - ptP.x) / vtV.x) ;
}
else if ( vtV.x < -EPS_ZERO) {
dU1 = max( dU1, ( ptMax.x - ptP.x) / vtV.x) ;
dU2 = min( dU2, ( ptMin.x - ptP.x) / vtV.x) ;
}
// Confronto con piani ZX (perpendicolari ad asse Y)
if ( vtV.y > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.y - ptP.y) / vtV.y) ;
dU2 = min( dU2, ( ptMax.y - ptP.y) / vtV.y) ;
}
else if ( vtV.y < -EPS_ZERO) {
dU1 = max( dU1, ( ptMax.y - ptP.y) / vtV.y) ;
dU2 = min( dU2, ( ptMin.y - ptP.y) / vtV.y) ;
}
// Confronto con piani XY (perpendicolari ad asse Z)
if ( vtV.z > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.z - ptP.z) / vtV.z) ;
dU2 = min( dU2, ( ptMax.z - ptP.z) / vtV.z) ;
}
else if ( vtV.z < -EPS_ZERO) {
dU1 = max( dU1, ( ptMax.z - ptP.z) / vtV.z) ;
dU2 = min( dU2, ( ptMin.z - ptP.z) / vtV.z) ;
}
return ( dU2 >= dU1) ;
}
//----------------------------------------------------------------------------
int
LineDisc( const Point3d& ptPLine, const Vector3d& vtVLine,
-5
View File
@@ -34,11 +34,6 @@
// Costanti tipologia di componente lineare
enum LinType { Line = 0, Ray = 1, Segment = 2} ;
//----------------------------------------------------------------------------
bool IntersLineBox( const Point3d& ptP, const Vector3d& vtV,
const Point3d& ptMin, const Point3d& ptMax, double& dU1, double& dU2) ;
// Costanti tipologia di intersezioni fra un componente lineare e un disco
enum LinCompDiscIntersType { D_ERROR_INT = -1, D_NO_INTERS = 0, D_BOUNDARY_INT_LINE_NOT_IN_PLANE = 1,
D_INNER_INT_LINE_NOT_IN_PLANE = 2, D_ONE_INT_LINE_ON_PLANE = 3,
+3 -4
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2019
// EgalTech 2015-2022
//----------------------------------------------------------------------------
// File : IntersLineSurfTm.cpp Data : 09.03.15 Versione : 2.1b6
// File : IntersLineSurfTm.cpp Data : 08.01.22 Versione : 2.4a3
// Contenuto : Implementazione della intersezione linea/superficie trimesh.
//
//
@@ -14,8 +14,7 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ProjPlane.h"
#include "IntersLineSurfStd.h"
#include "/EgtDev/Include/EGkSurfTriMesh.h"
#include "IntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
+34 -6
View File
@@ -1,8 +1,8 @@
//----------------------------------------------------------------------------
// EgalTech 2020-2020
//----------------------------------------------------------------------------
// File : IntersLineBox.cpp Data : 07.05.20 Versione : 2.2e1
// Contenuto : Implementazione della intersezione linea/box.
// File : IntersPlaneBox.cpp Data : 07.05.20 Versione : 2.2e1
// Contenuto : Implementazione della intersezione piano/box.
//
//
//
@@ -20,19 +20,47 @@
using namespace std ;
//----------------------------------------------------------------------------
// Box e piano devono essere nello stesso riferimento. Il box deve essere axis aligned.
bool
IntersPlaneBox( const Point3d& ptOn, const Vector3d& vtN, const BBox3d& b3Box,
TestIntersPlaneBox( const Plane3d& plPlane, const BBox3d& b3Box)
{
// Verifica del piano
if ( ! plPlane.IsValid())
return false ;
// Centro e estensione del box
Point3d ptCen ;
Vector3d vtExt ;
if ( ! b3Box.GetCenterExtent( ptCen, vtExt))
return false ;
// Distanza del centro dal piano
double dDist = DistPointPlane( ptCen, plPlane) ;
// Proiezione dell'estensione sulla normale al piano
Vector3d vtN = plPlane.GetVersN() ;
double dProjExt = vtExt.x * abs( vtN.x) + vtExt.y * abs( vtN.y) + vtExt.z * abs( vtN.z) ;
// Confronto distanza del centro con estensione proiettata
return ( abs( dDist) < dProjExt + EPS_SMALL) ;
}
//----------------------------------------------------------------------------
bool
IntersPlaneBox( const Plane3d& plPlane, const BBox3d& b3Box,
PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria)
{
// Creo il piano
Plane3d plPlane ;
if ( ! plPlane.Set( ptOn, vtN))
// Verifico il piano
if ( ! plPlane.IsValid())
return false ;
// Recupero i dati del Box
Point3d ptMin ;
double dDimX, dDimY, dDimZ ;
if ( ! b3Box.GetMinDim( ptMin, dDimX, dDimY, dDimZ))
return false ;
// Pulisco vettori intersezioni
vPnt.clear() ;
vBpt.clear() ;
vTria.clear() ;
// Verifico se può esistere intersezione
if ( ! TestIntersPlaneBox( plPlane, b3Box))
return true ;
// Contorno di base
PolyLine PL ;
PL.AddUPoint( 0, ptMin) ;
+1 -1
View File
@@ -116,7 +116,7 @@ IntersSurfTmSurfTm( const ISurfTriMesh& Stm1, const ISurfTriMesh& Stm2,
}
}
// se altrimenti sovrapposizione
else if ( nRes == ITTT_OVERLAPS) {
else if ( nRes == ITTT_OVERLAPS || nRes == ITTT_COUNTER_OVERLAPS) {
for ( const auto& Tria : vIttTria) {
// verifico se triangolo già inserito
bool bFound = false ;
+34 -5
View File
@@ -83,8 +83,37 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p
// se i triangoli sono complanari
if ( nResPP == IPPT_OVERLAPS ||
((( nVertPos1 == 0 && nVertNeg1 == 0) || ( nVertPos2 == 0 && nVertNeg2 == 0)) &&
( trTria1.GetN() ^ trTria2.GetN()).SqLen() < 25 * SIN_EPS_ANG_SMALL * SIN_EPS_ANG_SMALL))
return IntersCoplanarTriaTria( trTria1, trTria2, vTria) ;
( trTria1.GetN() ^ trTria2.GetN()).SqLen() < 25 * SIN_EPS_ANG_SMALL * SIN_EPS_ANG_SMALL)) {
// verifica per triangoli con normali controverse
bool bCounter = false ;
Triangle3d trMyTria2 = trTria2 ;
if ( trTria1.GetN() * trTria2.GetN() < 0) {
Point3d ptV0 = trMyTria2.GetP( 0) ;
trMyTria2.SetP( 0, trMyTria2.GetP( 1)) ;
trMyTria2.SetP( 1, ptV0) ;
trMyTria2.Validate() ;
bCounter = true ;
}
// verifica per triangoli coincidenti
bool bAreSameTria = ( ( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 0)) &&
AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 1)) &&
AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 2))) ||
( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 1)) &&
AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 2)) &&
AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 0))) ||
( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 2)) &&
AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 0)) &&
AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 1)))) &&
( AreSameVectorExact( trTria1.GetN(), trMyTria2.GetN())) ;
if ( bAreSameTria) {
vTria.emplace_back( trTria1) ;
return ( bCounter ? ITTT_COUNTER_OVERLAPS : ITTT_OVERLAPS) ;
}
if ( ITTT_OVERLAPS == IntersCoplanarTriaTria( trTria1, trMyTria2, vTria)) {
return ( bCounter ? ITTT_COUNTER_OVERLAPS : ITTT_OVERLAPS) ;
}
return ITTT_NO ;
}
// limito la linea di intersezione con il primo triangolo
Point3d ptSt1, ptEn1 ;
@@ -112,7 +141,7 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p
int
IntersCoplanarTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, TRIA3DVECTOR& vTria)
{
// Se i tre vertici del secondo triangolo stanno tutti a destra di almeno un lato del primo, non c'è intersezione
// Se i tre vertici del secondo triangolo stanno tutti a destra di almeno un lato del primo, non c' intersezione
for ( int i = 0 ; i < 3 ; ++ i) {
Vector3d vtSide = trTria1.GetP( ( i + 1) % 3) - trTria1.GetP( i) ;
Vector3d vtSN = vtSide ^ trTria1.GetN() ;
@@ -122,7 +151,7 @@ IntersCoplanarTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, TR
( trTria2.GetP( 2) - trTria1.GetP( i)) * vtSN > - EPS_TRIA_H)
return ITTT_NO ;
}
// Se i tre vertici del primo triangolo stanno tutti a destra di almeno un lato del secondo, non c'è intersezione
// Se i tre vertici del primo triangolo stanno tutti a destra di almeno un lato del secondo, non c' intersezione
for ( int i = 0 ; i < 3 ; ++ i) {
Vector3d vtSide = trTria2.GetP( ( i + 1) % 3) - trTria2.GetP( i) ;
Vector3d vtSN = vtSide ^ trTria2.GetN() ;
@@ -205,7 +234,7 @@ int
FindTriaTriaIntersType( const Triangle3d& trTria1, const Triangle3d& trTria2, const Point3d& ptLineSt, const Vector3d& vtLineDir,
double dStU1, double dEnU1, double dStU2, double dEnU2, int nRes1, int nRes2, double& dIntStU, double& dIntEnU)
{
// Controllo su validità input
// Controllo su validit input
if ( ! ( trTria1.IsValid() && trTria2.IsValid() && vtLineDir.IsNormalized()))
return ITTT_NO ;
// Casi
+52 -15
View File
@@ -68,18 +68,36 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
{
// pulisco tutto
Reset() ;
// verifico se la curva è un segmento di retta
bool bIsLine = false ;
const CurveLine* pLine = GetBasicCurveLine( pCrv) ;
if ( pLine != nullptr)
bIsLine = true ;
else {
const CurveComposite* pCompo = GetBasicCurveComposite( pCrv) ;
Point3d ptStart, ptEnd ;
if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd))
bIsLine = true ;
}
// verifico che la curva esista e sia piana
Plane3d plPlane ;
if ( pCrv == nullptr || ! pCrv->IsFlat( plPlane))
if ( pCrv == nullptr || ! pCrv->IsFlat( plPlane, bIsLine, 10 * EPS_SMALL))
return false ;
// se esiste estrusione, verifico sia perpendicolare al piano della curva
// recupero o assegno estrusione
Vector3d vtExtr ;
if ( pCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall()) {
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtExtr))
return false ;
}
else
if ( ! pCrv->GetExtrusion( vtExtr) || vtExtr.IsSmall()) {
vtExtr = plPlane.GetVersN() ;
if ( vtExtr.IsZminus())
vtExtr.Invert() ;
}
// recupero normale al piano della curva
Vector3d vtNorm = plPlane.GetVersN() ;
if ( vtNorm * vtExtr < 0)
vtNorm.Invert() ;
// verifico che estrusione non sia troppo vicina al piano della curva (almeno 30 gradi di angolazione)
double dExtrOnN = vtExtr * vtNorm ;
if ( dExtrOnN < 0.5)
return false ;
// recupero spessore
double dThick ;
pCrv->GetThickness( dThick) ;
@@ -102,6 +120,9 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
// determino se necessario cambiare riferimento ( dal vettore estrusione)
bool bNeedRef = ( ! vtExtr.IsZplus()) ;
// determino se necessario effettuare scalatura
bool bNeedScale = ( abs( dExtrOnN) < cos( 0.1 * DEGTORAD)) ;
// creo una copia della curva
CurveComposite ccCopy ;
if ( ! ccCopy.CopyFrom( pCrv))
@@ -109,13 +130,23 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
ccCopy.SetExtrusion( vtExtr) ;
// se necessario cambio il riferimento
Frame3d frExtr ;
if ( bNeedRef) {
Frame3d frCopy ;
if ( bNeedScale) {
// calcolo il riferimento con vtNorm come asse Z e componente di vtExtr perpendicolare a vtNorm come asse X
if ( ! frCopy.Set( ORIG, vtNorm, vtExtr - dExtrOnN * vtNorm))
return false ;
ccCopy.SetExtrusion( vtNorm) ;
// esprimo la curva in questo riferimento
ccCopy.ToLoc( frCopy) ;
// scalo lungo l'asse X locale
ccCopy.Scale( GLOB_FRM, dExtrOnN, 1, 1) ;
}
else if ( bNeedRef) {
// calcolo il riferimento OCS con VtExtr come asse Z
if ( ! frExtr.Set( ORIG, vtExtr))
if ( ! frCopy.Set( ORIG, vtExtr))
return false ;
// esprimo la curva in questo riferimento
ccCopy.ToLoc( frExtr) ;
ccCopy.ToLoc( frCopy) ;
}
// verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+)
@@ -429,7 +460,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
inOk.Set( dStart, dEnd) ;
IntersCurveCurve ccInt( *pCrv, *pCircS) ;
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, ccPart))
if ( ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccPart))
return false ;
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
@@ -478,7 +509,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
inOk.Set( dStart, dEnd) ;
IntersCurveCurve ccInt( *pCrv, *pCircE) ;
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, ccPart))
if ( ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccPart))
return false ;
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
@@ -601,9 +632,15 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
}
// riporto il risultato nel riferimento originale
if ( bNeedRef) {
if ( bNeedScale) {
for ( auto pCrv : m_CrvLst) {
pCrv->Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
pCrv->ToGlob( frCopy) ;
}
}
else if ( bNeedRef) {
for ( auto pCrv : m_CrvLst)
pCrv->ToGlob( frExtr) ;
pCrv->ToGlob( frCopy) ;
}
// assegno estrusione e spessore come curva originale
+223 -5
View File
@@ -22,6 +22,7 @@
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EgtNumUtils.h"
using namespace std ;
@@ -829,12 +830,11 @@ PolyLine::MyChangeStart( int nPos)
// solo per polilinee chiuse
if ( ! IsClosed())
return false ;
// cancello ultimo punto ( coincide con primo)
// cancello l'ultimo punto ( coincide con il primo)
m_lUPoints.pop_back() ;
// sposto la metà iniziale dei punti alla fine
for ( int i = 0 ; i < nPos ; ++ i)
m_lUPoints.splice( m_lUPoints.end(), m_lUPoints, m_lUPoints.begin()) ;
// aggiungo punto finale come copia dell'iniziale
// sposto la parte iniziale dei punti alla fine
m_lUPoints.splice( m_lUPoints.end(), m_lUPoints, m_lUPoints.begin(), next( m_lUPoints.begin(), nPos)) ;
// aggiungo il punto finale come copia dell'iniziale
m_lUPoints.push_back( m_lUPoints.front()) ;
return true ;
@@ -1296,3 +1296,221 @@ PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
return true ;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
DistPointPolyLine( const Point3d& ptP, const PolyLine& plPoly, double& dDist)
{
// La polilinea deve contenere almeno due punti
if ( plPoly.GetPointNbr() < 2)
return false ;
// Ciclo sui punti della polilinea
dDist = INFINITO ;
Point3d ptStart, ptEnd ;
plPoly.GetFirstPoint( ptStart) ;
while ( plPoly.GetNextPoint( ptEnd)) {
// distanza del punto dal segmento della polilinea
DistPointLine PointLineDistCalc( ptP, ptStart, ptEnd) ;
double dPlDist ;
PointLineDistCalc.GetDist( dPlDist) ;
if ( dPlDist < dDist)
dDist = dPlDist ;
// assegno nuovo inizio
ptStart = ptEnd ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler)
{
// La polilinea deve essere chiusa e piatta, altrimenti non ha senso parlare di interno
Plane3d plPlane ;
double dArea ;
if ( ! plPoly.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL))
return false ;
// Impongo l'orientamento CCW
if ( dArea < 0)
plPlane.Invert() ;
// Il punto deve giacere nel piano della polilinea
if ( ! PointInPlaneEpsilon( ptP, plPlane, 10 * EPS_SMALL))
return false ;
// Riferimento alla lista dei punti
PNTULIST& List = const_cast<PolyLine&>( plPoly).GetUPointList() ;
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
double dMinSqDist = SQ_INFINITO ;
Point3d ptMinDist ;
auto itMinDistEnd = List.end() ;
auto itStart = List.begin() ;
auto itEnd = next( itStart) ;
for ( ; itEnd != List.end() ; ++ itStart, ++ itEnd) {
// Distanza del punto dal segmento corrente
DistPointLine dDistCalc( ptP, itStart->first, itEnd->first) ;
double dSqDist ;
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
dDistCalc.GetMinDistPoint( ptMinDist) ;
itMinDistEnd = itEnd ;
}
}
// Determino tangente di riferimento
Vector3d vtTang ;
// se minima distanza nell'estremo iniziale del segmento
if ( AreSamePointApprox( ptMinDist, prev( itMinDistEnd)->first)) {
// direzione del segmento
Vector3d vtCurrTg = itMinDistEnd->first - prev( itMinDistEnd)->first ;
vtCurrTg.Normalize() ;
// direzione del segmento precedente
Vector3d vtPrevTg ;
if ( prev( itMinDistEnd) != List.begin())
vtPrevTg = prev( itMinDistEnd)->first - prev( itMinDistEnd, 2)->first ;
else
vtPrevTg = prev( itMinDistEnd)->first - prev( List.rbegin())->first ;
vtPrevTg.Normalize() ;
// tangente media
vtTang = vtPrevTg + vtCurrTg ;
vtTang.Normalize() ;
}
// se altrimenti minima distanza nell'estremo finale del segmento
else if ( AreSamePointApprox( ptMinDist, itMinDistEnd->first)) {
// direzione del segmento
Vector3d vtCurrTg = itMinDistEnd->first - prev( itMinDistEnd)->first ;
vtCurrTg.Normalize() ;
// direzione del segmento successivo
Vector3d vtNextTg ;
if ( next( itMinDistEnd) != List.end())
vtNextTg = next( itMinDistEnd)->first - itMinDistEnd->first ;
else
vtNextTg = next( List.begin())->first - itMinDistEnd->first ;
vtNextTg.Normalize() ;
// tangente media
vtTang = vtCurrTg + vtNextTg ;
vtTang.Normalize() ;
}
// altrimenti minima distanza con l'interno
else {
vtTang = itMinDistEnd->first - prev( itMinDistEnd)->first ;
}
// Determino la posizione del punto
Vector3d vtDiff = ptP - ptMinDist ;
Vector3d vtOut = vtTang ^ plPlane.GetVersN() ;
vtOut.Normalize() ;
return ( vtDiff * vtOut < -dToler) ;
}
//----------------------------------------------------------------------------
bool
GetPointParamOnPolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler, double& dPar)
{
// La polilinea deve contenere almeno due punti
if ( plPoly.GetPointNbr() < 2)
return false ;
// Ciclo sui punti della polilinea
int nSeg = -1 ;
double dMinSqDist = SQ_INFINITO ;
double dMinPar = -1 ;
Point3d ptStart, ptEnd ;
plPoly.GetFirstPoint( ptStart) ;
while ( plPoly.GetNextPoint( ptEnd)) {
// aggiorno l'indice
++ nSeg ;
// distanza del punto dal segmento della polilinea
DistPointLine dDistCalc( ptP, ptStart, ptEnd) ;
double dSqDist ;
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
double dSegPar ;
dDistCalc.GetParamAtMinDistPoint( dSegPar) ;
dMinPar = nSeg + dSegPar ;
}
// assegno nuovo inizio
ptStart = ptEnd ;
}
// Il punto è sulla linea se la sua distanza rispetta la tolleranza
return ( dMinSqDist < dToler * dToler) ;
}
//----------------------------------------------------------------------------
bool
ChangePolyLineStart( PolyLine& plPoly, const Point3d& ptNewStart, double dToler)
{
// La polilinea deve essere chiusa
if ( ! plPoly.IsClosed())
return false ;
// Riferimento alla lista dei punti
PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
double dMinSqDist = SQ_INFINITO ;
auto itMinDistEnd = LoopList.end() ;
auto itStart = LoopList.begin() ;
auto itEnd = next( itStart) ;
for ( ; itEnd != LoopList.end() ; ++ itStart, ++ itEnd) {
// Distanza del punto dal segmento corrente
DistPointLine dDistCalc( ptNewStart, itStart->first, itEnd->first) ;
double dSqDist ;
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
itMinDistEnd = itEnd ;
}
}
// Se il punto non sta sulla polilinea, non ha senso cambiare l'inizio
if ( dMinSqDist > dToler * dToler)
return false ;
// Se il punto non coincide con un vertice, lo aggiungo
auto itNewStart = LoopList.end() ;
if ( AreSamePointApprox( ptNewStart, prev( itMinDistEnd)->first))
itNewStart = prev( itMinDistEnd) ;
else if ( AreSamePointApprox( ptNewStart, itMinDistEnd->first))
itNewStart = itMinDistEnd ;
else
itNewStart = LoopList.emplace( itMinDistEnd, ptNewStart, 0) ;
// Cancello l'ultimo punto ( coincide con il primo)
LoopList.pop_back() ;
// Sposto la parte iniziale dei punti alla fine
LoopList.splice( LoopList.end(), LoopList, LoopList.begin(), itNewStart) ;
// Aggiungo il punto finale come copia dell'iniziale
LoopList.push_back( LoopList.front()) ;
return true ;
}
//----------------------------------------------------------------------------
bool
SplitPolyLineAtPoint( const PolyLine& plPoly, const Point3d& ptP, double dToler, PolyLine& plPoly1, PolyLine& plPoly2)
{
// La polilinea deve contenere almeno due punti
if ( plPoly.GetPointNbr() < 2)
return false ;
// Riferimento alla lista dei punti
const PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
double dMinSqDist = SQ_INFINITO ;
auto itMinDistEnd = LoopList.end() ;
auto itStart = LoopList.begin() ;
auto itEnd = next( itStart) ;
for ( ; itEnd != LoopList.end() ; ++ itStart, ++ itEnd) {
// Distanza del punto dal segmento corrente
DistPointLine dDistCalc( ptP, itStart->first, itEnd->first) ;
double dSqDist ;
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
itMinDistEnd = itEnd ;
}
}
// Se il punto non sta sulla polilinea, non ha senso spezzare
if ( dMinSqDist > dToler * dToler)
return false ;
// Copio i punti opportuni nella prima parte
PNTULIST& LoopList1 = plPoly1.GetUPointList() ;
for ( auto it = LoopList.begin() ; it != itMinDistEnd ; ++ it)
LoopList1.emplace_back( it->first, it->second) ;
plPoly1.AddUPoint( 0, ptP) ;
// Copio i punti opportuni nella seconda parte
PNTULIST& LoopList2 = plPoly2.GetUPointList() ;
for ( auto it = itMinDistEnd ; it != LoopList.end() ; ++ it)
LoopList2.emplace_back( it->first, it->second) ;
plPoly2.AddUPoint( 0, ptP, false) ;
return true ;
}
+46 -10
View File
@@ -17,6 +17,7 @@
#include "CurveArc.h"
#include "CurveComposite.h"
#include "SurfFlatRegion.h"
#include "AdjustLoops.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EgkPolyLine.h"
#include "/EgtDev/Include/EgkBiArcs.h"
@@ -278,13 +279,34 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
//----------------------------------------------------------------------------
ISurfFlatRegion*
GetSurfFlatRegionFromPolyLine( const PolyLine& ContourPolyLine)
GetSurfFlatRegionFromTriangle( const Triangle3d& Tria)
{
// Creo la regione.
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSfr))
return nullptr ;
// Creo curva composita.
// Creo curva composita.
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
if ( IsNull( pLoop))
return nullptr ;
if ( ! pLoop->AddPoint( Tria.GetP( 0)) ||
! pLoop->AddLine( Tria.GetP( 1)) ||
! pLoop->AddLine( Tria.GetP( 2)) ||
! pLoop->Close())
return nullptr ;
pSfr->AddExtLoop( Release( pLoop)) ;
return Release( pSfr) ;
}
//----------------------------------------------------------------------------
ISurfFlatRegion*
GetSurfFlatRegionFromPolyLine( const PolyLine& ContourPolyLine)
{
// Creo la regione.
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSfr))
return nullptr ;
// Creo curva composita.
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
if ( IsNull( pLoop))
return nullptr ;
@@ -306,13 +328,13 @@ GetSurfFlatRegionFromPolyLine( const PolyLine& ContourPolyLine)
ISurfFlatRegion*
GetSurfFlatRegionFromPolyLineVector( const POLYLINEVECTOR& vContoursPolyLineVec)
{
// Creo la regione.
// Creo la regione.
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSfr))
return nullptr ;
// Ciclo sulle PolyLine.
// Ciclo sulle PolyLine.
for ( int nL = 0 ; nL < int( vContoursPolyLineVec.size()) ; ++ nL) {
// Creo curva composita.
// Creo curva composita.
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
if ( IsNull( pLoop))
return nullptr ;
@@ -326,11 +348,11 @@ GetSurfFlatRegionFromPolyLineVector( const POLYLINEVECTOR& vContoursPolyLineVec)
ptSt = ptEn ;
bContinue = vContoursPolyLineVec[nL].GetNextPoint( ptEn) ;
}
// Loop esterno
// Loop esterno
if ( nL == 0) {
pSfr->AddExtLoop( Release( pLoop)) ;
}
// Loop interno
// Loop interno
else {
pSfr->AddIntLoop( Release( pLoop)) ;
}
@@ -363,8 +385,20 @@ SurfFlatRegionByContours::AddCurve( ICurve* pCrv)
// verifico sia chiusa
if ( ! pMyCrv->IsClosed())
return false ;
// la inserisco nel vettore delle curve
m_vpCrv.push_back( Release( pMyCrv)) ;
// verifico sia piana e imposto estrusione come normale al piano
double dArea ;
Plane3d plPlane ;
if ( ! pMyCrv->GetArea( plPlane, dArea))
return false ;
pMyCrv->SetExtrusion( plPlane.GetVersN()) ;
pMyCrv->SetThickness( 0) ;
// rimuovo eventuali sovrapposizioni (calcolate nel suo piano)
ICURVEPLIST CrvLst ;
if ( ! AdjustLoops( Release( pMyCrv), CrvLst))
return false ;
// la/le inserisco nel vettore delle curve
for ( auto& pSingCrv : CrvLst)
m_vpCrv.push_back( pSingCrv) ;
return true ;
}
@@ -418,6 +452,7 @@ SurfFlatRegionByContours::GetSurf( void)
if ( IsNull( pSfr))
return nullptr ;
// aggiungo le diverse curve
bool bExtLoop = false ;
bool bFirstCrv ;
do {
bFirstCrv = true ;
@@ -436,6 +471,7 @@ SurfFlatRegionByContours::GetSurf( void)
}
// provo a inserirla
if ( pSfr->AddExtLoop( Release( pCrv))) {
bExtLoop = true ;
bFirstCrv = false ;
delete m_vpCrv[j] ;
m_vpCrv[j] = nullptr ;
@@ -460,7 +496,7 @@ SurfFlatRegionByContours::GetSurf( void)
}
} while ( m_bAllowedMultiChunk && ! bFirstCrv) ;
// se non valida, errore
if ( ! pSfr->IsValid())
if ( ! bExtLoop || ! pSfr->IsValid())
return nullptr ;
// restituisco la superficie
return Release( pSfr) ;
+5 -2
View File
@@ -35,8 +35,10 @@ GEOOBJ_REGISTER( SRF_BEZIER, NGE_S_BEZ, SurfBezier) ;
//----------------------------------------------------------------------------
SurfBezier::SurfBezier(void)
: m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nDegU(), m_nDegV(), m_nSpanU(), m_nSpanV(), m_bRat( false),
m_bTrimmed( false), m_pTrimReg( nullptr), m_nTempProp( 0)
m_bTrimmed( false), m_pTrimReg( nullptr)
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -566,7 +568,8 @@ SurfBezier::CopyFrom( const SurfBezier& sbSrc)
m_vPtCtrl = sbSrc.m_vPtCtrl ;
if ( sbSrc.m_bRat)
m_vWeCtrl = sbSrc.m_vWeCtrl ;
m_nTempProp = sbSrc.m_nTempProp ;
m_nTempProp[0] = sbSrc.m_nTempProp[0] ;
m_nTempProp[1] = sbSrc.m_nTempProp[1] ;
return true ;
}
+6 -5
View File
@@ -53,10 +53,11 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // ISurf
bool IsSimple( void) const override
@@ -165,7 +166,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
//-----------------------------------------------------------------------------
+15 -11
View File
@@ -33,8 +33,10 @@ GEOOBJ_REGISTER( SRF_FLATRGN, NGE_S_FRG, SurfFlatRegion) ;
//----------------------------------------------------------------------------
SurfFlatRegion::SurfFlatRegion( void)
: m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nTempProp()
: m_pSTM( nullptr), m_nStatus( TO_VERIFY)
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -55,7 +57,8 @@ SurfFlatRegion::Clear( void)
delete pLoop ;
m_vpLoop.clear() ;
m_nTempProp = 0 ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -162,7 +165,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
for ( auto i : m_vExtInd) {
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, ccClass) ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_OUT) {
bOk = false ;
break ;
@@ -175,7 +178,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
continue ;
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
if ( ccInt.GetCrossOrOverlapIntersCount() == 0 &&
ccInt.GetCurveClassification( 0, ccClass) &&
ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) &&
! ccClass.empty() && ccClass[0].nClass == CRVC_OUT) {
bOk = true ;
break ;
@@ -295,7 +298,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[m_vExtInd[i]]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, ccClass) ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
@@ -306,7 +309,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
IntersCurveCurve ccInt2( *pMyCrv, *m_vpLoop[k]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 0, ccClass2) ||
! ccInt2.GetCurveClassification( 0, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
@@ -397,7 +400,8 @@ SurfFlatRegion::CopyFrom( const SurfFlatRegion& sfrSrc)
m_vpLoop.push_back( pCrv) ;
}
m_vExtInd = sfrSrc.m_vExtInd ;
m_nTempProp = sfrSrc.m_nTempProp ;
m_nTempProp[0] = sfrSrc.m_nTempProp[0] ;
m_nTempProp[1] = sfrSrc.m_nTempProp[1] ;
m_nStatus = sfrSrc.m_nStatus ;
return ( m_nStatus == OK && ! m_vpLoop.empty()) ;
}
@@ -1146,7 +1150,7 @@ SurfFlatRegion::CloneChunk( int nChunk) const
//----------------------------------------------------------------------------
bool
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
{
// la curva deve già essere nel riferimento intrinseco della regione
// verifico lo stato
@@ -1175,7 +1179,7 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass
IntersCurveCurve ccInt( Crv, *pLoop) ;
// classificazione
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, ccPart))
if ( ! ccInt.GetCurveClassification( 0, dLenMin, ccPart))
return false ;
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
@@ -1268,7 +1272,7 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const
SurfFlatRegion::GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
{
// verifico lo stato
if ( m_nStatus != OK || m_vpLoop.empty())
@@ -1289,7 +1293,7 @@ SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass)
pCrvLoc = pCopyCrv ;
}
// esecuzione classificazione nel riferimento intrinseco
return MyGetCurveClassification( *pCrvLoc, ccClass) ;
return MyGetCurveClassification( *pCrvLoc, dLenMin, ccClass) ;
}
//----------------------------------------------------------------------------
+8 -7
View File
@@ -51,10 +51,11 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // ISurf
bool IsSimple( void) const override
@@ -91,7 +92,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
const SurfTriMesh* GetAuxSurf( void) const override ;
SurfFlatRegion* CloneChunk( int nChunk) const override ;
bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ;
bool GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const override ;
bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ;
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
public : // IGeoObjRW
@@ -130,7 +131,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
ICurve* GetMyLoop( int nChunk, int nLoop) const ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
void ResetAuxSurf( void) const ;
bool ConvertArcsToBezierCurves( void) ;
bool MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const ;
bool MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const ;
static bool MySelectCurves( const PCRV_DEQUE& vpLoop, const SurfFlatRegion& Other,
int nType1, bool bInvert1, int nType2, bool bInvert2, PCRV_DEQUE& vpCurve) ;
static bool MyChainCurves( PCRV_DEQUE& vpCurve, PCRV_DEQUE& vpLoop) ;
@@ -144,7 +145,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
Frame3d m_frF ; // riferimento intrinseco
PCRV_DEQUE m_vpLoop ; // deque delle curve che formano i loop
INTVECTOR m_vExtInd ; // indice dei loop esterni nel precedente vettore
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
} ;
//-----------------------------------------------------------------------------
+2 -2
View File
@@ -289,7 +289,7 @@ SurfFlatRegion::MySelectCurves( const PCRV_DEQUE& vpLoop, const SurfFlatRegion&
for ( auto& pLoop : vpLoop) {
// eseguo classificazione
CRVCVECTOR ccClass ;
if ( ! Other.MyGetCurveClassification( *pLoop, ccClass))
if ( ! Other.MyGetCurveClassification( *pLoop, EPS_SMALL, ccClass))
return false ;
// creo intervalli validi, tenendo classificazioni ricevute
Intervals inOk1( EPS_PARAM), inOk2( EPS_PARAM) ;
@@ -441,7 +441,7 @@ SurfFlatRegion::MyNewSurfFromLoops( PCRV_DEQUE& vpLoop)
CRVCVECTOR ccClass ;
IntersCurveCurve ccInt( *vpLoop[l], *pExtLoop) ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, ccClass) ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// lo inserisco
+3
View File
@@ -27,6 +27,9 @@ SurfFlatRegion::Offset( double dDist, int nType)
int nChunk = GetChunkCount() ;
if ( nChunk == 0)
return false ;
// se offset nullo, non devo fare alcunché
if ( abs( dDist) < 10 * EPS_SMALL)
return true ;
// creo una nuova regione
PtrOwner<SurfFlatRegion> pSfr( new( nothrow) SurfFlatRegion) ;
if ( IsNull( pSfr))
+116 -305
View File
@@ -18,10 +18,10 @@
#include "GeoObjFactory.h"
#include "NgeWriter.h"
#include "NgeReader.h"
#include "SurfFlatRegion.h"
#include "DistPointLine.h"
#include "Triangulate.h"
#include "GeoConst.h"
#include "SurfFlatRegion.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkPointGrid3d.h"
#include "/EgtDev/Include/EGkPolyLine.h"
@@ -41,10 +41,12 @@ GEOOBJ_REGISTER( SRF_TRIMESH, NGE_S_TRM, SurfTriMesh) ;
SurfTriMesh::SurfTriMesh( void)
: m_nStatus( TO_VERIFY), m_dLinTol( STM_STD_LIN_TOL), m_dBoundaryAng( STM_STD_BOUNDARY_ANG),
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bOriented( false), m_bClosed( false), m_bFaceted( false),
m_nTimeStamp( 0), m_nTempProp( 0), m_nMaxTFlag( 0), m_nParts( -1), m_pHGrd3d( nullptr)
m_nTimeStamp( 0), m_nMaxTFlag( 0), m_nParts( -1), m_pHGrd3d( nullptr)
{
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -237,7 +239,7 @@ SurfTriMesh::RemoveTriangle( int nId)
// indice vertice
int nV = m_vTria[nId].nIdVert[i] ;
// se vertice non c'è passo al prossimo
if ( nV < 0 || nV >= int( m_vTria.size()))
if ( nV < 0 || nV >= int( m_vVert.size()))
continue ;
if ( m_vVert[nV].nIdTria == nId) {
int nAdjP = m_vTria[nId].nIdAdjac[i] ;
@@ -989,7 +991,7 @@ SurfTriMesh::MarchOneTria( int& nT, int& nV, int nTimeStamp,
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetSilhouette( const Vector3d& vtDir, POLYLINEVECTOR& vPL) const
SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL) const
{
// Verifico lo stato
if ( m_nStatus != OK)
@@ -1000,6 +1002,19 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, POLYLINEVECTOR& vPL) const
if ( ! vtVers.Normalize())
return false ;
// Controlli su tolleranza
dTol = max( dTol, 100 * EPS_SMALL) ;
// Determino il riferimento di proiezione
Frame3d frOCS ; frOCS.Set( ORIG, vtVers) ;
Frame3d frBox = frOCS ; frBox.Invert() ;
BBox3d b3Box ;
GetBBox( frBox, b3Box) ;
frOCS.Translate( b3Box.GetMin().z * frOCS.VersZ()) ;
#if 0
// *** 1° Sfruttando le adiacenze ***
// Non funziona perchè genera loop con anelli
// Copio la superficie
PtrOwner<SurfTriMesh> pStm( Clone()) ;
if ( IsNull( pStm))
@@ -1011,14 +1026,100 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, POLYLINEVECTOR& vPL) const
if ( pStm->m_vTria[i].nIdVert[0] == SVT_DEL)
continue ;
// verifico la normale
if ( pStm->m_vTria[i].vtN * vtVers < - EPS_ZERO)
if ( pStm->m_vTria[i].vtN * vtVers < EPS_ZERO)
pStm->RemoveTriangle( i) ;
}
// dichiaro facce non calcolate
pStm->m_bFaceted = false ;
// Proietto la superficie
pStm->Scale( frOCS, 1, 1, 0) ;
// Recupero i loop della nuova superficie
return pStm->GetLoops( vPL) ;
POLYLINEVECTOR vMyPL ;
if ( pStm->GetLoops( vMyPL)) {
// calcolo la regione della superficie proiettata
bool bOk = true ;
PtrOwner<ISurfFlatRegion> pSfr ;
for ( int i = 0 ; i < int( vMyPL.size()) && bOk ; ++ i) {
// Regione di un loop
PtrOwner<ISurfFlatRegion> pSfrPart( GetSurfFlatRegionFromPolyLine( vMyPL[i])) ;
if ( ! IsNull( pSfrPart)) {
pSfrPart->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr))
if ( pSfrPart->GetNormVersor() * vtVers > 0)
bOk = pSfr.Set( Release( pSfrPart)) ;
else
bOk = false ;
else {
if ( pSfrPart->GetNormVersor() * vtVers > 0)
bOk = pSfr->Add( *pSfrPart) ;
else {
pSfrPart->Invert() ;
bOk = pSfr->Subtract( *pSfrPart) ;
}
}
}
else
bOk = false ;
}
// Verifico esistenza della regione
if ( bOk && ! IsNull( pSfr)) {
// Effettuo contro-offset
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
// Recupero i contorni della regione
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
PolyLine PL ;
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
vPL.emplace_back( PL) ;
}
}
return true ;
}
}
vPL.clear() ;
#endif
// *** 2° Mediante unione delle regioni dei triangoli proiettati ***
// calcolo la regione dei triangoli proiettati
PtrOwner<ISurfFlatRegion> pSfr ;
Triangle3d Tria ;
int nT = GetFirstTriangle( Tria) ;
while ( nT != SVT_NULL) {
// verifico la normale e il triangolo proiettato
if ( Tria.GetN() * vtVers > EPS_ZERO &&
Tria.Scale( frOCS, 1, 1, 0) && Tria.GetSqMinHeight() > SQ_EPS_SMALL) {
PtrOwner<ISurfFlatRegion> pSfrTria( GetSurfFlatRegionFromTriangle( Tria)) ;
if ( ! IsNull( pSfrTria)) {
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr))
pSfr.Set( Release( pSfrTria)) ;
else
pSfr->Add( *pSfrTria) ;
}
}
// passo al successivo
nT = GetNextTriangle( nT, Tria) ;
}
// Se non esiste la regione
if ( IsNull( pSfr))
return false ;
// Effettuo contro-offset
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
// Recupero i contorni della regione
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
PolyLine PL ;
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
vPL.emplace_back( PL) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
@@ -1068,7 +1169,8 @@ SurfTriMesh::CopyFrom( const SurfTriMesh& stmSrc)
m_vTria = stmSrc.m_vTria ;
m_vFacet = stmSrc.m_vFacet ;
m_nTimeStamp = stmSrc.m_nTimeStamp ;
m_nTempProp = stmSrc.m_nTempProp ;
m_nTempProp[0] = stmSrc.m_nTempProp[0] ;
m_nTempProp[1] = stmSrc.m_nTempProp[1] ;
m_nMaxTFlag = stmSrc.m_nMaxTFlag ;
m_nParts = stmSrc.m_nParts ;
return true ;
@@ -1593,8 +1695,10 @@ SurfTriMesh::TestSealing( void)
// verifico le adiacenze
if ( m_vTria[i].nIdAdjac[0] == SVT_NULL ||
m_vTria[i].nIdAdjac[1] == SVT_NULL ||
m_vTria[i].nIdAdjac[2] == SVT_NULL)
m_vTria[i].nIdAdjac[2] == SVT_NULL) {
bClosed = false ;
break ;
}
}
}
// aggiorno la chiusura della superficie
@@ -1614,7 +1718,7 @@ SurfTriMesh::AdjustTopology( void)
return true ;
}
// dichiaro sfaccettatura da ricalcolare
ResetFaceting() ;
m_bFaceted = false ;
// invalido calcolo connessione
m_nParts = - 1 ;
// verifica indici
@@ -2828,7 +2932,7 @@ SurfTriMesh::DoCompacting( double dTol)
//----------------------------------------------------------------------------
bool
SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther)
SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther, double dTol)
{
// recupero l'altra superficie
const SurfTriMesh* pOther = dynamic_cast<const SurfTriMesh*>( &stmOther) ;
@@ -2870,7 +2974,7 @@ SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther)
ptOP.ToGlob( frOther) ;
// se non c'è già un vertice con la stessa posizione lo inserisco
int nNewId ;
if ( ! VertGrid.Find( ptOP, 2 * EPS_SMALL, nNewId)) {
if ( ! VertGrid.Find( ptOP, dTol, nNewId)) {
if ( ( nNewId = AddVertex( ptOP)) == SVT_NULL)
return false ;
VertGrid.InsertPoint( ptOP, nNewId) ;
@@ -2880,7 +2984,7 @@ SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther)
}
int nVIdSize = int( vVId.size()) ;
// inserisco i triangoli dell'altra trimesh
// aggiungo i triangoli dell'altra trimesh
for ( int nOtId = 0 ; nOtId < pOther->GetTriangleSize() ; ++ nOtId) {
// recupero gli indici dei vertici del triangolo
int vOId[3] ;
@@ -3297,299 +3401,6 @@ SurfTriMesh::Invert( void)
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq)
{
#define UseTria 1
#if UseTria
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// classifico i vertici rispetto al piano
double dTol = max( min( 0.5 * m_dLinTol, 10 * EPS_SMALL), EPS_SMALL) ;
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
double dDist = DistPointPlane( m_vVert[i].ptP, plPlane) ;
if ( abs( dDist) < dTol) {
m_vVert[i].nTemp = 0 ;
if ( abs( dDist) > EPS_SMALL)
m_vVert[i].ptP -= plPlane.GetVersN() * dDist ;
}
else if ( dDist > 0)
m_vVert[i].nTemp = +1 ;
else
m_vVert[i].nTemp = -1 ;
}
// aggiorno timestamp dei triangoli
for ( auto& Tria : m_vTria)
Tria.nTemp = m_nTimeStamp ;
++ m_nTimeStamp ;
// sistemo i triangoli (eventualmente li elimino)
bool bModif = false ;
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
// salto i triangoli cancellati e quelli aggiunti
if ( m_vTria[i].nIdVert[0] == SVT_DEL || m_vTria[i].nTemp == m_nTimeStamp)
continue ;
// se flag abilita e giace sul piano ed equiverso, lo salvo
if ( bSaveOnEq &&
m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 0 &&
m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 0 &&
m_vVert[ m_vTria[i].nIdVert[2]].nTemp == 0 &&
AreSameVectorApprox( m_vTria[i].vtN, plPlane.GetVersN()))
;
// se giace sul piano o dalla parte esterna del piano, lo cancello
else if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp != -1 &&
m_vVert[ m_vTria[i].nIdVert[1]].nTemp != -1 &&
m_vVert[ m_vTria[i].nIdVert[2]].nTemp != -1) {
bModif = true ;
RemoveTriangle( i) ;
}
// se giace dalla parte interna con al massimo un lato sul piano, lo conservo
else if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp != 1 &&
m_vVert[ m_vTria[i].nIdVert[1]].nTemp != 1 &&
m_vVert[ m_vTria[i].nIdVert[2]].nTemp != 1)
;
// altrimenti attraversa il piano, devo modificarlo
else {
bModif = true ;
int nDisc = m_vVert[ m_vTria[i].nIdVert[0]].nTemp +
m_vVert[ m_vTria[i].nIdVert[1]].nTemp +
m_vVert[ m_vTria[i].nIdVert[2]].nTemp ;
// se ha un vertice all'interno e uno sul piano -> 1 nuovo vertice e 1 nuovo triangolo
if ( nDisc == 0) {
// classifico i vertici
int nVertOn, nVertIn, nVertOut ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 0) {
nVertOn = 0 ;
nVertIn = 1 ;
nVertOut = 2 ;
if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 0) {
nVertOn = 1 ;
nVertIn = 2 ;
nVertOut = 0 ;
if ( m_vVert[ m_vTria[i].nIdVert[2]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
else {
nVertOn = 2 ;
nVertIn = 0 ;
nVertOut = 1 ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
// calcolo il punto di intersezione del lato che attraversa il piano
double dDistIn = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP, plPlane) ;
double dDistOut = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP, plPlane) ;
Point3d ptInt = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
dDistIn / ( dDistIn + dDistOut)) ;
// inserisco il nuovo vertice
int nNewV = AddVertex( ptInt) ;
// inserisco il nuovo triangolo
int nIdVert[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
nIdVert[nVertOut] = nNewV ;
int nIdTria = AddTriangle( nIdVert) ;
if ( nIdTria == SVT_NULL)
return false ;
if ( nIdTria != SVT_DEL)
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( i) ;
}
// se ha un vertice all'interno e due all'esterno -> 2 nuovi vertici e 1 nuovo triangolo
else if ( nDisc == 1) {
// classifico i vertici
int nVertIn, nVertOut1, nVertOut2 ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == -1) {
nVertIn = 0 ;
nVertOut1 = 1 ;
nVertOut2 = 2 ;
}
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == -1) {
nVertIn = 1 ;
nVertOut1 = 2 ;
nVertOut2 = 0 ;
}
else {
nVertIn = 2 ;
nVertOut1 = 0 ;
nVertOut2 = 1 ;
}
// calcolo i punti di intersezione dei lati che attraversano il piano
double dDistIn = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP, plPlane) ;
double dDistOut1 = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut1]].ptP, plPlane) ;
double dDistOut2 = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut2]].ptP, plPlane) ;
Point3d ptInt1 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut1]].ptP,
dDistIn / ( dDistIn + dDistOut1)) ;
Point3d ptInt2 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut2]].ptP,
dDistIn / ( dDistIn + dDistOut2)) ;
// inserisco i nuovi vertici
int nNewV1 = AddVertex( ptInt1) ;
int nNewV2 = AddVertex( ptInt2) ;
// inserisco il nuovo triangolo
int nIdVert[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
nIdVert[nVertOut1] = nNewV1 ;
nIdVert[nVertOut2] = nNewV2 ;
int nIdTria = AddTriangle( nIdVert) ;
if ( nIdTria == SVT_NULL)
return false ;
if ( nIdTria != SVT_DEL)
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( i) ;
}
// altrimenti ha due vertici all'interno e uno all'esterno -> 2 nuovi vertici e 2 nuovi triangoli
else {
// classifico i vertici
int nVertIn1, nVertIn2, nVertOut ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 1) {
nVertOut = 0 ;
nVertIn1 = 1 ;
nVertIn2 = 2 ;
}
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 1) {
nVertOut = 1 ;
nVertIn1 = 2 ;
nVertIn2 = 0 ;
}
else {
nVertOut = 2 ;
nVertIn1 = 0 ;
nVertIn2 = 1 ;
}
// calcolo i punti di intersezione dei lati che attraversano il piano
double dDistIn1 = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP, plPlane) ;
double dDistIn2 = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP, plPlane) ;
double dDistOut = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP, plPlane) ;
Point3d ptInt1 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
dDistIn1 / ( dDistIn1 + dDistOut)) ;
Point3d ptInt2 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
dDistIn2 / ( dDistIn2 + dDistOut)) ;
// inserisco i nuovi vertici
int nNewV1 = AddVertex( ptInt1) ;
int nNewV2 = AddVertex( ptInt2) ;
// inserisco i nuovi triangoli
int nIdVert1[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
int nIdVert2[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
double dSqDist1 = SqDist( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP, ptInt2) ;
double dSqDist2 = SqDist( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP, ptInt1) ;
if ( dSqDist1 <= dSqDist2) {
nIdVert1[nVertOut] = nNewV1 ;
nIdVert1[nVertIn2] = nNewV2 ;
nIdVert2[nVertOut] = nNewV2 ;
}
else {
nIdVert1[nVertOut] = nNewV1 ;
nIdVert2[nVertOut] = nNewV2 ;
nIdVert2[nVertIn1] = nNewV1 ;
}
int nIdTria1 = AddTriangle( nIdVert1) ;
int nIdTria2 = AddTriangle( nIdVert2) ;
if ( nIdTria1 == SVT_NULL || nIdTria2 == SVT_NULL)
return false ;
if ( nIdTria1 != SVT_DEL)
m_vTria[nIdTria1].nTemp = m_nTimeStamp ;
if ( nIdTria2 != SVT_DEL)
m_vTria[nIdTria2].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( i) ;
}
}
}
// se effettuate modifiche
if ( bModif) {
// aggiorno tutto
if ( ! AdjustVertices() || ! DoCompacting())
return false ;
}
return true ;
#else
bool bModif = false ;
// Setto i triangoli come né fuori né dentro.
int nTriaNum = GetTriangleSize() ;
for ( int nT = 0 ; nT < nTriaNum ; ++ nT) {
m_vTria[nT].nTempPart = 0 ;
}
INTERSCHAINMAP IntersLineMap ;
// Ciclo su tutte le facce.
int nFacetNum = GetFacetCount() ;
for ( int nF = 0 ; nF < nFacetNum ; ++ nF) {
// Dati della faccia
POLYLINEVECTOR vLoopVec ;
GetFacetLoops( nF, vLoopVec) ;
if ( vLoopVec.empty())
continue ;
PtrOwner<SurfFlatRegion> pReg( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vLoopVec))) ;
if ( IsNull( pReg))
return false ;
LineFacetClassVector IntersLinePart ;
int nIntType = IntersFacetPlane( *pReg, vLoopVec[0], plPlane, IntersLinePart) ;
if ( nIntType == FacetPlaneIntersType::FPI_CUT) {
for ( int nPart = 0 ; nPart < int( IntersLinePart.size()) ; ++ nPart) {
// Salvo intersezione per la faccia.
auto it = IntersLineMap.find( nF) ;
if ( it != IntersLineMap.end()) {
it->second.emplace_back( IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn)) ;
}
else {
IntersLineMap.emplace( nF, IntersInnChain( 1, IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn))) ;
}
}
}
else if ( nIntType == FacetPlaneIntersType::FPI_ON) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = pReg->GetNormVersor() * plPlane.GetVersN() > 0. ? 2 : - 2 ;
}
else if ( nIntType == FacetPlaneIntersType::FPI_INN) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = 1 ;
}
else if ( nIntType == FacetPlaneIntersType::FPI_OUT) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = - 1 ;
}
else
;
}
// Divido le facce.
PieceMap NewFacet ;
SplitFacet( IntersLineMap, NewFacet) ;
INTERSEDGEMAP EdgeInterLineMap, EdgeEdgeLineMap ;
RetriangulateFacetPieces( NewFacet, EdgeInterLineMap, EdgeEdgeLineMap) ;
int nNumTria = GetTriangleSize() ;
for ( int nT = 0 ; nT < nNumTria ; ++ nT)
if ( m_vTria[nT].nTempPart == - 1 || m_vTria[nT].nTempPart == - 2 || ( ! bSaveOnEq && m_vTria[nT].nTempPart == 2))
RemoveTriangle( nT) ;
return AdjustVertices() && DoCompacting() ;
#endif
}
//----------------------------------------------------------------------------
void
SurfTriMesh::ResetHashGrids3d( void) const
+39 -48
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2019
// EgalTech 2014-2021
//----------------------------------------------------------------------------
// File : SurfTriMesh.h Data : 12.02.19 Versione : 2.1b2
// File : SurfTriMesh.h Data : 26.09.21 Versione : 2.3i2
// Contenuto : Dichiarazione della classe Superficie TriMesh.
//
//
@@ -94,34 +94,15 @@ typedef std::unordered_map< int, Chain> CHAINMAP ;
typedef std::unordered_map< int, TRIA3DVECTOR> TRIA3DVECTORMAP ;
//----------------------------------------------------------------------------
// Struttura per la ricerca delle T-Junction
struct TEdgeId {
int nTriaId ;
int nEdge ;
} ;
// Overloading dell'operatore < per TEdgeSet
inline bool operator<( const TEdgeId& TEdgeA, const TEdgeId& TEdgeB) {
if ( TEdgeA.nTriaId != TEdgeB.nTriaId)
return ( TEdgeA.nTriaId < TEdgeB.nTriaId) ;
return ( TEdgeA.nEdge < TEdgeB.nEdge) ;
}
// Loop con T-Junction
typedef std::vector<TEdgeId> TJuncLoop ;
// Vettore di loop con T-Junction
typedef std::vector<TJuncLoop> TJuncLoopVec ;
// Set di TEdgeId
typedef std::set<TEdgeId> TJEdgeSet ;
// Definizione strutture intersezione linea-faccia
//----------------------------------------------------------------------------
// Struttura intersezione linea-faccia
struct LineFacetClass {
Point3d ptSt, ptEn ;
int nTypeA, nTypeB ;
LineFacetClass() {
LineFacetClass( void) {
nTypeA = 0 ;
nTypeB = 0 ;
}
LineFacetClass( const Point3d& ptS, const Point3d ptE, int nTpA, int nTpB) {
LineFacetClass( const Point3d& ptS, const Point3d& ptE, int nTpA, int nTpB) {
ptSt = ptS ;
ptEn = ptE ;
nTypeA = nTpA ;
@@ -131,28 +112,27 @@ struct LineFacetClass {
typedef std::vector<LineFacetClass> LineFacetClassVector ;
//----------------------------------------------------------------------------
enum FacetPlaneIntersType { FPI_ERROR = 0, FPI_CUT = 1, FPI_INN = 2, FPI_OUT = 3, FPI_ON = 4 } ;
enum FacetPlaneIntersType { FPI_ERROR = 0, FPI_CUT = 1, FPI_IN = 2, FPI_OUT = 3, FPI_ON = 4 } ;
//----------------------------------------------------------------------------
// Definizione strutture e contenitori
// Contatti interno-interno
// Strutture e contenitori contatti interno-interno
struct IntersInnSeg {
Point3d ptSt ;
Point3d ptEn ;
Vector3d vtOuter ;
IntersInnSeg(void) {
IntersInnSeg( void) {
;
}
IntersInnSeg(const Point3d& ptS, const Point3d& ptE) {
ptSt = ptS;
ptEn = ptE;
IntersInnSeg( const Point3d& ptS, const Point3d& ptE) {
ptSt = ptS ;
ptEn = ptE ;
}
IntersInnSeg(const Point3d& ptS, const Point3d& ptE, const Vector3d& vtO) {
ptSt = ptS;
ptEn = ptE;
vtOuter = vtO;
IntersInnSeg( const Point3d& ptS, const Point3d& ptE, const Vector3d& vtO) {
ptSt = ptS ;
ptEn = ptE ;
vtOuter = vtO ;
}
};
} ;
typedef std::vector<IntersInnSeg> IntersInnChain ;
typedef std::vector<IntersInnChain> INNCHAINVECTOR ;
typedef std::unordered_map<int, IntersInnChain> INTERSCHAINMAP ;
@@ -164,7 +144,7 @@ struct IntersEdge {
IntersEdge( const Point3d& ptS, const Point3d& ptE, const INTVECTOR& vOFI) {
ptSt = ptS;
ptEn = ptE;
vOthFacetIndex = vOFI;
vOthFacetIndex = vOFI ;
}
} ;
typedef std::vector<IntersEdge> IntersEdgeVec ;
@@ -206,10 +186,11 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // ISurf
bool IsSimple( void) const override
@@ -248,7 +229,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool CreateByScrewing( const PolyLine& PL, const Point3d& ptAx, const Vector3d& vtAx,
double dAngRot, double dStepRot, double dMove) override ;
bool DoCompacting( double dTol = EPS_SMALL) override ;
bool DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther = GLOB_FRM) override ;
bool DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther = GLOB_FRM, double dTol = 2 * EPS_SMALL) override ;
int GetVertexCount( void) const override ;
int GetTriangleCount( void) const override ;
int GetTriangleCount( int nTFlag) const override ;
@@ -277,7 +258,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetTriangleBoundaryEdges( int nId, TriFlags3d& TFlags) const override ;
bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const override ;
bool GetLoops( POLYLINEVECTOR& vPL) const override ;
bool GetSilhouette( const Vector3d& vtDir, POLYLINEVECTOR& vPL) const override ;
bool GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL) const override ;
int GetFacetCount( void) const override ;
int GetFacetSize( void) const override
{ return int( m_vFacet.size()) ; }
@@ -304,6 +285,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetSurfClassification( const ISurfTriMesh& ClassifierSurf,
INTVECTOR& vTriaIn, INTVECTOR& vTriaOut, INTVECTOR& vTriaOnP, INTVECTOR& vTriaOnM, INTVECTOR& vTriaIndef) override ;
bool CutWithOtherSurf( const ISurfTriMesh& CutterSurf, bool bInVsOut, bool bSaveOnEq) override ;
bool Repair( double dMaxEdgeLen = MAX_EDGE_LEN_STD) override ;
bool GetAllTriaOverlapBox( const BBox3d& b3Box, INTVECTOR& vT) const override ;
const BBox3d& GetAllTriaBox( void) const override ;
int GetPartCount( void) const override ;
@@ -369,9 +351,9 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool MarchOneTria( int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ;
bool VerifyPolylinesForTwoCurves( const PolyLine& PL1, const PolyLine& PL2) const ;
bool AddBiTriangle( const int nIdVert[4]) ;
bool ResetFaceting( void) ;
bool VerifyFaceting( void) const ;
bool UpdateFaceting( void) ;
bool UpdateOneFace( int nFacet, int nT) ;
bool UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane, int nT) ;
bool SetFacet( int nInd, int nT) ;
bool VerifyAdjacTriaFacet( int nT, INTVECTOR& vT) const ;
@@ -380,16 +362,20 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
void ResetHashGrids3d( void) const ;
bool VerifyHashGrids3d( void) const ;
bool VerifyConnection( void) const ;
bool CutTriangleByPlane( int nTriaId, const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool CutByFacets( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMATRIX& cvBoundClosedLoopVec, BOOLVECTOR& vbInOut) ;
bool RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf, bool& bModif) ;
bool AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf) ;
bool IntersectTriMeshTriangle( SurfTriMesh& Other) ;
int IntersFacetPlane( const SurfFlatRegion& Region, const PolyLine& ExtLoop, const Plane3d& plCutPlane,
LineFacetClassVector& IntersLinePart) ;
int VerifyLoopPlane( const PolyLine& ExtLoop, const Plane3d& plCutPlane) ;
int IntersFacetPlane( const SurfFlatRegion& Region, const Plane3d& plCutPlane,
LineFacetClassVector& IntersLinePart) ;
bool IntersFacetFacet( const SurfFlatRegion& RegionA, const PolyLine& ExtLoopA,
const SurfFlatRegion& RegionB, const PolyLine& ExtLoopB,
LineFacetClassVector& IntersLinePart) ;
bool ItersectTriMeshFacets( SurfTriMesh& Other) ;
bool IntersectTriMeshFacets( SurfTriMesh& Other) ;
bool RetriangulateFacetPieces( const PieceMap& NewFacet,
const INTERSEDGEMAP& EdgeInterLineMap,
const INTERSEDGEMAP& EdgeEdgeLineMap) ;
@@ -406,6 +392,11 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool RemoveTripleTriangles( void) ;
bool ScanForTripleTriangles( bool& bModified) ;
bool FlipTriangles( int nTA, int nTB) ;
bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true) ;
bool AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) ;
bool DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist) ;
bool ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop) ;
bool SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2) ;
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
@@ -422,7 +413,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
TRIAVECTOR m_vTria ; // vettore dei triangoli
INTVECTOR m_vFacet ; // vettore delle sfaccettature
mutable int m_nTimeStamp ; // orologio locale
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nMaxTFlag ; // massimo valore dei TFlag dei triangoli
mutable int m_nParts ; // numero di parti connesse (-1 se da calcolare)
mutable HashGrids3d* m_pHGrd3d ; // Hash Grid 3d nel suo riferimento
+415 -1393
View File
File diff suppressed because it is too large Load Diff
+874
View File
@@ -0,0 +1,874 @@
//----------------------------------------------------------------------------
// EgalTech 2019-2021
//----------------------------------------------------------------------------
// File : SurfTriMeshCuts.cpp Data : 06.11.21 Versione : 2.3k3
// Contenuto : Implementazione delle funzioni di taglio per SurfFTrimesh.
//
//
//
// Modifiche : 06.11.21 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "CurveComposite.h"
#include "SurfTriMesh.h"
#include "SurfFlatRegion.h"
#include "DistPointLine.h"
#include "Triangulate.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EgkSfrCreate.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
using namespace std ;
//----------------------------------------------------------------------------
const double CUT_SCALE = 1024 ;
//----------------------------------------------------------------------------
bool
SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq)
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// recupero il numero originale di triangoli e di facce
int nTriaOriCnt = GetTriangleCount() ;
int nFacetOriCnt = GetFacetCount() ;
// eseguo il taglio con il metodo delle faccette o dei triangoli (per ora solo coi triangoli)
bool bModif = false ;
if ( true || ! CutByFacets( plPlane, bSaveOnEq, bModif)) {
bModif = false ;
if ( ! CutByTriangles( plPlane, bSaveOnEq, bModif))
return false ;
}
// se effettuate modifiche
if ( bModif) {
// aggiorno tutto
if ( ! AdjustVertices() || ! DoCompacting())
return false ;
}
// se superficie originale a facce, cerco di semplificarle in ogni caso
if ( nFacetOriCnt < 200 || double( nTriaOriCnt) / nFacetOriCnt > 4) {
if ( ! SimplifyFacets())
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Cut")
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// classifico i vertici rispetto al piano
double dTol = max( min( 0.5 * m_dLinTol, 10 * EPS_SMALL), EPS_SMALL) ;
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
double dDist = DistPointPlane( m_vVert[i].ptP, plPlane) ;
if ( abs( dDist) < dTol) {
m_vVert[i].nTemp = 0 ;
if ( abs( dDist) > EPS_SMALL)
m_vVert[i].ptP -= plPlane.GetVersN() * dDist ;
}
else if ( dDist > 0)
m_vVert[i].nTemp = +1 ;
else
m_vVert[i].nTemp = -1 ;
}
// aggiorno timestamp dei triangoli
for ( auto& Tria : m_vTria)
Tria.nTemp = m_nTimeStamp ;
++ m_nTimeStamp ;
// sistemo i triangoli (eventualmente li elimino)
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
// salto i triangoli cancellati e quelli aggiunti
if ( m_vTria[i].nIdVert[0] == SVT_DEL || m_vTria[i].nTemp == m_nTimeStamp)
continue ;
CutTriangleByPlane( i, plPlane, bSaveOnEq, bModif) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::CutTriangleByPlane( int nT, const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
{
// se flag abilita e giace sul piano ed equiverso, lo salvo
if ( bSaveOnEq &&
m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == 0 &&
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == 0 &&
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp == 0 &&
AreSameVectorApprox( m_vTria[nT].vtN, plPlane.GetVersN()))
;
// se giace sul piano o dalla parte esterna del piano, lo cancello
else if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp != -1 &&
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp != -1 &&
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp != -1) {
bModif = true ;
RemoveTriangle( nT) ;
}
// se giace dalla parte interna con al massimo un lato sul piano, lo conservo
else if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp != 1 &&
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp != 1 &&
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp != 1)
;
// altrimenti attraversa il piano, devo modificarlo
else {
bModif = true ;
int nDisc = m_vVert[ m_vTria[nT].nIdVert[0]].nTemp +
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp +
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp ;
// se ha un vertice all'interno e uno sul piano -> 1 nuovo vertice e 1 nuovo triangolo
if ( nDisc == 0) {
// classifico i vertici
int nVertOn, nVertIn, nVertOut ;
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == 0) {
nVertOn = 0 ;
nVertIn = 1 ;
nVertOut = 2 ;
if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
else if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == 0) {
nVertOn = 1 ;
nVertIn = 2 ;
nVertOut = 0 ;
if ( m_vVert[ m_vTria[nT].nIdVert[2]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
else {
nVertOn = 2 ;
nVertIn = 0 ;
nVertOut = 1 ;
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
// calcolo il punto di intersezione del lato che attraversa il piano
double dDistIn = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP, plPlane) ;
double dDistOut = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP, plPlane) ;
Point3d ptInt = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP,
dDistIn / ( dDistIn + dDistOut)) ;
// inserisco il nuovo vertice
int nNewV = AddVertex( ptInt) ;
// inserisco il nuovo triangolo
int nIdVert[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
nIdVert[nVertOut] = nNewV ;
int nIdTria = AddTriangle( nIdVert) ;
if ( nIdTria == SVT_NULL)
return false ;
if ( nIdTria != SVT_DEL)
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( nT) ;
}
// se ha un vertice all'interno e due all'esterno -> 2 nuovi vertici e 1 nuovo triangolo
else if ( nDisc == 1) {
// classifico i vertici
int nVertIn, nVertOut1, nVertOut2 ;
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == -1) {
nVertIn = 0 ;
nVertOut1 = 1 ;
nVertOut2 = 2 ;
}
else if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == -1) {
nVertIn = 1 ;
nVertOut1 = 2 ;
nVertOut2 = 0 ;
}
else {
nVertIn = 2 ;
nVertOut1 = 0 ;
nVertOut2 = 1 ;
}
// calcolo i punti di intersezione dei lati che attraversano il piano
double dDistIn = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP, plPlane) ;
double dDistOut1 = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut1]].ptP, plPlane) ;
double dDistOut2 = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut2]].ptP, plPlane) ;
Point3d ptInt1 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[nT].nIdVert[nVertOut1]].ptP,
dDistIn / ( dDistIn + dDistOut1)) ;
Point3d ptInt2 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[nT].nIdVert[nVertOut2]].ptP,
dDistIn / ( dDistIn + dDistOut2)) ;
// inserisco i nuovi vertici
int nNewV1 = AddVertex( ptInt1) ;
int nNewV2 = AddVertex( ptInt2) ;
// inserisco il nuovo triangolo
int nIdVert[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
nIdVert[nVertOut1] = nNewV1 ;
nIdVert[nVertOut2] = nNewV2 ;
int nIdTria = AddTriangle( nIdVert) ;
if ( nIdTria == SVT_NULL)
return false ;
if ( nIdTria != SVT_DEL)
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( nT) ;
}
// altrimenti ha due vertici all'interno e uno all'esterno -> 2 nuovi vertici e 2 nuovi triangoli
else {
// classifico i vertici
int nVertIn1, nVertIn2, nVertOut ;
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == 1) {
nVertOut = 0 ;
nVertIn1 = 1 ;
nVertIn2 = 2 ;
}
else if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == 1) {
nVertOut = 1 ;
nVertIn1 = 2 ;
nVertIn2 = 0 ;
}
else {
nVertOut = 2 ;
nVertIn1 = 0 ;
nVertIn2 = 1 ;
}
// calcolo i punti di intersezione dei lati che attraversano il piano
double dDistIn1 = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn1]].ptP, plPlane) ;
double dDistIn2 = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn2]].ptP, plPlane) ;
double dDistOut = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP, plPlane) ;
Point3d ptInt1 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn1]].ptP,
m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP,
dDistIn1 / ( dDistIn1 + dDistOut)) ;
Point3d ptInt2 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn2]].ptP,
m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP,
dDistIn2 / ( dDistIn2 + dDistOut)) ;
// inserisco i nuovi vertici
int nNewV1 = AddVertex( ptInt1) ;
int nNewV2 = AddVertex( ptInt2) ;
// inserisco i nuovi triangoli
int nIdVert1[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
int nIdVert2[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
double dSqDist1 = SqDist( m_vVert[m_vTria[nT].nIdVert[nVertIn1]].ptP, ptInt2) ;
double dSqDist2 = SqDist( m_vVert[m_vTria[nT].nIdVert[nVertIn2]].ptP, ptInt1) ;
if ( dSqDist1 <= dSqDist2) {
nIdVert1[nVertOut] = nNewV1 ;
nIdVert1[nVertIn2] = nNewV2 ;
nIdVert2[nVertOut] = nNewV2 ;
}
else {
nIdVert1[nVertOut] = nNewV1 ;
nIdVert2[nVertOut] = nNewV2 ;
nIdVert2[nVertIn1] = nNewV1 ;
}
int nIdTria1 = AddTriangle( nIdVert1) ;
int nIdTria2 = AddTriangle( nIdVert2) ;
if ( nIdTria1 == SVT_NULL || nIdTria2 == SVT_NULL)
return false ;
if ( nIdTria1 != SVT_DEL)
m_vTria[nIdTria1].nTemp = m_nTimeStamp ;
if ( nIdTria2 != SVT_DEL)
m_vTria[nIdTria2].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( nT) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::CutByFacets( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
{
// Setto posizione triangoli non definita
for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT)
m_vTria[nT].nTempPart = 0 ;
INTERSCHAINMAP IntersLineMap ;
// Ciclo su tutte le facce.
for ( int nF = 0 ; nF < GetFacetCount() ; ++ nF) {
// Dati della faccia
POLYLINEVECTOR vLoopVec ;
GetFacetLoops( nF, vLoopVec) ;
if ( vLoopVec.empty())
continue ;
// Verifico la posizione del loop esterno
int nIntType = VerifyLoopPlane( vLoopVec[0], plPlane) ;
// Se interseca il piano di taglio, calcolo la divisione della faccia
LineFacetClassVector IntersLinePart ;
if ( nIntType == FPI_CUT) {
PtrOwner<SurfFlatRegion> pReg( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vLoopVec))) ;
if ( IsNull( pReg) || ! pReg->IsValid())
return false ;
nIntType = IntersFacetPlane( *pReg, plPlane, IntersLinePart) ;
}
// Gestione dei risultati
if ( nIntType == FPI_CUT) {
for ( int nPart = 0 ; nPart < int( IntersLinePart.size()) ; ++ nPart) {
// Salvo intersezione per la faccia.
auto it = IntersLineMap.find( nF) ;
if ( it != IntersLineMap.end()) {
it->second.emplace_back( IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn)) ;
}
else {
IntersLineMap.emplace( nF, IntersInnChain( 1, IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn))) ;
}
}
}
else if ( nIntType == FPI_ON) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
Vector3d vtNf ;
GetFacetNormal( nF, vtNf) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = ( vtNf * plPlane.GetVersN() > 0 ? 2 : -2) ;
}
else if ( nIntType == FPI_IN) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = 1 ;
}
else if ( nIntType == FPI_OUT) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = -1 ;
}
else
return false ;
}
// Divido le facce.
PieceMap NewFacet ;
SplitFacet( IntersLineMap, NewFacet) ;
INTERSEDGEMAP EdgeInterLineMap, EdgeEdgeLineMap ;
RetriangulateFacetPieces( NewFacet, EdgeInterLineMap, EdgeEdgeLineMap) ;
// Elimino i triangoli superflui
for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT) {
if ( m_vTria[nT].nTempPart == 0 ||
m_vTria[nT].nTempPart == -1 ||
m_vTria[nT].nTempPart == -2 ||
( ! bSaveOnEq && m_vTria[nT].nTempPart == 2)) {
RemoveTriangle( nT) ;
bModif = true ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// Risultato : 0=nessuna intersezione, 1=intersezione è un punto, 2=intersezione è un segmento
static int
IntersRectangleTriangle( const Point3d& ptP, const Vector3d& vtL1, const Vector3d& vtL2,
const Triangle3d& trTria, Point3d& ptStSeg, Point3d& ptEnSeg)
{
// Assegno tolleranza lineare
double dTol = EPS_SMALL ;
// Definisco il piano del rettangolo
Plane3d plRectanglePlane ;
if ( ! plRectanglePlane.Set( ptP, vtL1 ^ vtL2))
return -1 ;
// Interseco il piano con il triangolo (recupero estremi in ordine inverso per mantenere l'esterno a destra nei loop)
int nPlTrIntRes = IntersPlaneTria( plRectanglePlane, trTria, ptEnSeg, ptStSeg) ;
if ( nPlTrIntRes != IntPlaneTriaType::IPTT_YES)
return 0 ;
// Limito il segmento col rettangolo
Vector3d vtSegDir = ptEnSeg - ptStSeg ;
double dSegLen = vtSegDir.Len() ;
vtSegDir /= dSegLen ;
// utilizzo piani ortogonali al rettangolo passanti per i suoi estremi
Plane3d plTrim1 ; plTrim1.Set( ptP, -vtL1) ;
Plane3d plTrim2 ; plTrim2.Set( ptP + vtL1, vtL1) ;
if ( vtSegDir * vtL1 < 0.)
swap( plTrim1, plTrim2) ;
Point3d ptInt1 ;
int nLnPl1IntRes = IntersLinePlane( ptStSeg, vtSegDir, dSegLen, plTrim1, ptInt1, false) ;
Point3d ptInt2 ;
int nLnPl2IntRes = IntersLinePlane( ptStSeg, vtSegDir, dSegLen, plTrim2, ptInt2, false) ;
// Se il segmento giace in uno dei due piani
if ( ( nLnPl1IntRes == ILPT_NO && nLnPl2IntRes == ILPT_INPLANE) ||
( nLnPl2IntRes == ILPT_NO && nLnPl1IntRes == ILPT_INPLANE))
return ( AreSamePointEpsilon( ptStSeg, ptEnSeg, dTol) ? 1 : 2) ;
// Se non ci sono intersezioni
if ( nLnPl1IntRes == ILPT_NO && nLnPl2IntRes == ILPT_NO) {
// se è tra i due piani
if (( ptStSeg - plTrim1.GetPoint()) * plTrim1.GetVersN() < 0. &&
( ptStSeg - plTrim2.GetPoint()) * plTrim2.GetVersN() < 0.)
return ( AreSamePointEpsilon( ptStSeg, ptEnSeg, dTol) ? 1 : 2) ;
// altrimenti è esterno
else
return 0 ;
}
// Posizioni parametriche delle intersezioni sul segmento
double dLen1 = ( ptInt1 - ptStSeg) * vtSegDir ;
double dLen2 = ( ptInt2 - ptStSeg) * vtSegDir ;
// Se la prima intersezione supera la fine o la seconda viene prima dell'inizio, non ci sono intersezioni
if ( dLen1 > dSegLen + EPS_ZERO || dLen2 < -EPS_ZERO)
return 0 ;
// Eventuale aggiustamento inizio
if ( dLen1 > 0.) {
ptStSeg = ptInt1 ;
dSegLen -= dLen1 ;
dLen2 -= dLen1 ;
}
// Eventuale aggiustamento fine
if ( dLen2 < dSegLen) {
ptEnSeg = ptInt2 ;
dSegLen = dLen2 ;
}
// Assegno il tipo di intersezione
return ( dSegLen > dTol ? 2 : 1) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
{
// La superficie deve essere valida
if ( m_nStatus != OK)
return false ;
// La curva deve essere valida e chiusa, il vettore estrusione deve essere non nullo
Vector3d vtExtr ;
if ( ! cvCurve.GetExtrusion( vtExtr) || vtExtr.IsSmall() || ! cvCurve.IsClosed())
return false ;
// Recupero il numero originale di triangoli e di facce
int nTriaOriCnt = GetTriangleCount() ;
int nFacetOriCnt = GetFacetCount() ;
// Approssimo la curva con segmenti
CurveComposite cvCompo ;
{
PolyLine PL ;
if ( ! cvCurve.ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) || ! cvCompo.FromPolyLine( PL))
return false ;
}
// Eseguo scalature
Frame3d frScalingRef;
frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ;
Scale( frScalingRef, CUT_SCALE, CUT_SCALE, CUT_SCALE) ;
cvCompo.Scale( frScalingRef, CUT_SCALE, CUT_SCALE, CUT_SCALE) ;
// Appiattisco la polilinea nel piano perpendicolare all'estrusione
Frame3d frCurve ;
Point3d ptStart ; cvCompo.GetStartPoint( ptStart) ;
frCurve.Set( ptStart, vtExtr) ;
cvCompo.ToLoc( frCurve) ;
if ( ! cvCompo.Scale( GLOB_FRM, 1, 1, 0)) {
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
return false ;
}
double dArea ;
cvCompo.GetAreaXY( dArea) ;
BBox3d b3Crv ;
cvCompo.GetLocalBBox( b3Crv) ;
cvCompo.ToGlob( frCurve) ;
// Assegno il senso di rotazione della curva (visto dalla punta del vettore estrusione)
bool bCCW = ( dArea > 0) ;
// Recupero Bounding-box della trimesh
BBox3d b3SurfBox ;
GetLocalBBox( b3SurfBox) ;
// Trovo minima e massima distanza dei vertici del bounding-box della TriMesh dal piano della curva
b3SurfBox.ToLoc( frCurve) ;
Point3d ptMin, ptMax ;
b3SurfBox.GetMinMax( ptMin, ptMax) ;
Vector3d vtMax = ( ptMax.z + 10) * vtExtr ;
Vector3d vtMin = ( ptMin.z - 10) * vtExtr ;
// Ciclo sui triangoli
bool bModif = false ;
int nNumTria = GetTriangleSize() ;
for ( int nT = 0 ; nT < nNumTria ; ++ nT) {
// Recupero il triangolo
Triangle3d trTria ;
if ( ! GetTriangle( nT, trTria))
continue ;
// Box del triangolo nel riferimento locale della curva
BBox3d b3Tria ;
trTria.GetLocalBBox( b3Tria) ;
b3Tria.ToLoc( frCurve) ;
// Se il box del triangolo non interseca quello locale della curva
if ( ! b3Crv.OverlapsXY( b3Tria)) {
// Se la parte da conservare è quella all'interno della curva, elimino il triangolo
if ( bCCW) {
RemoveTriangle( nT) ;
bModif = true ;
}
continue ;
}
// Determino se il centro del triangolo cade all'interno della curva
bool bTriaCenIn = false ;
{
// centro proiettato sul piano della curva
Point3d ptCen = trTria.GetCentroid() ;
ptCen = ptCen - ( ptCen - ptStart) * vtExtr * vtExtr ;
// calcolo distanza
DistPointCurve dstPC( ptCen, cvCompo) ;
double dDist ; dstPC.GetDist( dDist) ;
// se maggiore oltre il limite originale
if ( dDist > CUT_SCALE * EPS_SMALL) {
int nSide ;
if ( dstPC.GetSideAtMinDistPoint( 0, vtExtr, nSide))
bTriaCenIn = ( nSide == MDS_LEFT) ;
}
// altrimenti ricalcolo con centro del triangolo spostato all'interno sulla normale
else {
Point3d ptCen2 = trTria.GetCentroid() - CUT_SCALE * EPS_SMALL * trTria.GetN() ;
DistPointCurve dstP2C( ptCen2, cvCompo) ;
int nSide2 ;
if ( dstP2C.GetSideAtMinDistPoint( 0, vtExtr, nSide2))
bTriaCenIn = ( nSide2 == MDS_LEFT && bSaveOnEq) ;
}
}
// Vettore di catene di punti e flag sulla complanarità del triangolo con uno dei rettangoli
CHAINVECTOR vChain ;
bool bTriaOn = false ;
// Segnalatore di taglio piccolo, punto e vettore per costruire il piano per eseguirlo
int nSmallCutState = 0 ;
Point3d ptSmallCutPnt ;
Vector3d vtSmallCutVec ;
// Ciclo sui segmenti
int nChainCnt = 0 ;
bool bChain = false ;
Point3d ptChSt, ptChEn ;
const ICurve* pCrv = cvCompo.GetFirstCurve() ;
while ( pCrv != nullptr) {
// estremi del segmento
Point3d ptSt ; pCrv->GetStartPoint( ptSt) ;
Point3d ptEn ; pCrv->GetEndPoint( ptEn) ;
// Se il segmento giace sul piano del triangolo, lo segnalo.
if ( abs( ( ptSt - trTria.GetCentroid()) * trTria.GetN()) < CUT_SCALE * EPS_SMALL &&
abs( ( ptEn - trTria.GetCentroid()) * trTria.GetN()) < CUT_SCALE * EPS_SMALL &&
abs( trTria.GetN() * vtExtr) < EPS_SMALL)
bTriaOn = true ;
// Intersezione fra il rettangolo (ottenuto dall'estrusione del segmento corrente) e il triangolo
Point3d ptSegSt, ptSegEn ;
int nInt = IntersRectangleTriangle( ptSt + vtMin, ptEn - ptSt, vtMax - vtMin, trTria, ptSegSt, ptSegEn) ;
if ( nInt == 2) {
// Creo nuova catena se non c'è già o se discontinuità
if ( ! bChain || ( ! AreSamePointApprox( ptSegSt, ptChEn) && ! AreSamePointApprox( ptSegEn, ptChSt))) {
++ nChainCnt ;
vChain.resize( nChainCnt) ;
bChain = false ;
}
// Assegno i dati di intersezione
IntSegment CurInters ;
CurInters.ptSt = ptSegSt ;
CurInters.ptEn = ptSegEn ;
// Inserisco nella catena
if ( ! bChain) {
vChain[nChainCnt - 1].emplace_back( CurInters) ;
ptChSt = CurInters.ptSt ;
ptChEn = CurInters.ptEn ;
}
else if ( AreSamePointApprox(ptSegSt, ptChEn)) {
vChain[nChainCnt - 1].emplace_back(CurInters) ;
ptChEn = CurInters.ptEn ;
}
else {
vChain[nChainCnt - 1].insert(vChain[nChainCnt - 1].begin(), CurInters) ;
ptChSt = CurInters.ptSt ;
}
bChain = true ;
}
else {
// Taglio piccolo
if ( nInt == 1) {
if ( nSmallCutState == 0)
nSmallCutState = 1 ;
else
nSmallCutState = 2 ;
ptSmallCutPnt = ptSt ;
vtSmallCutVec = ptEn - ptSt ;
}
bChain = false ;
}
pCrv = cvCompo.GetNextCurve() ;
}
// Gestisco il taglio piccolo.
if ( nSmallCutState == 1 && int( vChain.size()) == 0) {
Plane3d plPlane ;
plPlane.Set( ptSmallCutPnt, vtSmallCutVec ^ ( vtMax - vtMin)) ;
for ( int nV = 0 ; nV < 3 ; ++ nV) {
double dDist = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nV]].ptP, plPlane) ;
if ( abs( dDist) < EPS_SMALL) {
m_vVert[m_vTria[nT].nIdVert[nV]].nTemp = 0 ;
if ( abs( dDist) > EPS_SMALL)
m_vVert[m_vTria[nT].nIdVert[nV]].ptP -= plPlane.GetVersN() * dDist ;
}
else if ( dDist > 0)
m_vVert[m_vTria[nT].nIdVert[nV]].nTemp = +1 ;
else
m_vVert[m_vTria[nT].nIdVert[nV]].nTemp = -1 ;
}
CutTriangleByPlane( nT, plPlane, bSaveOnEq, bModif) ;
continue ;
}
for ( auto itI = vChain.begin() ; itI != vChain.end() ; ) {
bool bErased = false ;
auto itJ = itI ;
++ itJ ;
for ( ; itJ != vChain.end() && ! bErased ; ) {
if ( int( itI->size()) == 1 && int( itJ->size()) == 1 &&
AreSamePointEpsilon( itI->back().ptSt, itJ->back().ptEn, 2 * EPS_SMALL) &&
AreSamePointEpsilon( itI->back().ptEn, itJ->back().ptSt, 2 * EPS_SMALL)) {
itJ = vChain.erase( itJ) ;
bErased = true ;
}
else
++ itJ ;
}
if ( bErased) {
itI = vChain.erase( itI) ;
bErased = false ;
}
else
++ itI ;
}
nChainCnt = int( vChain.size()) ;
// unisco eventuali catene estreme che sono parte di una stessa catena
if ( nChainCnt > 1) {
if ( AreSamePointApprox( vChain[0].front().ptSt, vChain[nChainCnt - 1].back().ptEn)) {
vChain[0].insert( vChain[0].begin(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ;
vChain.pop_back() ;
-- nChainCnt ;
}
else if ( AreSamePointApprox( vChain[0].back().ptEn, vChain[nChainCnt - 1].front().ptSt)) {
vChain[0].insert(vChain[0].end(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ;
vChain.pop_back() ;
-- nChainCnt ;
}
}
// Elimino la seconda copia di catene doppie
for ( int nI = 0 ; nI < nChainCnt ; ++ nI) {
for ( int nJ = nI + 1 ; nJ < nChainCnt ; ++ nJ) {
if ( vChain[nI].size() == vChain[nJ].size()) {
bool bSame = true ;
for ( int nK = 0 ; nK < int( vChain[nI].size()) ; ++ nK) {
if ( ! AreSamePointApprox( vChain[nI][nK].ptSt, vChain[nJ][nK].ptSt) ||
! AreSamePointApprox( vChain[nI][nK].ptEn, vChain[nJ][nK].ptEn)) {
bSame = false ;
break ;
}
}
if ( bSame) {
vChain.erase( vChain.begin() + nJ) ;
-- nChainCnt ;
-- nJ ;
}
}
}
}
// Fra le catene trovate separo le aperte dalle chiuse
CHAINVECTOR cvClosedChain ;
CHAINVECTOR cvOpenChain ;
for ( int nL = 0 ; nL < int( vChain.size()) ; ++ nL) {
int nCurLoopLast = max( int(vChain[nL].size()) - 1, 0) ;
if ( AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][nCurLoopLast].ptEn) && nCurLoopLast > 0)
cvClosedChain.emplace_back( vChain[nL]) ;
else {
cvOpenChain.emplace_back( vChain[nL]) ;
}
}
for ( auto it = cvClosedChain.begin() ; it != cvClosedChain.end() ; ) {
if ( int( it->size()) < 3)
it = cvClosedChain.erase( it) ;
else
++ it ;
}
// Se più di una catena chiusa oppure catene chiuse e aperte, errore
if ( cvClosedChain.size() > 1 || ( cvClosedChain.size() > 0 && int( cvOpenChain.size()) > 0)) {
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
return false ;
}
// Se c'è una catena chiusa
if ( cvClosedChain.size() == 1) {
// Ne ricavo una PolyLine
PolyLine plInLoop ;
for ( int nLine = 0 ; nLine < int( cvClosedChain[0].size()) ; ++ nLine) {
plInLoop.AddUPoint( 0., cvClosedChain[0][nLine].ptSt) ;
plInLoop.AddUPoint( 0., cvClosedChain[0][nLine].ptEn) ;
}
// I tre vertici sono dalla parte interna della curva (triangolo con buco)
if ( ! bCCW) {
// Rimuovo il triangolo corrente
RemoveTriangle( nT) ;
// Definisco il loop esterno (è il triangolo)
PolyLine plExtLoop ;
plExtLoop.AddUPoint( 0., trTria.GetP( 0)) ;
plExtLoop.AddUPoint( 0., trTria.GetP( 1)) ;
plExtLoop.AddUPoint( 0., trTria.GetP( 2)) ;
plExtLoop.AddUPoint( 0., trTria.GetP( 0)) ;
// Eseguo triangolazione
POLYLINEVECTOR vPL ;
vPL.emplace_back( plExtLoop) ;
vPL.emplace_back( plInLoop) ;
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( vPL, vPt, vTr)) {
// Inserisco i nuovi triangoli
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ;
int nNewId[3] = { AddVertex( vPt[nNewTriaVertId[0]]),
AddVertex( vPt[nNewTriaVertId[1]]),
AddVertex( vPt[nNewTriaVertId[2]]) } ;
AddTriangle( nNewId) ;
bModif = true ;
}
}
}
// Se nessun vertice dalla parte interna della curva (rimane solo l'area della curva)
else {
// Rimuovo il triangolo corrente
RemoveTriangle( nT) ;
// Eseguo triangolazione
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( plInLoop, vPt, vTr)) {
// Inserisco i nuovi triangoli
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ;
int nNewId[3] = { AddVertex(vPt[nNewTriaVertId[0]]),
AddVertex(vPt[nNewTriaVertId[1]]),
AddVertex(vPt[nNewTriaVertId[2]]) } ;
AddTriangle( nNewId) ;
bModif = true ;
}
}
}
}
// Loop aperti, devo chiuderli
else if ( cvOpenChain.size() > 0) {
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
// I loop chiusi trovati precedentemente sono interni a uno dei sotto-loop
// chiusi di cui è formato il perimetro.
PNTVECTOR cvFirstLoop ;
cvFirstLoop.emplace_back( trTria.GetP( 0)) ;
cvFirstLoop.emplace_back( trTria.GetP( 1)) ;
cvFirstLoop.emplace_back( trTria.GetP( 2)) ;
PNTMATRIX cvBoundClosedLoopVec ;
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
BOOLVECTOR vbInOut ;
vbInOut.push_back( true) ;
// Divido il loop di partenza in sotto-loop
while ( cvOpenChain.size() > 0) {
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
for ( int nLoop = 0 ; nLoop < int( cvBoundClosedLoopVec.size()) ; ++ nLoop) {
// Estremi del loop aperto
int nLastOpenLoopPoint = max( int( cvOpenChain[nLastOpenLoopN].size()) - 1, 0) ;
Point3d ptOpenLoopStP = cvOpenChain[nLastOpenLoopN][0].ptSt ;
Point3d ptOpenLoopEnP = cvOpenChain[nLastOpenLoopN][nLastOpenLoopPoint].ptEn ;
PNTVECTOR Loop1, Loop2 ;
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
if ( ! ( bChangedStart && bSplitted))
continue ;
Chain cvCounterChain ;
for ( int nPt = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nPt >= 0 ; -- nPt) {
IntSegment CurSeg ;
CurSeg.ptSt = cvOpenChain[nLastOpenLoopN][nPt].ptEn ;
CurSeg.ptEn = cvOpenChain[nLastOpenLoopN][nPt].ptSt ;
cvCounterChain.emplace_back( CurSeg) ;
}
bool bAdded1 = AddChainToChain( cvCounterChain, Loop1) ;
bool bAdded2 = AddChainToChain( cvOpenChain[nLastOpenLoopN], Loop2) ;
if ( ! ( bAdded1 && bAdded2))
continue ;
// Aggiungo i nuovi loop nel vettore
int nCurSize = int( cvBoundClosedLoopVec.size()) ;
cvBoundClosedLoopVec.resize( nCurSize + 1) ;
vbInOut.resize( nCurSize + 1) ;
for ( int nCL = nCurSize - 1 ; nCL > nLoop ; -- nCL) {
cvBoundClosedLoopVec[nCL + 1] = cvBoundClosedLoopVec[nCL] ;
vbInOut[nCL + 1] = vbInOut[nCL] ;
}
cvBoundClosedLoopVec[nLoop] = Loop1 ;
cvBoundClosedLoopVec[nLoop + 1] = Loop2 ;
vbInOut[nLoop] = false ;
vbInOut[nLoop + 1] = true ;
++ nLoop ;
}
cvOpenChain.resize( nLastOpenLoopN) ;
}
// Rimuovo il triangolo corrente
RemoveTriangle( nT) ;
// Se il triangolo originale aveva il centro interno alla curva oppure devo tenere le parti
// di superficie che hanno una parte giacente sul rettangolo della superficie di taglio,
// aggiungo i nuovi triangoli.
if ( ! bTriaOn || bSaveOnEq) {
// Trasformo i loop compositi in loop polyline
POLYLINEVECTOR vplPolyVec ;
vplPolyVec.resize( cvBoundClosedLoopVec.size()) ;
for ( int nLoop = 0 ; nLoop < int( vplPolyVec.size()) ; ++ nLoop) {
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine) {
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ;
}
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][0]) ;
if ( vbInOut[nLoop]) {
// Eseguo triangolazione
Triangulate CreateTriangulation ;
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( vplPolyVec[nLoop], vPt, vTr)) {
// Inserisco i nuovi triangoli
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2] } ;
int nNewId[3] = { AddVertex(vPt[nNewTriaVertId[0]]),
AddVertex(vPt[nNewTriaVertId[1]]),
AddVertex(vPt[nNewTriaVertId[2]]) } ;
AddTriangle( nNewId) ;
bModif = true ;
}
}
}
}
}
}
// da eliminare
else if ( ! bTriaCenIn) {
RemoveTriangle( nT) ;
bModif = true ;
}
}
// Se avvenuta modifica, aggiorno tutto
if ( bModif) {
// aggiorno tutto
if ( ! AdjustVertices() || ! DoCompacting()) {
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
return false ;
}
}
// Ripristino scala originale
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
// se superficie originale a facce, cerco di semplificarle in ogni caso
if ( nFacetOriCnt < 200 || double( nTriaOriCnt) / nFacetOriCnt > 4) {
if ( ! SimplifyFacets())
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::GeneralizedCut")
}
return true ;
}
+61 -37
View File
@@ -22,15 +22,6 @@
using namespace std ;
//----------------------------------------------------------------------------
bool
SurfTriMesh::ResetFaceting( void)
{
m_bFaceted = false ;
m_vFacet.clear() ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::VerifyFaceting( void) const
@@ -44,14 +35,36 @@ SurfTriMesh::VerifyFaceting( void) const
bool
SurfTriMesh::UpdateFaceting( void)
{
// salvo vecchio vettore facce
INTVECTOR vOldFacet = m_vFacet ;
// reset faceting
m_bFaceted = false ;
m_vFacet.clear() ;
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i)
m_vTria[i].nIdFacet = SVT_NULL ;
// ricostruisco le sfaccettature
bool bOk = true ;
// indice faccia corrente
int nFacet = -1 ;
// ricostruisco le sfaccettature come definite in precedenza (dove possibile)
bool bOk = true ;
for ( int j = 0 ; j < int( vOldFacet.size()) ; ++ j) {
int i = vOldFacet[j] ;
// salto triangoli inesistenti o già assegnati
if ( i >= int( m_vTria.size()) ||
m_vTria[i].nIdVert[0] == SVT_DEL ||
m_vTria[i].nIdFacet != SVT_NULL)
continue ;
// assegno indice di faccia al triangolo
m_vTria[i].nIdFacet = ++ nFacet ;
m_vFacet.push_back( i) ;
// aggiorno faccia
if ( ! UpdateOneFace( nFacet, i))
bOk = false ;
}
// ricostruisco le altre sfaccettature
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// salto triangoli cancellati o già assegnati
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
@@ -60,32 +73,9 @@ SurfTriMesh::UpdateFaceting( void)
// assegno indice di faccia al triangolo
m_vTria[i].nIdFacet = ++ nFacet ;
m_vFacet.push_back( i) ;
// piano del triangolo
Plane3d plPlane ;
if ( ! plPlane.Set( m_vVert[m_vTria[i].nIdVert[0]].ptP, m_vTria[i].vtN)) {
LOG_ERROR( GetEGkLogger(), "SurfTM : UpdateFaceting error in triangle data")
return false ;
}
// set di triangoli da aggiornare
set<int> stTria ;
stTria.insert( i) ;
// finchè set non vuoto
while ( ! stTria.empty()) {
// tolgo un triangolo dal set
const auto iIt = stTria.begin() ;
int nT = *iIt ;
stTria.erase( iIt) ;
// aggiorno i triangoli adiacenti
for ( int j = 0 ; j < 3 ; ++ j) {
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nIdFacet == SVT_NULL) {
if ( ! UpdateTriaFaceting( nT, nFacet, plPlane, nAdjT))
bOk = false ;
if ( m_vTria[nAdjT].nIdFacet == nFacet)
stTria.insert( nAdjT) ;
}
}
}
// aggiorno faccia
if ( ! UpdateOneFace( nFacet, i))
bOk = false ;
}
// se ci sono stati problemi, salvo nel log
@@ -97,6 +87,40 @@ SurfTriMesh::UpdateFaceting( void)
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::UpdateOneFace( int nFacet, int nT)
{
// piano del triangolo
Plane3d plPlane ;
if ( ! plPlane.Set( m_vVert[m_vTria[nT].nIdVert[0]].ptP, m_vTria[nT].vtN)) {
LOG_ERROR( GetEGkLogger(), "SurfTM : UpdateFaceting error in triangle data")
return false ;
}
// set di triangoli da aggiornare
set<int> stTria ;
stTria.insert( nT) ;
// finchè set non vuoto
bool bOk = true ;
while ( ! stTria.empty()) {
// tolgo un triangolo dal set
const auto iIt = stTria.begin() ;
int nT = *iIt ;
stTria.erase( iIt) ;
// aggiorno i triangoli adiacenti
for ( int j = 0 ; j < 3 ; ++ j) {
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nIdFacet == SVT_NULL) {
if ( ! UpdateTriaFaceting( nT, nFacet, plPlane, nAdjT))
bOk = false ;
if ( m_vTria[nAdjT].nIdFacet == nFacet)
stTria.insert( nAdjT) ;
}
}
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane, int nT)
+604
View File
@@ -0,0 +1,604 @@
//----------------------------------------------------------------------------
// EgalTech 2021-2021
//----------------------------------------------------------------------------
// File : SurfTriMeshUtilities.cpp Data : 01.11.21 Versione : 2.3k1
// Contenuto : Implementazione funzioni di utilità di Superfici TriMesh.
//
//
//
// Modifiche : 25.10.21 LM Creazione modulo.
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "Triangulate.h"
#include "SurfTriMesh.h"
#include "DistPointLine.h"
#include <unordered_map>
using namespace std ;
//----------------------------------------------------------------------------
bool
SurfTriMesh::RemoveTJunctions(void)
{
// Vettore di indici dei vertici sui lati del triangolo corrente
unordered_map< int, INTVECTOR> TriaMap ;
// Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
// Se il triangolo non è valido, passo al successivo
Triangle3d trTria ;
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
continue ;
// Vettore degli altri vertici sul contorno del triangolo
INTVECTOR vVertOtl ;
// Box del triangolo
BBox3d b3Tria ;
trTria.GetLocalBBox( b3Tria) ;
INTVECTOR vNearTria ;
GetAllTriaOverlapBox( b3Tria, vNearTria) ;
// Ciclo sui lati del triangolo
for ( int nSeg = 0 ; nSeg < 3 ; ++ nSeg) {
// aggiungo al vettore il vertice iniziale del lato
vVertOtl.emplace_back( m_vTria[nT].nIdVert[nSeg]) ;
// Se in questo lato il triangolo è adiacente a un altro, lo salto.
if ( m_vTria[nT].nIdAdjac[nSeg] != SVT_DEL && m_vTria[nT].nIdAdjac[nSeg] != SVT_NULL)
continue ;
int nPrevSize = int( vVertOtl.size()) ;
// recupero la geometria del lato
Point3d ptSegSt = trTria.GetP( nSeg) ;
Point3d ptSegEn = trTria.GetP( ( nSeg + 1) % 3) ;
Vector3d vtSeg = ptSegEn - ptSegSt ;
double dSegLen = vtSeg.Len() ;
if ( dSegLen < EPS_SMALL)
continue ;
vtSeg /= dSegLen ;
// Ciclo sui triangoli vicini
for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) {
// Salto il triangolo se è quello di riferimento
if ( vNearTria[nI] == nT)
continue ;
// Cerco i vertici che stanno sul lato del triangolo
for ( int nVert = 0 ; nVert < 3 ; ++ nVert) {
Point3d ptVert ;
if ( ! GetVertex( m_vTria[vNearTria[nI]].nIdVert[nVert], ptVert))
continue ;
double dProj = ( ptVert - ptSegSt) * vtSeg ;
double dOrt = ( ( ptVert - ptSegSt) - dProj * vtSeg).SqLen() ;
if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < SQ_EPS_TRIA_H)
vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ;
}
}
// Riordino i vertici sul segmento
auto SortVerteces = [ this, &ptSegSt, &vtSeg]( const int nV1, const int nV2)
{ Point3d ptV1, ptV2 ;
GetVertex( nV1, ptV1) ;
GetVertex( nV2, ptV2) ;
return ( ( ptV1 - ptSegSt) * vtSeg < ( ptV2 - ptSegSt) * vtSeg) ;
} ;
sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVerteces) ;
}
// Se ci sono più di 3 vertici
if ( vVertOtl.size() > 3) {
// Elimino i vertici ripetuti
vVertOtl.erase( unique( vVertOtl.begin(), vVertOtl.end()), vVertOtl.end()) ;
// Se ci sono ancora più di 3 vertici, inserisco nel Map
if ( vVertOtl.size() > 3)
TriaMap.emplace( nT, vVertOtl) ;
}
}
// Ciclo sui triangoli da sistemare
for ( auto itT = TriaMap.begin() ; itT != TriaMap.end() ; ++ itT) {
// Indice del triangolo
int nT = itT->first ;
// Vettore degli altri vertici sul perimetro
const INTVECTOR& vVertOtl = itT->second ;
// Se il triangolo non è valido, passo al successivo
Triangle3d trTria ;
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
continue ;
// Salvo eventuale indice di faccetta
int nFacet = m_vTria[nT].nIdFacet ;
if ( nFacet > int( m_vFacet.size()) || m_vFacet[nFacet] != nT)
nFacet = SVT_NULL ;
// Rimuovo il triangolo
int nTFlag = m_vTria[nT].nTFlag ;
RemoveTriangle( nT) ;
// Aggiungo i nuovi triangoli
int nLastNewTria = SVT_NULL ;
// Se ci sono 4 vertici, inserisco due triangoli
if ( vVertOtl.size() == 4) {
// se 1-2-3 è triangolo (e quindi 0-1-3)
int nNew1Id[3] = { vVertOtl[1], vVertOtl[2], vVertOtl[3]} ;
int nNew1Tria = AddTriangle( nNew1Id, nTFlag) ;
if ( nNew1Tria != SVT_NULL && nNew1Tria != SVT_DEL) {
nLastNewTria = nNew1Tria ;
int nNew2Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[3]} ;
int nNew2Tria = AddTriangle( nNew2Id, nTFlag) ;
if ( nNew2Tria != SVT_NULL && nNew2Tria != SVT_DEL)
nLastNewTria = nNew2Tria ;
}
// altrimenti 0-1-2 e 2-3-0
else {
int nNew3Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[2]} ;
int nNew3Tria = AddTriangle( nNew3Id, nTFlag) ;
if ( nNew3Tria != SVT_NULL && nNew3Tria != SVT_DEL)
nLastNewTria = nNew3Tria ;
int nNew4Id[3] = { vVertOtl[2], vVertOtl[3], vVertOtl[0]} ;
int nNew4Tria = AddTriangle( nNew4Id, nTFlag) ;
if ( nNew4Tria != SVT_NULL && nNew4Tria != SVT_DEL)
nLastNewTria = nNew4Tria ;
}
}
// altrimenti inserisco un ventaglio di triangoli dal centro ai vertici
else {
Point3d ptTriaCen = trTria.GetCentroid() ;
int nCenIndex = AddVertex( ptTriaCen) ;
int nVertNum = int( vVertOtl.size()) ;
for ( int nStV = 0 ; nStV < nVertNum ; ++ nStV) {
int nEnV = ( nStV + 1) % nVertNum ;
int nNewId[3] = { nCenIndex, vVertOtl[nStV], vVertOtl[nEnV]} ;
int nNewTria = AddTriangle( nNewId, nTFlag) ;
if ( nNewTria != SVT_NULL && nNewTria != SVT_DEL)
nLastNewTria = nNewTria ;
}
}
// Eventuale aggiustamento per indice di faccetta
if ( nFacet != SVT_NULL && nLastNewTria != SVT_NULL)
m_vFacet[nFacet] = nLastNewTria ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
IsVertex( PNTULIST& PointList, PNTULIST::const_iterator itCurr)
{
// recupero il punto precedente
PNTULIST::const_iterator itPrev ;
if ( itCurr == PointList.begin())
itPrev = prev( PointList.end(), 2) ;
else
itPrev = prev( itCurr) ;
// recupero il punto successivo
auto itNext = next( itCurr) ;
if ( itNext == PointList.end())
itNext = next( PointList.begin()) ;
// se cambia faccia adiacente tra prima e dopo, va bene
if ( itPrev->second != itCurr->second)
return true ;
// se lati aperti e cambia direzione tra prima e dopo, va bene
if ( itPrev->second == -1) {
DistPointLine PointLineDistCalc( itCurr->first, itPrev->first, itNext->first) ;
double dDist ;
if ( PointLineDistCalc.GetDist( dDist) && dDist > EPS_SMALL)
return true ;
}
// altrimenti non va bene
return false ;
}
//----------------------------------------------------------------------------
static bool
ChooseGoodStartPoint( PNTULIST& PointList)
{
// se il punto iniziale è un vertice, non devo fare alcunché
if ( IsVertex( PointList, PointList.begin()))
return true ;
// altrimenti cerco il vertice più vicino
for ( auto it = next( PointList.begin()) ; it != PointList.end() ; ++it) {
if ( IsVertex( PointList, it)) {
// se ultimo punto non devo fare alcunché
if ( next( it) == PointList.end())
return false ;
// cancello ultimo punto ( coincide con primo)
PointList.pop_back() ;
// sposto la parte iniziale dei punti alla fine
PointList.splice( PointList.end(), PointList, PointList.begin(), it) ;
// aggiungo punto finale come copia dell'iniziale
PointList.push_back( PointList.front()) ;
// ho finito
return true ;
}
}
return false ;
}
//----------------------------------------------------------------------------
static bool
AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
{
// Ciclo sui punti del loop
auto itLast = PointList.begin() ;
for ( auto it = next( itLast) ; it != PointList.end() ; ++ it) {
// Se dal punto corrente inizia un segmento adiacente a un'altra faccia
if ( itLast->second != it->second) {
// Elimino i punti interni
auto itNextToLast = next( itLast) ;
for ( auto itInn = itNextToLast ; itInn != it ; ) {
itInn = PointList.erase( itInn) ;
bModif = true ;
}
// Se la lunghezza del segmento supera il limite imposto
double dSegLen = Dist( it->first, itLast->first) ;
if ( dSegLen > dMaxEdgeLen) {
// determino il numero di step
double dRatio = dSegLen / dMaxEdgeLen ;
int nStepCount = int( dRatio) + 1 ;
// inserisco i punti
auto itAdd = it ;
for ( int nP = 1 ; nP < nStepCount ; ++ nP) {
double dCoeff = double( nP) / nStepCount ;
itAdd = PointList.insert( itAdd, POINTU( Media( itLast->first, it->first, 1 - dCoeff), itLast->second)) ;
bModif = true ;
}
}
// Nuovo punto di riferimento
itLast = it ;
}
// Se sono due segmenti liberi non allineati
else if ( itLast->second == - 1) {
// Calcolo se i punti compresi fra gli estremi sono allineati
bool bAreAligned = true ;
auto itNextToLast = next( itLast) ;
for ( auto itInn = itNextToLast ; itInn != it && bAreAligned ; ++ itInn) {
DistPointLine PointLineDistCalc( itInn->first, itLast->first, it->first) ;
double dDist ;
if ( PointLineDistCalc.GetDist( dDist))
bAreAligned = ( dDist < EPS_SMALL) ;
}
// Se i punti sono allineati
if ( bAreAligned) {
// Verifico se il successivo punto non è più allineato
auto itNextToCurr = next( it) ;
if ( itNextToCurr != PointList.end()) {
for ( auto itInn = itNextToLast ; itInn != itNextToCurr && bAreAligned ; ++ itInn) {
DistPointLine PointLineDistCalc( itInn->first, itLast->first, itNextToCurr->first) ;
double dDist ;
if ( PointLineDistCalc.GetDist( dDist))
bAreAligned = ( dDist < EPS_SMALL) ;
}
}
// Se ho trovato un insieme massimale di punti allineati li processo
if ( ! bAreAligned || itNextToCurr == PointList.end()) {
// Elimino i punti interni
for ( auto itInn = itNextToLast ; itInn != it ; ) {
itInn = PointList.erase( itInn) ;
bModif = true ;
}
// Se la lunghezza del segmento supera il limite imposto
double dSegLen = Dist( it->first, itLast->first) ;
if ( dSegLen > dMaxEdgeLen) {
// determino il numero di step
double dRatio = dSegLen / dMaxEdgeLen ;
int nStepCount = int( dRatio) + 1 ;
// inserisco i punti
auto itAdd = it ;
for ( int nP = 1 ; nP < nStepCount ; ++ nP) {
double dCoeff = double( nP) / nStepCount ;
itAdd = PointList.insert( itAdd, POINTU( Media( itLast->first, it->first, 1 - dCoeff), itLast->second)) ;
bModif = true ;
}
}
// Nuovo punto di riferimento
itLast = it ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
{
// La trimesh deve essere valida
if ( ! IsValid())
return false ;
// Se la lunghezza massima del lato del triangolo sul bordo della faccia è nulla e non forzata, non devo fare alcunché
if ( dMaxEdgeLen < EPS_SMALL && ! bForced)
return true ;
// Recupero il numero delle facce (esegue anche una verifica delle stesse)
int nFacetCnt = GetFacetCount() ;
// Ciclo sulle facce della mesh per trovare quelle da ritriangolare
unordered_map< int, pair< PNTVECTOR, INTVECTOR>> FacetMap ;
for ( int nF = 0 ; nF < nFacetCnt ; ++ nF) {
// Recupero i loop della faccia (il parametro indica la faccia adiacente)
POLYLINEVECTOR LoopVec ;
GetFacetLoops( nF, LoopVec) ;
// Ciclo sui loop della faccia
bool bToRetriangulate = bForced ;
for ( int nL = 0 ; nL < int( LoopVec.size()) ; ++ nL) {
// Lista dei punti del loop
PNTULIST& PointList = LoopVec[nL].GetUPointList() ;
// Mi assicuro che il punto iniziale/finale non sia all'interno di un possibile segmento
if ( ! ChooseGoodStartPoint( PointList))
continue ;
// Sistemo il loop
bool bModif = false ;
if ( ! AdjustLoop( PointList, dMaxEdgeLen, bModif))
return false ;
if ( bModif)
bToRetriangulate = true ;
}
// Se non richiesta ritriangolazione dai bordi, verifico se ci sono vertici di triangoli interni (*** disabilitato ***)
if ( false && ! bToRetriangulate) {
// numero dei triangoli nella faccia
INTVECTOR vFacetTria ;
GetAllTriaInFacet( nF, vFacetTria) ;
int nTriaCnt = int( vFacetTria.size()) ;
// numero dei lati di contorno della faccia
int nSideCnt = 0 ;
for ( int nL = 0 ; nL < int( LoopVec.size()) ; ++ nL)
nSideCnt += LoopVec[nL].GetLineNbr() ;
// numero dei buchi della faccia
int nHoleCnt = int( LoopVec.size()) - 1 ;
// dalla formula di Eulero adattata al caso ( nTriaCnt = nSideCnt + 2 * ( nHoleCnt - 1))
if ( nTriaCnt != nSideCnt + 2 * ( nHoleCnt - 1))
bToRetriangulate = true ;
}
// Se da ritriangolare
if ( bToRetriangulate) {
// Eseguo la ritriangolazione della faccia
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( LoopVec, vPt, vTr)) {
FacetMap.emplace( nF, make_pair( vPt, vTr)) ;
}
// Se non riesco a triangolare anche solo questa faccia, interrompo tutto
else
return false ;
}
}
// Ciclo sulle facce da ritriangolare per eliminare i triangoli (nel contempo salvo flag colore)
INTVECTOR vDelTria ;
unordered_map< int, int> ColorMap ;
for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) {
// Recupero i triangoli della faccia
INTVECTOR vFacetTria ;
GetAllTriaInFacet( itF->first, vFacetTria) ;
vDelTria.insert( vDelTria.end(), vFacetTria.begin(), vFacetTria.end()) ;
// Salvo il colore della faccia da flag di un suo triangolo
ColorMap.emplace( itF->first, m_vTria[m_vFacet[itF->first]].nTFlag) ;
}
// Cancello i triangoli
for ( int nT : vDelTria)
RemoveTriangle( nT) ;
// Applico le nuove triangolazioni delle facce
for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) {
const PNTVECTOR& vPt = itF->second.first ;
const INTVECTOR& vTr = itF->second.second ;
// Inserisco i nuovi triangoli
bool bFirstTria = true ;
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewId[3] = { AddVertex( vPt[vTr[n]]),
AddVertex( vPt[vTr[n + 1]]),
AddVertex( vPt[vTr[n + 2]])} ;
auto itCol = ColorMap.find( itF->first) ;
int nTFlag = ( itCol != ColorMap.end() ? itCol->second : 0) ;
int nNewTriaId = AddTriangle( nNewId, nTFlag) ;
if ( nNewTriaId != SVT_NULL && nNewTriaId != SVT_DEL) {
m_vTria[nNewTriaId].nIdFacet = itF->first ;
if ( bFirstTria) {
m_vFacet[itF->first] = nNewTriaId ;
bFirstTria = false ;
}
}
}
}
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
// Eseguo aggiustamenti
return ( AdjustVertices() && DoCompacting()) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
{
// Se la catena da aggiungere è vuota, non devo fare alcunchè
if ( ChainToAdd.size() == 0)
return true ;
// Se la catena originale è vuota, non è possibile aggiungere nulla
if ( OrigChain.size() == 0)
return false ;
// Se la catena originale è chiusa non posso aggiungere nulla
int nLastOrig = max( int( OrigChain.size()) - 1, 0) ;
if ( AreSamePointApprox( OrigChain[0], OrigChain[nLastOrig]))
return false ;
int nLastToAdd = max( int( ChainToAdd.size()) - 1, 0) ;
if ( AreSamePointApprox( OrigChain[nLastOrig], ChainToAdd[0].ptSt)) {
for ( int nPt = 1 ; nPt <= nLastToAdd ; ++ nPt) {
if ( nPt == nLastToAdd) {
if ( ! AreSamePointApprox(OrigChain[0], ChainToAdd[nPt].ptSt))
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
}
else if ( nPt == 1) {
if ( ! AreSamePointApprox( OrigChain[nLastOrig], ChainToAdd[nPt].ptSt))
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
}
else
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
}
return true ;
}
else
return false ;
}
//----------------------------------------------------------------------------
// Una faccia di una trimesh ha una sola componente connessa, con un loop esterno e possibili loop interni
bool
SurfTriMesh::DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist)
{
// Verifico la presenza del loop esterno
if ( vPolyVec.size() < 1)
return false ;
// Proietto il punto sul piano della faccia, utilizzando il loop esterno
Plane3d plPlane ;
double dArea ;
if ( ! vPolyVec[0].IsClosedAndFlat( plPlane, dArea))
return false ;
double dDistPtPl = DistPointPlane( ptP, plPlane) ;
Point3d ptProjP = ptP + dDistPtPl * plPlane.GetVersN() ;
// Verifico se il punto proiettato è esterno al loop esterno
int nPtOut = -1 ;
if ( ! IsPointInsidePolyLine( ptProjP, vPolyVec[0], EPS_SMALL))
nPtOut = 0 ;
// Verifico se il punto proiettato è interno ai loop interni (quindi esterno alla faccia)
for ( int nLoop = 1 ; nLoop < int( vPolyVec.size()) && nPtOut < 0 ; ++ nLoop) {
Plane3d plPlane ;
double dArea ;
if ( ! vPolyVec[nLoop].IsClosedAndFlat( plPlane, dArea))
return false ;
if ( IsPointInsidePolyLine( ptProjP, vPolyVec[nLoop], EPS_SMALL))
nPtOut = nLoop ;
}
// Se il punto si proietta sulla faccia, la distanza dalla faccia coincide con quella dal piano
if ( nPtOut < 0) {
dPointFacetDist = abs( dDistPtPl) ;
return true ;
}
// Altrimenti calcolo la minima distanza del punto dalla polilinea del contorno a cui è esterno
double dDist ;
if ( DistPointPolyLine( ptP, vPolyVec[nPtOut], dDist)) {
dPointFacetDist = dDist ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop)
{
// Cerco il tratto del loop chiuso più vicino al punto
int nMinSeg = - 1 ;
double dMinSqDinst = DBL_MAX ;
for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) {
// Estremi del segmento corrente del loop
Point3d ptSegSt = Loop[nPt] ;
Point3d ptSegEn = Loop[( nPt + 1) % int( Loop.size())] ;
// Distanza del punto dal segmento del loop
DistPointLine dDistCalc( ptNewStart, ptSegSt, ptSegEn) ;
double dSqDist ;
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDinst) {
dMinSqDinst = dSqDist ;
nMinSeg = nPt ;
}
}
// Se il punto non sta sul loop, errore
if ( dMinSqDinst > SQ_EPS_SMALL)
return false ;
// Verifico che il punto stia su un vertice, in tal caso non devo fare nulla
bool bOnStart = AreSamePointApprox( Loop[nMinSeg], ptNewStart) ;
bool bOnEnd = AreSamePointApprox( Loop[( nMinSeg + 1) % int( Loop.size())], ptNewStart) ;
if ( bOnStart || bOnEnd) {
if ( bOnEnd) {
++ nMinSeg ;
if ( nMinSeg % int( Loop.size()) == 0)
return true ;
}
PNTVECTOR vTempVec ;
for ( int nPt = 0 ; nPt < nMinSeg ; ++ nPt)
vTempVec.emplace_back( Loop[nPt]) ;
int nSize = int( Loop.size()) ;
for ( int nPt = 0 ; nPt < nSize - nMinSeg ; ++ nPt) {
Loop[nPt] = Loop[nPt + nMinSeg] ;
}
for ( int nPt = 0 ; nPt < int( vTempVec.size()) ; ++ nPt) {
Loop[nPt + nSize - nMinSeg] = vTempVec[nPt] ;
}
return true ;
}
// Ridimensiono il loop
Loop.resize( Loop.size() + 1) ;
// Copio i primi punti
PNTVECTOR LoopTemp ;
for ( int nPt = 0 ; nPt <= nMinSeg ; ++ nPt)
LoopTemp.emplace_back( Loop[nPt]) ;
// Aggiungo il nuovo punto all'inizio
Loop[0] = ptNewStart ;
// Sposto gli ultimi in testa
int nLastPointNum = int( Loop.size()) - 1 - nMinSeg ;
for ( int nPt = 1 ; nPt <= nLastPointNum ; ++ nPt) {
Loop[nPt] = Loop[nPt + nMinSeg] ;
}
// Porto i primi in fondo
for ( int nPt = 0 ; nPt < int( LoopTemp.size()) ; ++ nPt) {
Loop[nPt + nLastPointNum] = LoopTemp[nPt] ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2)
{
// Cerco il tratto del loop chiuso più vicino al punto
int nMinSeg = -1 ;
double dMinSqDinst = DBL_MAX ;
for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) {
// Estremi del segmento corrente del loop
Point3d ptSegSt = Loop[nPt] ;
Point3d ptSegEn = Loop[( nPt + 1) % int(Loop.size())] ;
// Distanza del punto dal segmento del loop
DistPointLine dDistCalc( ptStop, ptSegSt, ptSegEn) ;
double dSqDist ;
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDinst) {
dMinSqDinst = dSqDist ;
nMinSeg = nPt ;
}
}
// Se il punto non sta sul loop, errore
if ( dMinSqDinst > SQ_EPS_SMALL)
return false ;
// Verifico che il punto stia su un vertice, in tal caso non devo aggiungerlo
bool bFirst = AreSamePointApprox( Loop[nMinSeg], ptStop) ;
bool bLast = AreSamePointApprox( Loop[( nMinSeg + 1) % int( Loop.size())], ptStop) ;
// Se il punto è sul vertice finale del segmento, aggiungo il vertice alla lista da inglobare al primo loop
if ( bLast)
++ nMinSeg ;
// Inglobo fino a nSeg nel primo loop
for ( int nPt = 0 ; nPt <= nMinSeg && nPt < int( Loop.size()) ; ++ nPt)
Loop1.emplace_back( Loop[nPt]) ;
// Se il punto è interno al segmento, lo inglobo in entrambi i loop
if ( ! ( bFirst || bLast)) {
Loop1.emplace_back( ptStop) ;
Loop2.emplace_back( ptStop) ;
}
else {
if ( nMinSeg != int( Loop.size()) )
Loop2.emplace_back( Loop[nMinSeg]) ;
}
// Inglobo gli ultimi vertici in Loop2
for ( int nPt = nMinSeg + 1 ; nPt < int( Loop.size()) ; ++ nPt)
Loop2.emplace_back( Loop[nPt]) ;
Loop2.emplace_back( Loop[0]) ;
return true ;
}
+184 -21
View File
@@ -27,9 +27,9 @@ using namespace std ;
//----------------------------------------------------------------------------
Tool::Tool( bool bApproxWithLines)
: m_dLinTol( LIN_TOL_STD), m_dAngTolDeg( ANG_TOL_APPROX_DEG), m_nType( UNDEF), m_nCurrentNum( 0), m_dHeight( 0), m_dTipHeight( 0),
m_dRadius( 0), m_dRCorner( 0), m_dTipRadius( 0), m_dRefRadius( 0), m_dCutterHeight( 0), m_dMrtChsWidth( 0), m_dMrtChsThickness( 0),
m_bApproxWithLines( bApproxWithLines)
: m_bApproxWithLines( bApproxWithLines), m_dLinTol( LIN_TOL_STD), m_dAngTolDeg( ANG_TOL_APPROX_DEG),
m_nType( UNDEF), m_nCurrentNum( 0), m_dHeight( 0), m_dTipHeight( 0), m_dRadius( 0), m_dRCorner( 0),
m_dTipRadius( 0), m_dRefRadius( 0), m_dCutterHeight( 0), m_dMrtChsWidth( 0), m_dMrtChsThickness( 0)
{
}
@@ -100,9 +100,13 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR,
Point3d pt3( m_dRadius, - m_dHeight, 0) ;
Point3d pt4( 0, - m_dHeight, 0) ;
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1);
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt4) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// utensile naso di toro
else if ( dCornR < dR - EPS_SMALL) {
@@ -120,10 +124,15 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR,
Point3d pt3( m_dTipRadius, - m_dHeight, 0) ;
Point3d pt4( 0, - m_dHeight, 0) ;
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1);
m_Outline.AddLine( pt2);
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddArcTg( pt3) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddLine( pt4) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
// se da approosimare
if ( m_bApproxWithLines)
return SetGenTool( sToolName, &m_Outline, nToolNum) ;
@@ -143,9 +152,13 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR,
Point3d pt2( m_dRadius, - m_dHeight + m_dTipHeight, 0) ;
Point3d pt4( 0, - m_dHeight, 0) ;
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1);
m_Outline.AddLine( pt2);
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddArcTg( pt4) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// impossibile
else
@@ -201,9 +214,14 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
// profilo
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( Point3d( m_dTipRadius, - m_dHeight, 0)) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
// eventuali sistemazioni per altezza tagliente
if ( ModifyForCutterHeight())
return SetGenTool( sToolName, &m_Outline, nToolNum) ;
@@ -213,7 +231,7 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
// Altrimenti utensile generico
// se Tip a punta ( TipRadius è raggio teorico della parte finale dell'utensile senza raccordo)
// se Tip a punta ( TipRadius raggio teorico della parte finale dell'utensile senza raccordo)
if ( m_dTipRadius < m_dRadius) {
// se punta a sfera
if ( m_dTipRadius < EPS_SMALL) {
@@ -242,10 +260,16 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
// creazione curva composita
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// altrimenti punta a naso di toro
else {
@@ -271,16 +295,22 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
// creazione curva composita
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddCurve( Release( pArc)) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
}
// altrimenti Tip a coda di rondine ( TipRadius è raggio misurabile della parte finale dell'utensile)
// altrimenti Tip a coda di rondine ( TipRadius raggio misurabile della parte finale dell'utensile)
else {
// il raggio della punta non può essere inferiore al raggio corner
// il raggio della punta non pu essere inferiore al raggio corner
if ( m_dTipRadius < m_dRCorner)
return false ;
// Assegno il raggio di riferimento
@@ -305,10 +335,16 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
// creazione curva composita
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// eventuali sistemazioni per altezza tagliente
@@ -321,7 +357,7 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
bool
Tool::ModifyForCutterHeight( void)
{
// Se altezza tagliente non definita o superiore alla altezza utensile non devo fare alcunché
// Se altezza tagliente non definita o superiore alla altezza utensile non devo fare alcunch
if ( m_dCutterHeight < EPS_SMALL || m_dCutterHeight > m_dHeight - EPS_SMALL)
return false ;
// quota di taglio
@@ -340,6 +376,8 @@ Tool::ModifyForCutterHeight( void)
m_Outline.TrimStartAtParam( dU) ;
m_Outline.AddLine( Point3d( 0, dYtrim, 0), false) ;
m_Outline.AddLine( ORIG, false) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
return true ;
}
return false ;
@@ -375,22 +413,36 @@ Tool::SetSawTool( const string& sToolName, double dH, double dR,
// creazione profilo
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddLine( pt4) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// altrimenti con raggio corner
else {
// creazione profilo
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt3 - X_AX * dCornR) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddArcTg( pt3 - Y_AX * dCornR) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddLine( pt4 + Y_AX * dCornR) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddArcTg( pt4 - X_AX * dCornR) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 5, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
}
// altrimenti senza gambo
@@ -405,18 +457,28 @@ Tool::SetSawTool( const string& sToolName, double dH, double dR,
// creazione profilo
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt4) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// altrimenti con raggio corner
else {
// creazione profilo
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt3 - X_AX * dCornR) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddArcTg( pt3 - Y_AX * dCornR) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt4 + Y_AX * dCornR) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddArcTg( pt4 - X_AX * dCornR) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
}
// Assegno il raggio di riferimento
@@ -436,17 +498,30 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
if ( pToolOutline != &m_Outline)
m_Outline.Clear() ;
m_ArcLineApprox.Clear() ;
// Copio il profilo e garantisco sia di soli archi e rette (converto eventuali curve di Bezier)
if ( ! m_Outline.CopyFrom( pToolOutline) ||
! m_Outline.ArcsBezierCurvesToArcsPerpExtr( m_dLinTol, m_dAngTolDeg))
return false ;
// Ciclo sulle curve componenti
// Valuto se tutte le curve tagliano
m_ArcLineApprox.SetTempProp( 1, 1) ;
const ICurve* pCurve = m_Outline.GetFirstCurve() ;
while ( pCurve != nullptr && m_ArcLineApprox.GetTempProp( 1) == 1) {
int nCutTempProp = pCurve->GetTempProp( 1) ;
if ( nCutTempProp == 0) {
m_ArcLineApprox.SetTempProp( 0, 1) ;
}
pCurve = m_Outline.GetNextCurve() ;
}
// Ciclo sulle curve componenti
pCurve = m_Outline.GetFirstCurve() ;
while ( pCurve != nullptr) {
// Se la curva è un arco ed è richiesto la verifica per l'approssimazione,
int nCutTempProp = pCurve->GetTempProp( 1) ;
// Se la curva un arco ed richiesto la verifica per l'approssimazione,
// verifico se approssimarlo
if ( m_bApproxWithLines && pCurve->GetType() == CRV_ARC) {
@@ -454,11 +529,11 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
Point3d ptO = GetBasicCurveArc( pCurve)->GetCenter() ;
double dRadius = GetBasicCurveArc( pCurve)->GetRadius() ;
// Se il centro è fuori dall'asse devo approssimare
// Se il centro fuori dall'asse devo approssimare
bool bCurrApprox = ( abs( ptO.x) > EPS_SMALL) ;
// Se una delle altre curve dista dal centro meno del raggio, devo approssimare
for ( int nI = 0 ; ! bCurrApprox && nI < m_Outline.GetCurveCount() ; ++ nI) {
for ( int nI = 0 ; ! bCurrApprox && nI < m_Outline.GetCurveCount() && m_ArcLineApprox.GetTempProp( 1) == 1 ; ++ nI) {
const ICurve* pOtherCrv = m_Outline.GetCurve( nI) ;
if ( pOtherCrv != pCurve) {
DistPointCurve CalcDist( ptO, *pOtherCrv) ;
@@ -493,6 +568,7 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
m_vArcNormals.emplace_back( vtExtN) ;
int nCvCount = m_ArcLineApprox.GetCurveCount() ;
m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, int( m_vArcNormals.size()) - 1) ;
m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, nCutTempProp, 1) ;
}
}
// altrimenti lo aggiungo semplicemente
@@ -500,16 +576,20 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
m_ArcLineApprox.AddCurve( *pCurve, true) ;
int nCvCount = m_ArcLineApprox.GetCurveCount() ;
m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, - 1) ;
m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, nCutTempProp, 1) ;
}
}
// altrimenti è segmento e lo aggiungo semplicemente
else
// altrimenti segmento e lo aggiungo semplicemente
else {
m_ArcLineApprox.AddCurve( *pCurve, true) ;
int nCvCount = m_ArcLineApprox.GetCurveCount() ;
m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, nCutTempProp, 1) ;
}
pCurve = m_Outline.GetNextCurve() ;
}
// Il profilo dell'utensile deve stare nel 1° e 4° quadrante del piano XY
// Il profilo dell'utensile deve stare nel 1 e 4 quadrante del piano XY
BBox3d Bounding ;
m_Outline.GetLocalBBox( Bounding) ;
if ( Bounding.GetMin().x < - 10 * EPS_SMALL)
@@ -521,7 +601,7 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
// Assegno le dimensioni dell'utensile
m_dHeight = - Bounding.GetMin().y ;
m_dRadius = Bounding.GetMax().x ;
// Assegno il raggio di riferimento se non già assegnato
// Assegno il raggio di riferimento se non gi assegnato
if ( m_dRefRadius < EPS_SMALL)
m_dRefRadius = 0.25 * m_dRadius ;
@@ -579,3 +659,86 @@ Tool::SetChiselTool( const string& sToolName, double dH, double dW, double dTh,
return true ;
}
//----------------------------------------------------------------------------
bool
Tool::SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRC, int nToolNum)
{
// Impostazioni generali
m_sName = sToolName ;
m_nCurrentNum = nToolNum ;
m_nType = UNDEF ;
m_Outline.Clear() ;
m_ArcLineApprox.Clear() ;
// verifica sulle minime dimensioni globali
if ( dH < EPS_SMALL || dR < EPS_SMALL || dRC < - EPS_SMALL)
return false ;
m_dHeight = dH ;
m_dRadius = dR ;
m_dRCorner = dRC ;
m_dTipHeight = 0 ;
m_dTipRadius = 0 ;
m_dRefRadius = 0 ;
m_dCutterHeight = dH ;
bool bToolDefined = true ;
double dSquareCornerRadProj = m_dRCorner * m_dRCorner - 0.25 * m_dHeight * m_dHeight ;
// Utensile sfiancato
if ( dSquareCornerRadProj > 0) {
double dCenX = m_dRadius - m_dRCorner ;
double dCylRad = dCenX + sqrt( dSquareCornerRadProj) ;
// Utensile mal definito
if ( dCylRad < EPS_SMALL)
return false ;
// Profilo
m_Outline.AddPoint( Point3d( 0, 0, 0)) ;
m_Outline.AddLine( Point3d( dCylRad, 0, 0)) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
CurveArc cvArc ;
cvArc.SetC2P( Point3d( dCenX, - 0.5 * m_dHeight, 0), Point3d( dCylRad, 0, 0), Point3d( dCylRad, - m_dHeight, 0)) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( Point3d( 0, - m_dHeight, 0)) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
bToolDefined = SetGenTool( sToolName, &m_Outline, nToolNum) ;
}
// Utensile cilindrico con eventuale raggio corner
else {
// Utensile mal definito
if ( m_dRadius - m_dRCorner < 0)
return false ;
// Utensile sferico
else if ( m_dRadius - m_dRCorner < EPS_SMALL)
;
// Raggio corner nullo: cilindro
else if ( m_dRCorner < EPS_SMALL) {
;
}
else {
// Profilo
m_Outline.AddPoint( Point3d( 0, 0, 0)) ;
m_Outline.AddLine( Point3d( m_dRadius - m_dRCorner, 0, 0)) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
CurveArc cvArc ;
cvArc.SetC2P( Point3d( m_dRadius - m_dRCorner, - m_dRCorner, 0), Point3d( m_dRadius - m_dRCorner, 0, 0), Point3d( m_dRadius, - m_dRCorner, 0)) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( Point3d( m_dRadius, - m_dHeight + m_dRCorner, 0)) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
cvArc.SetC2P( Point3d( m_dRadius - m_dRCorner, - m_dHeight + m_dRCorner, 0), Point3d( m_dRadius, - m_dHeight + m_dRCorner, 0), Point3d( m_dRadius - m_dRCorner, - m_dHeight, 0)) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( Point3d( 0, - m_dHeight, 0)) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
bToolDefined = SetGenTool( sToolName, &m_Outline, nToolNum) ;
}
}
m_nType = ADDITIVE ;
return bToolDefined ;
}
+6 -2
View File
@@ -16,7 +16,7 @@
#include "CurveComposite.h"
//----------------------------------------------------------------------------
class Tool
class Tool
{
public :
Tool( bool bApproxWithLines = false) ;
@@ -33,6 +33,7 @@ class Tool
bool SetGenTool( const std::string& sToolName, const ICurveComposite* pToolOutline, int nToolNum) ;
bool SetMortiserTool( const std::string& sToolName, double dH, double dW, double dTh, double dRc, int nToolNum) ;
bool SetChiselTool( const std::string& sToolName, double dH, double dW, double dTh, int nToolNum) ;
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRC, int nToolNum) ;
bool SetToolNum( int nToolNum)
{ m_nCurrentNum = nToolNum ; return true ; }
int GetType() const
@@ -61,6 +62,8 @@ class Tool
{ return ( m_ArcLineApprox.GetCurveCount() == 0 ? m_Outline : m_ArcLineApprox) ; }
const VCT3DVECTOR& GetArcNormalVec( void) const
{ return m_vArcNormals ; }
bool GetCuttingFlag() const
{ return ( m_nType == GEN ? m_ArcLineApprox.GetTempProp( 1) == 1 : true ) ; }
public :
enum ToolType { UNDEF = 0, // Utensile indefinito
@@ -70,7 +73,8 @@ class Tool
BULLNOSEMILL = 4, // Naso di toro
CONEMILL = 5, // Con parte terminale conica
MORTISER = 6, // Mortasatrice
CHISEL = 7} ; // Scalpello
CHISEL = 7, // Scalpello
ADDITIVE = 8} ; // Additivo
private :
bool ModifyForCutterHeight( void) ;
+199 -61
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
// EgalTech 2014-2021
//----------------------------------------------------------------------------
// File : Triangulate.cpp Data : 23.06.14 Versione : 1.5f6
// File : Triangulate.cpp Data : 18.12.21 Versione : 2.3l
// Contenuto : Implementazione della classe Triangulate.
//
//
@@ -16,6 +16,7 @@
#include "DllMain.h"
#include "Triangulate.h"
#include "ProjPlane.h"
#include "earcut.hpp"
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
@@ -29,6 +30,9 @@ enum EarStatus{ EAS_NULL = -1, EAS_NO = 0, EAS_OK = 1} ;
//----------------------------------------------------------------------------
static bool ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi) ;
//----------------------------------------------------------------------------
static bool FORCE_EARCUT_HPP = false ;
//----------------------------------------------------------------------------
// In : PolyLine
// Out : PNTVECTOR (Point3d Vector) : points of the polyline
@@ -37,6 +41,9 @@ static bool ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi) ;
bool
Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// pulisco i vettori di ritorno
vPt.clear() ;
vTr.clear() ;
// verifico che la polilinea sia chiusa e piana e calcolo il piano medio del poligono
double dArea ;
Plane3d plPlane ;
@@ -46,8 +53,13 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
bool bCCW ;
if ( ! CalcProjPlane( plPlane.GetVersN(), m_nPlane, bCCW))
return false ;
// forzo esecuzione triangolazione con earcut.hpp
if ( FORCE_EARCUT_HPP) {
return MakeByEC_HPP( PL, bCCW, vPt, vTr) ;
}
// riempio il vettore con i vertici del poligono da triangolare
vPt.clear() ;
vPt.reserve( PL.GetPointNbr() - 1) ;
// salto il primo punto (coincide con l'ultimo)
Point3d ptP ;
@@ -59,18 +71,12 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
// se non CCW inverto il vettore dei punti
if ( ! bCCW)
reverse( vPt.begin(), vPt.end()) ;
// creo il vettore degli indici del Poligono
INTVECTOR vPol ;
int n = int( vPt.size()) ;
vPol.reserve( n) ;
for ( int i = 0 ; i < n ; ++ i)
vPol.push_back( i) ;
// eseguo la triangolazione
if ( ! MakeByEC2( vPt, vPol, vTr) &&
! MakeByEC3( vPt, vPol, vTr)) {
if ( ! MakeByEC2( vPt, vTr) &&
! MakeByEC3( vPt, vTr)) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC23(1)")
return false ;
return MakeByEC_HPP( PL, bCCW, vPt, vTr) ;
}
// se era CW, devo invertire il senso dei triangoli
@@ -115,6 +121,12 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
! AreOppositeVectorApprox( plExtPlane.GetVersN(), plPlane.GetVersN()))
return false ;
}
// forzo esecuzione triangolazione con earcut.hpp
if ( FORCE_EARCUT_HPP) {
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
}
// se non CCW inverto tutte le polilinee
if ( ! bCCW) {
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
@@ -122,8 +134,7 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
}
// calcolo ordine decrescente su Xmax o Ymax o Zmax secondo m_nPlane per le curve interne
INTVECTOR vOrd ;
if ( ! SortInternalLoops( vPL, vOrd))
return false ;
bool bOk = SortInternalLoops( vPL, vOrd) ;
// riempio il vettore con i punti dei poligoni da triangolare
// calcolo spazio totale e spazio massimo per un percorso interno
int nTot = vPL[0].GetPointNbr() - 1 ;
@@ -136,22 +147,27 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
// riservo spazio pari al totale dei punti (anche quelli ripetuti di chiusura che servono per i link)
vPt.reserve( nTot) ;
// inserisco i punti del contorno esterno (tranne il primo che coincide con l'ultimo)
if ( ! GetPntVectorFromPolyline( vPL[0], false, vPt))
return false ;
bOk = bOk && GetPntVectorFromPolyline( vPL[0], false, vPt) ;
// ciclo sui percorsi interni ordinati secondo Xmax decrescente
PNTVECTOR vPi ;
vPi.reserve( nMax) ;
for ( int i = 1 ; i < int( vPL.size()) ; ++ i) {
for ( int i = 1 ; bOk && i < int( vPL.size()) ; ++ i) {
// riordino il percorso per avere punto iniziale con Xmax
if ( ! GetPntVectorFromPolyline( vPL[vOrd[i]], true, vPi))
return false ;
if ( ! GetPntVectorFromPolyline( vPL[vOrd[i]], true, vPi)) {
bOk = false ;
break ;
}
// cerco un punto del percorso esterno visibile dal punto iniziale del precedente interno
int nI ;
if ( ! GetOuterPntToJoin( vPt, vPi[0], nI))
return false ;
if ( ! GetOuterPntToJoin( vPt, vPi[0], nI)) {
bOk = false ;
break ;
}
// riordino percorso esterno per avere questo punto all'inizio
if ( ! ChangeStartPntVector( nI, vPt))
return false ;
if ( ! ChangeStartPntVector( nI, vPt)) {
bOk = false ;
break ;
}
// ripeto punto iniziale
vPt.push_back( vPt[0]) ;
// accodo percorso interno
@@ -167,20 +183,14 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
const_cast<PolyLine&>(vPL[i]).Invert( true) ;
}
// creo il vettore degli indici del Poligono
INTVECTOR vPol ;
int n = int( vPt.size()) ;
vPol.reserve( n) ;
// non devo gestire separatamente CCW perchè ho già invertito i punti
for ( int i = 0 ; i < n ; ++ i)
vPol.push_back( i) ;
if ( ! bOk)
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
// eseguo la triangolazione
if ( ! MakeByEC2( vPt, vPol, vTr) &&
! MakeByEC3( vPt, vPol, vTr)) {
if ( ! MakeByEC2( vPt, vTr) &&
! MakeByEC3( vPt, vTr)) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC23(N)")
return false ;
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
}
// se era CW, devo invertire il senso dei triangoli
@@ -190,33 +200,113 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
return true ;
}
//----------------------------------------------------------------------------
// Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0])
// Ear Clipping algorithm from mapbox
//----------------------------------------------------------------------------
bool
Triangulate::PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
const INTVECTOR& vPrev, const INTVECTOR& vNext)
Triangulate::MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// points number
int n = int( vPol.size()) ;
// overall box
BBox3d b3All ;
for ( int j = 0 ; j < n ; ++ j)
b3All.Add( vPt[vPol[j]]) ;
// grid cell dimension
double dCellDim ;
b3All.GetRadius( dCellDim) ;
dCellDim *= 2 / sqrt( n) ;
// grid
if ( ! m_VertGrid.Init( 2 * n, dCellDim))
// pulisco i vettori di ritorno
vPt.clear() ;
vTr.clear() ;
// riempio il vettore con i vertici del poligono da triangolare
vPt.reserve( PL.GetPointNbr() - 1) ;
// salto il primo punto (coincide con l'ultimo)
Point3d ptP ;
if ( ( bCCW && ! PL.GetFirstPoint( ptP)) ||
( ! bCCW && ! PL.GetLastPoint( ptP)))
return false ;
for ( int j = 0 ; j < n ; ++ j) {
// insert only reflex vertex
if ( ! TriangleIsCCW( vPt[vPol[vPrev[j]]], vPt[vPol[j]], vPt[vPol[vNext[j]]])) {
if ( ! m_VertGrid.InsertPoint( vPt[vPol[j]], j))
return false ;
// inserisco i punti
while ( ( bCCW && PL.GetNextPoint( ptP)) ||
( ! bCCW && PL.GetPrevPoint( ptP)))
vPt.push_back( ptP) ;
// Create array
using Point = array<double, 2> ;
vector<vector<Point>> polygon ;
// Fill polygon structure with actual data. Any winding order works.
// The first polyline defines the main polygon.
polygon.resize( 1) ;
polygon[0].reserve( vPt.size()) ;
for ( int i = 0 ; i < int( vPt.size()) ; ++i) {
switch ( m_nPlane) {
default : // PL_XY
polygon[0].push_back( { vPt[i].x, vPt[i].y}) ;
break ;
case PL_YZ :
polygon[0].push_back( { vPt[i].y, vPt[i].z}) ;
break ;
case PL_ZX :
polygon[0].push_back( { vPt[i].z, vPt[i].x}) ;
break ;
}
}
m_vVert.reserve( n / 5) ;
// Run tessellation
// Returns array of indices that refer to the vertices of the input polygon.
// Three subsequent indices form a triangle. Output triangles are counterclockwise.
vTr = mapbox::earcut<int32_t>( polygon) ;
if ( vTr.empty()) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC_HPP(1)")
return false ;
}
if ( ! bCCW)
reverse( vTr.begin(), vTr.end()) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC_HPP( const POLYLINEVECTOR& vPL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// pulisco i vettori di ritorno
vPt.clear() ;
vTr.clear() ;
// Creo il vettore con i punti dei poligoni da triangolare
// calcolo spazio totale e spazio massimo per un percorso interno
int nTot = vPL[0].GetPointNbr() - 1 ;
for ( int i = 1 ; i < int( vPL.size()) ; ++i)
nTot += vPL[i].GetPointNbr() - 1 ;
// riservo spazio pari al totale dei punti (esclusi quelli ripetuti)
vPt.reserve( nTot) ;
// Create array
using Point = array<double, 2> ;
vector<vector<Point>> polygon ;
polygon.resize( vPL.size()) ;
// Eseguo riempimento di vettore e array
for ( int i = 0 ; i < int( vPL.size()) ; ++i) {
polygon[i].reserve( vPL[i].GetPointNbr() - 1) ;
// salto il primo punto (coincide con l'ultimo)
Point3d ptP ;
if ( ( bCCW && ! vPL[i].GetFirstPoint( ptP)) ||
( ! bCCW && ! vPL[i].GetLastPoint( ptP)))
return false ;
// inserisco i punti
while ( ( bCCW && vPL[i].GetNextPoint( ptP)) ||
( ! bCCW && vPL[i].GetPrevPoint( ptP))) {
vPt.push_back( ptP) ;
switch ( m_nPlane) {
default : // PL_XY
polygon[i].push_back( { ptP.x, ptP.y}) ;
break ;
case PL_YZ :
polygon[i].push_back( { ptP.y, ptP.z}) ;
break ;
case PL_ZX :
polygon[i].push_back( { ptP.z, ptP.x}) ;
break ;
}
}
}
// Run tessellation
// Returns array of indices that refer to the vertices of the input polygon.
// Three subsequent indices form a triangle. Output triangles are counterclockwise.
vTr = mapbox::earcut<int32_t>( polygon) ;
if ( vTr.empty()) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC_HPP(N)")
return false ;
}
if ( ! bCCW)
reverse( vTr.begin(), vTr.end()) ;
return true ;
}
@@ -225,16 +315,22 @@ Triangulate::PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
// Ear Clipping algorithm
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
Triangulate::MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr)
{
// Clear triangle vector
vTr.clear() ;
// At least 3 points
int n = int( vPol.size()) ;
int n = int( vPt.size()) ;
if ( n < 3)
return false ;
// Creo il vettore degli indici del Poligono
INTVECTOR vPol ;
vPol.reserve( n) ;
for ( int i = 0 ; i < n ; ++ i)
vPol.push_back( i) ;
// Preallocate triangle vector ( #triangles = n - 2)
vTr.reserve( 3 * ( n - 2)) ;
@@ -297,16 +393,22 @@ Triangulate::MakeByEC( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& v
// Ear Clipping algorithm enhanced, choose smaller diagonal
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr)
{
// Clear triangle vector
vTr.clear() ;
// At least 3 points
int n = int( vPol.size()) ;
int n = int( vPt.size()) ;
if ( n < 3)
return false ;
// Creo il vettore degli indici del Poligono
INTVECTOR vPol ;
vPol.reserve( n) ;
for ( int i = 0 ; i < n ; ++ i)
vPol.push_back( i) ;
// Preallocate triangle vector ( #triangles = n - 2)
vTr.reserve( 3 * ( n - 2)) ;
@@ -418,16 +520,22 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
// AR = ( Lmax * Lmax) / ( 2 * Area) = SqLenMax / L1 * L2
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr)
{
// Clear triangle vector
vTr.clear() ;
// At least 3 points
int n = int( vPol.size()) ;
int n = int( vPt.size()) ;
if ( n < 3)
return false ;
// Creo il vettore degli indici del Poligono
INTVECTOR vPol ;
vPol.reserve( n) ;
for ( int i = 0 ; i < n ; ++ i)
vPol.push_back( i) ;
// Preallocate triangle vector ( #triangles = n - 2)
vTr.reserve( 3 * ( n - 2)) ;
@@ -525,6 +633,36 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
return true ;
}
//----------------------------------------------------------------------------
bool
Triangulate::PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
const INTVECTOR& vPrev, const INTVECTOR& vNext)
{
// points number
int n = int( vPol.size()) ;
// overall box
BBox3d b3All ;
for ( int j = 0 ; j < n ; ++ j)
b3All.Add( vPt[vPol[j]]) ;
// grid cell dimension
double dCellDim ;
b3All.GetRadius( dCellDim) ;
dCellDim *= 2 / sqrt( n) ;
// grid
if ( ! m_VertGrid.Init( 2 * n, dCellDim))
return false ;
for ( int j = 0 ; j < n ; ++ j) {
// insert only reflex vertex
if ( ! TriangleIsCCW( vPt[vPol[vPrev[j]]], vPt[vPol[j]], vPt[vPol[vNext[j]]])) {
if ( ! m_VertGrid.InsertPoint( vPt[vPol[j]], j))
return false ;
}
}
m_vVert.reserve( n / 5) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
@@ -800,7 +938,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
// indice punto successivo
int j = ( i + 1 < nNumPt) ? i + 1 : 0 ;
// mi metto nel piano principale
switch (m_nPlane) {
switch ( m_nPlane) {
default : // PL_XY
// se i punti coincidono
if ( abs( vPt[i].x - ptP.x) < EPS_SMALL && abs( vPt[i].y - ptP.y) < EPS_SMALL) {
+5 -3
View File
@@ -24,11 +24,13 @@ class Triangulate
bool Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
private :
bool MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeByEC_HPP( const POLYLINEVECTOR& vPL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
const INTVECTOR& vPrev, const INTVECTOR& vNext) ;
bool MakeByEC( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr) ;
bool MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr) ;
bool MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr) ;
bool TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
const INTVECTOR& vPrev, INTVECTOR& vNext, int i) ;
double CalcTriangleAspectRatio( const Point3d& ptPa, const Point3d& ptPb, const Point3d& ptPc) ;
+96 -18
View File
@@ -34,8 +34,8 @@ GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
//----------------------------------------------------------------------------
VolZmap::VolZmap(void)
: m_nStatus( TO_VERIFY), m_nMapNum( 0), m_nNumBlock( 0), m_nConnectedCompoCount( 0), m_dStep( 10.0),
m_nVoxNumPerBlock( N_VOXBLOCK), m_nDexVoxRatio( 1), m_nShape( GENERIC), m_nTempProp( 0), m_Tool( true)
: m_nStatus( TO_VERIFY), m_dStep( 10.0), m_nMapNum( 0), m_nShape( GENERIC), m_nVoxNumPerBlock( N_VOXBLOCK),
m_nDexVoxRatio( 1), m_nNumBlock( 0), m_nConnectedCompoCount( 0), m_nCurrTool( - 1)
{
for ( int i = 0 ; i < N_MAPS ; ++ i) {
m_nNx[i] = 0 ;
@@ -45,7 +45,8 @@ VolZmap::VolZmap(void)
m_dMaxZ[i] = 0 ;
m_nFracLin[i] = 0 ;
}
m_Tool.SetTolerances( LIN_TOL_STD, ANG_TOL_APPROX_DEG) ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -72,8 +73,9 @@ VolZmap::Clear( void)
m_Values[i].clear() ;
}
m_dStep = EPS_SMALL ;
m_nTempProp = 0 ;
m_Tool.Clear() ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
ResetAllTools() ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -138,7 +140,8 @@ VolZmap::CopyFrom( const VolZmap& vzmSrc)
m_dStep = vzmSrc.m_dStep ;
m_nStatus = vzmSrc.m_nStatus ;
m_nTempProp = vzmSrc.m_nTempProp ;
m_nTempProp[0] = vzmSrc.m_nTempProp[0] ;
m_nTempProp[1] = vzmSrc.m_nTempProp[1] ;
// dimensiono membri legati ai blocchi
m_BlockToUpdate = vzmSrc.m_BlockToUpdate ;
@@ -758,7 +761,6 @@ VolZmap::CheckMapConnection( void)
int tStopIntZ = int( m_Values[0][tDexZ].size()) ;
// Ciclo sugli intervalli del dexel
for ( int tIntZ = 0 ; tIntZ < tStopIntZ ; ++ tIntZ) {
if ( m_Values[0][tDexZ][tIntZ].nCompo == 0) {
++ m_nConnectedCompoCount ;
m_Values[0][tDexZ][tIntZ].nCompo = m_nConnectedCompoCount ;
@@ -1677,8 +1679,10 @@ VolZmap::Cut( const Plane3d& plPlane)
Plane3d plMyPlane = plPlane ;
plMyPlane.ToLoc( m_MapFrame) ;
// Imposto numero fittizio di utensile per avere il colore di sezione opportuno
int nToolNumOld = m_Tool.GetCurrentToolNum() ;
m_Tool.SetToolNum( 1) ;
if ( m_nCurrTool < 0)
return false ;
int nToolNumOld = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
m_vTool[m_nCurrTool].SetToolNum( 1) ;
// Interseco lo Zmap col piano, ciclando sulle griglie
bool bModified = false ;
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
@@ -1732,7 +1736,7 @@ VolZmap::Cut( const Plane3d& plPlane)
}
// Ripristino numero utensile
m_Tool.SetToolNum( nToolNumOld) ;
m_vTool[m_nCurrTool].SetToolNum( nToolNumOld) ;
if ( bModified == true) {
// Imposto forma generica
@@ -1967,14 +1971,18 @@ VolZmap::CalcBlockNum( void)
bool
VolZmap::SetToolTolerances( double dLinTol, double dAngTolDeg)
{
return m_Tool.SetTolerances( dLinTol, dAngTolDeg) ;
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetTolerances( dLinTol, dAngTolDeg) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetStdTool( const string& sToolName, double dH, double dR, double dCornR, double dCutterH, int nFlag)
{
return m_Tool.SetStdTool( sToolName, dH, dR, dCornR, dCutterH, nFlag) ;
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetStdTool( sToolName, dH, dR, dCornR, dCutterH, nFlag) ;
}
//----------------------------------------------------------------------------
@@ -1982,7 +1990,9 @@ bool
VolZmap::SetAdvTool( const string& sToolName,
double dH, double dR, double dTipH, double dTipR, double dCornR, double dCutterH, int nFlag)
{
return m_Tool.SetAdvTool( sToolName, dH, dR, dTipH, dTipR, dCornR, dCutterH, nFlag) ;
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetAdvTool( sToolName, dH, dR, dTipH, dTipR, dCornR, dCutterH, nFlag) ;
}
//----------------------------------------------------------------------------
@@ -1990,33 +2000,101 @@ bool
VolZmap::SetSawTool( const string& sToolName,
double dH, double dR, double dThick, double dStemR, double dCornR, int nFlag)
{
return m_Tool.SetSawTool( sToolName, dH, dR, dThick, dStemR, dCornR, nFlag) ;
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetSawTool( sToolName, dH, dR, dThick, dStemR, dCornR, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline, int nFlag)
{
return m_Tool.SetGenTool( sToolName, pToolOutline, nFlag) ;
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetGenTool( sToolName, pToolOutline, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetMortiserTool( const string& sToolName, double dH, double dW, double dTh, double dRc, int nFlag)
{
return m_Tool.SetMortiserTool( sToolName, dH, dW, dTh, dRc, nFlag) ;
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetMortiserTool( sToolName, dH, dW, dTh, dRc, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetChiselTool( const string& sToolName, double dH, double dW, double dTh, int nFlag)
{
return m_Tool.SetChiselTool( sToolName, dH, dW, dTh, nFlag) ;
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetChiselTool( sToolName, dH, dW, dTh, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetAdditiveTool(const std::string& sToolName, double dH, double dR, double dRC, int nFlag)
{
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetAdditiveTool( sToolName, dH, dR, dRC, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetCurrTool( int nCurrTool)
{
if ( nCurrTool < 0 || nCurrTool >= int( m_vTool.size()))
return false ;
m_nCurrTool = nCurrTool ;
return true ;
}
//----------------------------------------------------------------------------
int
VolZmap::GetToolCount( void) const
{
return int( m_vTool.size()) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AddTool( void)
{
m_vTool.emplace_back( true) ;
m_vTool.back().SetTolerances( LIN_TOL_STD, ANG_TOL_APPROX_DEG) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ResetAllTools( void)
{
bool bOk = true ;
for ( int n = 0 ; n < int( m_vTool.size()) ; ++ n) {
bOk = bOk || m_vTool[n].Clear() ;
}
m_vTool.clear() ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ResetTool( void)
{
return m_Tool.Clear() ;
if ( m_vTool.empty())
return true ;
bool bOk = m_vTool.back().Clear() ;
m_vTool.erase( m_vTool.begin() + int( m_vTool.size()) - 1) ;
return bOk ;
}
//----------------------------------------------------------------------------
const ICurveComposite&
VolZmap::GetToolOutline( bool bApprox) const
{
if ( m_nCurrTool < 0)
return cvEmptyOutline ;
return ( bApprox ? m_vTool[m_nCurrTool].GetApproxOutline() : m_vTool[m_nCurrTool].GetOutline()) ;
}
+87 -13
View File
@@ -60,10 +60,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
public : // IVolZmap
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -71,6 +72,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) override ;
bool CreateEmptyMap( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex) override ;
int GetBlockCount( void) const override ;
int GetBlockUpdatingCounter( int nBlock) const override ;
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
@@ -89,9 +91,15 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool SetGenTool( const std::string& sToolName, const ICurveComposite* pToolOutline, int nFlag) override ;
bool SetMortiserTool( const std::string& sToolName, double dH, double dW, double dTh, double dRc, int nFlag) override ;
bool SetChiselTool( const std::string& sToolName, double dH, double dW, double dTh, int nFlag) override ;
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRC, int nFlag) override ;
bool SetCurrTool( int nCurrTool) override ;
int GetToolCount( void) const override ;
int GetCurrTool( void) const override
{ return m_nCurrTool ; }
bool AddTool( void) override ;
bool ResetAllTools( void) override ;
bool ResetTool( void) override ;
const ICurveComposite& GetToolOutline( bool bApprox = false) const override
{ return ( bApprox ? m_Tool.GetApproxOutline() : m_Tool.GetOutline()) ;}
const ICurveComposite& GetToolOutline( bool bApprox = false) const override ;
bool MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Point3d& ptPe, const Vector3d& vtDe) override ;
bool MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) override ;
@@ -302,10 +310,45 @@ class VolZmap : public IVolZmap, public IGeoObjRW
inline bool TestParaBBox( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtD, const Vector3d& vtA,
double dLenX, double dLenY, double dLenZ,
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
// Asportazioni superfici elementari vuote
bool SurfCircCrown_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) ;
bool SurfCircCrown_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) ;
bool SurfCircCrown_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) ;
bool SurfCircCrown_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) ;
/*bool SurfCyl_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dRad, bool bTapB, bool bTapT) ;
bool SurfCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dRad, bool bTapB, bool bTapT) ;*/
bool SurfCyl_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dRad, bool bOuterCutter) ;
bool SurfCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
const Vector3d& vtToolDir, double dHei, double dRad, bool bOuterCutter, bool bTapB, bool bTapT) ;
bool SurfConus_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad,
bool bOuterCutter, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool SurfConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dMaxRad, double dMinRad, bool bOuterCutter, bool bTapB, bool bTapT,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool SurfConus_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad,
bool bOuterCutter, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool SurfConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dHei, double dMaxRad, double dMinRad, bool bOuterCutter, bool bTapB, bool bTapT,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool SurfSphericalShellPart_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dRad, double dInfH, double dSupH, bool bOuterCutter) ;
bool SurfSphericalShell_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dRad, double dHei, bool bOuterCutter) ;
// Additivo
bool AddingMotion( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx) ;
bool AddingCylinder( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dRad) ;
bool AddingTruncatedCone( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dMaxRad, double dMinRad, double dHei,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool AddingSphere( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad) ;
bool AddingGeneral( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx) ;
// Intersezioni
bool IntersLineBox( const Point3d& ptP, const Vector3d& vtV, const Point3d& ptMin, const Point3d& ptMax) const ;
bool IntersLineBox( const Point3d& ptP, const Vector3d& vtV, const Point3d& ptMin, const Point3d& ptMax,
double& dU1, double& dU2) const ;
bool IntersLineZMapLattice( const Point3d& ptP, const Vector3d& vtV, double& dU1, double& dU2) const ;
bool IntersLineZMapBBox( const Point3d& ptP, const Vector3d& vtV, double& dU1, double& dU2) const ;
bool IntersLineDexel( const Point3d& ptP, const Vector3d& vtV, int nGrid, int nI, int nJ,
@@ -316,7 +359,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
bool IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting = true) const ;
bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen,
bool bTapLow, bool bTapUp,
@@ -326,11 +369,39 @@ class VolZmap : public IVolZmap, public IGeoObjRW
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
bool IntersLineMyPolyhedron( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& PolyFrame, double dLenX, double dLenY, double dLenZ, double dDeltaX,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting = true) const ;
bool IntersLineTruncatedPyramid( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& frTruncPyramFrame, double dSegMin, double dSegMax, double dHeight,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
bool TestIntersPlaneZmapBBox( const Plane3d& plPlane) const ;
// Intersezioni per asportazioni avanzate
int IntersLineCircCrown( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptCen, const Vector3d& vtAx, double dMaxRad, double dMinRad,
Point3d& ptInt, Vector3d& vtN) const ;
int IntersLineParallelogram( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptParOrig, const Vector3d& vtSeg1, const Vector3d& vtSeg2,
bool bExtNorm, Point3d& ptInt, Vector3d& vtN) const ;
int IntersLineCylinderCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptBaseCen, const Vector3d& vtAx, double dRad, double dH, bool bInOut,
const std::vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
int IntersLineCircSweptSurfCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptCen, const Vector3d& vtAx, double dRad, const Vector3d& vtSweptVec, bool bInOut,
const std::vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
int IntersLineConeCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptVert, const Vector3d& vtAx, double dRad, double dH, bool bInOut,
const std::vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
int IntersLineSphereCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineD,
const Point3d& ptCen, double dRad, bool bInOut,
const std::vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
int IntersLineCatTongue( const Point3d& ptLineP, const Vector3d& vtLineD,
const Point3d& ptCenSt, const Point3d& ptCenEn, const Vector3d& vtNorm, double dRad,
Point3d& ptInt, Vector3d& vtN) const ;
// Voxel: esistenza e passaggio da N a ijk per i voxel
bool IsValidVoxel( int nN) const ;
bool IsValidVoxel( int nI, int nJ, int nK) const ;
@@ -401,7 +472,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
Status m_nStatus ; // stato
int m_nTempProp ; // proprietà temporanea
int m_nTempProp[2] ; // vettore proprietà temporanee
double m_dStep ; // passo delle griglie
int m_nMapNum ; // numero di griglie ( 1 o 3)
Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap
@@ -451,7 +522,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
mutable std::atomic<bool> m_bBreak ;
std::atomic<bool> m_bIsBox ;
Tool m_Tool ;
// Utensili
std::vector<Tool> m_vTool ;
int m_nCurrTool ;
CurveComposite cvEmptyOutline ;
} ;
+30 -123
View File
@@ -16,10 +16,12 @@
#include "CurveLine.h"
#include "VolZmap.h"
#include "GeoConst.h"
#include "IntersLineBox.h"
#include "IntersLineSurfStd.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSphere.h"
#include "/EgtDev/Include/EGkIntersPlaneBox.h"
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h"
@@ -30,103 +32,6 @@
using namespace std ;
//----------------------------------------------------------------------------
// Box e piano devono essere nello stesso riferimento. Il box deve essere axis aligned.
static bool
TestIntersPlaneBox( const BBox3d& b3Box, const Plane3d& plPlane)
{
// Calcolo le distanze con segno dei punti dal piano
Point3d ptE0 = b3Box.GetMin() ;
double dDist0 = DistPointPlane( ptE0, plPlane) ;
Point3d ptE1( b3Box.GetMax().x, b3Box.GetMin().y, b3Box.GetMin().z) ;
double dDist1 = DistPointPlane( ptE1, plPlane) ;
Point3d ptE2( b3Box.GetMax().x, b3Box.GetMax().y, b3Box.GetMin().z) ;
double dDist2 = DistPointPlane( ptE2, plPlane) ;
Point3d ptE3( b3Box.GetMin().x, b3Box.GetMax().y, b3Box.GetMin().z) ;
double dDist3 = DistPointPlane( ptE3, plPlane) ;
Point3d ptE4( b3Box.GetMin().x, b3Box.GetMin().y, b3Box.GetMax().z) ;
double dDist4 = DistPointPlane( ptE4, plPlane) ;
Point3d ptE5( b3Box.GetMax().x, b3Box.GetMin().y, b3Box.GetMax().z) ;
double dDist5 = DistPointPlane( ptE5, plPlane) ;
Point3d ptE6 = b3Box.GetMax() ;
double dDist6 = DistPointPlane( ptE6, plPlane) ;
Point3d ptE7( b3Box.GetMin().x, b3Box.GetMax().y, b3Box.GetMax().z) ;
double dDist7 = DistPointPlane( ptE7, plPlane) ;
// Distanze tutte positive
if ( dDist0 > EPS_SMALL && dDist1 > EPS_SMALL && dDist2 > EPS_SMALL && dDist3 > EPS_SMALL &&
dDist4 > EPS_SMALL && dDist5 > EPS_SMALL && dDist6 > EPS_SMALL && dDist7 > EPS_SMALL)
return false ;
// Distanze tutte negative
if ( dDist0 < - EPS_SMALL && dDist1 < - EPS_SMALL && dDist2 < - EPS_SMALL && dDist3 < - EPS_SMALL &&
dDist4 < - EPS_SMALL && dDist5 < - EPS_SMALL && dDist6 < - EPS_SMALL && dDist7 < - EPS_SMALL)
return false ;
// Il piano interseca il box
return true ;
}
//----------------------------------------------------------------------------
// Punti e vettore devono esse espressi nel medesimo sistema di riferimento.
// Il box è allineato con gli assi di tale sistema di riferimento.
// Viene restituito true in caso di intersezione, false altrimenti.
bool
VolZmap::IntersLineBox( const Point3d& ptP, const Vector3d& vtV, const Point3d& ptMin, const Point3d& ptMax) const
{
double dU1, dU2 ;
return IntersLineBox( ptP, vtV, ptMin, ptMax, dU1, dU2) ;
}
//----------------------------------------------------------------------------
// Punti e vettore devono esse espressi nel medesimo sistema di riferimento.
// Il box è allineato con gli assi di tale sistema di riferimento.
// In dU1, dU2 vengono restituiti i parametri a cui si trovano le intersezioni.
// Viene restituito true in caso di intersezione, false altrimenti.
bool
VolZmap::IntersLineBox( const Point3d& ptP, const Vector3d& vtV,
const Point3d& ptMin, const Point3d& ptMax, double& dU1, double& dU2) const
{
// Il box è allineato agli assi
dU1 = - INFINITO ;
dU2 = INFINITO ;
// confronto con piani YZ (perpendicolari ad asse X)
if ( vtV.x > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.x - ptP.x) / vtV.x) ;
dU2 = min( dU2, ( ptMax.x - ptP.x) / vtV.x) ;
}
else if ( vtV.x < - EPS_ZERO) {
dU1 = max( dU1, ( ptMax.x - ptP.x) / vtV.x) ;
dU2 = min( dU2, ( ptMin.x - ptP.x) / vtV.x) ;
}
else if ( ptP.x < ptMin.x - EPS_SMALL || ptP.x > ptMax.x + EPS_SMALL)
return false ;
// confronto con piani ZX (perpendicolari ad asse Y)
if ( vtV.y > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.y - ptP.y) / vtV.y) ;
dU2 = min( dU2, ( ptMax.y - ptP.y) / vtV.y) ;
}
else if ( vtV.y < - EPS_ZERO) {
dU1 = max( dU1, ( ptMax.y - ptP.y) / vtV.y) ;
dU2 = min( dU2, ( ptMin.y - ptP.y) / vtV.y) ;
}
else if ( ptP.y < ptMin.y - EPS_SMALL || ptP.y > ptMax.y + EPS_SMALL)
return false ;
// confronto con piani XY (perpendicolari ad asse Z)
if ( vtV.z > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.z - ptP.z) / vtV.z) ;
dU2 = min( dU2, ( ptMax.z - ptP.z) / vtV.z) ;
}
else if ( vtV.z < - EPS_ZERO) {
dU1 = max( dU1, ( ptMax.z - ptP.z) / vtV.z) ;
dU2 = min( dU2, ( ptMin.z - ptP.z) / vtV.z) ;
}
else if ( ptP.z < ptMin.z - EPS_SMALL || ptP.z > ptMax.z + EPS_SMALL)
return false ;
return ( dU2 >= dU1) ;
}
//----------------------------------------------------------------------------
// La retta è rappresentata da un punto e dal versore espressi nel riferimento dello Zmap.
// Se non vi è intersezione, viene restituito falso
@@ -249,7 +154,7 @@ VolZmap::IntersRayDexel( const Point3d& ptP, const Vector3d& vtV, int nGrid, int
}
//----------------------------------------------------------------------------
// Calcola la profondità del materiale lungo un raggio, identificato da un punto e un versoreore.
// Calcola la profondità del materiale lungo un raggio, identificato da un punto e un versore.
// Punto e versore devono essere espressi nel sistema di riferimento locale, in cui è immerso quello dello Zmap.
// InLength = distanza di ingresso (se -1 il punto è interno, se -2 il punto è esterno e il raggio non interseca lo Zmap)
// OutLength = distanza di uscita
@@ -293,7 +198,7 @@ VolZmap::GetDepthWithDexel( const Point3d& ptPLoc, const Vector3d& vtDLoc, doubl
double dOutLen[N_MAPS] ;
// Ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
Point3d ptP0 = ptP ;
Vector3d vtV0 = vtD ;
@@ -417,7 +322,7 @@ VolZmap::GetDepthWithDexel( const Point3d& ptPLoc, const Vector3d& vtDLoc, doubl
else {
dInLength = INFINITO ;
dOutLength = - INFINITO ;
for ( int nGr = 0 ; nGr < 3 ; ++ nGr) {
for ( int nGr = 0 ; nGr < m_nMapNum ; ++ nGr) {
if ( dInLen[nGr] > -2 && dInLen[nGr] < dInLength)
dInLength = dInLen[nGr] ;
if ( dOutLen[nGr] > -2 && dOutLen[nGr] > dOutLength)
@@ -2376,7 +2281,7 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
bool
VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting) const
{
// Porto la linea nel riferimento del cilindro
Point3d ptP = ptLineSt ; ptP.ToLoc( CylFrame) ;
@@ -2386,14 +2291,14 @@ VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
int nBasInt = 0 ;
if ( abs( vtV.z) > EPS_ZERO) {
// le linee tangenti al cilindro non sono considerate intersecanti
double EpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
double dEpsRad = ( bSubtracting ? ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) : EPS_SMALL) ;
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * EpsRad) {
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
nBasInt += 1 ;
vtN1 = Z_AX ;
}
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * EpsRad) {
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
nBasInt += 2 ;
vtN2 = - Z_AX ;
}
@@ -2776,7 +2681,7 @@ VolZmap::IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d&
bool
VolZmap::IntersLineMyPolyhedron( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& PolyFrame, double dLenX, double dLenY, double dLenZ, double dDeltaZ,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting) const
{
// Controllo sulle dimensioni lineari affinché sia valido il poliedro
if ( dLenX <= EPS_SMALL || dLenY <= EPS_SMALL || dLenZ <= EPS_SMALL)
@@ -2800,17 +2705,19 @@ VolZmap::IntersLineMyPolyhedron( const Point3d& ptLineSt, const Vector3d& vtLine
// Controlli affinché non vengano tagliati dexel a filo
// con il passaggio dell'utensile:
// Controllo sulle facce 1 e 2
if ( abs( vtV.y) < EPS_ZERO && abs( ptP.y) > ptFacet135.y)
return false ;
// Controllo sulle facce 3 e 4
if ( abs( vtV.x) < EPS_ZERO && ( ptP.x < ptFacet135.x || ptP.x > ptFacet246.x))
return false ;
// Controllo sulle facce 5 e 6
double dP1 = abs ( ( ptFacet135 - ptP) * vtOb) ;
double dP2 = abs ( ( ptFacet246 - ptP) * vtOb) ;
if ( abs( vtV * vtOb) < EPS_ZERO && ( dP1 < EPS_SMALL || dP2 < EPS_SMALL))
return false ;
if ( bSubtracting) {
// Controllo sulle facce 1 e 2
if ( abs( vtV.y) < EPS_ZERO && abs( ptP.y) > ptFacet135.y)
return false ;
// Controllo sulle facce 3 e 4
if ( abs( vtV.x) < EPS_ZERO && ( ptP.x < ptFacet135.x || ptP.x > ptFacet246.x))
return false ;
// Controllo sulle facce 5 e 6
double dP1 = abs ( ( ptFacet135 - ptP) * vtOb) ;
double dP2 = abs ( ( ptFacet246 - ptP) * vtOb) ;
if ( abs( vtV * vtOb) < EPS_ZERO && ( dP1 < EPS_SMALL || dP2 < EPS_SMALL))
return false ;
}
// Punti notevoli
Point3d ptI1 = ptP + ( ( ptFacet135.y - ptP.y) / vtV.y) * vtV ;
@@ -3130,8 +3037,8 @@ VolZmap::GetPartVolume( int nPart, double& dVol) const
// Eseguo il calcolo della lunghezza totale degli spilloni
double dLen = 0 ;
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
for ( int nDex = 0 ; nDex < int( m_Values[nMap].size()) ; ++ nDex) {
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
for ( int nDex = 0 ; nDex < m_nDim[nMap] ; ++ nDex) {
for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) {
// se il pezzo di spillone appartiene alla parte, ne aggiungo la lunghezza
if ( m_Values[nMap][nDex][nInt].nCompo == nPart + 1) {
@@ -3188,7 +3095,7 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
if ( ! GetBlockBox( nBlockIJK, b3BlockBox))
return false ;
// Se c'è intersezione valuto tutti i voxel interni
if ( IntersLineBox( ptLocP, vtDirL, b3BlockBox.GetMin(), b3BlockBox.GetMax())) {
if ( TestIntersLineBox( ptLocP, vtDirL, b3BlockBox.GetMin(), b3BlockBox.GetMax())) {
// Ciclo sui voxel del blocco.
// Triangoli smooth
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
@@ -3199,7 +3106,7 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
m_BlockSmoothTria[nB][nV].k } ;
GetVoxelBox( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], b3Vox) ;
// Se non c'è intersezione col voxel, passo al successivo.
if ( ! IntersLineBox( ptLocP, vtDirL, b3Vox.GetMin(), b3Vox.GetMax()))
if ( ! TestIntersLineBox( ptLocP, vtDirL, b3Vox.GetMin(), b3Vox.GetMax()))
continue ;
for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) {
Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
@@ -3374,7 +3281,7 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
if ( ! GetBlockBox( nBlockIJK, b3BlockBox))
return false ;
// Se c'è intersezione valuto tutti i voxel interni
if ( TestIntersPlaneBox( b3BlockBox, plPlaneLoc)) {
if ( TestIntersPlaneBox( plPlaneLoc, b3BlockBox)) {
// Ciclo sui voxel del blocco.
// Triangoli smooth
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
@@ -3382,7 +3289,7 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
BBox3d b3Vox ;
GetVoxelBox( m_BlockSmoothTria[nB][nV].i, m_BlockSmoothTria[nB][nV].j, m_BlockSmoothTria[nB][nV].k, b3Vox) ;
// Se non c'è intersezione col voxel, passo al successivo.
if ( ! TestIntersPlaneBox(b3Vox, plPlaneLoc))
if ( ! TestIntersPlaneBox( plPlaneLoc, b3Vox))
continue ;
for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) {
Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
@@ -3486,5 +3393,5 @@ bool
VolZmap::TestIntersPlaneZmapBBox( const Plane3d& plPlane) const
{
BBox3d b3Zmap( ORIG, Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ;
return TestIntersPlaneBox( b3Zmap, plPlane) ;
return TestIntersPlaneBox( plPlane, b3Zmap) ;
}
+76 -2
View File
@@ -220,7 +220,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
// Determino le intersezioni della retta con la regione
CRVCVECTOR IntersectionResults ;
Surf.GetCurveClassification( GridLine, IntersectionResults) ;
Surf.GetCurveClassification( GridLine, EPS_SMALL, IntersectionResults) ;
// Analizzo le parti in cui la retta è stata divisa
int nPart = int( IntersectionResults.size()) ;
@@ -327,7 +327,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
// Determino le intersezioni della retta con la regione
CRVCVECTOR IntersectionResults ;
Surf.GetCurveClassification( GridLine, IntersectionResults) ;
Surf.GetCurveClassification( GridLine, EPS_SMALL, IntersectionResults) ;
// Analizzo le parti
int nPart = int( IntersectionResults.size()) ;
@@ -665,3 +665,77 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
return bCompleted ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CreateEmptyMap( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex)
{
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
if ( dStep < EPS_SMALL || dLengthX < EPS_SMALL || dLengthY < EPS_SMALL || dLengthZ < EPS_SMALL)
return false ;
// Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL
m_dStep = max( dStep, 100 * EPS_SMALL) ;
// Aggiorno la dimensione della mappa 1 o 3
m_nMapNum = ( bTriDex ? 3 : 1) ;
// Disponendo i sistemi di riferimento in una successione, le coordinate x,y,z
// di uno si ottengono da una permutazione ciclica di quelle del precedente sistema.
// es: X(n) = Z(n-1), Y(n) = X(n-1), Z(n) = Y(n-1)
// Definisco il sistema di riferimento intrinseco
m_MapFrame.Set( ptO, X_AX, Y_AX, Z_AX) ;
// Definisco i vettori dei limiti su indici
m_nNx[0] = max( int( ( dLengthX + EPS_SMALL) / m_dStep + 0.5), 1) ;
m_nNy[0] = max( int( ( dLengthY + EPS_SMALL) / m_dStep + 0.5), 1) ;
// Numero di componenti connesse
m_nConnectedCompoCount = 1 ;
// Se tridexel
if ( bTriDex) {
m_nNx[1] = m_nNy[0] ;
m_nNy[1] = max( int( ( dLengthZ + EPS_SMALL) / m_dStep + 0.5), 1) ;
m_nNx[2] = m_nNy[1] ;
m_nNy[2] = m_nNx[0] ;
}
// altrimenti mono dexel
else {
m_nNx[1] = 0 ;
m_nNy[1] = 0 ;
m_nNx[2] = 0 ;
m_nNy[2] = 0 ;
}
// Definisco il numero di blocchi lungo x,y e z
if ( ! CalcBlockNum())
return false ;
// Creazione delle mappe
// Calcolo del numero di celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_nDim[i] = m_nNx[i] * m_nNy[i] ;
// Creazione delle celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_Values[i].resize( m_nDim[i]) ;
// Definizione delle limitazioni iniziali in Z per ogni mappa
m_dMinZ[0] = 0 ;
m_dMaxZ[0] = dLengthZ ;
m_dMinZ[1] = 0 ;
m_dMaxZ[1] = ( bTriDex ? dLengthX : 0) ;
m_dMinZ[2] = 0 ;
m_dMaxZ[2] = ( bTriDex ? dLengthY : 0) ;
// Tipologia
m_nShape = GENERIC ;
// Aggiornamento dello stato
m_nStatus = OK ;
return true ;
}
+10 -9
View File
@@ -1,13 +1,13 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2019
// EgalTech 2015-2021
//----------------------------------------------------------------------------
// File : VolZmap.cpp Data : 07.03.19 Versione : 2.1c2
// File : VolZmap.cpp Data : 13.09.21 Versione : 2.3i1
// Contenuto : Implementazione della classe Volume Zmap (tre griglie)
//
//
//
// Modifiche : 22.01.15 DS Creazione modulo.
//
// 13.09.21 LM Correzione funzione che determina se voxel su frontiera di un blocco.
//
//----------------------------------------------------------------------------
@@ -18,6 +18,7 @@
#include "GeoConst.h"
#include "MC_Tables.h"
#include "PolygonPlane.h"
#include "IntersLineBox.h"
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkChainCurves.h"
@@ -844,7 +845,7 @@ VolZmap::UpdateTripleMapGraphics( void) const
VecTriHold.resize( m_nNumBlock) ;
// Ciclo sui blocchi per eliminare le slice fra blocchi da aggiornare
for ( int t = 0 ; t < m_nNumBlock ; ++ t) {
for ( int t = 0 ; t < m_nNumBlock ; ++ t) {
for ( auto it = m_SliceXY[t].begin() ; it != m_SliceXY[t].end() ;) {
int nSlIJK[3] ;
if ( GetVoxIJKFromN( it->first, nSlIJK[0], nSlIJK[1], nSlIJK[2])) {
@@ -1083,7 +1084,7 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
// Flag di regolarità dei campi scalare e vettoriale
bool bReg = true ;
// Ciclo sui segmenti
for ( int EdgeIndex = 0 ; EdgeIndex < 12 ; ++ EdgeIndex) {
// Se il segmento non attraversa la superficie passo al successivo
@@ -3984,13 +3985,13 @@ VolZmap::IsAVoxelOnBoundary( const int nLimits[], const int nIJK[], int nDeltaIn
-- nDeltaIndex[0] ;
else if ( nIJK[0] == nLimits[1] - 1)
++ nDeltaIndex[0] ;
if ( nIJK[0] == nLimits[0])
if ( nIJK[1] == nLimits[2])
-- nDeltaIndex[1];
else if ( nIJK[0] == nLimits[1] - 1)
else if ( nIJK[1] == nLimits[3] - 1)
++ nDeltaIndex[1];
if ( nIJK[0] == nLimits[0])
if ( nIJK[2] == nLimits[4])
-- nDeltaIndex[2];
else if ( nIJK[0] == nLimits[1] - 1)
else if ( nIJK[2] == nLimits[5] - 1)
++ nDeltaIndex[2];
return ( nDeltaIndex[0] != 0 || nDeltaIndex[1] != 0 || nDeltaIndex[2] != 0) ;
}
+4037 -547
View File
File diff suppressed because it is too large Load Diff
+823
View File
@@ -0,0 +1,823 @@
#pragma once
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <limits>
#include <memory>
#include <utility>
#include <vector>
namespace mapbox {
namespace util {
template <std::size_t I, typename T> struct nth {
inline static typename std::tuple_element<I, T>::type
get(const T& t) { return std::get<I>(t); };
};
}
namespace detail {
template <typename N = uint32_t>
class Earcut {
public:
std::vector<N> indices;
std::size_t vertices = 0;
template <typename Polygon>
void operator()(const Polygon& points);
private:
struct Node {
Node(N index, double x_, double y_) : i(index), x(x_), y(y_) {}
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
Node(Node&&) = delete;
Node& operator=(Node&&) = delete;
const N i;
const double x;
const double y;
// previous and next vertice nodes in a polygon ring
Node* prev = nullptr;
Node* next = nullptr;
// z-order curve value
int32_t z = 0;
// previous and next nodes in z-order
Node* prevZ = nullptr;
Node* nextZ = nullptr;
// indicates whether this is a steiner point
bool steiner = false;
};
template <typename Ring> Node* linkedList(const Ring& points, const bool clockwise);
Node* filterPoints(Node* start, Node* end = nullptr);
void earcutLinked(Node* ear, int pass = 0);
bool isEar(Node* ear);
bool isEarHashed(Node* ear);
Node* cureLocalIntersections(Node* start);
void splitEarcut(Node* start);
template <typename Polygon> Node* eliminateHoles(const Polygon& points, Node* outerNode);
Node* eliminateHole(Node* hole, Node* outerNode);
Node* findHoleBridge(Node* hole, Node* outerNode);
bool sectorContainsSector(const Node* m, const Node* p);
void indexCurve(Node* start);
Node* sortLinked(Node* list);
int32_t zOrder(const double x_, const double y_);
Node* getLeftmost(Node* start);
bool pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const;
bool isValidDiagonal(Node* a, Node* b);
double area(const Node* p, const Node* q, const Node* r) const;
bool equals(const Node* p1, const Node* p2);
bool intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2);
bool onSegment(const Node* p, const Node* q, const Node* r);
int sign(double val);
bool intersectsPolygon(const Node* a, const Node* b);
bool locallyInside(const Node* a, const Node* b);
bool middleInside(const Node* a, const Node* b);
Node* splitPolygon(Node* a, Node* b);
template <typename Point> Node* insertNode(std::size_t i, const Point& p, Node* last);
void removeNode(Node* p);
bool hashing;
double minX, maxX;
double minY, maxY;
double inv_size = 0;
template <typename T, typename Alloc = std::allocator<T>>
class ObjectPool {
public:
ObjectPool() { }
ObjectPool(std::size_t blockSize_) {
reset(blockSize_);
}
~ObjectPool() {
clear();
}
template <typename... Args>
T* construct(Args&&... args) {
if (currentIndex >= blockSize) {
currentBlock = alloc_traits::allocate(alloc, blockSize);
allocations.emplace_back(currentBlock);
currentIndex = 0;
}
T* object = &currentBlock[currentIndex++];
alloc_traits::construct(alloc, object, std::forward<Args>(args)...);
return object;
}
void reset(std::size_t newBlockSize) {
for (auto allocation : allocations) {
alloc_traits::deallocate(alloc, allocation, blockSize);
}
allocations.clear();
blockSize = std::max<std::size_t>(1, newBlockSize);
currentBlock = nullptr;
currentIndex = blockSize;
}
void clear() { reset(blockSize); }
private:
T* currentBlock = nullptr;
std::size_t currentIndex = 1;
std::size_t blockSize = 1;
std::vector<T*> allocations;
Alloc alloc;
typedef typename std::allocator_traits<Alloc> alloc_traits;
};
ObjectPool<Node> nodes;
};
template <typename N> template <typename Polygon>
void Earcut<N>::operator()(const Polygon& points) {
// reset
indices.clear();
vertices = 0;
if (points.empty()) return;
double x;
double y;
int threshold = 80;
std::size_t len = 0;
for (size_t i = 0; threshold >= 0 && i < points.size(); i++) {
threshold -= static_cast<int>(points[i].size());
len += points[i].size();
}
//estimate size of nodes and indices
nodes.reset(len * 3 / 2);
indices.reserve(len + points[0].size());
Node* outerNode = linkedList(points[0], true);
if (!outerNode || outerNode->prev == outerNode->next) return;
if (points.size() > 1) outerNode = eliminateHoles(points, outerNode);
// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
hashing = threshold < 0;
if (hashing) {
Node* p = outerNode->next;
minX = maxX = outerNode->x;
minY = maxY = outerNode->y;
do {
x = p->x;
y = p->y;
minX = std::min<double>(minX, x);
minY = std::min<double>(minY, y);
maxX = std::max<double>(maxX, x);
maxY = std::max<double>(maxY, y);
p = p->next;
} while (p != outerNode);
// minX, minY and size are later used to transform coords into integers for z-order calculation
inv_size = std::max<double>(maxX - minX, maxY - minY);
inv_size = inv_size != .0 ? (1. / inv_size) : .0;
}
earcutLinked(outerNode);
nodes.clear();
}
// create a circular doubly linked list from polygon points in the specified winding order
template <typename N> template <typename Ring>
typename Earcut<N>::Node*
Earcut<N>::linkedList(const Ring& points, const bool clockwise) {
using Point = typename Ring::value_type;
double sum = 0;
const std::size_t len = points.size();
std::size_t i, j;
Node* last = nullptr;
// calculate original winding order of a polygon ring
for (i = 0, j = len > 0 ? len - 1 : 0; i < len; j = i++) {
const auto& p1 = points[i];
const auto& p2 = points[j];
const double p20 = util::nth<0, Point>::get(p2);
const double p10 = util::nth<0, Point>::get(p1);
const double p11 = util::nth<1, Point>::get(p1);
const double p21 = util::nth<1, Point>::get(p2);
sum += (p20 - p10) * (p11 + p21);
}
// link points into circular doubly-linked list in the specified winding order
if (clockwise == (sum > 0)) {
for (i = 0; i < len; i++) last = insertNode(vertices + i, points[i], last);
} else {
for (i = len; i-- > 0;) last = insertNode(vertices + i, points[i], last);
}
if (last && equals(last, last->next)) {
removeNode(last);
last = last->next;
}
vertices += len;
return last;
}
// eliminate colinear or duplicate points
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::filterPoints(Node* start, Node* end) {
if (!end) end = start;
Node* p = start;
bool again;
do {
again = false;
if (!p->steiner && (equals(p, p->next) || area(p->prev, p, p->next) == 0)) {
removeNode(p);
p = end = p->prev;
if (p == p->next) break;
again = true;
} else {
p = p->next;
}
} while (again || p != end);
return end;
}
// main ear slicing loop which triangulates a polygon (given as a linked list)
template <typename N>
void Earcut<N>::earcutLinked(Node* ear, int pass) {
if (!ear) return;
// interlink polygon nodes in z-order
if (!pass && hashing) indexCurve(ear);
Node* stop = ear;
Node* prev;
Node* next;
int iterations = 0;
// iterate through ears, slicing them one by one
while (ear->prev != ear->next) {
iterations++;
prev = ear->prev;
next = ear->next;
if (hashing ? isEarHashed(ear) : isEar(ear)) {
// cut off the triangle
indices.emplace_back(prev->i);
indices.emplace_back(ear->i);
indices.emplace_back(next->i);
removeNode(ear);
// skipping the next vertice leads to less sliver triangles
ear = next->next;
stop = next->next;
continue;
}
ear = next;
// if we looped through the whole remaining polygon and can't find any more ears
if (ear == stop) {
// try filtering points and slicing again
if (!pass) earcutLinked(filterPoints(ear), 1);
// if this didn't work, try curing all small self-intersections locally
else if (pass == 1) {
ear = cureLocalIntersections(filterPoints(ear));
earcutLinked(ear, 2);
// as a last resort, try splitting the remaining polygon into two
} else if (pass == 2) splitEarcut(ear);
break;
}
}
}
// check whether a polygon node forms a valid ear with adjacent nodes
template <typename N>
bool Earcut<N>::isEar(Node* ear) {
const Node* a = ear->prev;
const Node* b = ear;
const Node* c = ear->next;
if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
// now make sure we don't have other points inside the potential ear
Node* p = ear->next->next;
while (p != ear->prev) {
if (pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
area(p->prev, p, p->next) >= 0) return false;
p = p->next;
}
return true;
}
template <typename N>
bool Earcut<N>::isEarHashed(Node* ear) {
const Node* a = ear->prev;
const Node* b = ear;
const Node* c = ear->next;
if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
// triangle bbox; min & max are calculated like this for speed
const double minTX = std::min<double>(a->x, std::min<double>(b->x, c->x));
const double minTY = std::min<double>(a->y, std::min<double>(b->y, c->y));
const double maxTX = std::max<double>(a->x, std::max<double>(b->x, c->x));
const double maxTY = std::max<double>(a->y, std::max<double>(b->y, c->y));
// z-order range for the current triangle bbox;
const int32_t minZ = zOrder(minTX, minTY);
const int32_t maxZ = zOrder(maxTX, maxTY);
// first look for points inside the triangle in increasing z-order
Node* p = ear->nextZ;
while (p && p->z <= maxZ) {
if (p != ear->prev && p != ear->next &&
pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
area(p->prev, p, p->next) >= 0) return false;
p = p->nextZ;
}
// then look for points in decreasing z-order
p = ear->prevZ;
while (p && p->z >= minZ) {
if (p != ear->prev && p != ear->next &&
pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
area(p->prev, p, p->next) >= 0) return false;
p = p->prevZ;
}
return true;
}
// go through all polygon nodes and cure small local self-intersections
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::cureLocalIntersections(Node* start) {
Node* p = start;
do {
Node* a = p->prev;
Node* b = p->next->next;
// a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2])
if (!equals(a, b) && intersects(a, p, p->next, b) && locallyInside(a, b) && locallyInside(b, a)) {
indices.emplace_back(a->i);
indices.emplace_back(p->i);
indices.emplace_back(b->i);
// remove two nodes involved
removeNode(p);
removeNode(p->next);
p = start = b;
}
p = p->next;
} while (p != start);
return filterPoints(p);
}
// try splitting polygon into two and triangulate them independently
template <typename N>
void Earcut<N>::splitEarcut(Node* start) {
// look for a valid diagonal that divides the polygon into two
Node* a = start;
do {
Node* b = a->next->next;
while (b != a->prev) {
if (a->i != b->i && isValidDiagonal(a, b)) {
// split the polygon in two by the diagonal
Node* c = splitPolygon(a, b);
// filter colinear points around the cuts
a = filterPoints(a, a->next);
c = filterPoints(c, c->next);
// run earcut on each half
earcutLinked(a);
earcutLinked(c);
return;
}
b = b->next;
}
a = a->next;
} while (a != start);
}
// link every hole into the outer loop, producing a single-ring polygon without holes
template <typename N> template <typename Polygon>
typename Earcut<N>::Node*
Earcut<N>::eliminateHoles(const Polygon& points, Node* outerNode) {
const size_t len = points.size();
std::vector<Node*> queue;
for (size_t i = 1; i < len; i++) {
Node* list = linkedList(points[i], false);
if (list) {
if (list == list->next) list->steiner = true;
queue.push_back(getLeftmost(list));
}
}
std::sort(queue.begin(), queue.end(), [](const Node* a, const Node* b) {
return a->x < b->x;
});
// process holes from left to right
for (size_t i = 0; i < queue.size(); i++) {
outerNode = eliminateHole(queue[i], outerNode);
outerNode = filterPoints(outerNode, outerNode->next);
}
return outerNode;
}
// find a bridge between vertices that connects hole with an outer ring and and link it
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::eliminateHole(Node* hole, Node* outerNode) {
Node* bridge = findHoleBridge(hole, outerNode);
if (!bridge) {
return outerNode;
}
Node* bridgeReverse = splitPolygon(bridge, hole);
// filter collinear points around the cuts
Node* filteredBridge = filterPoints(bridge, bridge->next);
filterPoints(bridgeReverse, bridgeReverse->next);
// Check if input node was removed by the filtering
return outerNode == bridge ? filteredBridge : outerNode;
}
// David Eberly's algorithm for finding a bridge between hole and outer polygon
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::findHoleBridge(Node* hole, Node* outerNode) {
Node* p = outerNode;
double hx = hole->x;
double hy = hole->y;
double qx = -std::numeric_limits<double>::infinity();
Node* m = nullptr;
// find a segment intersected by a ray from the hole's leftmost Vertex to the left;
// segment's endpoint with lesser x will be potential connection Vertex
do {
if (hy <= p->y && hy >= p->next->y && p->next->y != p->y) {
double x = p->x + (hy - p->y) * (p->next->x - p->x) / (p->next->y - p->y);
if (x <= hx && x > qx) {
qx = x;
if (x == hx) {
if (hy == p->y) return p;
if (hy == p->next->y) return p->next;
}
m = p->x < p->next->x ? p : p->next;
}
}
p = p->next;
} while (p != outerNode);
if (!m) return 0;
if (hx == qx) return m; // hole touches outer segment; pick leftmost endpoint
// look for points inside the triangle of hole Vertex, segment intersection and endpoint;
// if there are no points found, we have a valid connection;
// otherwise choose the Vertex of the minimum angle with the ray as connection Vertex
const Node* stop = m;
double tanMin = std::numeric_limits<double>::infinity();
double tanCur = 0;
p = m;
double mx = m->x;
double my = m->y;
do {
if (hx >= p->x && p->x >= mx && hx != p->x &&
pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p->x, p->y)) {
tanCur = std::abs(hy - p->y) / (hx - p->x); // tangential
if (locallyInside(p, hole) &&
(tanCur < tanMin || (tanCur == tanMin && (p->x > m->x || sectorContainsSector(m, p))))) {
m = p;
tanMin = tanCur;
}
}
p = p->next;
} while (p != stop);
return m;
}
// whether sector in vertex m contains sector in vertex p in the same coordinates
template <typename N>
bool Earcut<N>::sectorContainsSector(const Node* m, const Node* p) {
return area(m->prev, m, p->prev) < 0 && area(p->next, m, m->next) < 0;
}
// interlink polygon nodes in z-order
template <typename N>
void Earcut<N>::indexCurve(Node* start) {
assert(start);
Node* p = start;
do {
p->z = p->z ? p->z : zOrder(p->x, p->y);
p->prevZ = p->prev;
p->nextZ = p->next;
p = p->next;
} while (p != start);
p->prevZ->nextZ = nullptr;
p->prevZ = nullptr;
sortLinked(p);
}
// Simon Tatham's linked list merge sort algorithm
// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::sortLinked(Node* list) {
assert(list);
Node* p;
Node* q;
Node* e;
Node* tail;
int i, numMerges, pSize, qSize;
int inSize = 1;
for (;;) {
p = list;
list = nullptr;
tail = nullptr;
numMerges = 0;
while (p) {
numMerges++;
q = p;
pSize = 0;
for (i = 0; i < inSize; i++) {
pSize++;
q = q->nextZ;
if (!q) break;
}
qSize = inSize;
while (pSize > 0 || (qSize > 0 && q)) {
if (pSize == 0) {
e = q;
q = q->nextZ;
qSize--;
} else if (qSize == 0 || !q) {
e = p;
p = p->nextZ;
pSize--;
} else if (p->z <= q->z) {
e = p;
p = p->nextZ;
pSize--;
} else {
e = q;
q = q->nextZ;
qSize--;
}
if (tail) tail->nextZ = e;
else list = e;
e->prevZ = tail;
tail = e;
}
p = q;
}
tail->nextZ = nullptr;
if (numMerges <= 1) return list;
inSize *= 2;
}
}
// z-order of a Vertex given coords and size of the data bounding box
template <typename N>
int32_t Earcut<N>::zOrder(const double x_, const double y_) {
// coords are transformed into non-negative 15-bit integer range
int32_t x = static_cast<int32_t>(32767.0 * (x_ - minX) * inv_size);
int32_t y = static_cast<int32_t>(32767.0 * (y_ - minY) * inv_size);
x = (x | (x << 8)) & 0x00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F;
x = (x | (x << 2)) & 0x33333333;
x = (x | (x << 1)) & 0x55555555;
y = (y | (y << 8)) & 0x00FF00FF;
y = (y | (y << 4)) & 0x0F0F0F0F;
y = (y | (y << 2)) & 0x33333333;
y = (y | (y << 1)) & 0x55555555;
return x | (y << 1);
}
// find the leftmost node of a polygon ring
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::getLeftmost(Node* start) {
Node* p = start;
Node* leftmost = start;
do {
if (p->x < leftmost->x || (p->x == leftmost->x && p->y < leftmost->y))
leftmost = p;
p = p->next;
} while (p != start);
return leftmost;
}
// check if a point lies within a convex triangle
template <typename N>
bool Earcut<N>::pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const {
return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
(ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
(bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
}
// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
template <typename N>
bool Earcut<N>::isValidDiagonal(Node* a, Node* b) {
return a->next->i != b->i && a->prev->i != b->i && !intersectsPolygon(a, b) && // dones't intersect other edges
((locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
(area(a->prev, a, b->prev) != 0.0 || area(a, b->prev, b) != 0.0)) || // does not create opposite-facing sectors
(equals(a, b) && area(a->prev, a, a->next) > 0 && area(b->prev, b, b->next) > 0)); // special zero-length case
}
// signed area of a triangle
template <typename N>
double Earcut<N>::area(const Node* p, const Node* q, const Node* r) const {
return (q->y - p->y) * (r->x - q->x) - (q->x - p->x) * (r->y - q->y);
}
// check if two points are equal
template <typename N>
bool Earcut<N>::equals(const Node* p1, const Node* p2) {
return p1->x == p2->x && p1->y == p2->y;
}
// check if two segments intersect
template <typename N>
bool Earcut<N>::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) {
int o1 = sign(area(p1, q1, p2));
int o2 = sign(area(p1, q1, q2));
int o3 = sign(area(p2, q2, p1));
int o4 = sign(area(p2, q2, q1));
if (o1 != o2 && o3 != o4) return true; // general case
if (o1 == 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
if (o2 == 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
if (o3 == 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
if (o4 == 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
return false;
}
// for collinear points p, q, r, check if point q lies on segment pr
template <typename N>
bool Earcut<N>::onSegment(const Node* p, const Node* q, const Node* r) {
return q->x <= std::max<double>(p->x, r->x) &&
q->x >= std::min<double>(p->x, r->x) &&
q->y <= std::max<double>(p->y, r->y) &&
q->y >= std::min<double>(p->y, r->y);
}
template <typename N>
int Earcut<N>::sign(double val) {
return (0.0 < val) - (val < 0.0);
}
// check if a polygon diagonal intersects any polygon segments
template <typename N>
bool Earcut<N>::intersectsPolygon(const Node* a, const Node* b) {
const Node* p = a;
do {
if (p->i != a->i && p->next->i != a->i && p->i != b->i && p->next->i != b->i &&
intersects(p, p->next, a, b)) return true;
p = p->next;
} while (p != a);
return false;
}
// check if a polygon diagonal is locally inside the polygon
template <typename N>
bool Earcut<N>::locallyInside(const Node* a, const Node* b) {
return area(a->prev, a, a->next) < 0 ?
area(a, b, a->next) >= 0 && area(a, a->prev, b) >= 0 :
area(a, b, a->prev) < 0 || area(a, a->next, b) < 0;
}
// check if the middle Vertex of a polygon diagonal is inside the polygon
template <typename N>
bool Earcut<N>::middleInside(const Node* a, const Node* b) {
const Node* p = a;
bool inside = false;
double px = (a->x + b->x) / 2;
double py = (a->y + b->y) / 2;
do {
if (((p->y > py) != (p->next->y > py)) && p->next->y != p->y &&
(px < (p->next->x - p->x) * (py - p->y) / (p->next->y - p->y) + p->x))
inside = !inside;
p = p->next;
} while (p != a);
return inside;
}
// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits
// polygon into two; if one belongs to the outer ring and another to a hole, it merges it into a
// single ring
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::splitPolygon(Node* a, Node* b) {
Node* a2 = nodes.construct(a->i, a->x, a->y);
Node* b2 = nodes.construct(b->i, b->x, b->y);
Node* an = a->next;
Node* bp = b->prev;
a->next = b;
b->prev = a;
a2->next = an;
an->prev = a2;
b2->next = a2;
a2->prev = b2;
bp->next = b2;
b2->prev = bp;
return b2;
}
// create a node and util::optionally link it with previous one (in a circular doubly linked list)
template <typename N> template <typename Point>
typename Earcut<N>::Node*
Earcut<N>::insertNode(std::size_t i, const Point& pt, Node* last) {
Node* p = nodes.construct(static_cast<N>(i), util::nth<0, Point>::get(pt), util::nth<1, Point>::get(pt));
if (!last) {
p->prev = p;
p->next = p;
} else {
assert(last);
p->next = last->next;
p->prev = last;
last->next->prev = p;
last->next = p;
}
return p;
}
template <typename N>
void Earcut<N>::removeNode(Node* p) {
p->next->prev = p->prev;
p->prev->next = p->next;
if (p->prevZ) p->prevZ->nextZ = p->nextZ;
if (p->nextZ) p->nextZ->prevZ = p->prevZ;
}
}
template <typename N = uint32_t, typename Polygon>
std::vector<N> earcut(const Polygon& poly) {
mapbox::detail::Earcut<N> earcut;
earcut(poly);
return std::move(earcut.indices);
}
}