Compare commits

..

71 Commits

Author SHA1 Message Date
Daniele Bariletti 7882964b26 EgtGeomKernel :
- corretto bug nella richiesta degli edge3D di una Bezier.
2024-03-25 09:59:21 +01:00
Daniele Bariletti 4ab4a2fc81 EgtGeomKernel :
- correzioni ad Edges3D della Bezier. #11
2024-03-22 16:11:51 +01:00
Daniele Bariletti a6d9811595 Merge remote-tracking branch 'origin/master' into CmdCreateSurfBezier 2024-03-21 15:02:59 +01:00
Daniele Bariletti c94a62f5b2 EgtGeomKernel
- cambiato il nome della funzione per richiedere gli edge di una Bezier.
2024-03-21 15:00:37 +01:00
Daniele Bariletti 535011072d EgtGeomKernel :
- corretta e ultimata la funzione edges3D per Bezier. #11
2024-03-21 12:57:59 +01:00
Daniele Bariletti 718f5ce716 EgtGeomKernel :
- ottimizzata la funzione per restituire gli edge 3D di una Bezier.
MANCA:
- debug
- debug su closedV
- debug closedU + ClosedV.
2024-03-20 17:55:24 +01:00
Daniele Bariletti 3f02119ef7 EgtGeomKernel :
- corretta la funzione che restituisce gli edge 3D di una Bezier.
2024-03-20 11:56:50 +01:00
Daniele Bariletti 632b711b2a EgtGeomKernel :
- edge 3D di una Bezier tramite calcolo delle autointersezioni in 3D.
2024-03-20 09:40:16 +01:00
Riccardo Elitropi 07faeaaa11 EgtGeomKernel :
- correzione booleane Trimesh.
2024-03-19 11:59:18 +01:00
SaraP d253312139 EgtGeomKernel :
- gestione traslazione, rotazione e cambi di frame per Voronoi
- aggiunta funzione per resettare Voronoi degli oggetti.
2024-03-15 16:03:51 +01:00
Dario Sassi 5952eee22c EgtGeomKernel :
- modifiche e correzioni varie a dimensioni angolari, diametrali e radiali.
2024-03-14 20:00:44 +01:00
Daniele Bariletti 4483434711 EgtGeomKernel :
- migliorata gestione degli edge3D delle sup di Bezier. #11
2024-03-14 18:02:16 +01:00
Daniele Bariletti 93678ce56c EgtGeomKernel :
- migliorata la gestione dell'aggiornamento degli edge3D delle superfici Bezier.
2024-03-14 10:03:34 +01:00
Daniele Bariletti 8c4b0bde37 EgtGeomKernel :
- corretto un bug nell'aggiornamento della grafica dopo il trim di sup di Bezier. #11
2024-03-13 16:36:12 +01:00
Daniele Bariletti 67c03daa42 EgtGeomKernel :
- nella get Edges3D per sup di Bezier gestito il caso di sup trimmate.
2024-03-13 15:59:55 +01:00
Daniele Bariletti 469d1c3445 EgtGeomKernel :
- aggiunta della funzione per richiedere gli edge 3D o come linea spezzata o come curva Bezier. #11
2024-03-12 09:35:09 +01:00
Dario Sassi 7d3284fef3 EgtGeomKernel 2.6c2 :
- modifiche a SurfTriMesh per flag visualizzazione spigoli vivi in shading
- modifiche a VolZmap per flag visualizzazione spigoli vivi in shading
- aggiunte funzioni PreSave, PostSave e PostLoad per consentire di convertire nuovi parametri delle entità in info prima del salvataggio e riprenderli alla lettura.
2024-03-10 10:20:44 +01:00
Daniele Bariletti 3857cd4b5a Merge branch 'master' into CmdCreateSurfBezier 2024-03-08 16:38:34 +01:00
Daniele Bariletti a04a748552 EgtGeomKernel :
- pulizia del codice
- aggiunta commenti.
2024-03-08 16:29:10 +01:00
Daniele Bariletti 13ecae3829 EgtGeomKernel :
- correzione del raffinamento dei punti di intersezione tra un piano e una sup di bezier.
2024-03-08 16:16:02 +01:00
Daniele Bariletti 1acd97d42a EgtGeomKernel :
- correzioni all'aggiunta di taglia aperti (nel parametrico) ad una superficie di bezier già trimmata.
2024-03-08 09:55:53 +01:00
Daniele Bariletti 6a92f6b80f EgtGeomKernel :
- pulizia del codice.
2024-03-06 14:52:57 +01:00
Daniele Bariletti bf3760808e EgtGeomKernel :
- correzione di errori nella gestione del taglio sul polo e sul bordo di chiusura di una sup. di Bezier.
2024-03-05 17:17:12 +01:00
SaraP 3630b85632 EgtGeomKernel :
- corretto errore offset regioni con Voronoi.
2024-03-04 16:19:27 +01:00
Daniele Bariletti 45226d0b6f EgtGeomKernel :
- correzione errori nel cut delle sup. di Bezier
- miglioramento del raffinamento dell'unproject per sup. di Bezier.
2024-03-04 14:51:23 +01:00
Dario Sassi fdce6e1853 EgtGeomKernel 2.6c1 :
- piccolissima aggiunta a offset di regioni.
2024-03-02 11:52:34 +01:00
SaraP 8ffa9d7fb7 EgtGeomKernel :
- corretto errore offset con Voronoi.
2024-03-01 16:50:55 +01:00
Daniele Bariletti 96ea6bc73e EgtGeomKernel :
- correzioni al cut di una superficie Bezier.
2024-03-01 11:37:12 +01:00
Dario Sassi 360484c9af EgtGeomKernel :
- correzioni a RemoveAlignedPoints di Polyline (si usano indici e non il parametro U come ordine dei punti).
2024-02-29 08:47:44 +01:00
Dario Sassi 47606bffcd Merge remote-tracking branch 'origin/Douglas-Peucker' 2024-02-28 17:36:44 +01:00
Daniele Bariletti 7a2af0b5f2 EgtGeomKernel :
- spostato il filtro delle intersezioni Line-SupBez da executor a GeomKernel.
2024-02-28 10:30:49 +01:00
Daniele Bariletti 8d2ae598e5 Merge remote-tracking branch 'origin/master' into CmdCreateSurfBezier 2024-02-28 09:29:32 +01:00
Dario Sassi aea99a635f EgtGeomKernel :
- eliminati salvataggi di debug dalle booleanne delle trimesh.
2024-02-27 18:25:01 +01:00
Dario Sassi ce139c6925 EgtGeomKernel 2.6b4 :
- aggiunta funzione GetSurfTriMeshTransSwept per creare superficie swept di traslazione.
2024-02-27 18:18:13 +01:00
Daniele Bariletti 4b19936136 Merge branch 'master' into CmdCreateSurfBezier 2024-02-27 17:18:55 +01:00
Daniele Bariletti 6efb3a6e7f EgtGeomKernel :
- corretta funzione di trim di sup. di Bezier con piani, in zone di punti di polo.
2024-02-27 16:34:28 +01:00
SaraP 5dcf5f5616 EgtGeomKernel :
- in Voronoi deallocata memoria non utilizzata.
2024-02-27 14:27:17 +01:00
Dario Sassi 451ef8356b EgtGeomKernel :
- aggiunta funzione IntersCurveSurfTm
- funzioni di intersezione Line e Plane con Zmap separate dall'oggetto per l'interfaccia
2024-02-26 15:00:15 +01:00
Daniele Bariletti 3a623996d2 EgtGeomKernel :
- corretta la funzione per il trim di sup. di Bezier con piani, in zone di salto per periodicità e in caso di tagli multipli.
2024-02-26 09:48:02 +01:00
Daniele Bariletti 4bada73c83 EgtGeomKernel :
- inizio modifica al calcolo di tagli multipli ad una superficie di Bezier.
2024-02-23 10:19:04 +01:00
Daniele Bariletti 156d0eea4b EgtGeomKernel :
- corretta e migliorata la fuzione di cut per superfici di Bezier.
Manca :
- da migliorare i tagli multipli alle superfici di Bezier.
2024-02-22 17:39:44 +01:00
Riccardo Elitropi 6e810f050e Merge commit 'bd90fc2b59f3167c57dc9f13d2a99b40c63883bc' 2024-02-21 17:04:26 +01:00
Riccardo Elitropi 6bfb5c619f Merge commit 'fae6a7cd78972d7b91457994d525dba16d4e5945' into Douglas-Peucker 2024-02-21 16:55:28 +01:00
Riccardo Elitropi bd90fc2b59 Merge commit 'fae6a7cd78972d7b91457994d525dba16d4e5945' into BoolStm 2024-02-21 16:54:51 +01:00
Riccardo Elitropi 5800093e53 EgtGeomKernel :
- correzione inversione delle isole ordinate per area.
- migliorie varie.
2024-02-21 16:49:28 +01:00
SaraP fae6a7cd78 EgtGeomKernel :
- corretto errore offset regione.
2024-02-20 15:50:29 +01:00
Riccardo Elitropi 65daddfced EgtGeomKernel :
- piccole modifiche.
2024-02-20 13:10:20 +01:00
Daniele Bariletti c303b1273d EgtGeomKernel :
- aggiunta la funzione per creare una sfera come superficie bezier
- aggiunta la funzione per tagliare una superificie bezier con un piano.
2024-02-20 12:28:45 +01:00
Riccardo Elitropi 95915b16e5 EgtGeomKernel :
- migliorie per Stm booleans.
2024-02-19 13:07:50 +01:00
Dario Sassi ddade325c4 EgtGeomKernel 2.6b3 :
- standardizzate le funzione Collision Detection sia per trimesh sia per Zmap (ex Avoid...)
- nelle funzioni Cde ora se arrivano geometrie errate si ritorna collisione (maggior sicurezza).
2024-02-16 08:43:15 +01:00
Daniele Bariletti 8d0c04e092 Merge branch 'Dist-Inters_Bezier' into CmdCreateSurfBezier 2024-02-14 14:43:50 +01:00
Daniele Bariletti 5d62db3e73 EgtGeomKernel :
- aggiunta funzione per creare una sfera come sup Bezier.
2024-02-14 14:40:57 +01:00
Riccardo Elitropi 46b91bb49d Merge commit '47e79756d17ae312d89d3617289bccabcb4bcf66' into BoolStm 2024-02-14 08:32:48 +01:00
Dario Sassi c8ce0a242e EgtGeomKernel 2.6b2 :
- a ProjectCurveOnSurfTm aggiunto parametro dMaxSegmLen per massima distanza tra punti risultanti.
2024-02-13 14:34:31 +01:00
Riccardo Elitropi 8be2246249 Merge commit '47e79756d17ae312d89d3617289bccabcb4bcf66' into Douglas-Peucker 2024-02-13 12:37:57 +01:00
Daniele Bariletti 1005aae0e9 Merge branch 'master' into Dist-Inters_Bezier 2024-02-12 12:54:14 +01:00
Daniele Bariletti 47e79756d1 EgtGeomKernel :
- corretto bug nella triangolazione delle sup. di Bezier.
2024-02-12 12:53:57 +01:00
Daniele Bariletti 0f8012ce61 EgtGeomKernel :
- implementata l'intersezione tra linea e sup bezier.
2024-02-12 12:52:56 +01:00
SaraP 595421bcdd EgtGeomKernel :
- gestone delle eccezioni di vroni
- correzioni varie.
2024-02-12 12:22:24 +01:00
Daniele Bariletti 2c159d7ce6 EgtGeomKernel :
- aggiunta funzione di raffinamento dei punti di intersezione per Bezier.
2024-02-08 12:02:12 +01:00
Daniele Bariletti b4058ad363 EgtGeomKernel :
- aggiunta delle intersezioni tra linee e SupBez.
2024-02-08 09:28:49 +01:00
Daniele Bariletti 6b5de066b7 Merge branch 'master' into Dist-Inters_Bezier 2024-02-06 16:03:42 +01:00
Daniele Bariletti 517a66b0fe EgtGeomKernel :
- aggiunta di commenti al codice di triangolazione per le bezier.
2024-02-06 15:57:11 +01:00
Riccardo Elitropi 56cff98cf3 EgtGeomKernel :
- miglioria codice.
2024-02-06 13:15:13 +01:00
Riccardo Elitropi 3168bee865 Merge commit '7cd83efd97d2ab771362e2b18eb3db62bd9fb6e4' into Douglas-Peucker 2024-02-06 10:24:43 +01:00
Riccardo Elitropi 3d2f8c1495 EgtGeomKernel :
- approsimazione PolyLine con Douglas-Peucker.
2024-02-06 10:23:22 +01:00
Daniele Bariletti 7cd83efd97 Merge branch 'ExtDimension_angular' 2024-02-05 15:54:09 +01:00
Riccardo Elitropi 751ea085a6 Merge commit '1280037d1dfe7821c6efd45953cb7cf1e3705ecb' into BoolStm 2023-12-22 09:24:54 +01:00
Riccardo Elitropi 15ed754512 EgtGeomKernel :
- gestiti più chunk per la triangolaziome ( MakeAdvanced)
- piccole modifiche a Intersezione e creazione di Stm da curve.
2023-12-07 13:13:28 +01:00
Daniele Bariletti a3531c4841 EgtGeomKernel :
- correzione su coordinate U e V ai vertici delle TriMesh.
2023-09-19 10:07:51 +02:00
Daniele Bariletti d7ec1fd304 EgtGeomKernel :
- aggiunta delle coordinate U e V ai vertici delle TriMesh.
Manca da modificare :
- funzione MoveVertex
- surfBezier.cpp quando verrà aggiunto il ramo Trim&Mesh.
2023-09-18 10:55:43 +02:00
82 changed files with 5033 additions and 1294 deletions
+15 -5
View File
@@ -19,10 +19,23 @@
using namespace std ;
//----------------------------------------------------------------------------
// Il sistema di riferimento è allineato con il box e ha origine in un suo vertice.
// La distanza di sicurezza ha effetto solo se maggiore di EPS_SMALL.
// Il sistema di riferimento del box è riferito a quello della superficie.
// La funzione restituisce :
// - true in caso di collisione o inconsistenza dei parametri di input
// - false in caso di assenza di collisione.
//----------------------------------------------------------------------------
bool
CDeBoxClosedSurfTm( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, const ISurfTriMesh& Stm)
CDeBoxClosedSurfTm( const Frame3d& frBox, const Vector3d& vtDiag, const ISurfTriMesh& Stm, double dSafeDist)
{
// Se il box non è ben definito non ha senso proseguire
if ( vtDiag.IsSmall())
return true ;
// Se superficie non valida o aperta, non ha senso proseguire
if ( ! Stm.IsValid() || ! Stm.IsClosed())
return true ;
// Recupero BBox del poliedro
BBox3d b3Poly = Stm.GetAllTriaBox() ;
// Calcolo il BBox del parallelepipedo
@@ -39,13 +52,10 @@ CDeBoxClosedSurfTm( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDi
for ( int nT : vT) {
Triangle3d Tria ;
if ( Stm.GetTriangle( nT, Tria)) {
if ( CDeBoxTria( frBox, vtDiag, dSafeDist, Tria))
if ( CDeBoxTria( frBox, vtDiag, Tria, dSafeDist))
return true ;
}
}
// Se superficie aperta, non c'è collisione
if ( ! Stm.IsClosed())
return false ;
// Se il BBox del parallelepipedo non è interno a quello del poliedro e viceversa, non c'è collisione
if ( ! b3Poly.Encloses( b3Box) && ! b3Box.Encloses( b3Poly))
return false ;
+1 -1
View File
@@ -171,7 +171,7 @@ CDeSimpleBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, const Triangle3d
//----------------------------------------------------------------------------
bool
CDeBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, const Triangle3d& trTria)
CDeBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, const Triangle3d& trTria, double dSafeDist)
{
// Porto il triangolo nel riferimento del box
Triangle3d trTriaL = trTria ;
+1 -1
View File
@@ -17,4 +17,4 @@
//----------------------------------------------------------------------------
bool CDeSimpleBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, const Triangle3d& trTria) ;
bool CDeBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, const Triangle3d& trTria) ;
bool CDeBoxTria( const Frame3d& frBox, const Vector3d& vtDiag, const Triangle3d& trTria, double dSafeDist) ;
+1 -1
View File
@@ -97,7 +97,7 @@ CDeSimpleCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Tr
//----------------------------------------------------------------------------
bool
CDeCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, double dSafeDist, const Triangle3d& trTria)
CDeCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Triangle3d& trTria, double dSafeDist)
{
return CDeSimpleCapsTria( ptP1, ptP2, dR + max( 0., dSafeDist), trTria) ;
}
+1 -1
View File
@@ -16,4 +16,4 @@
//----------------------------------------------------------------------------
bool CDeSimpleCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Triangle3d& trTria) ;
bool CDeCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, double dSafeDist, const Triangle3d& trTria) ;
bool CDeCapsTria( const Point3d& ptP1, const Point3d& ptP2, double dR, const Triangle3d& trTria, double dSafeDist) ;
+8 -7
View File
@@ -22,24 +22,25 @@
using namespace std ;
//----------------------------------------------------------------------------
// La funzione restituisce true in caso di collisone, false in caso di assenza
// di collisione o inconsistenza dei parametri di input.
// Le due superfici devono essere espresse nel medesimo sistema di riferimento.
// La distanza di sicurezza ha effetto solo se maggiore di EPS_SMALL.
// Se necessario cerco la collisione con un offset della superficie B costituito
// da sfere centrate nei vertici, cilindri con i segmenti per asse e il triangolo
// originale traslato di una costante pari alla distanza di sicurezza lungo la
// sua normale.
// da sfere centrate nei vertici, cilindri con gli spigoli per asse e il triangolo
// originale traslato della distanza di sicurezza lungo la sua normale.
// La funzione restituisce :
// - true in caso di collisione o inconsistenza dei parametri di input
// - false in caso di assenza di collisione.
//----------------------------------------------------------------------------
bool
CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& SurfB, double dSafeDist)
{
// Recupero le superfici base
const SurfTriMesh* pSrfA = GetBasicSurfTriMesh( &SurfA) ;
const SurfTriMesh* pSrfB = GetBasicSurfTriMesh( &SurfB) ;
// Se le superfici non sono valide o non sono chiuse, non ha senso proseguire.
// Se le superfici non sono valide o non sono chiuse, non ha senso proseguire
if ( pSrfA == nullptr || ! pSrfA->IsValid() || ! pSrfA->IsClosed() ||
pSrfB == nullptr || ! pSrfB->IsValid() || ! pSrfB->IsClosed())
return false ;
return true ;
// Se i box delle superfici non si intersecano, ho finito.
BBox3d b3BoxA, b3BoxB ;
pSrfA->GetLocalBBox( b3BoxA) ;
+12 -8
View File
@@ -21,15 +21,22 @@ using namespace std ;
//----------------------------------------------------------------------------
// Il sistema di riferimento deve avere l'asse di simmetria del cono come asse Z e origine nel centro della base.
// La distanza di sicurezza ha effetto solo se maggiore di epsilon, altrimenti è ignorata ed è ininfluente.
// Il sistema di riferimento del cono deve essere immerso in quello della superficie.
// La distanza di sicurezza ha effetto solo se maggiore di EPS_SMALL, altrimenti è ignorata ed è ininfluente.
// Il sistema di riferimento del cono è riferito a quello della superficie.
// La funzione restituisce :
// - true in caso di collisione o inconsistenza dei parametri di input
// - false in caso di assenza di collisione.
//----------------------------------------------------------------------------
bool
CDeConeFrustumClosedSurfTm( const Frame3d& frCone, double dBaseRad, double dTopRad, double dHeight,
double dSafeDist, const ISurfTriMesh& Stm)
const ISurfTriMesh& Stm, double dSafeDist)
{
// Se il tronco di cono non è ben definito non ha senso proseguire
if ( max( dBaseRad, dTopRad) < EPS_SMALL || dHeight < EPS_SMALL)
return false ;
return true ;
// Se superficie non valida o aperta, non ha senso proseguire
if ( ! Stm.IsValid() || ! Stm.IsClosed())
return true ;
// Recupero BBox della trimesh
BBox3d b3Surf = Stm.GetAllTriaBox() ;
// Calcolo il BBox del tronco di cono
@@ -49,13 +56,10 @@ CDeConeFrustumClosedSurfTm( const Frame3d& frCone, double dBaseRad, double dTopR
for ( int nT : vT) {
Triangle3d trTria ;
if ( Stm.GetTriangle( nT, trTria)) {
if ( CDeConeFrustumTria( frCone, dBaseRad, dTopRad, dHeight, dSafeDist, trTria))
if ( CDeConeFrustumTria( frCone, dBaseRad, dTopRad, dHeight, trTria, dSafeDist))
return true ;
}
}
// Se superficie aperta, non c'è collisione
if ( ! Stm.IsClosed())
return false ;
// Se il BBox del tronco di cono non è interno a quello del poliedro e viceversa, non c'è collisione
if ( ! b3Surf.Encloses( b3Cone) && ! b3Cone.Encloses( b3Surf))
return false ;
+4 -4
View File
@@ -134,7 +134,7 @@ CDeSimpleConeFrustumTria( const Frame3d& frCone, double dMinRad, double dMaxRad,
// La distanza di sicurezza ha effetto solo se maggiore di epsilon, altrimenti è ignorata ed è ininfluente.
bool
CDeConeFrustumTria( const Frame3d& frCone, double dBaseRad, double dTopRad, double dHeight,
double dSafeDist, const Triangle3d& trTria)
const Triangle3d& trTria, double dSafeDist)
{
// Se il tronco di cono o il triangolo non sono ben definiti non procedo
if ( max( dBaseRad, dTopRad) < EPS_SMALL || dHeight < EPS_SMALL || ! trTria.IsValid())
@@ -142,7 +142,7 @@ CDeConeFrustumTria( const Frame3d& frCone, double dBaseRad, double dTopRad, doub
// Se è un cilindro chiamo la routine apposita.
if ( abs( dBaseRad - dTopRad) < EPS_SMALL)
return CDeCylTria( frCone, max( dBaseRad, dTopRad), dHeight, dSafeDist, trTria) ;
return CDeCylTria( frCone, max( dBaseRad, dTopRad), dHeight, trTria, dSafeDist) ;
// Se il raggio di base è maggiore del raggio top cambio il sistema di riferimento.
double dMinRad = dBaseRad ;
@@ -156,11 +156,11 @@ CDeConeFrustumTria( const Frame3d& frCone, double dBaseRad, double dTopRad, doub
// Se è un cono, chiamo la routine apposita
if ( dMinRad < EPS_SMALL)
return CDeConeTria( frMyCone, dMaxRad, dHeight, dSafeDist, trTria) ;
return CDeConeTria( frMyCone, dMaxRad, dHeight, trTria, dSafeDist) ;
// Se distanza di sicurezza nulla
if ( dSafeDist < EPS_SMALL)
return CDeSimpleConeFrustumTria( frMyCone, dBaseRad, dTopRad, dHeight, trTria ) ;
return CDeSimpleConeFrustumTria( frMyCone, dBaseRad, dTopRad, dHeight, trTria) ;
// Verifica preliminare con tronco di cono esteso
double dDiffRad = dMaxRad - dMinRad ;
+1 -2
View File
@@ -20,6 +20,5 @@
// Il sistema di riferimento deve avere l'origine nel centro della base minore e l'asse
// di simmetria del cono, rivolto verso la direzione di apertura, come asse Z.
bool CDeSimpleConeFrustumTria( const Frame3d& frCone, double dMinRad, double dMaxRad, double dHeight, const Triangle3d& trTria) ;
// Il sistema di riferimento ha l'asse Z coincidente con l'asse di simmetria del cono e l'origine nel centro della base.
bool CDeConeFrustumTria( const Frame3d& frCone, double dBaseRad, double dTopRad, double dHeight,
double dSafeDist, const Triangle3d& trTria) ;
const Triangle3d& trTria, double dSafeDist) ;
+1 -1
View File
@@ -111,7 +111,7 @@ CDeSimpleConeTria( const Frame3d& frCone, double dRad, double dHeight, const Tri
//----------------------------------------------------------------------------
bool
CDeConeTria( const Frame3d& frCone, double dRad, double dHeight, double dSafeDist, const Triangle3d& trTria)
CDeConeTria( const Frame3d& frCone, double dRad, double dHeight, const Triangle3d& trTria, double dSafeDist)
{
// Verifico validità del cono
if ( dRad < EPS_SMALL || dHeight < EPS_SMALL)
+1 -1
View File
@@ -19,4 +19,4 @@
//----------------------------------------------------------------------------
// Il sistema di riferimento ha asse Z coincidente con l'asse del cono e origine nel vertice del cono (punto più basso).
bool CDeSimpleConeTria( const Frame3d& frCone, double dRad, double dHeight, const Triangle3d& trTria) ;
bool CDeConeTria( const Frame3d& frCone, double dRad, double dHeight, double dSafeDist, const Triangle3d& trTria) ;
bool CDeConeTria( const Frame3d& frCone, double dRad, double dHeight, const Triangle3d& trTria, double dSafeDist) ;
+13 -10
View File
@@ -18,17 +18,23 @@
using namespace std ;
//----------------------------------------------------------------------------
// Il toro convesso è il disco limitato dalla sola parte esterna del toro.
// Il toro convesso è il solido a disco limitato dalla sola parte esterna del toro.
// Raggio principale R1, raggio secondario R2.
// Il toro è posto nel piano XY del suo riferimento, centrato sull'origine.
// La funzione restituisce true in caso di collisione.
// La funzione restituisce :
// - true in caso di collisione o inconsistenza dei parametri di input
// - false in caso di assenza di collisione.
//----------------------------------------------------------------------------
bool
CDeConvexTorusClosedSurfTm( const Frame3d& frTorus, double dRad1, double dRad2,
double dSafeDist, const ISurfTriMesh& Stm)
const ISurfTriMesh& Stm, double dSafeDist)
{
// I raggi devono essere non nulli e la superficie ben definita.
if ( dRad1 < EPS_SMALL || dRad2 < EPS_SMALL || ! Stm.IsValid())
return false ;
// I raggi devono essere non nulli
if ( dRad1 < EPS_SMALL || dRad2 < EPS_SMALL)
return true ;
// Se superficie non valida o aperta, non ha senso proseguire
if ( ! Stm.IsValid() || ! Stm.IsClosed())
return true ;
// Box della superficie
BBox3d b3Surf = Stm.GetAllTriaBox() ;
// Box del toro (sempre completo)
@@ -47,13 +53,10 @@ CDeConvexTorusClosedSurfTm( const Frame3d& frTorus, double dRad1, double dRad2,
for ( int nT : vT) {
Triangle3d trTria ;
if ( Stm.GetTriangle( nT, trTria)) {
if ( CDeConvexTorusTria( frTorus, dRad1, dRad2, CT_TOT, dSafeDist, trTria))
if ( CDeConvexTorusTria( frTorus, dRad1, dRad2, CT_TOT, trTria, dSafeDist))
return true ;
}
}
// Se superficie aperta, non c'è collisione
if ( ! Stm.IsClosed())
return false ;
// Se il BBox del toro non è interno a quello del poliedro e viceversa, non c'è collisione
if ( ! b3Surf.Encloses( b3Torus) && ! b3Torus.Encloses( b3Surf))
return false ;
+2 -2
View File
@@ -61,7 +61,7 @@ CDeSimpleConvexTorusTria( const Frame3d& frTorus, double dRad1, double dRad2, in
bool bContinue = plyApprox.GetFirstPoint( ptSt) && plyApprox.GetNextPoint( ptEn) ;
while ( bContinue && ! bCollision) {
frConus.Set( Point3d( 0., 0., ptSt.z), Frame3d::TOP) ;
bCollision = CDeConeFrustumTria( frConus, ptSt.x, ptEn.x, ptEn.z - ptSt.z, 0., trMyTria) ;
bCollision = CDeSimpleConeFrustumTria( frConus, ptSt.x, ptEn.x, ptEn.z - ptSt.z, trMyTria) ;
ptSt = ptEn ;
bContinue = plyApprox.GetNextPoint( ptEn) ;
}
@@ -71,7 +71,7 @@ CDeSimpleConvexTorusTria( const Frame3d& frTorus, double dRad1, double dRad2, in
//----------------------------------------------------------------------------
bool
CDeConvexTorusTria( const Frame3d& frTorus, double dRad1, double dRad2, int nCtType,
double dSafeDist, const Triangle3d& trTria)
const Triangle3d& trTria, double dSafeDist)
{
// I raggi devono essere non nulli e il triangolo ben definito.
if ( dRad1 < EPS_SMALL || dRad2 < EPS_SMALL || ! trTria.IsValid())
+1 -1
View File
@@ -28,4 +28,4 @@ enum ConvexTorusType { CT_INF = -1, CT_SUP = 1, CT_TOT = 0} ;
bool CDeSimpleConvexTorusTria( const Frame3d& frTorus, double dRad1, double dRad2, int nCtType,
const Triangle3d& trTria) ;
bool CDeConvexTorusTria( const Frame3d& frTorus, double dRad1, double dRad2, int nCtType,
double dSafeDist, const Triangle3d& trTria) ;
const Triangle3d& trTria, double dSafeDist) ;
+18 -8
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2020-2020
// EgalTech 2020-2024
//----------------------------------------------------------------------------
// File : CDCylSurfTm.cpp Data : 09.01.20 Versione : 2.2a2
// File : CDCylSurfTm.cpp Data : 15.02.24 Versione : 2.6b2
// Contenuto : Implementazione della verifica di collisione tra
// Cylinder e Closed SurftriMesh.
//
@@ -19,17 +19,30 @@
using namespace std ;
//----------------------------------------------------------------------------
// Il sistema di riferimento deve avere l'asse di simmetria del cilindro come asse Z e origine nel centro della base o del top.
// La distanza di sicurezza ha effetto solo se maggiore di EPS_SMALL, altrimenti è ignorata ed è ininfluente.
// Il sistema di riferimento del cilindro è riferito a quello della superficie.
// La funzione restituisce :
// - true in caso di collisione o inconsistenza dei parametri di input
// - false in caso di assenza di collisione.
//----------------------------------------------------------------------------
bool
CDeCylClosedSurfTm( const Frame3d& frCyl, double dR, double dH, double dSafeDist, const ISurfTriMesh& Stm)
CDeCylClosedSurfTm( const Frame3d& frCyl, double dR, double dH, const ISurfTriMesh& Stm, double dSafeDist)
{
// Il cilindro deve essere ben definito
if ( dR < EPS_SMALL || dH < EPS_SMALL)
return true ;
// Se superficie non valida o aperta, non ha senso proseguire
if ( ! Stm.IsValid() || ! Stm.IsClosed())
return true ;
// Recupero BBox del poliedro
BBox3d b3Poly = Stm.GetAllTriaBox() ;
// Sistemazioni cilindro
Frame3d frMyCyl = frCyl ;
if ( dH < 0) {
frMyCyl.Translate( dH * frMyCyl.VersZ()) ;
dH = - dH ;
dH = -dH ;
}
// Calcolo il BBox del cilindro
BBox3d b3CylL( Point3d( -dR, -dR, 0),
@@ -46,13 +59,10 @@ CDeCylClosedSurfTm( const Frame3d& frCyl, double dR, double dH, double dSafeDist
for ( int nT : vT) {
Triangle3d Tria ;
if ( Stm.GetTriangle( nT, Tria)) {
if ( CDeCylTria( frMyCyl, dR, dH, dSafeDist, Tria))
if ( CDeCylTria( frMyCyl, dR, dH, Tria, dSafeDist))
return true ;
}
}
// Se superficie aperta, non c'è collisione
if ( ! Stm.IsClosed())
return false ;
// Se il BBox del cilindro non è interno a quello del poliedro e viceversa, non c'è collisione
if ( ! b3Poly.Encloses( b3Cyl) && ! b3Cyl.Encloses( b3Poly))
return false ;
+1 -1
View File
@@ -84,7 +84,7 @@ CDeSimpleCylTria( const Frame3d& frCyl, double dR, double dH, const Triangle3d&
//----------------------------------------------------------------------------
bool
CDeCylTria( const Frame3d& frCyl, double dR, double dH, double dSafeDist, const Triangle3d& trTria)
CDeCylTria( const Frame3d& frCyl, double dR, double dH, const Triangle3d& trTria, double dSafeDist)
{
// Se distanza di sicurezza nulla
if ( dSafeDist < EPS_SMALL)
+1 -1
View File
@@ -16,4 +16,4 @@
//----------------------------------------------------------------------------
bool CDeSimpleCylTria( const Frame3d& frCyl, double dR, double dH, const Triangle3d& trTria) ;
bool CDeCylTria( const Frame3d& frCyl, double dR, double dH, double dSafeDist, const Triangle3d& trTria) ;
bool CDeCylTria( const Frame3d& frCyl, double dR, double dH, const Triangle3d& trTria, double dSafeDist) ;
+12 -8
View File
@@ -22,16 +22,23 @@ using namespace std ;
// Il sistema di riferimento deve avere l'origine nel centro della Base, asse X lungo
// un segmento della stessa e asse Z ortogonale alle basi e diretta verso la base Top.
// Il sistema di riferimento della piramide deve essere immerso in quello della superficie.
// La funzione restituisce :
// - true in caso di collisione o inconsistenza dei parametri di input
// - false in caso di assenza di collisione.
//----------------------------------------------------------------------------
bool
CDeRectPrismoidClosedSurfTm( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight,
double dSafeDist, const ISurfTriMesh& Stm)
const ISurfTriMesh& Stm, double dSafeDist)
{
// Se il tronco di piramide non è definito o la superficie non ben definita non ha senso proseguire.
// Se il tronco di piramide non è definito non ha senso proseguire.
if ( max( dLenghtBaseX, dLenghtTopX) < EPS_SMALL ||
max( dLenghtBaseY, dLenghtTopY) < EPS_SMALL ||
dHeight < EPS_SMALL || ! Stm.IsValid())
return false ;
dHeight < EPS_SMALL)
return true ;
// Se superficie non valida o aperta, non ha senso proseguire
if ( ! Stm.IsValid() || ! Stm.IsClosed())
return true ;
// Recupero BBox della trimesh
BBox3d b3Surf = Stm.GetAllTriaBox() ;
// Calcolo il BBox del tronco di piramide
@@ -53,13 +60,10 @@ CDeRectPrismoidClosedSurfTm( const Frame3d& frPrismoid, double dLenghtBaseX, dou
Triangle3d trTria ;
if ( Stm.GetTriangle( nT, trTria)) {
if ( CDeRectPrismoidTria( frPrismoid, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, dHeight,
dSafeDist, trTria))
trTria, dSafeDist))
return true ;
}
}
// Se superficie aperta, non c'è collisione
if ( ! Stm.IsClosed())
return false ;
// Se il BBox del tronco di piramide non è interno a quello del poliedro e viceversa, non c'è collisione
if ( ! b3Surf.Encloses( b3Pyr) && ! b3Pyr.Encloses( b3Surf))
return false ;
+1 -1
View File
@@ -134,7 +134,7 @@ CDeSimpleRectPrismoidTria( const Frame3d& frPrismoid, double dLenghtBaseX, doubl
bool
CDeRectPrismoidTria( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight,
double dSafeDist, const Triangle3d& trTria)
const Triangle3d& trTria, double dSafeDist)
{
// Se il tronco di piramide o il triangolo non sono ben definiti non procedo
if ( max( dLenghtBaseX, dLenghtTopX) < EPS_SMALL ||
+1 -1
View File
@@ -26,4 +26,4 @@ bool CDeSimpleRectPrismoidTria( const Frame3d& frPrismoid, double dLenghtBaseX,
// asse X lungo un lato della stessa e asse Z ortogonale alle basi e diretta verso la base Top.
bool CDeRectPrismoidTria( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight,
double dSafeDist, const Triangle3d& trTria) ;
const Triangle3d& trTria, double dSafeDist) ;
+12 -5
View File
@@ -19,10 +19,20 @@
using namespace std ;
//----------------------------------------------------------------------------
// La funzione restituisce :
// - true in caso di collisione o inconsistenza dei parametri di input
// - false in caso di assenza di collisione.
//----------------------------------------------------------------------------
bool
CDeSpheClosedSurfTm( const Point3d& ptCen, double dR, double dSafeDist, const ISurfTriMesh& Stm)
CDeSpheClosedSurfTm( const Point3d& ptCen, double dR, const ISurfTriMesh& Stm, double dSafeDist)
{
// Il raggio deve essere non nullo
if ( dR < EPS_SMALL)
return true ;
// Se superficie non valida o aperta, non ha senso proseguire
if ( ! Stm.IsValid() || ! Stm.IsClosed())
return true ;
// Recupero BBox del poliedro
BBox3d b3Poly = Stm.GetAllTriaBox() ;
// Calcolo il BBox della sfera
@@ -38,13 +48,10 @@ CDeSpheClosedSurfTm( const Point3d& ptCen, double dR, double dSafeDist, const IS
for ( int nT : vT) {
Triangle3d Tria ;
if ( Stm.GetTriangle( nT, Tria)) {
if ( CDeSpheTria( ptCen, dR, dSafeDist, Tria))
if ( CDeSpheTria( ptCen, dR, Tria, dSafeDist))
return true ;
}
}
// Se superficie aperta, non c'è collisione
if ( ! Stm.IsClosed())
return false ;
// Se il BBox della sfera non è interno a quello del poliedro e viceversa, non c'è collisione
if ( ! b3Sphe.Encloses( b3Poly) && ! b3Poly.Encloses( b3Sphe))
return false ;
+1 -1
View File
@@ -31,7 +31,7 @@ CDeSimpleSpheTria( const Point3d& ptCen, double dR, const Triangle3d& trTria)
//----------------------------------------------------------------------------
bool
CDeSpheTria( const Point3d& ptCen, double dR, double dSafeDist, const Triangle3d& trTria)
CDeSpheTria( const Point3d& ptCen, double dR, const Triangle3d& trTria, double dSafeDist)
{
return CDeSimpleSpheTria( ptCen, dR + max( 0., dSafeDist), trTria) ;
}
+1 -1
View File
@@ -16,4 +16,4 @@
//----------------------------------------------------------------------------
bool CDeSimpleSpheTria( const Point3d& ptCen, double dR, const Triangle3d& trTria) ;
bool CDeSpheTria( const Point3d& ptCen, double dR, double dSafeDist, const Triangle3d& trTria) ;
bool CDeSpheTria( const Point3d& ptCen, double dR, const Triangle3d& trTria, double dSafeDist) ;
+1 -1
View File
@@ -368,4 +368,4 @@ ClampSegmentOutPlane( const Plane3d& plPlane, Point3d& ptSegP, const Vector3d& v
dSegLen -= dIntersLen ;
}
return true ;
}
}
+55 -45
View File
@@ -189,7 +189,7 @@ CurveArc::Set3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d&
// calcolo del versore normale
m_VtN = vtA ^ vtB ;
double dNSqLen = m_VtN.SqLen() ;
// se i punti sono praticamente allineati non si può calcolare la circonferenza
// se i punti sono praticamente allineati non si può calcolare la circonferenza
if ( ! m_VtN.Normalize( EPS_ZERO))
return false ;
// calcolo del centro
@@ -216,17 +216,17 @@ CurveArc::Set3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d&
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, dAng2Deg, bDet2) || ! bDet2)
return false ;
// deduzione dell'angolo al centro
// se uno dei due angoli è nullo, errore
// se uno dei due angoli è nullo, errore
if ( abs( dAng1Deg) < EPS_ANG_SMALL || abs( dAng2Deg) < EPS_ANG_SMALL)
return false ;
// se i due angoli hanno lo stesso segno e Ang1 è minore di Ang2 in modulo
// se i due angoli hanno lo stesso segno e Ang1 è minore di Ang2 in modulo
else if ( dAng1Deg * dAng2Deg > 0 && abs( dAng1Deg) < abs( dAng2Deg))
m_dAngCenDeg = dAng2Deg ;
// altrimenti hanno segno opposto oppure Ang1 è maggiore di Ang2 in modulo
// altrimenti hanno segno opposto oppure Ang1 è maggiore di Ang2 in modulo
else
m_dAngCenDeg = - _copysign( ANG_FULL, dAng2Deg) + dAng2Deg ;
}
// non c'è DeltaN
// non c'è DeltaN
m_dDeltaN = 0 ;
// imposto ricalcolo di Voronoi
@@ -255,7 +255,7 @@ CurveArc::Set2PNB( const Point3d& ptIni, const Point3d& ptFin, const Vector3d& v
Vector3d vtDiff = ptFin - ptIni ;
if ( vtDiff.IsSmall())
return false ;
// deltaN eventuale ( è componente parallela a VtN)
// deltaN eventuale ( è componente parallela a VtN)
m_dDeltaN = vtDiff * m_VtN ;
vtDiff -= m_dDeltaN * m_VtN ;
if ( abs( m_dDeltaN) < EPS_SMALL)
@@ -304,7 +304,7 @@ CurveArc::Set2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStart
// calcolo del versore normale
m_VtN = vtA ^ vtB ;
double dNSqLen = m_VtN.SqLen() ;
// se tangente e punti sono praticamente allineati non si può calcolare la circonferenza
// se tangente e punti sono praticamente allineati non si può calcolare la circonferenza
if ( ! m_VtN.Normalize( EPS_ZERO))
return false ;
// calcolo del centro
@@ -321,7 +321,7 @@ CurveArc::Set2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStart
double dAng1Deg ;
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, dAng1Deg, bDet1) || ! bDet1)
return false ;
// poichè il senso di rotazione è sempre CCW, se l'angolo è negativo prendo il suo complemento al giro
// poichè il senso di rotazione è sempre CCW, se l'angolo è negativo prendo il suo complemento al giro
if ( dAng1Deg < 0)
m_dAngCenDeg = ANG_FULL + dAng1Deg ;
else
@@ -414,7 +414,7 @@ CurveArc::Set2PRS( const Point3d& ptStart, const Point3d& ptEnd, double dRad, bo
bool bDet ;
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, m_dAngCenDeg, bDet) || ! bDet)
return false ;
// quando è 180deg il segno è determinato solo dal senso
// quando è 180deg il segno è determinato solo dal senso
if ( abs( m_dAngCenDeg - ANG_STRAIGHT) < 10 * EPS_ANG_SMALL &&
( ( bCCW && m_dAngCenDeg < 0) ||
( ! bCCW && m_dAngCenDeg > 0)))
@@ -529,7 +529,7 @@ CurveArc::SetC2P( const Point3d& ptCen, const Point3d& ptStart, const Point3d& p
if ( m_dRad < EPS_ZERO)
return false ;
m_VtS /= m_dRad ;
// calcolo l'angolo al centro (la funzione trova sempre il più piccolo)
// calcolo l'angolo al centro (la funzione trova sempre il più piccolo)
bool bDet ;
if ( ! m_VtS.GetRotation( ( ptNearEnd - m_PtCen), m_VtN, m_dAngCenDeg, bDet) || ! bDet)
return false ;
@@ -733,7 +733,7 @@ CurveArc::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// assegno il box nel riferimento
@@ -820,7 +820,7 @@ CurveArc::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
}
}
// se c'è estrusione, devo tenerne conto
// se c'è estrusione, devo tenerne conto
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
Vector3d vtFrExtr = m_VtExtr ;
vtFrExtr.ToGlob( frRef) ;
@@ -838,7 +838,7 @@ bool
CurveArc::Validate( void)
{
if ( m_nStatus == TO_VERIFY) {
// limito l'angolo al centro a un giro se è piatto ( non è elica)
// limito l'angolo al centro a un giro se è piatto ( non è elica)
if ( abs( m_dDeltaN) < EPS_SMALL) {
if ( m_dAngCenDeg > ANG_FULL)
m_dAngCenDeg = ANG_FULL ;
@@ -1167,7 +1167,7 @@ CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLin
return false ;
}
// se necessario, sistemo per convessità dalla parte ammessa
// se necessario, sistemo per convessità dalla parte ammessa
if ( nType == APL_RIGHT_CONVEX || nType == APL_LEFT_CONVEX) {
if ( ! PL.MakeConvex( vtExtr, ( nType == APL_LEFT_CONVEX)))
return false ;
@@ -1241,7 +1241,7 @@ CurveArc::CopyParamRange( double dUStart, double dUEnd) const
return nullptr ;
// se il parametro start supera quello di end
if ( dUStart > dUEnd - EPS_PARAM) {
// se curva aperta, il trim la cancella completamente quindi non resta alcunchè
// se curva aperta, il trim la cancella completamente quindi non resta alcunchè
if ( ! IsClosed())
return nullptr ;
// se curva chiusa, il trim si avvolge attorno al punto di giunzione
@@ -1331,7 +1331,7 @@ bool
CurveArc::MyExtendedOffset( double dDist, bool bAll, int nType)
{
// bAll == true fa accettare raggi nulli ==> da usare solo internamente
// quando si è sicuri di aumentare subito il raggio o di cancellare
// quando si è sicuri di aumentare subito il raggio o di cancellare
// la curva deve essere validata
if ( m_nStatus != OK)
@@ -1409,7 +1409,7 @@ CurveArc::ModifyEnd( const Point3d& ptNewEnd)
ptOldEndIntr.ToLoc( frIntr) ;
Point3d ptEndIntr = ptNewEnd ;
ptEndIntr.ToLoc( frIntr) ;
// se coincidono nel piano XY, è cambiato solo il deltaN
// se coincidono nel piano XY, è cambiato solo il deltaN
if ( AreSamePointXYExact( ptOldEndIntr, ptEndIntr)) {
m_dDeltaN += ptEndIntr.z - ptOldEndIntr.z ;
}
@@ -1615,8 +1615,10 @@ CurveArc::Translate( const Vector3d& vtMove)
if ( m_nStatus != OK)
return false ;
// imposto ricalcolo di Voronoi
ResetVoronoiObject() ;
// traslo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->Translate( vtMove) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -1634,12 +1636,14 @@ CurveArc::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, dou
if ( m_nStatus != OK)
return false ;
// verifico validità dell'asse di rotazione
// verifico validità dell'asse di rotazione
if ( vtAx.IsSmall())
return false ;
// imposto ricalcolo di Voronoi
ResetVoronoiObject() ;
// ruoto Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -1787,7 +1791,7 @@ CurveArc::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
if ( m_nStatus != OK)
return false ;
// verifico validità del piano di specchiatura
// verifico validità del piano di specchiatura
if ( vtNorm.IsSmall())
return false ;
@@ -1815,11 +1819,11 @@ CurveArc::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vt
if ( m_nStatus != OK)
return false ;
// verifico validità dei parametri
// verifico validità dei parametri
if ( vtNorm.IsSmall() || vtDir.IsSmall())
return false ;
// possibile solo se l'arco è piatto e il piano di scorrimento coincide con quello dell'arco
// possibile solo se l'arco è piatto e il piano di scorrimento coincide con quello dell'arco
if ( ! ( abs( m_dDeltaN) < EPS_SMALL) ||
! AreSameOrOppositeVectorExact( m_VtN, vtNorm))
return false ;
@@ -1849,16 +1853,18 @@ CurveArc::ToGlob( const Frame3d& frRef)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identità, non devo fare alcunché
// se frame identità, non devo fare alcunché
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo di Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->ToGlob( frRef) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -1876,16 +1882,18 @@ CurveArc::ToLoc( const Frame3d& frRef)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identità, non devo fare alcunché
// se frame identità, non devo fare alcunché
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo di Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->ToLoc( frRef) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -1903,16 +1911,18 @@ CurveArc::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità dei frame
// verifico validità dei frame
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
return false ;
// se i due riferimenti coincidono, non devo fare alcunché
// se i due riferimenti coincidono, non devo fare alcunché
if ( AreSameFrame( frOri, frDest))
return true ;
// imposto ricalcolo di Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -1989,12 +1999,12 @@ CurveArc::MyCalcPointParamPosiz( const Point3d& ptP, double& dU, int& nPos, doub
// verifica posizione punto su arco
nPos = PP_NULL ; // fuori
if ( abs( DiffAngle( dAngDeg, 0) * DEGTORAD * m_dRad) < dLinTol) {
nPos = ( IsACircle() ? PP_MID : PP_START) ; // se cerchio è interno, altrimenti vicino a inizio
nPos = ( IsACircle() ? PP_MID : PP_START) ; // se cerchio è interno, altrimenti vicino a inizio
dU = AngleNearAngle( dAngDeg, 0) / m_dAngCenDeg ;
dU = max( dU, 0.) ;
}
else if ( abs( DiffAngle( dAngDeg, m_dAngCenDeg) * DEGTORAD * m_dRad) < dLinTol) {
nPos = ( IsACircle() ? PP_MID : PP_END) ; // se cerchio è interno, altrimenti vicino a fine
nPos = ( IsACircle() ? PP_MID : PP_END) ; // se cerchio è interno, altrimenti vicino a fine
dU = AngleNearAngle( dAngDeg, m_dAngCenDeg) / m_dAngCenDeg ;
dU = min( dU, 1.) ;
}
@@ -2011,7 +2021,7 @@ CurveArc::ChangeRadius( double dNewRadius)
if ( m_nStatus != OK)
return false ;
// verifico validità del raggio
// verifico validità del raggio
if ( ! ( dNewRadius > EPS_SMALL && dNewRadius < MAX_ARC_RAD))
return false ;
@@ -2057,7 +2067,7 @@ CurveArc::ChangeAngCenter( double dNewAngCenDeg)
if ( m_nStatus != OK)
return false ;
// verifico accettabilità angolo
// verifico accettabilità angolo
if ( ! ( abs( m_dAngCenDeg) > EPS_ANG_ZERO))
return false ;
@@ -2153,11 +2163,11 @@ CurveArc::Flip( void)
//----------------------------------------------------------------------------
// Oggetto locale per approssimazione di archi
// Approx interna è quella cordale standard.
// Approx esterna è quella tangente a inizio e fine con metà tratto e un punto in più.
// Approx interna è quella cordale standard.
// Approx esterna è quella tangente a inizio e fine con metà tratto e un punto in più.
// I punti si calcolano a partire dal triangolo tra due punti consecutivi interni e il centro,
// usando il versore medio dal centro e moltiplicandolo per il coefficiente ( 2 / ( 1 + cosA)).
// Il versore dell'ultimo punto è già stato calcolato per il penultimo.
// Il versore dell'ultimo punto è già stato calcolato per il penultimo.
//----------------------------------------------------------------------------
ArcApproxer::ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const CurveArc& arArc)
{
@@ -2281,7 +2291,7 @@ CurveArc::GetVoronoiObject() const
if ( m_nStatus != OK)
return nullptr ;
// se non è stato calcolato, lo calcolo
// se non è stato calcolato, lo calcolo
if ( m_pVoronoiObj == nullptr)
CalcVoronoiObject() ;
+5 -2
View File
@@ -186,7 +186,10 @@ class CurveArc : public ICurveArc, public IGeoObjRW
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
CurveArc( void) ;
@@ -200,13 +203,13 @@ class CurveArc : public ICurveArc, public IGeoObjRW
bool MyExtendedOffset( double dDist, bool bAll, int nType = OFF_FILLET) ;
bool MyCalcPointParamPosiz( const Point3d& ptP, double& dU, int& nPos, double dLinTol) const ;
Voronoi* GetVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
private :
bool CopyFrom( const CurveArc& caSrc) ;
bool Validate( void) ;
bool GetDir( double dU, Vector3d& vtDir) const ;
bool CalcVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
@@ -222,7 +225,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[2] ; // vettore proprietà temporanee
int m_nTempProp[2] ; // vettore proprietà temporanee
double m_dTempParam[2] ; // vettore parametri temporanei
mutable Voronoi* m_pVoronoiObj ; // Voronoi
} ;
+49 -30
View File
@@ -2,7 +2,7 @@
// EgalTech 2013-2013
//----------------------------------------------------------------------------
// File : CurveAux.cpp Data : 22.11.13 Versione : 1.3a1
// Contenuto : Implementazione di alcune funzioni di utilità per le curve.
// Contenuto : Implementazione di alcune funzioni di utilità per le curve.
//
//
//
@@ -39,7 +39,7 @@ IsClosed( const ICurve& crvC)
bool
IsValidParam( const ICurve& crvC, double dPar, ICurve::Side nSide)
{
// recupero l'intervallo di validità del parametro
// recupero l'intervallo di validità del parametro
double dStart, dEnd ;
if ( ! crvC.GetDomain( dStart, dEnd))
return false ;
@@ -60,11 +60,11 @@ IsValidParam( const ICurve& crvC, double dPar, ICurve::Side nSide)
bool
IsStartParam( const ICurve& crvC, double dPar)
{
// recupero l'intervallo di validità del parametro
// recupero l'intervallo di validità del parametro
double dStart, dEnd ;
if ( ! crvC.GetDomain( dStart, dEnd))
return false ;
// se il parametro non è nell'intorno dell'inizio
// se il parametro non è nell'intorno dell'inizio
if ( abs( dPar - dStart) > EPS_PARAM)
return false ;
return true ;
@@ -74,11 +74,11 @@ IsStartParam( const ICurve& crvC, double dPar)
bool
IsEndParam( const ICurve& crvC, double dPar)
{
// recupero l'intervallo di validità del parametro
// recupero l'intervallo di validità del parametro
double dStart, dEnd ;
if ( ! crvC.GetDomain( dStart, dEnd))
return false ;
// se il parametro non è nell'intorno della fine
// se il parametro non è nell'intorno della fine
if ( abs( dPar - dEnd) > EPS_PARAM)
return false ;
return true ;
@@ -98,7 +98,7 @@ GetNearestExtremityToPoint( const Point3d& ptP, const ICurve& Curve, bool& bStar
return false ;
// se curva aperta
if ( ! AreSamePointApprox( ptStart, ptEnd)) {
// è il più vicino tra inizio e fine
// è il più vicino tra inizio e fine
bStart = ( SqDist( ptP, ptStart) <= SqDist( ptP, ptEnd)) ;
return true ;
}
@@ -186,7 +186,7 @@ GetPointTang( const ICurve& crvC, double dU, ICurve::Side nS, Point3d& ptPos, Ve
return false ;
double dUmod = dU + ( nS == ICurve::FROM_MINUS ? -1 : +1) * 100 * EPS_PARAM ;
Point3d ptDummy ;
// se anche la derivata seconda è nulla, provo a spostarmi di poco
// se anche la derivata seconda è nulla, provo a spostarmi di poco
if ( ! vtTang.Normalize( EPS_ZERO)) {
if ( ! crvC.GetPointD1D2( dUmod, nS, ptDummy, &vtDummy, &vtTang))
return false ;
@@ -263,14 +263,14 @@ GetPointDiffGeom( const ICurve& crvC, double dU, ICurve::Side nS, CrvPointDiffGe
bool
ImproveCurveParamAtPoint( double& dU, const Point3d& ptP, const ICurve* pCrv)
{
// Da usare quando il parametro è già molto vicino a quello esatto
// Da usare quando il parametro è già molto vicino a quello esatto
// calcolo il punto della curva in corrispondenza al parametro
Point3d ptQ ;
Vector3d vtD ;
if ( ! pCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptQ, &vtD))
return false ;
// se sono uguali, è già tutto ok
// se sono uguali, è già tutto ok
if ( AreSamePointExact( ptP, ptQ))
return true ;
// se derivata nulla, non posso migliorare
@@ -332,7 +332,7 @@ CurveGetArea( const ICurve& crvC, Plane3d& plPlane, double& dArea)
bool
CurveDump( const ICurve& crvC, string& sOut, bool bMM, const char* szNewLine)
{
// verifico validità curva
// verifico validità curva
if ( ! crvC.IsValid())
return false ;
@@ -455,7 +455,7 @@ ArcToBezierCurve( const ICurve* pCrv)
ICurve*
CurveToNoArcsCurve( const ICurve* pCrv)
{
// verifico validità curva
// verifico validità curva
if ( pCrv == nullptr)
return nullptr ;
// se arco, devo trasformarlo in curva di Bezier (semplice o composta)
@@ -479,7 +479,7 @@ CurveToNoArcsCurve( const ICurve* pCrv)
ICurve*
CurveToArcsPerpExtrCurve( const ICurve* pCrv, double dLinTol, double dAngTolDeg)
{
// verifico validità curva
// verifico validità curva
if ( pCrv == nullptr)
return nullptr ;
// se arco in piano non perpendicolare ad estrusione, curva composita o curva di Bezier trasformo
@@ -525,13 +525,13 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// se periodica
if ( cnData.bPeriodic || ! cnData.bClamped) {
// va trasformata in non-periodica (clamped)
// bisogna aumentare la molteplicità dei nodi u_p-1 e u_(m-p+1) fino ad arrivare al grado della nurbs
// bisogna aumentare la molteplicità dei nodi u_p-1 e u_(m-p+1) fino ad arrivare al grado della nurbs
// e poi scartare nodi e punti fuori dalla regione clamped ( al di fuori della regione u_p-1 -> u_(m-p+1))
// l'agoritmo per l'inserimento dei nodi l' A5.1 del libro delle Nurbs ( Piegl e Tiller), con qualche modifica
// agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p
// agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p
// comincio ad aumentare la molteplictià del nodo u_m-p+1
// comincio ad aumentare la molteplictià del nodo u_m-p+1
int nCP = int( cnData.vCP.size()) ;
int nU = nCP + cnData.nDeg - 1 ;
int nDeg = cnData.nDeg ;
@@ -540,12 +540,12 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
DBLVECTOR vBW ;
vBW.resize( nDeg + 1) ;
// trovo il nodo di cui aumentare la molteplicità e ne calcolo la molteplicità
// trovo il nodo di cui aumentare la molteplicità e ne calcolo la molteplicità
int b = nU - nDeg - 1 + 1 ;
int i = b ;
while ( b > 0 && abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO)
-- b ;
int mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg
int mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg
// recupero i punti da modificare
if ( ! cnData.bRat) {
for ( int i = 0 ; i <= nDeg - mult ; ++ i)
@@ -559,7 +559,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
}
// salvo i punti inalterati
int r = nDeg - mult ; // numero di volte che dovrò inserire il nodo
int r = nDeg - mult ; // numero di volte che dovrò inserire il nodo
cnData.vCP.resize( nCP + r) ;
for ( int p = nCP - 1 ; p > b - mult ; --p) {
cnData.vCP[r + p] = cnData.vCP[p] ;
@@ -604,12 +604,12 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
nU = nU + r ;
nCP = nCP + r ;
// aumento la molteplicità del punto u_p-1
// aumento la molteplicità del punto u_p-1
b = nDeg - 1 ;
i = b ;
while ( b > 0 && abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO)
-- b ;
mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg
mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg
// recupero i punti da modificare
if ( ! cnData.bRat) {
for ( int i = 0 ; i <= nDeg - mult ; ++ i)
@@ -719,7 +719,7 @@ NurbsToBezierCurve( const CNurbsData& cnData)
if ( ! bOk)
return nullptr ;
// se 1 solo intervallo, la Nurbs è già una curva di Bezier
// se 1 solo intervallo, la Nurbs è già una curva di Bezier
if ( nInt == 1) {
// creo la curva di Bezier
PtrOwner<CurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
@@ -738,14 +738,14 @@ NurbsToBezierCurve( const CNurbsData& cnData)
return nullptr ;
}
}
// se non è una curva ma un punto, la invalido
// se non è una curva ma un punto, la invalido
if ( pCrvBez->IsAPoint())
pCrvBez->Init( cnData.nDeg, cnData.bRat) ;
// restituisco la curva
return Release( pCrvBez) ;
}
// altrimenti è equivalente ad una curva composita, la creo
// altrimenti è equivalente ad una curva composita, la creo
PtrOwner<CurveComposite> pCrvCompo( CreateBasicCurveComposite()) ;
if ( IsNull( pCrvCompo))
return nullptr ;
@@ -813,7 +813,7 @@ NurbsToBezierCurve( const CNurbsData& cnData)
return nullptr ;
// se precedente saltata
if ( bPrevRejected) {
// prendo l'ultimo punto della curva composita per garantire la continuità
// prendo l'ultimo punto della curva composita per garantire la continuità
Point3d ptEnd ;
if ( pCrvCompo->GetEndPoint( ptEnd))
vBC[0] = ptEnd ;
@@ -833,13 +833,13 @@ NurbsToBezierCurve( const CNurbsData& cnData)
return nullptr ;
}
}
// se è una vera curva, la aggiungo alla curva composita
// se è una vera curva, la aggiungo alla curva composita
if ( ! pCrvBez->IsAPoint()) {
if ( ! pCrvCompo->AddCurve( Release( pCrvBez)))
return nullptr ;
bPrevRejected = false ;
}
// altrimenti è un punto, la cancello
// altrimenti è un punto, la cancello
else {
pCrvBez.Reset() ;
bPrevRejected = true ;
@@ -911,7 +911,7 @@ FlattenCurve( const ICurve& crCrv, double dToler, double dAngToler, int nFlag)
Point3d ptCen ;
if ( ! crCrv.GetCentroid( ptCen))
return nullptr ;
// Verifico se curva già piatta
// Verifico se curva già piatta
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL_INT, PL))
return nullptr ;
@@ -924,7 +924,7 @@ FlattenCurve( const ICurve& crCrv, double dToler, double dAngToler, int nFlag)
bFlat = false ;
bPoint = PL.GetNextPoint( ptP) ;
}
// Se curva già piatta, la copio ed esco
// Se curva già piatta, la copio ed esco
if ( bFlat) {
PtrOwner<ICurve> pCrv( crCrv.Clone()) ;
if ( IsNull( pCrv))
@@ -975,7 +975,7 @@ ProjectCurveOnPlane( const ICurve& crCrv, const Plane3d& plPlane)
// determino se curva piana e suo eventuale piano
Plane3d plCrv ;
if ( crCrv.IsFlat( plCrv, false, EPS_SMALL / 2)) {
// se il piano della curva è parallelo a quello di proiezione
// se il piano della curva è parallelo a quello di proiezione
if ( AreSameOrOppositeVectorExact( plCrv.GetVersN(), plPlane.GetVersN())) {
// copio la curva
PtrOwner<ICurve> pCrv( crCrv.Clone()) ;
@@ -1087,3 +1087,22 @@ CalcCurveFatCurve( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dRadius, bo
return pVoronoiObj->CalcFatCurve( vCrvs, dRadius, bSquareEnds, bSquareMids) ;
}
//----------------------------------------------------------------------------
void
ResetCurveVoronoi( const ICurve& crvC)
{
switch ( crvC.GetType()) {
case CRV_LINE :
GetBasicCurveLine( &crvC)->ResetVoronoiObject() ;
break ;
case CRV_ARC :
GetBasicCurveArc( &crvC)->ResetVoronoiObject() ;
break ;
case CRV_BEZIER :
GetBasicCurveBezier( &crvC)->ResetVoronoiObject() ;
break ;
case CRV_COMPO :
GetBasicCurveComposite( &crvC)->ResetVoronoiObject() ;
break ;
}
}
+20 -10
View File
@@ -1873,8 +1873,10 @@ CurveBezier::Translate( const Vector3d& vtMove)
if ( m_nStatus != OK)
return false ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// traslo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->Translate( vtMove) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -1897,8 +1899,10 @@ CurveBezier::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng,
if ( vtAx.IsSmall())
return false ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// ruoto Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -2032,8 +2036,10 @@ CurveBezier::ToGlob( const Frame3d& frRef)
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->ToGlob( frRef) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -2061,8 +2067,10 @@ CurveBezier::ToLoc( const Frame3d& frRef)
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->ToLoc( frRef) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -2090,8 +2098,10 @@ CurveBezier::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
if ( AreSameFrame( frOri, frDest))
return true ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
+7 -4
View File
@@ -117,7 +117,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
bool Invert( void) override ;
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override
{ return false ; } // l'offset di crvBezier non è crvBezier tranne in casi molto particolari
{ return false ; } // l'offset di crvBezier non è crvBezier tranne in casi molto particolari
bool ModifyStart( const Point3d& ptNewStart) override ;
bool ModifyEnd( const Point3d& ptNewEnd) override ;
bool SetExtrusion( const Vector3d& vtExtr) override
@@ -151,7 +151,10 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
CurveBezier( void) ;
@@ -165,6 +168,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
bool ApproxWithLines( int nStep, PolyLine& PL) const ;
bool GetApproxLength( double& dLen) const ;
Voronoi* GetVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
private :
bool CopyFrom( const CurveBezier& cbSrc) ;
@@ -183,7 +187,6 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
bool ToPowerBase( PolynomialPoint3d& pol3P) const ;
bool ToPowerBase( PolynomialPoint3d& pol3Num, Polynomial& polDen) const ;
bool CalcVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
@@ -194,12 +197,12 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
Status m_nStatus ; // stato
int m_nDeg ; // grado
bool m_bRat ; // flag di razionale/polinomiale
mutable double m_dParSing ; // eventuale parametro della singolarità (-1=no, -2=da calcolare)
mutable double m_dParSing ; // eventuale parametro della singolarità (-1=no, -2=da calcolare)
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
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[2] ; // vettore proprietà temporanee
int m_nTempProp[2] ; // vettore proprietà temporanee
double m_dTempParam[2] ; // vettore parametri temporanei
mutable Voronoi* m_pVoronoiObj ; // Voronoi
} ;
+140 -105
View File
@@ -186,7 +186,7 @@ CurveComposite::AddCurveByRelocate( CurveComposite& ccSrc, bool bEndOrStart, dou
bool
CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinTol)
{
// prendo la proprietà del puntatore
// prendo la proprietà del puntatore
PtrOwner<ICurve> pCrv( pSmplCrv) ;
if ( IsNull( pCrv))
return false ;
@@ -211,15 +211,15 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
if ( ! pCrv->GetStartPoint( ptCrvStart) || ! pCrv->GetEndPoint( ptCrvEnd))
return false ;
// se non è la prima
// se non è la prima
if ( ! m_CrvSmplS.empty()) {
// se inserita alla fine
if ( bEndOrStart) {
// verifico sia in continuità con il finale attuale
// verifico sia in continuità con il finale attuale
Point3d ptEnd ;
GetEndPoint( ptEnd) ;
if ( ! AreSamePointEpsilon( ptCrvStart, ptEnd, EPS_CONNECT)) {
// se in tolleranza, modifico l'inizio dell'entità
// se in tolleranza, modifico l'inizio dell'entità
if ( SqDist( ptCrvStart, ptEnd) < ( dLinTol * dLinTol)) {
// lunghezza della curva originale
double dOldLen ; pCrv->GetLength( dOldLen) ;
@@ -237,11 +237,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
}
// altrimenti inserita all'inizio
else {
// verifico sia in continuità con l'iniziale attuale
// verifico sia in continuità con l'iniziale attuale
Point3d ptStart ;
GetStartPoint( ptStart) ;
if ( ! AreSamePointEpsilon( ptCrvEnd, ptStart, EPS_CONNECT)) {
// se in tolleranza, modifico la fine dell'entità
// se in tolleranza, modifico la fine dell'entità
if ( SqDist( ptCrvEnd, ptStart) < ( dLinTol * dLinTol)) {
// lunghezza della curva originale
double dOldLen ; pCrv->GetLength( dOldLen) ;
@@ -286,7 +286,7 @@ CurveComposite::Close( void)
if ( ! GetStartPoint( ptStart) ||
! GetEndPoint( ptEnd))
return false ;
// se distanza inferiore al limite ridotto, non faccio alcunché
// se distanza inferiore al limite ridotto, non faccio alcunché
if ( AreSamePointEpsilon( ptStart, ptEnd, EPS_CONNECT))
return true ;
// se molto vicini li modifico
@@ -324,7 +324,7 @@ CurveComposite::FromSplit( const ICurve& cCrv, int nParts)
if ( ! cCrv.IsValid() || ! cCrv.IsSimple())
return false ;
// se 1 parte o meno, non fa alcunchè
// se 1 parte o meno, non fa alcunchè
if ( nParts <= 1)
return true ;
@@ -565,11 +565,11 @@ CurveComposite::Clone( void) const
bool
CurveComposite::CopyFrom( const IGeoObj* pGObjSrc)
{
// se sorgente è una curva composita
// se sorgente è una curva composita
const CurveComposite* pCC = GetBasicCurveComposite( pGObjSrc) ;
if ( pCC != nullptr)
return CopyFrom( *pCC) ;
// se sorgente è un'altro tipo di curva
// se sorgente è un'altro tipo di curva
const ICurve* pCrv = ::GetCurve( pGObjSrc) ;
if ( pCrv != nullptr) {
Clear() ;
@@ -782,7 +782,7 @@ CurveComposite::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
// passo alla curva successiva
pCrvSmpl = GetNextCurve() ;
}
// se c'è estrusione, devo tenerne conto (curve componenti sempre con vtExtr e dThick nulli)
// se c'è estrusione, devo tenerne conto (curve componenti sempre con vtExtr e dThick nulli)
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
Point3d ptMinExtr = b3Loc.GetMin() + m_VtExtr * m_dThick ;
Point3d ptMaxExtr = b3Loc.GetMax() + m_VtExtr * m_dThick ;
@@ -799,7 +799,7 @@ CurveComposite::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// inizializzo il box
@@ -816,7 +816,7 @@ CurveComposite::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
// passo alla curva successiva
pCrvSmpl = GetNextCurve() ;
}
// se c'è estrusione, devo tenerne conto (curve componenti sempre con vtExtr e dThick nulli)
// se c'è estrusione, devo tenerne conto (curve componenti sempre con vtExtr e dThick nulli)
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
Vector3d vtFrExtr = m_VtExtr ;
vtFrExtr.ToGlob( frRef) ;
@@ -838,14 +838,14 @@ CurveComposite::Validate( void)
// ciclo su tutte le curve
int nCount = 0 ;
for ( auto Iter = m_CrvSmplS.cbegin() ; Iter != m_CrvSmplS.cend() ; ++Iter) {
// verifico validità della curva e sua semplicità
// verifico validità della curva e sua semplicità
if ( ! (*Iter)->IsValid() || (*Iter)->GetType() == CRV_COMPO) {
m_nStatus = ERR ;
return false ;
}
// incremento contatore
++ nCount ;
// verifico continuità con la precedente (se non è la prima)
// verifico continuità con la precedente (se non è la prima)
if ( nCount > 1) {
(*Iter)->GetStartPoint( ptStart) ;
if ( ! AreSamePointApprox( ptPrevEnd, ptStart)) {
@@ -870,7 +870,7 @@ CurveComposite::Validate( void)
bool
CurveComposite::TestClosure( void)
{
// se non è chiusa, esco subito
// se non è chiusa, esco subito
if ( ! IsClosed())
return true ;
// verifico ed eventualmente aggiusto coincidenza punti estremi
@@ -939,7 +939,7 @@ CurveComposite::IsFlat( Plane3d& plPlane, bool bUseExtrusion, double dToler) con
} break ;
}
}
// recupero dati sulla planarità della polilinea
// recupero dati sulla planarità della polilinea
int nRank ;
Point3d ptCen ;
Vector3d vtDir ;
@@ -1022,7 +1022,7 @@ CurveComposite::GetMidPoint( Point3d& ptMid) const
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// determino il valore del parametro a metà lunghezza
// determino il valore del parametro a metà lunghezza
double dLen, dMid ;
if ( ! GetLength( dLen) || ! GetParamAtLength( 0.5 * dLen, dMid))
return false ;
@@ -1083,7 +1083,7 @@ CurveComposite::GetMidDir( Vector3d& vtDir) const
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// determino il valore del parametro a metà lunghezza
// determino il valore del parametro a metà lunghezza
double dLen, dMid ;
if ( ! GetLength( dLen) || ! GetParamAtLength( 0.5 * dLen, dMid))
return false ;
@@ -1363,7 +1363,7 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ;
// se speciale, approssimo ogni singola entità e conservo le estremità interne (joint)
// se speciale, approssimo ogni singola entità e conservo le estremità interne (joint)
if ( nType == APL_SPECIAL || nType == APL_SPECIAL_INT) {
// eseguo approssimazione
double dStartPar = 0 ;
@@ -1409,7 +1409,7 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P
Vector3d vtExtr = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ;
if ( ! PL.ApproxOnSide( vtExtr, ( nType == APL_LEFT || nType == APL_LEFT_CONVEX), dLinTol))
return false ;
// se necessario, sistemo per convessità dalla parte ammessa
// se necessario, sistemo per convessità dalla parte ammessa
if ( nType == APL_RIGHT_CONVEX || nType == APL_LEFT_CONVEX) {
if ( ! PL.MakeConvex( vtExtr, ( nType == APL_LEFT_CONVEX)))
return false ;
@@ -1418,7 +1418,7 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P
}
// altrimenti standard
// prima approssimazione lineare a 10 * Epsilon di ogni singola entità
// prima approssimazione lineare a 10 * Epsilon di ogni singola entità
if ( ! ApproxWithLines( 10 * EPS_SMALL, dAngTolDeg, APL_SPECIAL, PL))
return false ;
// eliminazione dei punti in tolleranza
@@ -1436,7 +1436,7 @@ CurveComposite::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA)
if ( m_nStatus != OK)
return false ;
// determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla
// determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla
Frame3d frNat ;
if ( ! m_VtExtr.IsSmall()) {
frNat.Set( ORIG, m_VtExtr) ;
@@ -1500,7 +1500,7 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin
double dMlStartPar = 0 ;
CurveByApprox crvByApprox ;
// determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla
// determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla
Frame3d frNat ;
if ( ! m_VtExtr.IsSmall()) {
frNat.Set( ORIG, m_VtExtr) ;
@@ -1617,12 +1617,12 @@ CurveComposite::CopyParamRange( double dUStart, double dUEnd) const
if ( dUStart < - EPS_PARAM || dUStart > dMaxU + EPS_PARAM ||
dUEnd < - EPS_PARAM || dUEnd > dMaxU + EPS_PARAM)
return nullptr ;
// se i parametri coincidono, non resta alcunchè
// se i parametri coincidono, non resta alcunchè
if ( abs( dUEnd - dUStart) < EPS_PARAM)
return nullptr ;
// se il parametro start supera quello di end
if ( dUStart > dUEnd - EPS_PARAM) {
// se curva aperta, il trim la cancella completamente quindi non resta alcunchè
// se curva aperta, il trim la cancella completamente quindi non resta alcunchè
if ( ! IsClosed())
return nullptr ;
// se curva chiusa, il trim si avvolge attorno al punto di giunzione
@@ -1681,7 +1681,7 @@ CurveComposite::Invert( void)
bool
CurveComposite::SimpleOffset( double dDist, int nType)
{
// se distanza di offset nulla, non devo fare alcunché
// se distanza di offset nulla, non devo fare alcunché
if ( abs( dDist) < EPS_SMALL)
return true ;
@@ -1842,7 +1842,7 @@ CurveComposite::AddArcTg( const Point3d& ptNew, bool bEndOrStart)
return false ;
// recupero il versore normale al piano ( estrusione oppure se nulla asse Z locale)
Vector3d vtN = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ;
// costruisco l'arco (in casi articolari può essere una linea)
// costruisco l'arco (in casi articolari può essere una linea)
PtrOwner<ICurve> pCrv ;
// se da aggiungere alla fine
if ( bEndOrStart) {
@@ -1875,7 +1875,7 @@ CurveComposite::AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEn
// verifico lo stato
if ( m_nStatus != OK && m_nStatus != TO_VERIFY)
return false ;
// costruisco l'arco (in casi articolari può essere una linea)
// costruisco l'arco (in casi articolari può essere una linea)
PtrOwner<ICurve> pCrv ;
// se da aggiungere alla fine
if ( bEndOrStart) {
@@ -1917,7 +1917,7 @@ CurveComposite::AddJoint( double dU)
if ( IsNull( pCrv1) || IsNull( pCrv2))
return false ;
// della prima curva tengo la parte dall'inizio al parametro, della seconda la rimanente
// ( se non riesco a trimmare, la nuova giunzione coincide con una già esistente, esco con successo)
// ( se non riesco a trimmare, la nuova giunzione coincide con una già esistente, esco con successo)
if ( ! pCrv1->TrimEndAtParam( dLocU) || ! pCrv2->TrimStartAtParam( dLocU))
return true ;
// elimino la curva originale
@@ -1955,17 +1955,17 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
else if ( IsClosed())
nNextCrv = 0 ;
ICurve* pNextCrv = ( nNextCrv != -1 ? m_CrvSmplS[ nNextCrv] : nullptr) ;
// recupero punto iniziale dell'entità precedente (se esiste)
// recupero punto iniziale dell'entità precedente (se esiste)
Point3d ptStart ;
if ( pPrevCrv != nullptr && ! pPrevCrv->GetStartPoint( ptStart))
return false ;
// recupero punto finale dell'entità successiva (se esiste)
// recupero punto finale dell'entità successiva (se esiste)
Point3d ptEnd ;
if ( pNextCrv != nullptr && ! pNextCrv->GetEndPoint( ptEnd))
return false ;
// modifico il punto finale dell'eventuale entità precedente
// modifico il punto finale dell'eventuale entità precedente
if ( pPrevCrv != nullptr && ! pPrevCrv->ModifyEnd( ptNewJoint)) {
// se entità precedente si annulla, la elimino
// se entità precedente si annulla, la elimino
if ( AreSamePointApprox( ptStart, ptNewJoint)) {
delete pPrevCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
@@ -1982,9 +1982,9 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
delete( pPrevCrv) ;
}
}
// modifico il punto iniziale dell'eventuale entità successiva
// modifico il punto iniziale dell'eventuale entità successiva
if ( pNextCrv != nullptr && ! pNextCrv->ModifyStart( ptNewJoint)) {
// se entità successiva si annulla, la elimino
// se entità successiva si annulla, la elimino
if ( AreSamePointApprox( ptNewJoint, ptEnd)) {
delete pNextCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
@@ -2101,17 +2101,17 @@ CurveComposite::MoveCurve( int nCrv, const Vector3d& vtMove)
else if ( IsClosed())
nNextCrv = 0 ;
ICurve* pNextCrv = ( nNextCrv != -1 ? m_CrvSmplS[ nNextCrv] : nullptr) ;
// recupero punti iniziale e finale dell'entità precedente (se esiste)
// recupero punti iniziale e finale dell'entità precedente (se esiste)
Point3d ptPrevStart, ptPrevEnd ;
if ( pPrevCrv != nullptr && ( ! pPrevCrv->GetStartPoint( ptPrevStart) || ! pPrevCrv->GetEndPoint( ptPrevEnd)))
return false ;
// recupero punti iniziale e finale dell'entità successiva (se esiste)
// recupero punti iniziale e finale dell'entità successiva (se esiste)
Point3d ptNextStart, ptNextEnd ;
if ( pNextCrv != nullptr && ( ! pNextCrv->GetStartPoint( ptNextStart) || ! pNextCrv->GetEndPoint( ptNextEnd)))
return false ;
// modifico il punto finale dell'eventuale entità precedente
// modifico il punto finale dell'eventuale entità precedente
if ( pPrevCrv != nullptr && ! pPrevCrv->ModifyEnd( ptPrevEnd + vtMove)) {
// se entità precedente si annulla, la elimino
// se entità precedente si annulla, la elimino
if ( AreSamePointApprox( ptPrevStart, ptPrevEnd + vtMove)) {
delete pPrevCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
@@ -2130,9 +2130,9 @@ CurveComposite::MoveCurve( int nCrv, const Vector3d& vtMove)
delete( pPrevCrv) ;
}
}
// modifico il punto iniziale dell'eventuale entità successiva
// modifico il punto iniziale dell'eventuale entità successiva
if ( pNextCrv != nullptr && ! pNextCrv->ModifyStart( ptNextStart + vtMove)) {
// se entità successiva si annulla, la elimino
// se entità successiva si annulla, la elimino
if ( AreSamePointApprox( ptNextStart + vtMove, ptNextEnd)) {
delete pNextCrv ;
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
@@ -2209,7 +2209,7 @@ CurveComposite::ModifyCurveToLine( int nCrv)
return false ;
// recupero la curva corrente
ICurve* pCrv = m_CrvSmplS[nCrv] ;
// se già linea non devo fare alcunchè
// se già linea non devo fare alcunchè
if ( pCrv->GetType() == CRV_LINE)
return true ;
// recupero gli estremi
@@ -2237,7 +2237,7 @@ CurveComposite::ModifyCurveToLine( int nCrv)
bool
CurveComposite::TrimStartAtParam( double dUTrim)
{
// verifico validità parametro
// verifico validità parametro
double dMaxU = double( m_CrvSmplS.size()) ;
if ( dUTrim < -EPS_PARAM || dUTrim > dMaxU - EPS_PARAM)
return false ;
@@ -2267,7 +2267,7 @@ CurveComposite::TrimStartAtParam( double dUTrim)
Iter = m_CrvSmplS.erase( Iter) ;
break ;
}
// altrimenti superata lunghezza ancora da tagliare (taglio già fatto al test sopra)
// altrimenti superata lunghezza ancora da tagliare (taglio già fatto al test sopra)
else {
break ;
}
@@ -2280,7 +2280,7 @@ CurveComposite::TrimStartAtParam( double dUTrim)
bool
CurveComposite::TrimEndAtParam( double dUTrim)
{
// verifico validità parametro
// verifico validità parametro
double dMaxU = double( m_CrvSmplS.size()) ;
if ( dUTrim < EPS_PARAM || dUTrim > dMaxU + EPS_PARAM)
return false ;
@@ -2301,7 +2301,7 @@ CurveComposite::TrimEndAtParam( double dUTrim)
dUToTrim -= ( dParEnd - dParStart) ;
// se da cancellare
if ( bToErase) {
// cancello l'entità, la tolgo dalla lista e passo alla successiva
// cancello l'entità, la tolgo dalla lista e passo alla successiva
delete (*Iter) ;
Iter = m_CrvSmplS.erase( Iter) ;
}
@@ -2311,7 +2311,7 @@ CurveComposite::TrimEndAtParam( double dUTrim)
}
// se lunghezza parametrica ancora da tagliare nulla (entro la tolleranza)
else if ( dUToTrim > - EPS_PARAM) {
// passo alla entità successiva
// passo alla entità successiva
++ Iter ;
// dichiaro ingresso in zona da cancellare
bToErase = true ;
@@ -2324,7 +2324,7 @@ CurveComposite::TrimEndAtParam( double dUTrim)
bToErase = true ;
continue ;
}
// passo alla entità successiva
// passo alla entità successiva
++ Iter ;
// dichiaro ingresso in zona da cancellare
bToErase = true ;
@@ -2389,7 +2389,7 @@ CurveComposite::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
bool
CurveComposite::TrimStartAtLen( double dLenTrim)
{
// verifico validità lunghezza risultante
// verifico validità lunghezza risultante
if ( dLenTrim < EPS_ZERO)
return true ;
double dLen ;
@@ -2443,7 +2443,7 @@ CurveComposite::TrimStartAtLen( double dLenTrim)
bool
CurveComposite::TrimEndAtLen( double dLenTrim)
{
// verifico validità lunghezza risultante
// verifico validità lunghezza risultante
if ( dLenTrim < EPS_SMALL)
return false ;
double dLen ;
@@ -2456,7 +2456,7 @@ CurveComposite::TrimEndAtLen( double dLenTrim)
double dLenToTrim = dLenTrim ;
for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) {
double dCrvLen = 0 ;
// se non sono già nella zona da cancellare, aggiorno lunghezze
// se non sono già nella zona da cancellare, aggiorno lunghezze
if ( ! bToErase) {
// lunghezza della curva
if ( ! (*Iter)->GetLength( dCrvLen))
@@ -2466,18 +2466,18 @@ CurveComposite::TrimEndAtLen( double dLenTrim)
}
// se da cancellare
if ( bToErase) {
// cancello l'entità, la tolgo dalla lista e passo alla successiva
// cancello l'entità, la tolgo dalla lista e passo alla successiva
delete (*Iter) ;
Iter = m_CrvSmplS.erase( Iter) ;
}
// se lunghezza ancora da tagliare non nulla
else if ( dLenToTrim > EPS_SMALL) {
// passo alla entità successiva
// passo alla entità successiva
++ Iter ;
}
// se lunghezza ancora da tagliare nulla (entro la tolleranza)
else if ( dLenToTrim > - EPS_SMALL) {
// passo alla entità successiva
// passo alla entità successiva
++ Iter ;
// dichiaro ingresso in zona da cancellare
bToErase = true ;
@@ -2489,7 +2489,7 @@ CurveComposite::TrimEndAtLen( double dLenTrim)
m_nStatus = ERR ;
return false ;
}
// passo alla entità successiva
// passo alla entità successiva
++ Iter ;
// dichiaro ingresso in zona da cancellare
bToErase = true ;
@@ -2565,8 +2565,10 @@ CurveComposite::Translate( const Vector3d& vtMove)
if ( m_nStatus != OK)
return false ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// traslo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->Translate( vtMove) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -2584,12 +2586,14 @@ CurveComposite::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità dell'asse di rotazione
// verifico validità dell'asse di rotazione
if ( vtAx.IsSmall())
return false ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// ruoto Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -2649,9 +2653,9 @@ CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou
// se tutto bene, passo alla prossima
if ( bOk)
++Iter ;
// altrimenti, l'entità si è annullata => devo toglierla dalla lista e cancellarla
// altrimenti, l'entità si è annullata => devo toglierla dalla lista e cancellarla
else {
// si è annullata l'entità, la elimino e la tolgo dalla lista
// si è annullata l'entità, la elimino e la tolgo dalla lista
delete (*Iter) ;
Iter = m_CrvSmplS.erase( Iter) ;
}
@@ -2699,7 +2703,7 @@ CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del piano di specchiatura
// verifico validità del piano di specchiatura
if ( vtNorm.IsSmall())
return false ;
@@ -2725,7 +2729,7 @@ CurveComposite::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità dei parametri
// verifico validità dei parametri
if ( vtNorm.IsSmall() || vtDir.IsSmall())
return false ;
@@ -2760,16 +2764,18 @@ CurveComposite::ToGlob( const Frame3d& frRef)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identità, non devo fare alcunché
// se frame identità, non devo fare alcunché
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->ToGlob( frRef) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -2790,16 +2796,18 @@ CurveComposite::ToLoc( const Frame3d& frRef)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identità, non devo fare alcunché
// se frame identità, non devo fare alcunché
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->ToLoc( frRef) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -2820,16 +2828,18 @@ CurveComposite::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità dei frame
// verifico validità dei frame
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
return false ;
// se i due riferimenti coincidono, non devo fare alcunché
// se i due riferimenti coincidono, non devo fare alcunché
if ( AreSameFrame( frOri, frDest))
return true ;
return true ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -2976,7 +2986,7 @@ CurveComposite::RemoveFirstOrLastCurve( bool bLast)
bool
CurveComposite::IsParamAtJoint( double dU) const
{
// se aperta e all'inizio o alla fine o lontano dagli interi non è giunzione
// se aperta e all'inizio o alla fine o lontano dagli interi non è giunzione
bool bClosed = IsClosed() ;
if ( ( ! bClosed && abs( dU) < EPS_PARAM) ||
( ! bClosed && abs( dU - double( m_CrvSmplS.size())) < EPS_PARAM) ||
@@ -2994,7 +3004,7 @@ CurveComposite::ChangeStartPoint( double dU)
if ( ! IsClosed())
return false ;
// questa funzione gestisce già anche il cambio di inizio su curve chiuse
// questa funzione gestisce già anche il cambio di inizio su curve chiuse
return TrimStartEndAtParam( dU, dU) ;
}
@@ -3004,19 +3014,19 @@ CurveComposite::ArcsToBezierCurves( void)
{
// verifico le singole curve
for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
// se arco, devo trasformare in una o più curve di Bezier
// se arco, devo trasformare in una o più curve di Bezier
if ( (*Iter)->GetType() == CRV_ARC) {
// eseguo trasformazione
PtrOwner<ICurve> pNewCrv( ArcToBezierCurve( (*Iter))) ;
if ( IsNull( pNewCrv))
return false ;
// se risultato è singola curva
// se risultato è singola curva
if ( pNewCrv->IsSimple()) {
// elimino l'arco e lo sostituisco con la curva di Bezier
delete (*Iter) ;
(*Iter) = Release( pNewCrv) ;
}
// altrimenti è una curva composita
// altrimenti è una curva composita
else {
CurveComposite* pCC = GetBasicCurveComposite( pNewCrv) ;
if ( pCC == nullptr)
@@ -3058,13 +3068,13 @@ CurveComposite::ArcsBezierCurvesToArcsPerpExtr( double dLinTol, double dAngTolDe
(*Iter)->SetExtrusion( V_NULL) ;
if ( IsNull( pNewCrv))
return false ;
// se risultato è singola curva
// se risultato è singola curva
if ( pNewCrv->IsSimple()) {
// elimino la curva originale e la sostituisco con l'arco
delete (*Iter) ;
(*Iter) = Release( pNewCrv) ;
}
// altrimenti è una curva composita
// altrimenti è una curva composita
else {
CurveComposite* pCC = GetBasicCurveComposite( pNewCrv) ;
if ( pCC == nullptr)
@@ -3130,7 +3140,7 @@ CurveComposite::StraightArcsToLines( double dLinTol, double dAngTolDeg)
static int
MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAngTol, bool bNeedSameProp)
{
// verifico compatibilità delle proprietà
// verifico compatibilità delle proprietà
int nTpr0P = pCrvP->GetTempProp( 0) ;
int nTpr0C = pCrvC->GetTempProp( 0) ;
int nTpr1P = pCrvP->GetTempProp( 1) ;
@@ -3177,7 +3187,7 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
if ( pLineC->ModifyStart( pLineP->GetStart())) {
// diminuisco la tolleranza corrente dell'errore attuale
dCurrLinTol -= COEFF_TOL * sqrt( dSqDist) ;
// se curve originali con proprietà diversa, la cancello
// se curve originali con proprietà diversa, la cancello
if ( nTpr0P != nTpr0C)
pLineC->SetTempProp( 0, 0) ;
if ( nTpr1P != nTpr1C)
@@ -3202,7 +3212,7 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
// verifico la coincidenza dei raggi
if ( abs( pArcP->GetRadius() - pArcC->GetRadius()) > dCurrLinTol)
return 0 ;
// verifico la collinearità delle normali (tenendo conto del raggio)
// verifico la collinearità delle normali (tenendo conto del raggio)
if ( ! (( pArcP->GetNormVersor() - pArcC->GetNormVersor()) * pArcP->GetRadius()).IsSmall() &&
! (( pArcP->GetNormVersor() + pArcC->GetNormVersor()) * pArcP->GetRadius()).IsSmall())
return 0 ;
@@ -3230,7 +3240,7 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
// verifico normale al piano dell'arco
if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0)
NewArc.InvertN() ;
// se curve originali con la stessa proprietà, la riporto
// se curve originali con la stessa proprietà, la riporto
if ( nTpr0P == nTpr0C)
NewArc.SetTempProp( nTpr0C, 0) ;
if ( nTpr1P == nTpr1C)
@@ -3255,7 +3265,7 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
pArcC->GetEndPoint( ptP3) ;
CurveArc NewArc ;
if ( NewArc.Set2PVN( ptP1, ptP3, vtDir1, pArcC->GetNormVersor())) {
// se curve originali con la stessa proprietà, la riporto
// se curve originali con la stessa proprietà, la riporto
if ( nTpr0P == nTpr0C)
NewArc.SetTempProp( nTpr0C, 0) ;
if ( nTpr1P == nTpr1C)
@@ -3293,11 +3303,11 @@ CurveComposite::MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd,
while ( iterC != m_CrvSmplS.end()) {
// se curve unite
switch ( MergeTwoCurves( *iterP, *iterC, dCurrLinTol, dCosAngTol, bNeedSameProp)) {
case -1 : // cancello l'entità precedente e la tolgo dalla lista
case -1 : // cancello l'entità precedente e la tolgo dalla lista
delete (*iterP) ;
iterC = m_CrvSmplS.erase( iterP) ;
break ;
case 1 : // cancello l'entità corrente e la tolgo dalla lista
case 1 : // cancello l'entità corrente e la tolgo dalla lista
delete (*iterC) ;
iterC = m_CrvSmplS.erase( iterC) ;
iterC = prev( iterC) ;
@@ -3314,11 +3324,11 @@ CurveComposite::MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd,
if ( bStartEnd && m_CrvSmplS.size() >= 2 && IsClosed()) {
iterC = m_CrvSmplS.begin() ;
switch ( MergeTwoCurves( *iterP, *iterC, dCurrLinTol, dCosAngTol, bNeedSameProp)) {
case -1 : // cancello l'entità precedente e la tolgo dalla lista
case -1 : // cancello l'entità precedente e la tolgo dalla lista
delete (*iterP) ;
m_CrvSmplS.erase( iterP) ;
break ;
case 1 : // cancello l'entità corrente e la tolgo dalla lista
case 1 : // cancello l'entità corrente e la tolgo dalla lista
delete (*iterC) ;
m_CrvSmplS.erase( iterC) ;
break ;
@@ -3377,7 +3387,7 @@ SplitTopBottomArcs( CurveComposite& cCompo)
// le ordino in senso crescente di ampiezza assoluta
if ( abs( dAng1) > abs( dAng2))
swap( dAng1, dAng2) ;
// verifico se la prima di queste rotazioni è compresa nell'arco
// verifico se la prima di queste rotazioni è compresa nell'arco
if ( abs( dAng1) > EPS_ANG_SMALL && abs( dAng1) < abs( pArc->GetAngCenter()) - EPS_ANG_SMALL) {
cCompo.AddJoint( i + dAng1 / pArc->GetAngCenter()) ;
}
@@ -3427,7 +3437,7 @@ CurveComposite::RemoveUndercutOnY( double dLinTol, double dAngTolDeg)
Point3d ptStart, ptEnd ;
pCompo->GetStartPoint( ptStart) ;
pCompo->GetEndPoint( ptEnd) ;
// se curva pressochè verticale non sottende alcunché, quindi la salto
// se curva pressochè verticale non sottende alcunché, quindi la salto
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL)
continue ;
// ordino gli estremi
@@ -3533,7 +3543,7 @@ CurveComposite::IsALine( double dLinTol, Point3d& ptStart, Point3d& ptEnd) const
// elimino i punti allineati entro la tolleranza
if ( ! PL.RemoveAlignedPoints( dLinTol))
return false ;
// se sono rimasti due punti è una retta
// se sono rimasti due punti è una retta
return ( PL.GetPointNbr() == 2) ;
}
@@ -3541,7 +3551,7 @@ CurveComposite::IsALine( double dLinTol, Point3d& ptStart, Point3d& ptEnd) const
bool
CurveComposite::IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const
{
// deve essere una sola entità
// deve essere una sola entità
if ( GetCurveCount() != 1)
return false ;
// deve essere un arco di circonferenza completo
@@ -3564,7 +3574,7 @@ CurveComposite::IsACircle( double dLinTol, Point3d& ptCen, Vector3d& vtN, double
if ( ! IsClosed())
return false ;
// se è formata da una sola entità arco che è una circonferenza
// se è formata da una sola entità arco che è una circonferenza
if ( IsOneCircle( ptCen, vtN, dRad, bCCW))
return true ;
@@ -3601,10 +3611,10 @@ CurveComposite::IsARectangle( double dLinTol, Point3d& ptP, Vector3d& vtL1, Vect
Point3d ptV2 ; PL.GetNextPoint( ptV2) ;
Point3d ptV3 ; PL.GetNextPoint( ptV3) ;
Point3d ptV4 ; PL.GetNextPoint( ptV4) ;
// verifico che le diagonali si incontrino nel loro punto medio (-> è un parallelogramma)
// verifico che le diagonali si incontrino nel loro punto medio (-> è un parallelogramma)
if ( ! AreSamePointEpsilon( Media( ptV1, ptV3), Media( ptV2, ptV4), dLinTol / 2))
return false ;
// verifico che le diagonali abbiano la stessa lunghezza (-> è un rettangolo)
// verifico che le diagonali abbiano la stessa lunghezza (-> è un rettangolo)
if ( abs( Dist( ptV1, ptV3) - Dist( ptV2, ptV4)) > dLinTol)
return false ;
// assegno i parametri del rettangolo
@@ -3637,7 +3647,7 @@ CurveComposite::IsATrapezoid( double dLinTol, Point3d& ptP, Vector3d& vtB1, Vect
Point3d ptV2 ; PL.GetNextPoint( ptV2) ;
Point3d ptV3 ; PL.GetNextPoint( ptV3) ;
Point3d ptV4 ; PL.GetNextPoint( ptV4) ;
// verifico se V4->V3 è parallelo a V1->V2
// verifico se V4->V3 è parallelo a V1->V2
double dV3B12, dV4B12 ;
if ( ! DistPointLine( ptV3, ptV1, ptV2, false).GetDist( dV3B12) ||
! DistPointLine( ptV4, ptV1, ptV2, false).GetDist( dV4B12))
@@ -3649,7 +3659,7 @@ CurveComposite::IsATrapezoid( double dLinTol, Point3d& ptP, Vector3d& vtB1, Vect
vtB2 = ptV3 - ptV4 ;
return true ;
}
// verifico se V1->V4 è parallelo a V2->V3
// verifico se V1->V4 è parallelo a V2->V3
double dV1B23, dV4B23 ;
if ( ! DistPointLine( ptV1, ptV2, ptV3, false).GetDist( dV1B23) ||
! DistPointLine( ptV4, ptV2, ptV3, false).GetDist( dV4B23))
@@ -3661,7 +3671,7 @@ CurveComposite::IsATrapezoid( double dLinTol, Point3d& ptP, Vector3d& vtB1, Vect
vtB2 = ptV4 - ptV1 ;
return true ;
}
// non è un trapezio
// non è un trapezio
return false ;
}
@@ -3747,7 +3757,7 @@ CurveComposite::GetVoronoiObject() const
if ( m_nStatus != OK)
return nullptr ;
// se non è stato calcolato, lo calcolo
// se non è stato calcolato, lo calcolo
if ( m_pVoronoiObj == nullptr)
CalcVoronoiObject() ;
@@ -3763,3 +3773,28 @@ CurveComposite::ResetVoronoiObject() const
delete m_pVoronoiObj ;
m_pVoronoiObj = nullptr ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::FromPoint(Point3d& ptStart)
{
// verifico lo stato
if ( m_nStatus != TO_VERIFY)
return false ;
// assegno il punto e setto lo stato
m_ptStart = ptStart ;
m_nStatus = IS_A_POINT ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::GetOnlyPoint(Point3d& ptStart) const
{
// verifico lo stato
if ( m_nStatus != IS_A_POINT)
return false ;
// restituisco il punto
ptStart = m_ptStart ;
return true ;
}
+9 -4
View File
@@ -150,7 +150,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool IsParamAtJoint( double dU) const override ;
ICurve* RemoveFirstOrLastCurve( bool bLast = true) override ;
bool ChangeStartPoint( double dU) override ;
bool AddPoint( const Point3d& ptStart) override ;
bool AddPoint( const Point3d& ptStart) override ; // funzione per aggiungere il ptStart prima di usare la funzione AddLine
bool AddLine( const Point3d& ptNew, bool bEndOrStart = true) override ;
bool AddLineTg( double dLen, bool bEndOrStart = true) override ;
bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ;
@@ -177,11 +177,16 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool GetCurveTempProp( int nCrv, int& nProp, int nPropInd = 0) const override ;
bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
bool FromPoint( Point3d& ptStart) override ; // funzione per settare la curva ad un unico punto
bool GetOnlyPoint( Point3d& ptStart) const override ; // funzione per recuperare l'unico punto da cui è composta la curva ( degenere)
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
CurveComposite( void) ;
@@ -195,6 +200,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool RelocateFrom( CurveComposite& ccSrc) ;
bool GetApproxLength( double& dLen) const ;
Voronoi* GetVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
private :
bool CopyFrom( const CurveComposite& ccSrc) ;
@@ -206,10 +212,9 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET) ;
bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ;
bool CalcVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ;
private :
typedef std::deque<ICurve*> PCRVSMPL_DEQUE ;
@@ -222,7 +227,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[2] ; // vettore proprietà temporanee
int m_nTempProp[2] ; // vettore proprietà temporanee
double m_dTempParam[2] ; // vettore parametri temporanei
mutable Voronoi* m_pVoronoiObj ; // Voronoi
mutable PCSD_CONST_ITER m_Iter ; // iteratore
+37 -27
View File
@@ -162,7 +162,7 @@ CurveLine::Dump( string& sOut, bool bMM, const char* szNewLine) const
// dati generali di una curva
if ( ! CurveDump( *this, sOut, bMM, szNewLine))
return false ;
// parametri : sono già compresi nei dati generali (PS e PE)
// parametri : sono già compresi nei dati generali (PS e PE)
return true ;
}
@@ -223,7 +223,7 @@ CurveLine::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
return false ;
// assegno il box in locale
b3Loc.Set( m_PtStart, m_PtEnd) ;
// se c'è estrusione, devo tenerne conto
// se c'è estrusione, devo tenerne conto
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
Point3d ptMinExtr = b3Loc.GetMin() + m_VtExtr * m_dThick ;
Point3d ptMaxExtr = b3Loc.GetMax() + m_VtExtr * m_dThick ;
@@ -241,7 +241,7 @@ CurveLine::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// porto gli estremi nel riferimento passato
@@ -251,7 +251,7 @@ CurveLine::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
ptFrEnd.ToGlob( frRef) ;
// assegno il box nel riferimento
b3Ref.Set( ptFrStart, ptFrEnd) ;
// se c'è estrusione, devo tenerne conto
// se c'è estrusione, devo tenerne conto
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
Vector3d vtFrExtr = m_VtExtr ;
vtFrExtr.ToGlob( frRef) ;
@@ -390,7 +390,7 @@ CurveLine::GetLength( double& dLen) const
if ( m_nStatus != OK)
return false ;
// la lunghezza è la distanza tra gli estremi
// la lunghezza è la distanza tra gli estremi
dLen = Dist( m_PtStart, m_PtEnd) ;
return ( dLen > EPS_SMALL) ;
@@ -416,7 +416,7 @@ CurveLine::GetLengthAtParam( double dU, double& dLen) const
return true ;
}
// la lunghezza totale è la distanza tra gli estremi
// la lunghezza totale è la distanza tra gli estremi
double dTotLen = Dist( m_PtStart, m_PtEnd) ;
// fine
@@ -448,7 +448,7 @@ CurveLine::GetParamAtLength( double dLen, double& dU) const
return true ;
}
// la lunghezza totale è la distanza tra gli estremi
// la lunghezza totale è la distanza tra gli estremi
double dTotLen = Dist( m_PtStart, m_PtEnd) ;
// se dopo fine, errore
@@ -811,8 +811,10 @@ CurveLine::Translate( const Vector3d& vtMove)
if ( m_nStatus != OK)
return false ;
// imposto ricalcolo di Voronoi
ResetVoronoiObject() ;
// traslo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->Translate( vtMove) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -830,12 +832,14 @@ CurveLine::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, do
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità dell'asse di rotazione
// verifico validità dell'asse di rotazione
if ( vtAx.IsSmall())
return false ;
// imposto ricalcolo di Voronoi
ResetVoronoiObject() ;
// ruoto Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -894,7 +898,7 @@ CurveLine::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del piano di specchiatura
// verifico validità del piano di specchiatura
if ( vtNorm.IsSmall())
return false ;
@@ -919,7 +923,7 @@ CurveLine::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& v
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità dei parametri
// verifico validità dei parametri
if ( vtNorm.IsSmall() || vtDir.IsSmall())
return false ;
@@ -949,16 +953,18 @@ CurveLine::ToGlob( const Frame3d& frRef)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identità, non devo fare alcunché
// se frame identità, non devo fare alcunché
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo di Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->ToGlob( frRef) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -973,16 +979,18 @@ CurveLine::ToLoc( const Frame3d& frRef)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identità, non devo fare alcunché
// se frame identità, non devo fare alcunché
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo di Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->ToLoc( frRef) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -997,16 +1005,18 @@ CurveLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità dei frame
// verifico validità dei frame
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
return false ;
// se i due riferimenti coincidono, non devo fare alcunché
// se i due riferimenti coincidono, non devo fare alcunché
if ( AreSameFrame( frOri, frDest))
return true ;
// imposto ricalcolo di Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -1065,7 +1075,7 @@ CurveLine::GetVoronoiObject() const
if ( m_nStatus != OK)
return nullptr ;
// se non è stato calcolato, lo calcolo
// se non è stato calcolato, lo calcolo
if ( m_pVoronoiObj == nullptr)
CalcVoronoiObject() ;
+6 -3
View File
@@ -146,7 +146,10 @@ class CurveLine : public ICurveLine, public IGeoObjRW
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
CurveLine( void) ;
@@ -158,12 +161,12 @@ class CurveLine : public ICurveLine, public IGeoObjRW
LOG_ERROR( GetEGkLogger(), "CurveLine : copy error")
return *this ; }
Voronoi* GetVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
private :
bool CopyFrom( const CurveLine& clSrc) ;
bool Validate( void) ;
bool CalcVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
bool CalcVoronoiObject( void) const ;
private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
@@ -175,7 +178,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW
Point3d m_PtEnd ; // punto finale
Vector3d m_VtExtr ; // vettore estrusione
double m_dThick ; // spessore
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp[2] ; // vettore proprietà temporanee
double m_dTempParam[2] ; // vettore parametri temporanei
mutable Voronoi* m_pVoronoiObj ; // Voronoi
} ;
BIN
View File
Binary file not shown.
+14
View File
@@ -309,14 +309,27 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="CurveByApprox.cpp" />
<ClCompile Include="CurveByInterp.cpp" />
<ClCompile Include="CurveCompositeOffset.cpp" />
<ClCompile Include="IntersCurveSurfTm.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="IntersLineVolZmap.cpp" />
<ClCompile Include="IntersPlaneVolZmap.cpp" />
<ClCompile Include="IntersLineSurfBez.cpp" />
<ClCompile Include="PolygonElevation.cpp" />
<ClCompile Include="SbzStandard.cpp" />
<ClCompile Include="Voronoi.cpp" />
<ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" />
<ClInclude Include="..\Include\EGkCDeConeFrustumClosedSurfTm.h" />
<ClInclude Include="..\Include\EGkCDeConvexTorusClosedSurfTm.h" />
<ClInclude Include="..\Include\EGkCDeRectPrismoidClosedSurfTm.h" />
<ClInclude Include="..\Include\EGkIntersCurveSurfTm.h" />
<ClInclude Include="..\Include\EGkIntersLineBox.h" />
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h" />
<ClInclude Include="..\Include\EGkIntersPlaneBox.h" />
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h" />
<ClInclude Include="..\Include\EGkPolygonElevation.h" />
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
<ClInclude Include="CDeBoxTria.h" />
@@ -449,6 +462,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="VolZmapGraphics.cpp" />
<ClCompile Include="VolZmapVolume.cpp" />
<ClCompile Include="VolZmap.cpp" />
<ClInclude Include="IntersLineSurfBez.h" />
<ClInclude Include="Voronoi.h" />
</ItemGroup>
<ItemGroup>
+56 -29
View File
@@ -43,15 +43,18 @@
<Filter Include="File di origine\GeoOffset">
<UniqueIdentifier>{f07670fd-9429-4b7e-ac6d-1c0022e756fb}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoCollision">
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoProject">
<UniqueIdentifier>{d96752da-1884-4a73-ba1b-5b20b606e469}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoElevation">
<UniqueIdentifier>{4c6a9dc5-8fac-4ecd-bde6-3e37e056712e}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoCollisionAvoid">
<UniqueIdentifier>{ae52e402-3063-45e3-b9f7-1710035a1f56}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoCollisionDetection">
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Vector3d.cpp">
@@ -273,6 +276,9 @@
<ClCompile Include="IntersLineSurfTm.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="IntersLineSurfBez.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="CircleCenTgCurve.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
@@ -372,17 +378,8 @@
<ClCompile Include="IntersLineSurfStd.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="CAvToolTriangle.cpp">
<Filter>File di origine\GeoCollision</Filter>
</ClCompile>
<ClCompile Include="CAvToolSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
</ClCompile>
<ClCompile Include="CDeBoxTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
</ClCompile>
<ClCompile Include="CAvSimpleSurfFrMove.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="IntersSurfTmSurfTm.cpp">
<Filter>File di origine\GeoInters</Filter>
@@ -400,19 +397,19 @@
<Filter>File di origine\Geo</Filter>
</ClCompile>
<ClCompile Include="CDeCylTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeBoxClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeCylClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeSpheTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeSpheClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="SurfBezier.cpp">
<Filter>File di origine\Geo</Filter>
@@ -430,34 +427,34 @@
<Filter>File di origine\GeoDist</Filter>
</ClCompile>
<ClCompile Include="CDeTriaTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeConeTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeUtility.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeClosedSurfTmClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeConeFrustumClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeConeFrustumTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeConvexTorusClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeConvexTorusTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeRectPrismoidClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeRectPrismoidTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="SurfTriMeshUtilities.cpp">
<Filter>File di origine\Geo</Filter>
@@ -469,7 +466,7 @@
<Filter>File di origine\Base</Filter>
</ClCompile>
<ClCompile Include="CDeCapsTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="Circle2P.cpp">
<Filter>File di origine\GeoCreate</Filter>
@@ -510,6 +507,27 @@
<ClCompile Include="PolygonElevation.cpp">
<Filter>File di origine\GeoElevation</Filter>
</ClCompile>
<ClCompile Include="IntersCurveSurfTm.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="CAvSimpleSurfFrMove.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="CAvToolSurfTm.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="CAvToolTriangle.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="IntersLineVolZmap.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="IntersPlaneVolZmap.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="SbzStandard.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@@ -1169,6 +1187,15 @@
<ClInclude Include="Voronoi.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkIntersCurveSurfTm.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc">
+124 -47
View File
@@ -21,6 +21,7 @@
#include "FontManager.h"
#include "FontAux.h"
#include "CurveArc.h"
#include "IntersLineLine.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkExtText.h"
#include "/EgtDev/Include/EGkUiUnits.h"
@@ -63,7 +64,7 @@ ExtDimension::~ExtDimension( void)
//----------------------------------------------------------------------------
bool
ExtDimension::SetStyle( double dExtLineLen, double dArrowLen, double dTextDist, bool bLenIsMM,
int nDecDigit, const string& sFont, double dTextHeight)
int nDecDigit, const string& sFont, double dTextHeight)
{
m_dExtLineLen = max( dExtLineLen, MIN_EXTLINELEN) ;
m_dArrowLen = max( dArrowLen, MIN_ARROWLEN) ;
@@ -200,7 +201,7 @@ ExtDimension::SetDiametral( const Point3d& ptCen, const Point3d& ptPos,
//----------------------------------------------------------------------------
bool
ExtDimension::SetAngular( const Point3d& ptP1, const Point3d& ptV, const Point3d& ptP2, const Point3d& ptPos,
ExtDimension::SetAngular( const Point3d& ptV, const Point3d& ptP1, const Point3d& ptP2, const Point3d& ptPos,
const Vector3d& vtN, const string& sText)
{
// dichiaro quota non ancora determinata
@@ -209,17 +210,16 @@ ExtDimension::SetAngular( const Point3d& ptP1, const Point3d& ptV, const Point3d
m_vtN = vtN ;
if ( ! m_vtN.Normalize())
return false ;
// porto i punti nel piano definito da P1 e N
m_ptP1 = ptP1 ;
m_ptP2 = ptP2 - ( ptP2 - m_ptP1) * m_vtN * m_vtN ;
m_ptP6 = ptV - ( ptV - m_ptP1) * m_vtN * m_vtN ;
m_ptPos = ptPos - ( ptPos - m_ptP1) * m_vtN * m_vtN ;
// verifico che i punti di misura non siano coincidenti
if ( AreSamePointApprox( m_ptP1, m_ptP2) || AreSamePointApprox( m_ptP1, m_ptP6) || AreSamePointApprox( m_ptP2, m_ptP5))
return false ;
// direzione di riferimento ( nel piano perpendicolare a vtN)
// porto i punti e le direzioni nel piano definito da V e N
m_ptP6 = ptV ;
m_ptPos = ptPos - ( ptPos - m_ptP6) * m_vtN * m_vtN ;
m_vtDir = m_ptPos - m_ptP6 ;
double dLenDir = m_vtDir.Len() ;
Vector3d vtLine1 = OrthoCompo( ptP1 - m_ptP6, m_vtN) ;
Vector3d vtLine2 = OrthoCompo( ptP2 - m_ptP6, m_vtN) ;
// verifico che i punti di misura non siano coincidenti
if ( ! vtLine1.Normalize() || ! vtLine2.Normalize() || dLenDir < EPS_SMALL)
return false ;
// controllo se è testo o se è la misura
double dFactor ;
@@ -243,20 +243,12 @@ ExtDimension::SetAngular( const Point3d& ptP1, const Point3d& ptV, const Point3d
m_vtDir = m_ptPos - m_ptP6 ;
dLenDir = m_vtDir.Len() ;
}
// calcolo le direzioni su cui giacciono i due lati dell'angolo
Vector3d vtLine1 = m_ptP1 - m_ptP6 ;
Vector3d vtLine2 = m_ptP2 - m_ptP6 ;
double dLen1 = vtLine1.Len() ;
double dLen2 = vtLine2.Len() ;
if ( ! vtLine1.Normalize() || ! vtLine2.Normalize())
return false ;
// segnalo se i punti che definiscono i lati sono più lontani dal centro di ptPos
bool bPt1Close = ( dLenDir < dLen1 ? true : false) ;
bool bPt2Close = ( dLenDir < dLen2 ? true : false) ;
m_ptP5 = m_ptP1 + ( dLenDir - dLen1) * vtLine1 ;
Point3d ptP5_bis = m_ptP2 + ( dLenDir - dLen2) * vtLine2 ;
m_ptP3 = m_ptP5 + ( bPt1Close ? - vtLine1 : vtLine1) * m_dExtLineLen ;
m_ptP4 = ptP5_bis + ( bPt2Close ? - vtLine2 : vtLine2) * m_dExtLineLen ;
// assegno gli altri punti notevoli della quotatura
m_ptP1 = m_ptP6 ;
m_ptP2 = m_ptP6 ;
m_ptP5 = m_ptP6 + vtLine1 * dLenDir ;
m_ptP3 = m_ptP6 + vtLine1 * ( dLenDir + m_dExtLineLen) ;
m_ptP4 = m_ptP6 + vtLine2 * ( dLenDir + m_dExtLineLen) ;
// assegnazione del testo
m_sText = sText ;
@@ -266,7 +258,84 @@ ExtDimension::SetAngular( const Point3d& ptP1, const Point3d& ptV, const Point3d
m_bToCalc = true ;
m_OGrMgr.Reset() ;
return true;
return true ;
}
//----------------------------------------------------------------------------
bool
ExtDimension::SetAngularEx( const Point3d& ptV1, const Point3d& ptP1,
const Point3d& ptV2, const Point3d& ptP2, const Point3d& ptPos,
const Vector3d& vtN, const string& sText)
{
// dichiaro quota non ancora determinata
m_nType = DT_NONE ;
// verifico la definizione del versore normale
m_vtN = vtN ;
if ( ! m_vtN.Normalize())
return false ;
// calcolo l'intersezione tra le due linee
CurveLine Line1 ;
if ( ! Line1.Set( ptV1, ptP1) || ! Line1.SetExtrusion( m_vtN))
return false ;
CurveLine Line2 ;
if ( ! Line2.Set( ptV2, ptP2) || ! Line2.SetExtrusion( m_vtN))
return false ;
IntersLineLine IntLL( Line1, Line2, false) ;
IntCrvCrvInfo Info ;
if ( ! IntLL.GetIntCrvCrvInfo( Info) || Info.bOverlap)
return false ;
Point3d ptV = Media( Info.IciA[0].ptI, Info.IciB[0].ptI) ;
// porto i punti e le direzioni nel piano definito da V1 e N
m_ptP6 = ptV ;
m_ptPos = ptPos - ( ptPos - m_ptP6) * m_vtN * m_vtN ;
m_vtDir = m_ptPos - m_ptP6 ;
double dLenDir = m_vtDir.Len() ;
Vector3d vtLine1 = OrthoCompo( ptP1 - m_ptP6, m_vtN) ;
Vector3d vtLine2 = OrthoCompo( ptP2 - m_ptP6, m_vtN) ;
// verifico che i punti di misura non siano coincidenti
if ( ! vtLine1.Normalize() || ! vtLine2.Normalize() || dLenDir < EPS_SMALL)
return false ;
// controllo se è testo o se è la misura
double dFactor ;
if ( m_sCalcText.find( IS_MEASURE) != string::npos) {
m_sCalcText = "300.00" ;
double dHalfDist = GetTextHalfDist( m_ptPos) ;
dFactor = 2.5 * dHalfDist ;
m_sCalcText = "" ;
}
else {
double dHalfDist = GetTextHalfDist( m_ptPos) ;
dFactor = 2.5 * dHalfDist ;
}
// allungo m_vtDir se è troppo vicino al centro
if ( m_vtDir.Len() < dFactor) {
Vector3d vtDir_n = m_vtDir ;
if ( ! vtDir_n.Normalize())
return false ;
m_ptPos = m_ptP6 + dFactor * vtDir_n ;
// ricalcolo m_vtDir
m_vtDir = m_ptPos - m_ptP6 ;
dLenDir = m_vtDir.Len() ;
}
// assegno gli altri punti notevoli della quotatura
m_ptP1 = ptV1 - ( ptV1 - m_ptP6) * m_vtN * m_vtN ;
m_ptP2 = ptV2 - ( ptV2 - m_ptP6) * m_vtN * m_vtN ;
m_ptP5 = m_ptP6 + vtLine1 * dLenDir ;
double dLen1 = Dist( m_ptP6, m_ptP1) ;
m_ptP3 = m_ptP6 + vtLine1 * ( dLenDir + m_dExtLineLen * ( dLen1 < dLenDir ? 1 : -1)) ;
double dLen2 = Dist( m_ptP6, m_ptP2) ;
m_ptP4 = m_ptP6 + vtLine2 * ( dLenDir + m_dExtLineLen * ( dLen2 < dLenDir ? 1 : -1)) ;
// assegnazione del testo
m_sText = sText ;
// assegno il tipo
m_nType = DT_ANGULAR ;
// imposto da calcolare
m_bToCalc = true ;
m_OGrMgr.Reset() ;
return true ;
}
//----------------------------------------------------------------------------
@@ -1012,6 +1081,7 @@ ExtDimension::Update( void) const
if ( ! GetTextMyBBox( b3Text) && ! b3Text.IsEmpty())
return false ;
double dHeight = b3Text.GetMax().y - b3Text.GetMin().y ;
double dLength = b3Text.GetMax().x - b3Text.GetMin().x ;
Vector3d vtPerpDir = m_ptPos - m_ptP6 ;
if ( ! vtPerpDir.Normalize())
return false ;
@@ -1020,11 +1090,11 @@ ExtDimension::Update( void) const
if ( ! frRef.Set( m_ptP6, m_vtN))
return false ;
double dAngDeg = 0 ;
if ( ! m_vtDir.GetAngle( frRef.VersX(), dAngDeg) || ! vtPerpDir.Rotate( m_vtN, ( dAngDeg < 90 ? 90 : -90)))
if ( ! m_vtDir.GetAngle( frRef.VersX(), dAngDeg) || ! vtPerpDir.Rotate( m_vtN, ( dAngDeg < 90 ? 90 : -90)))
return false ;
m_ptCalcPos = m_ptCalcPos + 0.6 * dHeight * vtPerpDir ;
// semidistanza di interruzione
double dHalfDist = GetTextHalfDist( m_ptCalcPos) ;
double dHalfDist = GetTextHalfDist( m_ptCalcPos, false) ;
// lunghezza della linea di misura
double dLen = Dist( m_ptP1, m_ptP2) ;
// determino come orientare le frecce e dove mettere il testo
@@ -1049,7 +1119,16 @@ ExtDimension::Update( void) const
Vector3d vtRad = m_ptPos - m_ptP5 ;
if ( ! vtRad.Normalize())
return false ;
m_ptCalcPos = m_ptPos + vtRad * ( dHalfDist + 2 * m_dArrowLen) ;
m_ptCalcPos = m_ptPos + vtRad * ( 2 * m_dArrowLen + m_dTextDist) ;
const double COMP_LIM = 0.1 ; // circa 5.7deg
if ( vtRad.x > COMP_LIM)
m_ptCalcPos += dLength / 2 * X_AX ;
else if ( vtRad.x < -COMP_LIM)
m_ptCalcPos -= dLength / 2 * X_AX ;
if ( vtRad.y > COMP_LIM)
m_ptCalcPos += dHeight / 2 * Y_AX ;
else if ( vtRad.y < -COMP_LIM)
m_ptCalcPos -= dHeight / 2 * Y_AX ;
}
// dichiaro ricalcolo eseguito
m_bToCalc = false ;
@@ -1058,8 +1137,8 @@ ExtDimension::Update( void) const
case DT_ANGULAR : {
// angolo
double dAngDeg, dAngDeg1, dAngDeg2 = 0 ;
Vector3d vtLine1 = m_ptP1 - m_ptP6 ;
Vector3d vtLine2 = m_ptP2 - m_ptP6 ;
Vector3d vtLine1 = m_ptP3 - m_ptP6 ;
Vector3d vtLine2 = m_ptP4 - m_ptP6 ;
Vector3d vtLine3 = m_ptPos - m_ptP6 ;
// calcolo gli angoli tra m_ptPos e i due punti che identificano i lati dell'angolo
// per capire se sto calcolando l'angolo interno o esterno
@@ -1074,10 +1153,9 @@ ExtDimension::Update( void) const
ReplaceString( m_sCalcText, IS_MEASURE, sAngDeg + "°") ;
}
// calcolo ptP5_bis
double dLen2 = vtLine2.Len() ;
if ( ! vtLine2.Normalize())
return false ;
Point3d ptP5_bis = m_ptP2 + ( m_vtDir.Len() - dLen2) * vtLine2 ;
Point3d ptP5_bis = m_ptP6 + m_vtDir.Len() * vtLine2 ;
// calcolo l'arco su cui metterò la misura
PtrOwner<CurveArc> pCrvPos( CreateBasicCurveArc()) ;
if ( IsNull( pCrvPos) || ! pCrvPos->Set3P( ptP5_bis, m_ptPos, m_ptP5, false))
@@ -1288,15 +1366,12 @@ ExtDimension::ApproxWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST&
if ( IsNull( pCrvPos))
return false ;
// calcolo ptP5_bis
Vector3d vtLine2 = m_ptP2 - m_ptP6 ;
double dLen2 = vtLine2.Len() ;
Vector3d vtLine2 = m_ptP4 - m_ptP6 ;
if ( ! vtLine2.Normalize())
return false ;
Point3d ptP5_bis = m_ptP2 + ( m_vtDir.Len() - dLen2) * vtLine2 ;
Point3d ptP5_bis = m_ptP6 + m_vtDir.Len() * vtLine2 ;
// approssimerò l'arco con una polyline
PolyLine plApprox ;
double dLinTol = 0.01 ;
double dAngTolDeg = 0.01 ;
// se non ho testo
if ( IsEmptyOrSpaces( m_sCalcText) || ! m_bCalcTextOn) {
if ( ! pCrvPos->SetC2PN( m_ptP6, ptP5_bis, m_ptP5, m_vtN) || ! pCrvPos->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_STD, plApprox))
@@ -1337,7 +1412,7 @@ ExtDimension::ApproxWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST&
dFactor = 0 ;
}
lstPL.emplace_back() ;
Vector3d vtLine1 = m_ptP1 - m_ptP6 ;
Vector3d vtLine1 = m_ptP3 - m_ptP6 ;
if ( ! vtLine1.Normalize())
return false ;
GetArrowHead( m_ptP5, ( m_bCalcArrowIn ? vtEndDir : - vtEndDir) + vtLine1 * dFactor, lstPL.back()) ;
@@ -1356,23 +1431,25 @@ ExtDimension::ApproxWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST&
//----------------------------------------------------------------------------
double
ExtDimension::GetTextHalfDist( const Point3d& ptText) const
ExtDimension::GetTextHalfDist( const Point3d& ptText, bool bUseRot) const
{
// semi distanza di interruzione
double dHalfDist = m_dTextHeight / 2 + m_dTextDist ;
// recupero il box di ingombro del testo
BBox3d b3Text ;
Vector3d vtDir = m_vtDir ;
if ( m_nType == DT_ANGULAR)
vtDir.Normalize() ;
if ( GetTextMyBBox( ptText, b3Text) && ! b3Text.IsEmpty()) {
double dHalfL = ( b3Text.GetMax().x - b3Text.GetMin().x) / 2 ;
double dHalfH = ( b3Text.GetMax().y - b3Text.GetMin().y) / 2 ;
dHalfDist = sqrt( dHalfL * dHalfL + dHalfH * dHalfH) ;
if ( abs( vtDir.x) > EPS_ZERO)
dHalfDist = min( dHalfDist, dHalfL / abs( vtDir.x)) ;
if ( abs( vtDir.y) > EPS_ZERO)
dHalfDist = min( dHalfDist, dHalfH / abs( vtDir.y)) ;
if ( bUseRot) {
Vector3d vtDir = m_vtDir ;
vtDir.Normalize() ;
double dCoeff = ( dHalfH > 1 ? dHalfL / dHalfH : 0) ;
if ( abs( vtDir.x) > dCoeff * abs( vtDir.y))
dHalfDist = min( dHalfDist, dHalfL / abs( vtDir.x)) ;
else
dHalfDist = min( dHalfDist, dHalfH / abs( vtDir.y)) ;
}
dHalfDist += m_dTextDist ;
}
return dHalfDist ;
+9 -3
View File
@@ -28,7 +28,7 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
ExtDimension* Clone( void) const override ;
GeoObjType GetType( void) const override ;
bool IsValid( void) const override
{ return ( m_nType != DT_NONE) ; }
{ return ( m_nType != DT_NONE) ; }
const std::string& GetTitle( void) const override ;
bool Dump( std::string& sOut, bool bMM = true, const char* szNewLine = "\n") const override ;
bool GetLocalBBox( BBox3d& b3Loc, int nFlag = BBF_STANDARD) const override ;
@@ -71,8 +71,11 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
const Vector3d& vtN, const std::string& sText) override ;
bool SetDiametral( const Point3d& ptCen, const Point3d& ptPos,
const Vector3d& vtN, const std::string& sText) override ;
bool SetAngular( const Point3d& ptP1, const Point3d& ptV, const Point3d& ptP2, const Point3d& ptPos,
bool SetAngular( const Point3d& ptV, const Point3d& ptP1, const Point3d& ptP2, const Point3d& ptPos,
const Vector3d& vtN, const std::string& sText) override ;
bool SetAngularEx( const Point3d& ptV1, const Point3d& ptP1,
const Point3d& ptV2, const Point3d& ptP2, const Point3d& ptPos,
const Vector3d& vtN, const std::string& sText) override ;
const Vector3d& GetNormVersor( void) const override
{ return m_vtN ; }
const Vector3d& GetDirVersor( void) const override
@@ -110,7 +113,10 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
ExtDimension( void) ;
@@ -126,7 +132,7 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
bool CopyFrom( const ExtDimension& gpSrc) ;
const std::string& GetSubType( void) const ;
bool Update( void) const ;
double GetTextHalfDist( const Point3d& ptText) const ;
double GetTextHalfDist( const Point3d& ptText, bool bUseRot = true) const ;
bool GetArrowHead( const Point3d& ptTip, const Vector3d& vtDir, PolyLine& PL) const ;
bool SetCurrFont( FontManager& fntMgr) const ;
bool ApproxTextWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST& lstPL) const ;
+3
View File
@@ -113,7 +113,10 @@ class ExtText : public IExtText, public IGeoObjRW
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
ExtText( void) ;
+1 -1
View File
@@ -3073,7 +3073,7 @@ GdbExecutor::VolZmapBBoxZmapIntersection( const STRVECTOR& vsParams)
return false ;
bool bInt ;
bInt = ! pZmap->AvoidBox( frBBoxFrame, ptEnd - ORIG) ;
bInt = pZmap->CDeBox( frBBoxFrame, ptEnd - ORIG) ;
return true ;
}*/
+10 -2
View File
@@ -101,6 +101,10 @@ GdbGeo::Save( int nBaseId, NgeWriter& ngeOut, INTUNORDSET* pSavedIds) const
if ( pGObjRW == nullptr)
return false ;
// eventuali modifiche prima del salvataggio
if ( ! pGObjRW->PreSave( * const_cast<GdbGeo*>( this)))
return false ;
// tipo entità e identificativi
if ( ! ngeOut.WriteKey( pGObjRW->GetNgeId()))
return false ;
@@ -124,7 +128,11 @@ GdbGeo::Save( int nBaseId, NgeWriter& ngeOut, INTUNORDSET* pSavedIds) const
// parametri geometrici
if ( ! ngeOut.WriteKey( NGE_G))
return false ;
return pGObjRW->Save( ngeOut) ;
if ( ! pGObjRW->Save( ngeOut))
return false ;
// eventuali ripristini dopo il salvataggio
return pGObjRW->PostSave( * const_cast<GdbGeo*>( this)) ;
}
//----------------------------------------------------------------------------
@@ -181,7 +189,7 @@ GdbGeo::Load( int nNgeId, NgeReader& ngeIn, int nBaseGdbId, int& nParentId)
// parametri geometrici
IGeoObjRW* pGObjRW = dynamic_cast<IGeoObjRW*>( m_pGeoObj) ;
return ( pGObjRW != nullptr && pGObjRW->Load( ngeIn)) ;
return ( pGObjRW != nullptr && pGObjRW->Load( ngeIn) && pGObjRW->PostLoad( *this)) ;
}
//----------------------------------------------------------------------------
+3
View File
@@ -83,7 +83,10 @@ class GeoFrame3d : public IGeoFrame3d, public IGeoObjRW
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
GeoFrame3d( void) ;
+7 -3
View File
@@ -1,13 +1,13 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
// EgalTech 2014-2024
//----------------------------------------------------------------------------
// File : GeoObjRW.h Data : 14.03.14 Versione : 1.5d5
// File : GeoObjRW.h Data : 08.03.24 Versione : 2.6c2
// Contenuto : Dichiarazione della interfaccia IGeoObjRW.
//
//
//
// Modifiche : 20.11.13 DS Creazione modulo.
//
// 08.03.24 DS Aggiunte PreSave, PostSave, PreLoad e PostLoad.
//
//----------------------------------------------------------------------------
@@ -15,6 +15,7 @@
class NgeWriter ;
class NgeReader ;
class GdbGeo ;
//-----------------------------------------------------------------------------
class __declspec( novtable) IGeoObjRW
@@ -22,5 +23,8 @@ class __declspec( novtable) IGeoObjRW
public :
virtual int GetNgeId( void) const = 0 ;
virtual bool Save( NgeWriter& ngeOut) const = 0 ;
virtual bool PreSave( GdbGeo& Wrapper) const = 0 ;
virtual bool PostSave( GdbGeo& Wrapper) const = 0 ;
virtual bool Load( NgeReader& ngeIn) = 0 ;
virtual bool PostLoad( GdbGeo& Wrapper) = 0 ;
} ;
+3
View File
@@ -77,7 +77,10 @@ class GeoPoint3d : public IGeoPoint3d, public IGeoObjRW
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
GeoPoint3d( void) ;
+3
View File
@@ -91,7 +91,10 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
GeoVector3d( void) ;
+223
View File
@@ -0,0 +1,223 @@
//----------------------------------------------------------------------------
// EgalTech 2024-2024
//----------------------------------------------------------------------------
// File : IntersCurveSurfTm.cpp Data : 23.02.24 Versione : 2.6b4
// Contenuto : Implementazione della intersezione curva/superficie trimesh.
//
//
//
// Modifiche : 23.02.24 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersCurveSurfTm.h"
using namespace std ;
//----------------------------------------------------------------------------
static void
UpdateInfoIntersCurveSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen, double dUs, double dUe,
int nT, const Triangle3d& Tria, ICSIVECTOR& vInfo)
{
Point3d ptInt, ptInt2 ;
int nRes = IntersLineTria( ptL, vtDir, dLen, Tria, ptInt, ptInt2, true) ;
if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) {
double dU = dUs + ( ptInt - ptL) * vtDir / dLen * ( dUe - dUs) ;
double dCosDN = vtDir * Tria.GetN() ;
vInfo.emplace_back( nRes, dU, nT, dCosDN, ptInt) ;
}
else if ( nRes == ILTT_SEGM || nRes == ILTT_SEGM_ON_EDGE) {
double dU = dUs + ( ptInt - ptL) * vtDir / dLen * ( dUe - dUs) ;
double dU2 = dUs + ( ptInt2 - ptL) * vtDir / dLen * ( dUe - dUs) ;
double dCosDN = vtDir * Tria.GetN() ;
vInfo.emplace_back( nRes, dU, dU2, nT, dCosDN, ptInt, ptInt2) ;
}
}
//----------------------------------------------------------------------------
static void
OrderInfoIntersCurveSurfTm( ICSIVECTOR& vInfo)
{
// se non trovati, esco
if ( vInfo.size() == 0)
return ;
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(),
[]( const IntCrvStmInfo& a, const IntCrvStmInfo& b)
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
return ( dUa < dUb) ; }) ;
}
//----------------------------------------------------------------------------
// Intersezione di una curva con una superficie TriMesh
//----------------------------------------------------------------------------
bool
IntersCurveSurfTm( const ICurve& Curve, const ISurfTriMesh& Stm, double dLinTol, ICSIVECTOR& vInfo)
{
// verifico i parametri ricevuti
if ( & Curve == nullptr || &Stm == nullptr || &vInfo == nullptr)
return false ;
dLinTol = max( dLinTol, EPS_SMALL) ;
vInfo.clear() ;
// approssimo la curva con una spezzata
PolyLine PL ;
if ( ! Curve.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_SPECIAL, PL))
return false ;
// per ogni segmento dell'approssimante cerco l'intersezione con la superficie
double dParS, dParE ;
Point3d ptStart, ptEnd ;
bool bFound = PL.GetFirstULine( &dParS, &ptStart, &dParE, &ptEnd) ;
while ( bFound) {
Vector3d vtDir = ptEnd - ptStart ;
double dLen = vtDir.Len() ;
if ( dLen > EPS_SMALL) {
vtDir /= dLen ;
// cerco i triangoli intersecati dal segmento
const double BOX_STEP = 10 ;
int nStep = int( ceil( dLen / BOX_STEP)) ;
Vector3d vtStep = dLen / nStep * vtDir ;
INTVECTOR vPrevT ;
for ( int i = 0 ; i < nStep ; ++ i) {
BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ;
INTVECTOR vT ;
if ( Stm.GetAllTriaOverlapBox( b3Box, vT)) {
for ( auto nT : vT) {
// se triangolo non ancora intersecato
if ( find( vPrevT.begin(), vPrevT.end(), nT) == vPrevT.end()) {
vPrevT.emplace_back( nT) ;
Triangle3d Tria ;
Stm.GetTriangle( nT, Tria) ;
// aggiorno info con intersezione
UpdateInfoIntersCurveSurfTm( ptStart, vtDir, dLen, dParS, dParE, nT, Tria, vInfo) ;
}
}
}
}
}
// passo al segmento successivo
bFound = PL.GetNextULine( &dParS, &ptStart, &dParE, &ptEnd) ;
}
// ordino il vettore delle eventuali intersezioni secondo il senso crescente del parametro di linea
OrderInfoIntersCurveSurfTm( vInfo) ;
return true ;
}
//----------------------------------------------------------------------------
bool
IntersCurveSurfTmExt( const ICurve& Curve, const ISurfTriMesh& Stm, double dLinTol, INTDBLVECTOR& vInters)
{
ICSIVECTOR vInfo ;
vInters.clear() ;
return ( IntersCurveSurfTm( Curve, Stm, dLinTol, vInfo) && FilterCurveSurfTmInters( Curve, vInfo, vInters)) ;
}
//----------------------------------------------------------------------------
bool
FilterCurveSurfTmInters( const ICurve& Curve, const ICSIVECTOR& vInfo, INTDBLVECTOR& vInters)
{
// verifico i parametri ricevuti
if ( & Curve == nullptr || &vInfo == nullptr || &vInters == nullptr)
return false ;
vInters.clear() ;
// info sulla curva
bool bClosedCrv = Curve.IsClosed() ;
double dParSCrv, dParECrv ;
Curve.GetDomain( dParSCrv, dParECrv) ;
// ciclo sulle intersezioni
for ( const auto& Info : vInfo) {
// se intersezione puntuale
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
int nFlag = CSIT_NONE ;
if ( Info.dCosDN > EPS_ZERO)
nFlag = CSIT_IN_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = CSIT_OUT_IN ;
vInters.emplace_back( nFlag, Info.dU) ;
}
// se altrimenti intersezione con coincidenza
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
vInters.emplace_back( CSIT_IN_ON, Info.dU) ;
vInters.emplace_back( CSIT_ON_IN, Info.dU2) ;
}
}
// elimino intersezioni ripetute
int nStart = ( bClosedCrv ? 0 : 1) ;
for ( int j = nStart ; j < int( vInters.size()) ; ) {
// intersezione precedente
int i = ( j > 0 ? j - 1 : int( vInters.size()) - 1) ;
// se hanno lo stesso parametro
if ( abs( vInters[i].second - vInters[j].second) < EPS_PARAM ||
( bClosedCrv && abs( vInters[i].second - dParECrv) < EPS_PARAM && abs( vInters[j].second - dParSCrv) < EPS_PARAM)) {
// flag per eseguita cancellazione
bool bSomeErased = false ;
// se sono entrambe entranti o uscenti, elimino la seconda
if ( ( vInters[i].first == CSIT_OUT_IN && vInters[j].first == CSIT_OUT_IN) ||
( vInters[i].first == CSIT_IN_OUT && vInters[j].first == CSIT_IN_OUT)) {
vInters.erase( vInters.begin() + j) ;
bSomeErased = true ;
}
// se una entrante e l'altra uscente, cambio in touch da fuori ed elimino la seconda
else if ( vInters[i].first == CSIT_OUT_IN && vInters[j].first == CSIT_IN_OUT) {
vInters[i].first = CSIT_OUT_OUT ;
vInters.erase( vInters.begin() + j) ;
bSomeErased = true ;
}
// se una uscente e l'altra entrante, cambio in touch da dentro ed elimino la seconda
else if ( vInters[i].first == CSIT_IN_OUT && vInters[j].first == CSIT_OUT_IN) {
vInters[i].first = CSIT_IN_IN ;
vInters.erase( vInters.begin() + j) ;
bSomeErased = true ;
}
// se una touch da fuori o da dentro e l'altra entrante o uscente, elimino la prima
else if ( ( vInters[i].first == CSIT_OUT_OUT || vInters[i].first == CSIT_IN_IN) &&
( vInters[j].first == CSIT_OUT_IN || vInters[j].first == CSIT_IN_OUT)) {
vInters.erase( vInters.begin() + i) ;
bSomeErased = true ;
}
// se una entrante o uscente e l'altra touch da fuori o da dentro, elimino la seconda
else if ( ( vInters[i].first == CSIT_OUT_IN || vInters[i].first == CSIT_IN_OUT) &&
( vInters[j].first == CSIT_OUT_OUT || vInters[j].first == CSIT_IN_IN)) {
vInters.erase( vInters.begin() + j) ;
bSomeErased = true ;
}
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
else if ( ( vInters[i].first == CSIT_OUT_IN || vInters[i].first == CSIT_IN_OUT || vInters[i].first == CSIT_NONE) &&
( vInters[j].first == CSIT_IN_ON || vInters[j].first == CSIT_OUT_ON)) {
vInters[j].first = ( vInters[i].first == CSIT_IN_OUT ? CSIT_IN_ON : CSIT_OUT_ON) ;
vInters.erase( vInters.begin() + i) ;
bSomeErased = true ;
}
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
else if ( ( vInters[i].first == CSIT_ON_IN || vInters[i].first == CSIT_ON_OUT) &&
( vInters[j].first == CSIT_OUT_IN || vInters[j].first == CSIT_IN_OUT || vInters[j].first == CSIT_NONE)) {
vInters[i].first = ( vInters[j].first == CSIT_IN_OUT ? CSIT_ON_OUT : CSIT_ON_IN) ;
vInters.erase( vInters.begin() + j) ;
bSomeErased = true ;
}
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
else if ( ( vInters[i].first == CSIT_ON_IN || vInters[i].first == CSIT_ON_OUT) &&
( vInters[j].first == CSIT_IN_ON || vInters[j].first == CSIT_OUT_ON)) {
vInters.erase( vInters.begin() + j) ;
vInters.erase( vInters.begin() + ( j > 0 ? i : i - 1)) ;
bSomeErased = true ;
}
if ( bSomeErased) {
if ( j > 0)
-- j ;
continue ;
}
}
// passo alla successiva
++ j ;
}
return true ;
}
+1 -1
View File
@@ -22,7 +22,7 @@ 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.
// In caso di intersezione viene restituito true e i parametri lunghezza in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
+1 -1
View File
@@ -17,7 +17,7 @@
//----------------------------------------------------------------------------
// Linea e box allineato agli assi sono nel medesimo riferimento.
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
// Con intersezione viene restituito true e i parametri lunghezza in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
+2 -2
View File
@@ -57,7 +57,7 @@ IntersLineLine::IntersLineLine( const CurveLine& Line1, const CurveLine& Line2,
//----------------------------------------------------------------------------
void
IntersLineLine::IntersInfiniteLines( const ICurveLine& Line1, const ICurveLine& Line2)
IntersLineLine::IntersInfiniteLines( const CurveLine& Line1, const CurveLine& Line2)
{
// linea 1 : Start, End, Direzione e Lunghezza
Point3d ptS1 = Line1.GetStart() ;
@@ -118,7 +118,7 @@ IntersLineLine::IntersInfiniteLines( const ICurveLine& Line1, const ICurveLine&
//----------------------------------------------------------------------------
void
IntersLineLine::IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Line2)
IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line2)
{
// verifico sovrapposizione box
BBox3d boxL1 ;
+2 -2
View File
@@ -38,8 +38,8 @@ class IntersLineLine
private :
IntersLineLine( void) ;
void IntersInfiniteLines( const ICurveLine& Line1, const ICurveLine& Line2) ;
void IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Line2) ;
void IntersInfiniteLines( const CurveLine& Line1, const CurveLine& Line2) ;
void IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line2) ;
private :
bool m_bOverlaps ;
+260
View File
@@ -0,0 +1,260 @@
//----------------------------------------------------------------------------
// EgalTech 2024
//----------------------------------------------------------------------------
// File : IntersLineSurfBez.cpp Data : 06.02.24 Versione : 2.6b1
// Contenuto : Implementazione della intersezione linea/superficie bezier.
//
//
//
// Modifiche : 06.02.24 DB Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkIntersLineSurfBez.h"
#include "/EgtDev/Include/EGkSurfBezier.h"
#include "DistPointLine.h"
#include "CurveLine.h"
using namespace std ;
//----------------------
bool
RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool bFinite,
const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz) {
// la funzione raffina la posisione del punto ptSP, minimizzando la distanza dalla retta e restituisce il punto di intersezione ptIBz
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
// usando un algoritmo di newton cerco di avvicinarmi il più possibile alla retta
DistPointLine dpl( ptIBz, ptL, vtL, dLen, bFinite) ;
double dDistNew = 0, dDistPre = 0 ;
dpl.GetDist(dDistNew) ;
int nCount = 0 ;
double dh = EPS_SMALL ;
pSurfBz->GetPointD1D2( ptSP.x, ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
// metodo di newton in più dimensioni
// vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi.
while ( dDistNew > EPS_SMALL && nCount < 100) {
dDistPre = dDistNew ;
Point3d ptIBzNew1 ;
pSurfBz->GetPointD1D2( ( ptSP.x + dh) / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ;
DistPointLine dplNewU( ptIBzNew1, ptL, vtL, dLen, bFinite) ;
dplNewU.GetDist( dDistNew) ;
double dfdU = ( dDistNew - dDistPre) / dh ;
Point3d ptIBzNew2 ;
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ( ptSP.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ;
DistPointLine dplNewV( ptIBzNew2, ptL, vtL, dLen, bFinite) ;
dplNewV.GetDist( dDistNew) ;
double dfdV = ( dDistNew - dDistPre) / dh ;
//// opzione 0
////scelgo h1 e h2 separatamente e in modo da annullare f(x)
//// opzione 1
//// valore fisso
//double dr = EPS_SMALL ;
//if ( dDistPre > 1)
// dr = 1 ;
//else if ( dDistPre > 0.1)
// dr = 0.1 ;
//else if ( dDistPre > 0.01)
// dr = 0.01 ;
//// opzione 2
//// valore direttamente vincolato
//double dr = dDistPre ;
//// opzione 3
//// valuto la deformazione locale in base allo spostamento del punto sulla bezier // non serve
//double dh1 = Dist( ptIBz, ptIBzNew1) ;
//double dh2 = Dist( ptIBz, ptIBzNew2) ;
// potrei valutare il nuovo spostamento in base all'ultima variazione di dDist
// potrei anche vedere se sto uscendo dal triangolo ( definito nello spazio parametrico)
// mi avvicino cercando di annullare la distanza in un colpo solo
double dr = - dDistPre / ( dfdU + dfdV) ;
pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptSP.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
DistPointLine dplNew( ptIBz, ptL, vtL, dLen, bFinite) ;
dplNew.GetDist( dDistNew) ;
++nCount ;
}
return nCount != 99 ;
}
////----------------------------------------------------------------------------
//bool
//RefineIntersBisec( const Point3d& ptL, const Vector3d& vtL, double dLen, bool bFinite,
// const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz) {
//
//}
//----------------------------------------------------------------------------
void
UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos,
const Point3d& ptSP2, const Point3d& ptIBz2, double dCos2, ILSBIVECTOR& vInfo)
{
if ( nILT == ILTT_IN || nILT == ILTT_EDGE || nILT == ILTT_VERT) {
double dU = ( ptIBz - ptL) * vtDir ;
vInfo.emplace_back( nILT, dU, nT, dCos, ptIBz, ptSP) ;
}
else if ( nILT == ILTT_SEGM || nILT == ILTT_SEGM_ON_EDGE) {
double dU = ( ptIBz - ptL) * vtDir ;
double dU2 = ( ptIBz2 - ptL) * vtDir ;
vInfo.emplace_back( nILT, dU, dU2, nT, dCos2, ptIBz, ptIBz2, ptSP, ptSP2) ;
}
}
//----------------------------------------------------------------------------
void
OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
{
// se non trovati, esco
if ( vInfo.size() == 0)
return ;
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(),
[]( const IntLinSbzInfo& a, const IntLinSbzInfo& b)
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
return ( dUa < dUb) ; }) ;
}
//----------------------------------------------------------------------------
// Intersezione di una linea con una superficie TriMesh
//----------------------------------------------------------------------------
bool
IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
ILSBIVECTOR& vInfo, bool bFinite)
{
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ;
if ( bFinite)
pCL->SetPVL(ptL, vtL, dLen) ;
else
pCL->SetPVL(ptL, vtL, 1e6) ;
// verifico linea
Vector3d vtDir = vtL ;
if ( ! vtDir.Normalize( EPS_ZERO))
return false ;
// verifico superficie
if ( pSurfBz == nullptr)
return false ;
// verifico parametro di ritorno
if ( &vInfo == nullptr)
return false ;
vInfo.clear() ;
// trovo le intersezioni con la trimesh ausiliaria
const ISurfTriMesh* pSurfTm = pSurfBz->GetAuxSurf() ;
ILSIVECTOR vInfoTm ;
if ( ! IntersLineSurfTm( ptL, vtL, dLen, *pSurfTm, vInfoTm, bFinite))
return false ;
// ricavo le intersezioni con la superficie di Bezier
for ( IntLinStmInfo InfoTm : vInfoTm ) {
// devo raffinare i parametri lungo la curva, l'angolo e i punti di intersezione
Point3d ptI, ptI2 ;
// devo trovare le intersezioni
Point3d ptSP, ptSP2 ; // coordinate parametriche delle soluzioni
pSurfBz->UnprojectPointFromStm( InfoTm.nT, InfoTm.ptI, ptSP, InfoTm.nILTT) ;
Point3d ptIBz, ptIBz2 ;
if ( ! RefineIntersNewton( ptL, vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz)) {
/////// posso provare anche a rilanciare newton con un punto di partenza diverso oppure con una direzione di avvicinamento diversa///////////////////////////////////
// per restare nel triangolo mi sposto verso un vertice
int nVert[3] ;
pSurfTm->GetTriangle( InfoTm.nT, nVert) ;
double dU0, dV0 ;
pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ;
ptSP = ptSP + Point3d(dU0, dV0, 0) ;
if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz))
return false ;
}
Vector3d vtN ;
pSurfBz->GetPointNrmD1D2(ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ;
double dCos = vtN * vtL ;
double dCos2 = 0 ;
// eventualmente ripeto tutto per ptI2 ( se ho un'intersezione con sovrapposizione)
if ( InfoTm.nILTT == ILTT_SEGM || InfoTm.nILTT == ILTT_SEGM_ON_EDGE ) {
pSurfBz->UnprojectPointFromStm( InfoTm.nT, InfoTm.ptI2, ptSP2, InfoTm.nILTT) ;
if ( ! RefineIntersNewton(ptL, vtL, dLen, bFinite, pSurfBz, ptSP2, ptIBz2) ) {
int nVert[3] ;
pSurfTm->GetTriangle( InfoTm.nT, nVert) ;
double dU0, dV0 ;
pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ;
ptSP = ptSP + Point3d(dU0, dV0, 0) ;
if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz))
return false ;
}
pSurfBz->GetPointNrmD1D2( ptSP2.x / SBZ_TREG_COEFF, ptSP2.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ;
dCos2 = vtN * vtL ;
}
UpdateInfoIntersLineSurfBz( ptL, vtL, InfoTm.nILTT, InfoTm.nT, ptSP, ptIBz, dCos, ptSP2, ptIBz2, dCos2, vInfo) ;
}
OrderInfoIntersLineSurfBz( vInfo) ;
return true ;
}
//----------------------------------------------------------------------------
bool
FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
{
// tengo per buone la classificazione delle intersezioni fatte sulla trimesh
// ciclo sulle intersezioni
for ( const auto& Info : vInfo) {
// se intersezione puntuale
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
int nFlag = LSBT_TOUCH ;
if ( Info.dCosDN > EPS_ZERO)
nFlag = LSBT_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = LSBT_IN ;
vInters.emplace_back( nFlag, Info.dU) ;
}
// se altrimenti intersezione con coincidenza
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
vInters.emplace_back( LSBT_TG_INI, Info.dU) ;
vInters.emplace_back( LSBT_TG_FIN, Info.dU2) ;
}
}
// elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) {
// intersezione precedente
size_t i = j - 1 ;
// se hanno lo stesso parametro
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
// se sono entrambe entranti o uscenti, elimino la seconda
if ( ( vInters[i].first == LSBT_IN && vInters[j].first == LSBT_IN) ||
( vInters[i].first == LSBT_OUT && vInters[j].first == LSBT_OUT)) {
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
else if ( ( vInters[i].first == LSBT_IN && vInters[j].first == LSBT_OUT) ||
( vInters[i].first == LSBT_OUT && vInters[j].first == LSBT_IN)) {
vInters[i].first = LSBT_TOUCH ;
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
else if ( ( vInters[i].first == LSBT_IN || vInters[i].first == LSBT_OUT || vInters[i].first == LSBT_TOUCH) && vInters[j].first == LSBT_TG_INI) {
vInters.erase( vInters.begin() + i) ;
continue ;
}
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
else if ( vInters[i].first == LSBT_TG_FIN && ( vInters[j].first == LSBT_IN || vInters[j].first == LSBT_OUT || vInters[j].first == LSBT_TOUCH)) {
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
else if ( i > 0 && vInters[i].first == LSBT_TG_FIN && vInters[j].first == LSBT_TG_INI) {
vInters.erase( vInters.begin() + j) ;
vInters.erase( vInters.begin() + i) ;
-- j ;
continue ;
}
}
// passo alla successiva
++ j ;
}
return true ;
}
+1
View File
@@ -0,0 +1 @@
#pragma once
+70 -5
View File
@@ -21,7 +21,7 @@
using namespace std ;
//----------------------------------------------------------------------------
void
static void
UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen,
int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite)
{
@@ -41,7 +41,7 @@ UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dL
}
//----------------------------------------------------------------------------
void
static void
OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
{
// se non trovati, esco
@@ -81,7 +81,7 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
// lo ingrandisco per non avere problemi con faccia piana su piani canonici
b3Stm.Expand( 10 * EPS_SMALL) ;
double dU1, dU2 ;
if ( ! IntersLineBox( ptL, vtL, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2))
if ( ! IntersLineBox( ptL, vtDir, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2))
return true ;
if ( bFinite) {
dU1 = max( dU1, 0.) ;
@@ -89,12 +89,12 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
if ( dU2 - dU1 < EPS_SMALL)
return true ;
}
Point3d ptStart = ptL + dU1 * vtL ;
Point3d ptStart = ptL + dU1 * vtDir ;
double dLenEff = dU2 - dU1 ;
// cerco i triangoli intersecati dalla linea
const double BOX_STEP = 10 ;
int nStep = int( ceil( dLenEff / BOX_STEP)) ;
Vector3d vtStep = dLenEff / nStep * vtL ;
Vector3d vtStep = dLenEff / nStep * vtDir ;
INTVECTOR vPrevT ;
for ( int i = 0 ; i < nStep ; ++ i) {
BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ;
@@ -189,3 +189,68 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
return true ;
}
//----------------------------------------------------------------------------
bool
FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters)
{
// ciclo sulle intersezioni
for ( const auto& Info : vInfo) {
// se intersezione puntuale
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
int nFlag = LST_TOUCH ;
if ( Info.dCosDN > EPS_ZERO)
nFlag = LST_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = LST_IN ;
vInters.emplace_back( nFlag, Info.dU) ;
}
// se altrimenti intersezione con coincidenza
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
vInters.emplace_back( LST_TG_INI, Info.dU) ;
vInters.emplace_back( LST_TG_FIN, Info.dU2) ;
}
}
// elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) {
// intersezione precedente
size_t i = j - 1 ;
// se hanno lo stesso parametro
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
// se sono entrambe entranti o uscenti, elimino la seconda
if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_IN) ||
( vInters[i].first == LST_OUT && vInters[j].first == LST_OUT)) {
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
else if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_OUT) ||
( vInters[i].first == LST_OUT && vInters[j].first == LST_IN)) {
vInters[i].first = LST_TOUCH ;
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
else if ( ( vInters[i].first == LST_IN || vInters[i].first == LST_OUT || vInters[i].first == LST_TOUCH) && vInters[j].first == LST_TG_INI) {
vInters.erase( vInters.begin() + i) ;
continue ;
}
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
else if ( vInters[i].first == LST_TG_FIN && ( vInters[j].first == LST_IN || vInters[j].first == LST_OUT || vInters[j].first == LST_TOUCH)) {
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
else if ( i > 0 && vInters[i].first == LST_TG_FIN && vInters[j].first == LST_TG_INI) {
vInters.erase( vInters.begin() + j) ;
vInters.erase( vInters.begin() + i) ;
-- j ;
continue ;
}
}
// passo alla successiva
++ j ;
}
return true ;
}
+106
View File
@@ -0,0 +1,106 @@
//----------------------------------------------------------------------------
// EgalTech 2024-2024
//----------------------------------------------------------------------------
// File : IntersLineVolZmap.cpp Data : 22.02.24 Versione : 2.6b4
// Contenuto : Implementazione della intersezione linea/VolZmap.
//
//
//
// Modifiche : 22.02.24 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "VolZmap.h"
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
using namespace std ;
//----------------------------------------------------------------------------
// Intersezione di una linea con la superficie di un solido VolZmap
//----------------------------------------------------------------------------
bool
IntersLineVolZmap( const Point3d& ptL, const Vector3d& vtL, const IVolZmap& Vzm, ILZIVECTOR& vInfo)
{
// verifico linea
Vector3d vtDir = vtL ;
if ( ! vtDir.Normalize( EPS_ZERO))
return false ;
// verifico volume
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
if ( pVzm == nullptr)
return false ;
// verifico parametro di ritorno
if ( &vInfo == nullptr)
return false ;
// eseguo intersezione
return pVzm->GetLineIntersection( ptL, vtL, vInfo) ;
}
//----------------------------------------------------------------------------
bool
FilterLineVolZmapInters( const ILZIVECTOR& vInfo, INTDBLVECTOR& vInters)
{
// ciclo sulle intersezioni
for ( const auto& Info : vInfo) {
// se intersezione puntuale
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
int nFlag = LZT_TOUCH ;
if ( Info.dCosDN > EPS_ZERO)
nFlag = LZT_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = LZT_IN ;
vInters.emplace_back( nFlag, Info.dU) ;
}
// se altrimenti intersezione con coincidenza
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
vInters.emplace_back( LZT_TG_INI, Info.dU) ;
vInters.emplace_back( LZT_TG_FIN, Info.dU2) ;
}
}
// elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) {
// intersezione precedente
size_t i = j - 1 ;
// se hanno lo stesso parametro
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
// se sono entrambe entranti o uscenti, elimino la seconda
if ( ( vInters[i].first == LZT_IN && vInters[j].first == LZT_IN) ||
( vInters[i].first == LZT_OUT && vInters[j].first == LZT_OUT)) {
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
else if ( ( vInters[i].first == LZT_IN && vInters[j].first == LZT_OUT) ||
( vInters[i].first == LZT_OUT && vInters[j].first == LZT_IN)) {
vInters[i].first = LZT_TOUCH ;
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
else if ( ( vInters[i].first == LZT_IN || vInters[i].first == LZT_OUT || vInters[i].first == LZT_TOUCH) && vInters[j].first == LZT_TG_INI) {
vInters.erase( vInters.begin() + i) ;
continue ;
}
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
else if ( vInters[i].first == LZT_TG_FIN && ( vInters[j].first == LZT_IN || vInters[j].first == LZT_OUT || vInters[j].first == LZT_TOUCH)) {
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
else if ( i > 0 && vInters[i].first == LZT_TG_FIN && vInters[j].first == LZT_TG_INI) {
vInters.erase( vInters.begin() + j) ;
vInters.erase( vInters.begin() + i) ;
-- j ;
continue ;
}
}
// passo alla successiva
++ j ;
}
return true ;
}
+37
View File
@@ -0,0 +1,37 @@
//----------------------------------------------------------------------------
// EgalTech 2024-2024
//----------------------------------------------------------------------------
// File : IntersPlaneVolZmap.cpp Data : 22.02.24 Versione : 2.6b4
// Contenuto : Implementazione della intersezione piano/VolZmap.
//
//
//
// Modifiche : 22.02.24 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "VolZmap.h"
#include "/EgtDev/Include/EGkIntersPlaneVolZmap.h"
using namespace std ;
//----------------------------------------------------------------------------
// Intersezione di unpiano con la superficie di un solido VolZmap
//----------------------------------------------------------------------------
bool
IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR& vpLoop)
{
// verifico volume
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
if ( pVzm == nullptr)
return false ;
// verifico parametro di ritorno
if ( &vpLoop == nullptr)
return false ;
// eseguo intersezione
return pVzm->GetPlaneIntersection( plPlane, vpLoop) ;
}
+3 -3
View File
@@ -119,12 +119,12 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p
Point3d ptSt1, ptEn1 ;
int nRes1 = IntersCoplanarLineTria( ptL, vtL, 100.0, trTria1, ptSt1, ptEn1, false) ;
// limito la liena di intersezione con il secondo triangolo
// limito la linea di intersezione con il secondo triangolo
Point3d ptSt2, ptEn2 ;
int nRes2 = IntersCoplanarLineTria( ptL, vtL, 100.0, trTria2, ptSt2, ptEn2, false) ;
// eseguo classificazione
double dIntStU, dIntEnU;
double dIntStU, dIntEnU ;
int nIntType = FindTriaTriaIntersType( trTria1, trTria2, ptL, vtL,
( ptSt1 - ptL) * vtL, ( ptEn1 - ptL) * vtL,
( ptSt2 - ptL) * vtL, ( ptEn2 - ptL) * vtL,
@@ -234,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
+3 -1
View File
@@ -30,7 +30,9 @@ IdentifyFillets( ICurveComposite* pCrvCo, double dDist)
if ( IsNull( pCrv))
return false ;
if ( IsFillet( pCrv, dDist))
pCrvCo->SetCurveTempParam( i, 1.0) ;
pCrvCo->SetCurveTempParam( i, 1.0) ;
else
pCrvCo->SetCurveTempParam( i, 0.0) ;
}
return true ;
}
+76 -55
View File
@@ -721,15 +721,42 @@ PolyLine::AdjustForMaxSegmentLen( double dMaxLen)
return true ;
}
//----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
static bool
PointsInTolerance( const PNTVECTOR& vRPT, const Point3d& ptP1, const Point3d& ptP2, double dSqTol)
DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const int nIndStart,
const int nIndEnd, INTVECTOR& vInd)
{
for ( const auto& ptQ : vRPT) {
double dSqDist ;
if ( ! DistPointLine( ptQ, ptP1, ptP2).GetSqDist( dSqDist) || dSqDist > dSqTol)
// se indici uguali, ritorno
if ( nIndStart == nIndEnd)
return true ;
// distanza massima e indice del punto associato
double dMaxSqDist = 0. ;
int nMaxInd = 0 ;
// scorro i punti intermedi tra nIndStart e nIndEnd
for ( int i = nIndStart + 1 ; i < nIndEnd ; ++ i) {
double dCurrSqDist = 0. ;
// distanza tra il punto attuale e la retta tra i punti di indici nIndStart ed nIndEnd
DistPointLine DPL( vPtU[i].first, vPtU[nIndStart].first, vPtU[nIndEnd].first) ;
if ( DPL.GetSqDist( dCurrSqDist) && dCurrSqDist > dMaxSqDist) {
// aggiorno i parametri
dMaxSqDist = dCurrSqDist ;
nMaxInd = i ;
}
}
// se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra
// (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd)
if ( dMaxSqDist > dSqTol) {
// inserisco il punto
vInd.push_back( nMaxInd) ;
// split
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nIndStart, nMaxInd, vInd) ||
! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, nIndEnd, vInd))
return false ;
}
return true ;
}
@@ -743,59 +770,53 @@ PolyLine::RemoveAlignedPoints( double dToler)
// controllo minimo valore di tolleranza
dToler = max( dToler, LIN_TOL_MIN) ;
double dSqTol = dToler * dToler ;
// si analizza la distanza di un punto dal segmento che unisce precedente e successivo
// punto precedente
auto precP = m_lUPoints.begin() ;
// punto corrente
auto currP = next( precP) ;
// punto successivo
auto nextP = next( currP) ;
// lista dei punti appena rimossi
PNTVECTOR vRPT ; vRPT.reserve( 20) ;
// mentre esiste un successivo
while ( nextP != m_lUPoints.end()) {
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
double dSqDist ;
// se da eliminare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vRPT, precP->first, nextP->first, dSqTol)) {
// aggiungo il punto nella lista dei rimossi
vRPT.emplace_back( currP->first) ;
// elimino il punto
m_lUPoints.erase( currP) ;
// avanzo con corrente e successivo
currP = nextP ;
++ nextP ;
}
// altrimenti da tenere
else {
// cancello la lista dei rimossi
vRPT.clear() ;
// avanzo il terzetto di uno step
precP = currP ;
currP = nextP ;
++ nextP ;
}
// vettore contenente i punti della polyline
PNTUVECTOR vPtU ; vPtU.reserve( m_lUPoints.size()) ;
for ( const auto& ptCurr : m_lUPoints)
vPtU.emplace_back( ptCurr) ;
// vettore indici dei punti rimanenti
INTVECTOR vInd ; vInd.reserve( vPtU.size()) ;
// se aperta
if ( ! IsClosed()) {
// considero tutti i punti della PolyLine
vInd.push_back( 0) ;
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vInd))
return false ;
vInd.push_back( vPtU.size() - 1) ;
}
// se curva chiusa con almeno 4 punti, devo analizzare il terzetto attorno alla chiusura
if ( IsClosed() && m_lUPoints.size() >= 4) {
// precP e currP sono già corretti
// il primo punto ripete l'ultimo (geometricamente coincide con currP)
auto firstP = m_lUPoints.begin() ;
// questo è il vero successivo
nextP = next( firstP) ;
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
double dSqDist ;
// se da eliminare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vRPT, precP->first, nextP->first, dSqTol)) {
// faccio coincidere il primo punto con il precedente
firstP->first = precP->first ;
// elimino il punto corrente
m_lUPoints.erase( currP) ;
// altrimenti chiusa
else {
// cerco il punto più distante dal primo
double dMaxDist = 0. ;
int nMaxInd = 0 ;
for ( int i = 1 ; i < int( vPtU.size()) ; ++ i) {
double dCurrDist = Dist( vPtU[0].first, vPtU[i].first) ;
if ( dCurrDist > dMaxDist) {
dMaxDist = dCurrDist ;
nMaxInd = i ;
}
}
// recupero due PolyLine di approssimazione
vInd.push_back( 0) ;
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, nMaxInd, vInd))
return false ;
vInd.push_back( nMaxInd) ;
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vInd))
return false ;
vInd.push_back( vPtU.size() - 1) ;
}
// ordino in senso crescente
sort( vInd.begin(), vInd.end()) ;
// rimetto in lista i soli punti rimasti
m_lUPoints.clear() ;
for ( auto Ind : vInd)
m_lUPoints.push_back( vPtU[Ind]) ;
return true ;
}
+24 -13
View File
@@ -18,6 +18,8 @@
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkProjectCurveSurfTm.h"
using namespace std ;
//----------------------------------------------------------------------------
static bool
PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, double dSqTol)
@@ -32,14 +34,17 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vector3d& vtDir, double dLinTol,
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen,
PNT5AXVECTOR& vPt5ax)
{
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
// approssimo la curva con una polilinea entro la metà della tolleranza
PolyLine PL ;
if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
const double MAX_SEG_LEN = 1 ;
const double MAX_SEG_LEN = min( dMaxSegmLen, 1.) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
@@ -85,23 +90,29 @@ ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vec
bFound = PL.GetNextUPoint( &dU, &ptP) ;
}
// rimuovo i punti allineati entro la tolleranza
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ;
double dSqTol = dLinTol * dLinTol ;
int nPrec = 0 ;
int nCurr = 1 ;
int nNext = 2 ;
while ( nNext < int( vMyPt5ax.size())) {
bool bRemove = false ;
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( vMyPt5ax[nCurr].ptP, vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ;
double dSqDist ;
// se distanza inferiore a tolleranza lineare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vMyPt5ax, nPrec, nCurr, nNext, dSqTol)) {
// verifico se errore angolare inferiore a limite
double dPar ; dPL.GetParamAtMinDistPoint( dPar) ;
Vector3d vtNew = Media( vMyPt5ax[nPrec].vtDir, vMyPt5ax[nNext].vtDir, dPar) ;
if ( vtNew.Normalize() && vtNew * vMyPt5ax[nCurr].vtDir > cos( 2 * DEGTORAD))
bRemove = true ;
// lunghezza del segmento che unisce gli adiacenti
double dSqLen = SqDist( vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ;
// se lunghezza inferiore al massimo, passo agli altri controlli
if ( dSqLen <= dSqMaxLen) {
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( vMyPt5ax[nCurr].ptP, vMyPt5ax[nPrec].ptP, vMyPt5ax[nNext].ptP) ;
double dSqDist ;
// se distanza inferiore a tolleranza lineare
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vMyPt5ax, nPrec, nCurr, nNext, dSqTol)) {
// verifico se errore angolare inferiore a limite
double dPar ; dPL.GetParamAtMinDistPoint( dPar) ;
Vector3d vtNew = Media( vMyPt5ax[nPrec].vtDir, vMyPt5ax[nNext].vtDir, dPar) ;
if ( vtNew.Normalize() && vtNew * vMyPt5ax[nCurr].vtDir > cos( 2 * DEGTORAD))
bRemove = true ;
}
}
// se da eliminare
if ( bRemove) {
+80
View File
@@ -0,0 +1,80 @@
//----------------------------------------------------------------------------
// EgalTech 2024
//----------------------------------------------------------------------------
// File : SbzSphere.cpp Data : 14.02.2024 Versione : 2.6b2
// Contenuto : Implementazione di funzioni per creazione di superfici Sbz
// standard : Box, Pyramid, Cylinder, Sphere, Cone.
//
//
// Modifiche : 14.02.2024 DB Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CurveArc.h"
#include "SurfTriMesh.h"
#include "SurfBezier.h"
#include "/EgtDev/Include/EGkSbzStandard.h"
using namespace std ;
//-------------------------------------------------------------------------------
ISurfBezier*
CreateBezierSphere( const Point3d& ptCenter, double dR)
{
// creo una superficie di Bezier di grado 2 con 45 punti di controllo
PtrOwner<ISurfBezier> pSrfBez( CreateSurfBezier()) ;
int nDegU = 2 ;
int nDegV = 2 ;
int nSpanU = 4 ; // i poli della sfera sono a coordinate ( 0,0,-R) e ( 0,0,R)
int nSpanV = 2 ;
bool bRat = true ;
double dW = SQRT2 ;
pSrfBez->Init(nDegU, nDegV, nSpanU, nSpanV, bRat) ;
// polo inferiore // dW = 1, dW = SQRT2 / 2
for ( int i = 0 ; i < 9; ++i) {
if ( i % 2 == 0)
dW = 1 ;
else
dW = SQRT2 / 2 ;
pSrfBez->SetControlPoint( i, 0, ptCenter + Point3d( 0, 0, -dR), dW) ;
}
// definisco la gabbia esterna // dW = SQRT2 / 2, dW = 1 / 2
// parto dal punto ( 0,-dR, -dR) e completo riga per riga
double dH = -dR ;
for ( int j = 1 ; j < 4 ; ++j ) {
Vector3d vtDir ( 0, -dR, 0) ;
Point3d pt(-dR,-dR,dH) ;
for ( int i = 0; i < 9 ; ++i ) {
// ogni due punti ruoto di 90 gradi a sinistra
if ( i%2 == 0) {
vtDir.Rotate( Z_AX, 90) ;
if ( j%2 == 1)
dW = SQRT2 / 2 ;
else
dW = 1 ;
}
else {
if ( j%2 == 1)
dW = 1. / 2. ;
else
dW = SQRT2 / 2 ;
}
pt += vtDir ;
pSrfBez->SetControlPoint( i, j, ptCenter + pt, dW) ;
}
dH += dR ;
}
// polo superiore // dW = 1, dW = SQRT2 / 2
for ( int i = 0 ; i < 9; ++i) {
if ( i % 2 == 0)
dW = 1 ;
else
dW = SQRT2 / 2 ;
pSrfBez->SetControlPoint( i, 4, ptCenter + Point3d( 0, 0, dR), dW) ;
}
return Release( pSrfBez) ;
}
+199 -37
View File
@@ -26,6 +26,7 @@
#include <algorithm>
#include <thread>
#include <future>
#include <EgtDev/Include/EGkIntersCurves.h>
using namespace std ;
@@ -749,6 +750,91 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol)
{
// verifica parametri
if ( pSect == nullptr || pGuide == nullptr)
return nullptr ;
// determino se la sezione è chiusa
bool bSectClosed = pSect->IsClosed() ;
// punto iniziale della sezione e vettore a inizio guida
Point3d ptStart ;
if ( ! pSect->GetStartPoint( ptStart))
return nullptr ;
Point3d ptGuide ;
if ( ! pGuide->GetStartPoint( ptGuide))
return nullptr ;
Vector3d vtDelta = ptStart - ptGuide ;
// calcolo la polilinea che approssima la guida
PolyLine PLG ;
if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLG))
return nullptr ;
// determino se la guida è chiusa
bool bGuideClosed = PLG.IsClosed() ;
// calcolo la superficie
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM))
return nullptr ;
// salvo tolleranza lineare usata
pSTM->SetLinearTolerance( dLinTol) ;
// superficie swept
PtrOwner<ICurve> pPrevCrv ;
Point3d ptP ;
bool bPoint = PLG.GetFirstPoint( ptP) ;
while ( bPoint) {
// nuova curva
PtrOwner<ICurve> pCurrCrv( pSect->Clone()) ;
if ( IsNull( pCurrCrv))
return nullptr ;
pCurrCrv->Translate( ptP - ptStart + vtDelta) ;
// se esiste la curva precedente, costruisco la rigata (di tipo minima distanza)
if ( ! IsNull( pPrevCrv)) {
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_ISOPAR, dLinTol)) ;
if ( IsNull( pSr))
return nullptr ;
pSTM->DoSewing( *pSr) ;
}
// salvo la curva come prossima precedente
pPrevCrv.Set( pCurrCrv) ;
// prossimo punto
bPoint = PLG.GetNextPoint( ptP) ;
}
// se richiesti caps e sezione chiusa e guida aperta
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
// calcolo la polilinea che approssima la sezione
PolyLine PLS ;
if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLS))
return nullptr ;
// verifico che la sezione sia chiusa e piatta
Plane3d plSect ; double dArea ;
if ( PLS.IsClosedAndFlat( plSect, dArea, 100 * EPS_SMALL)) {
// aggiungo il cap sull'inizio
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PLS))
return nullptr ;
pSci->Invert() ;
Point3d ptGi ; PLG.GetFirstPoint( ptGi) ;
pSci->Translate( ptGi - ptStart + vtDelta) ;
pSTM->DoSewing( *pSci) ;
// aggiungo il cap sulla fine
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PLS))
return nullptr ;
Point3d ptGe ; PLG.GetLastPoint( ptGe) ;
pSce->Translate( ptGe - ptStart + vtDelta) ;
pSTM->DoSewing( *pSce) ;
}
}
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
double dVol ;
if ( pSTM->GetVolume( dVol) && dVol < 0)
pSTM->Invert() ;
// restituisco la superficie
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshRuled( const Point3d& ptP, const ICurve* pCurve, double dLinTol)
@@ -800,56 +886,132 @@ bool
CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
POLYLINEVECTOR& vPL, Vector3d& vtN)
{
// se non ho curve, non faccio nulla
if ( int( vpCurve.size()) == 0)
return true ;
// calcolo le polilinee che approssimano le curve
POLYLINEVECTOR vPLtmp ;
vPLtmp.resize( vpCurve.size()) ;
vPL.resize( vpCurve.size()) ;
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPLtmp[i]))
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
return false ;
}
// ne calcolo l'area e genero un ordine in senso decrescente
typedef pair<int,double> INDAREA ; // coppia indice, area
typedef vector<INDAREA> INDAREAVECTOR ; // vettore di coppie indice, area
INDAREAVECTOR vArea ;
vArea.reserve( vPLtmp.size()) ;
Vector3d vtN0 ;
for ( int i = 0 ; i < int( vPLtmp.size()) ; ++ i) {
// verifico chiusura, calcolo piano medio e area
// ricavo versore normale
Plane3d plPlane ; double dArea ;
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
vtN = plPlane.GetVersN() ;
typedef std::pair<int,double> INDAREA ;
std::vector<INDAREA> m_vArea ;
// calcolo piano medio e area delle curve
m_vArea.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// calcolo piano medio e area
Plane3d plPlane ;
double dArea ;
if ( ! vPLtmp[i].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
return false ;
// imposto la normale del primo contorno come riferimento
if ( i == 0)
vtN0 = plPlane.GetVersN() ;
// verifico che le normali siano molto vicine
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN0))
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
return false ;
// assegno il segno all'area secondo il verso della normale
if ( ( plPlane.GetVersN() * vtN0) > 0)
vArea.emplace_back( i, dArea) ;
if ( ( plPlane.GetVersN() * vtN) > 0)
m_vArea.emplace_back( i, dArea) ;
else
vArea.emplace_back( i, - dArea) ;
m_vArea.emplace_back( i, - dArea) ;
}
sort( vArea.begin(), vArea.end(),
// ordino in senso decrescente sull'area
sort( m_vArea.begin(), m_vArea.end(),
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
// sposto le polilinee nel vettore da restituire secondo l'ordine
vPL.clear() ;
vPL.resize( vPLtmp.size()) ;
bool bCCW = true ;
for ( int i = 0 ; i < int( vPLtmp.size()) ; ++ i) {
// scambio
swap( vPL[i], vPLtmp[vArea[i].first]) ;
// verifico senso di rotazione del contorno esterno
if ( i == 0)
bCCW = ( vArea[i].second > 0) ;
// aggiusto gli altri contorni
else {
if ( ( bCCW && vArea[i].second > 0) || ( ! bCCW && vArea[i].second < 0))
vPL[i].Invert() ;
}
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
if ( ! frRef.IsValid())
return false ;
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vCrvCompo[i].Set( CreateCurveComposite()) ;
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
vCrvCompo[i]->ToLoc( frRef) ;
}
// restituisco la normale positiva alla regione
vtN = ( bCCW ? vtN0 : - vtN0) ;
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
// successive i loop interni
INTMATRIX vnPLIndMat ;
// vettore di indici per ordinare le PolyLine
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
vPL_IndOrder[i] = m_vArea[i].first ;
// aggiungo le diverse curve
bool bFirstCrv ;
Plane3d plExtLoop ;
double dAreaExtLoop = 0. ;
do {
bFirstCrv = true ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
// recupero indice di percorso e verifico sia valido
int j = m_vArea[i].first ;
if ( j < 0)
continue ;
// lo inserisco come esterno...
if ( bFirstCrv) {
vnPLIndMat.push_back({ j}) ;
m_vArea[i].first = -1 ;
dAreaExtLoop = m_vArea[i].second ;
// inverto se necessario
if ( m_vArea[i].second < EPS_SMALL) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
dAreaExtLoop *= -1 ;
}
bFirstCrv = false ;
}
// ... altrimenti verifico se il loop è interno o no
else {
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
// esterno a tutti i loop già inseriti nella riga attuale.
// verifica rispetto loop esterno
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
bool bOk = true ;
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
}
}
if ( bOk) {
// inserisco nella matrice
vnPLIndMat.back().push_back( j) ;
m_vArea[i].first = -1 ;
// inverto se necessario
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
}
}
}
}
} while ( ! bFirstCrv) ;
// ordino le PolyLine per area
POLYLINEVECTOR vPL_tmp ;
for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i)
vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ;
swap( vPL, vPL_tmp) ;
return true ;
}
+1639 -87
View File
File diff suppressed because it is too large Load Diff
+40 -1
View File
@@ -19,9 +19,12 @@
#include "CurveComposite.h"
#include "SurfTriMesh.h"
#include "SurfFlatRegion.h"
//#include "Tree.h"
#include "/EgtDev/Include/EGkSurfBezier.h"
#include "/EgtDev/Include/EGkGeoCollection.h"
using namespace std ;
class Tree ;
//----------------------------------------------------------------------------
class SurfBezier : public ISurfBezier, public IGeoObjRW
@@ -87,7 +90,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool SetControlPoint( int nIndU, int nIndV, const Point3d& ptCtrl, double dW) override
{ return SetControlPoint( GetInd( nIndU, nIndV), ptCtrl, dW) ; }
bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ;
bool SetTrimRegion( const ISurfFlatRegion& sfrTrimReg) override ;
bool SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtract = true) override ;
SurfFlatRegion* GetTrimRegion( void) const override ;
bool GetInfo( int& nDegU, int& nDegV, int& nSpanU, int& nSpanV, bool& bIsRat, bool& bTrimmed) const override ;
const Point3d& GetControlPoint( int nIndU, int nIndV, bool* pbOk) const override
@@ -111,12 +114,38 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ;
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
const SurfTriMesh* GetAuxSurf( void) const override ;
// funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione.
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ;
// funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier
// a nIL si può passare 5 come valore di default
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ;
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ;
// restituisce il corrispettivo parametrico di un punto qualunque della trimesh associata alla superficie
// ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie
// pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ;
// pPlCut è il piano di taglio su cui giace la curva
bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC, const Plane3d* pPlCut) const override ;
// funzione per tagliare una superficie di bezier con un piano ( cancello la parte dal lato positivo della normale del piano).
// bSaveOnEq indica se tenere i triangoli (della trimesh associata) che sono sul piano
bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ;
// funzione che calcola se gli edge sono collassati in poli. DEVE ESSERE STATA CHIAMATA PRIMA DI UN CUT
bool CalcPoles( void) override ;
// funzioni per incrementare le coordinate restando dentro lo spazio parametrico
bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ;
bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ;
// funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier
// se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
SurfBezier( void) ;
@@ -159,6 +188,11 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetCurveOnV( double dU, int nStep, PolyLine& plCrvV) const ;
double GetCurveOnUApproxLen( double dV) const ;
double GetCurveOnVApproxLen( double dU) const ;
// funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico)
bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ;
// restituisce il singolo edge della superficie non trimmata
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
bool UpdateEdgesFromTree( Tree& tr) const ;
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
@@ -170,11 +204,16 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
int m_nSpanV ; // numero di pezze in V
bool m_bRat ; // flag di razionale/polinomiale
bool m_bTrimmed ; // flag per presenza regione di trim
mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U
mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V
mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli
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[2] ; // vettore proprietà temporanee
double m_dTempParam[2] ; // vettore parametri temporanei
mutable vector<ICRVCOMPOPVECTOR> m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D
mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata
} ;
//-----------------------------------------------------------------------------
+47 -39
View File
@@ -75,7 +75,7 @@ SurfFlatRegion::Clear( void)
bool
SurfFlatRegion::AddExtLoop( const ICurve& cCrv)
{
// verifico validità curva
// verifico validità curva
if ( &cCrv == nullptr)
return false ;
// creo una copia della curva
@@ -221,7 +221,7 @@ SurfFlatRegion::MyAddExtLoop( ICurve* pCrv)
bool
SurfFlatRegion::AddIntLoop( const ICurve& cCrv)
{
// verifico validità curva
// verifico validità curva
if ( &cCrv == nullptr)
return false ;
// creo una copia della curva
@@ -435,7 +435,7 @@ SurfFlatRegion::GetTitle( void) const
bool
SurfFlatRegion::Dump( string& sOut, bool bMM, const char* szNewLine) const
{
// verifico validità regione
// verifico validità regione
if ( m_nStatus != OK)
sOut += string( "Status=Invalid") + szNewLine ;
// area
@@ -583,7 +583,7 @@ SurfFlatRegion::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
return false ;
// reset del bbox
b3Loc.Reset() ;
// è il bounding box dei loop esterni
// è il bounding box dei loop esterni
for ( auto i : m_vExtInd) {
BBox3d b3Tmp ;
if ( m_vpLoop[i]->GetBBox( m_frF, b3Tmp, nFlag))
@@ -603,7 +603,7 @@ SurfFlatRegion::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
Frame3d frCompo = m_frF * frRef ;
// reset del bbox
b3Ref.Reset() ;
// è il bounding box dei loop esterni
// è il bounding box dei loop esterni
for ( auto i : m_vExtInd) {
BBox3d b3Tmp ;
if ( m_vpLoop[i]->GetBBox( frCompo, b3Tmp, nFlag))
@@ -622,8 +622,9 @@ SurfFlatRegion::Translate( const Vector3d& vtMove)
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// traslo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->Translate( vtMove) ;
// traslo il riferimento
m_frF.Translate( vtMove) ;
return true ;
@@ -636,15 +637,16 @@ SurfFlatRegion::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità dell'asse di rotazione
// verifico validità dell'asse di rotazione
if ( vtAx.IsSmall())
return false ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// ruoto Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
// ruoto il riferimento
return m_frF.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
@@ -673,7 +675,7 @@ SurfFlatRegion::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou
return false ;
}
// parziale scalatura del riferimento (non può essere completa)
// parziale scalatura del riferimento (non può essere completa)
Frame3d frTrasf = m_frF ;
m_frF.PseudoScale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
@@ -712,7 +714,7 @@ SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
// verifico lo stato
if ( m_nStatus != OK || m_vpLoop.empty())
return false ;
// verifico validità del piano di specchiatura
// verifico validità del piano di specchiatura
if ( vtNorm.IsSmall())
return false ;
@@ -722,7 +724,7 @@ SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// parziale mirror del riferimento (non può essere completa)
// parziale mirror del riferimento (non può essere completa)
Frame3d frTrasf = m_frF ;
m_frF.PseudoMirror( ptOn, vtNorm) ;
@@ -762,7 +764,7 @@ SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector
// verifico lo stato
if ( m_nStatus != OK || m_vpLoop.empty())
return false ;
// verifico validità dei parametri
// verifico validità dei parametri
if ( vtNorm.IsSmall() || vtDir.IsSmall())
return false ;
@@ -778,7 +780,7 @@ SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector
return false ;
}
// parziale scorrimento del riferimento (non può essere completa)
// parziale scorrimento del riferimento (non può essere completa)
Frame3d frTrasf = m_frF ;
m_frF.PseudoShear( ptOn, vtNorm, vtDir, dCoeff) ;
@@ -832,19 +834,21 @@ SurfFlatRegion::ToGlob( const Frame3d& frRef)
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identità, non devo fare alcunché
// se frame identità, non devo fare alcunché
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->ToGlob( frRef) ;
// trasformo il riferimento
return m_frF.ToGlob( frRef) ; ;
@@ -857,19 +861,21 @@ SurfFlatRegion::ToLoc( const Frame3d& frRef)
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// se frame identità, non devo fare alcunché
// se frame identità, non devo fare alcunché
if ( IsGlobFrame( frRef))
return true ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->ToLoc( frRef) ;
// trasformo il riferimento
return m_frF.ToLoc( frRef) ; ;
@@ -882,19 +888,21 @@ SurfFlatRegion::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità dei frame
// verifico validità dei frame
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
return false ;
// se i due riferimenti coincidono, non devo fare alcunché
// se i due riferimenti coincidono, non devo fare alcunché
if ( AreSameFrame( frOri, frDest))
return true ;
// imposto ricalcolo della grafica
ResetAuxSurf() ;
m_OGrMgr.Reset() ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// trasformo Voronoi
if ( m_pVoronoiObj != nullptr)
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
// trasformo il riferimento
return m_frF.LocToLoc( frOri, frDest) ; ;
@@ -978,7 +986,7 @@ SurfFlatRegion::GetCentroid( Point3d& ptCen) const
return false ;
// medio il centro
ptCen /= dArea ;
// lo porto dal riferimento intrinseco a quello in cui è immersa l'entità
// lo porto dal riferimento intrinseco a quello in cui è immersa l'entità
ptCen.ToGlob( m_frF) ;
return true ;
}
@@ -997,7 +1005,7 @@ SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const
const ICurve* pCrv = GetMyLoop( nChunk, 0) ;
if ( pCrv == nullptr || ! pCrv->GetCentroid( ptCen))
return false ;
// lo porto dal riferimento intrinseco a quello in cui è immersa l'entità
// lo porto dal riferimento intrinseco a quello in cui è immersa l'entità
ptCen.ToGlob( m_frF) ;
return true ;
}
@@ -1023,7 +1031,7 @@ SurfFlatRegion::GetLoopCount( int nChunk) const
int nChunkMax = int( m_vExtInd.size()) - 1 ;
if ( nChunk < 0 || nChunk > nChunkMax)
return 0 ;
// se non è l'ultimo Chunk
// se non è l'ultimo Chunk
if ( nChunk < nChunkMax)
return ( m_vExtInd[nChunk+1] - m_vExtInd[nChunk]) ;
// altrimenti
@@ -1053,7 +1061,7 @@ SurfFlatRegion::GetChunkLoopFromInd( int nInd, int& nChunk, int& nLoop) const
// valori non validi
nChunk = - 1 ;
nLoop = - 1 ;
// verifico validità di nInd
// verifico validità di nInd
if ( nInd < 0 || nInd >= int( m_vpLoop.size()))
return false ;
// verifica esistenza array di chunks
@@ -1105,7 +1113,7 @@ SurfFlatRegion::GetLoop( int nChunk, int nLoop) const
return nullptr ;
// assegno la normale alla regione come estrusione
pCrv->SetExtrusion( Z_AX) ;
// la porto nel riferimento in cui è inserito l'oggetto
// la porto nel riferimento in cui è inserito l'oggetto
pCrv->ToGlob( m_frF) ;
return pCrv ;
}
@@ -1121,7 +1129,7 @@ SurfFlatRegion::ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, doub
// ne creo una approssimazione
if ( ! pMyCrv->ApproxWithLines( dLinTol, dAngTolDeg, nType, PL))
return false ;
// la porto nel riferimento in cui è inserito l'oggetto
// la porto nel riferimento in cui è inserito l'oggetto
PL.ToGlob( m_frF) ;
return true ;
}
@@ -1174,7 +1182,7 @@ SurfFlatRegion::GetAuxSurf( void) const
// la superficie deve essere validata
if ( m_nStatus != OK || m_vpLoop.empty())
return nullptr ;
// se già calcolata, la restituisco
// se già calcolata, la restituisco
if ( m_pSTM != nullptr)
return m_pSTM ;
// la creo e la salvo
@@ -1222,7 +1230,7 @@ SurfFlatRegion::CloneChunk( int nChunk) const
bool
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
{
// la curva deve già essere nel riferimento intrinseco della regione
// la curva deve già essere nel riferimento intrinseco della regione
// verifico lo stato
if ( m_nStatus != OK || m_vpLoop.empty())
return false ;
@@ -1254,7 +1262,7 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRV
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
case CRVC_IN :
// IN è Remove degli altri
// IN è Remove degli altri
break ;
case CRVC_OUT :
// intervallo standard
@@ -1383,7 +1391,7 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
if ( ! AreSameVectorApprox( m_frF.VersZ(), Reg2.m_frF.VersZ()))
return REGC_NULL ;
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
const ICurve* pCrv1Loc = GetMyLoop( nChunk, 0) ;
// curva esterna del chunk della seconda regione in locale nel riferimento intrinseco della prima
@@ -1453,7 +1461,7 @@ SurfFlatRegion::ResetVoronoiObject() const
bool
SurfFlatRegion::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound) const
{
// verifico se è stato calcolato
// verifico se è stato calcolato
if ( m_pVoronoiObj == nullptr)
if ( ! CalcVoronoiObject())
return false ;
@@ -1465,7 +1473,7 @@ SurfFlatRegion::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound) const
bool
SurfFlatRegion::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const
{
// verifico se è stato calcolato
// verifico se è stato calcolato
if ( m_pVoronoiObj == nullptr)
if ( ! CalcVoronoiObject())
return false ;
+8 -5
View File
@@ -96,7 +96,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
{ return m_frF.VersZ() ; }
int GetChunkCount( void) const override ;
int GetLoopCount( int nChunk) const override ;
ICurve* GetLoop( int nChunk, int nLoop) const override ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
ICurve* GetLoop( int nChunk, int nLoop) const override ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
bool ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
const SurfTriMesh* GetAuxSurf( void) const override ;
SurfFlatRegion* CloneChunk( int nChunk) const override ;
@@ -104,12 +104,16 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
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
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ;
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;
void ResetVoronoiObject( void) const override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
public :
SurfFlatRegion( void) ;
@@ -139,7 +143,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
int GetIndFromChunkLoop( int nChunk, int nLoop) const ;
bool GetChunkLoopFromInd( int nInd, int& nChunk, int& nLoop) const ;
ICurve* GetMyLoop( int nInd) const ; // indice nel vettore di tutti i loop
ICurve* GetMyLoop( int nChunk, int nLoop) const ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
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, double dLenMin, CRVCVECTOR& ccClass) const ;
@@ -149,7 +153,6 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
static SurfFlatRegion* MyNewSurfFromLoops( PCRV_DEQUE& vpLoop) ;
static bool MyTestAndDelete( PCRV_DEQUE& vpCrv) ;
bool CalcVoronoiObject( void) const ;
void ResetVoronoiObject( void) const ;
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
@@ -158,7 +161,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[2] ; // vettore proprietà temporanee
int m_nTempProp[2] ; // vettore proprietà temporanee
double m_dTempParam[2] ; // vettore parametri temporanei
mutable Voronoi* m_pVoronoiObj ; // Voronoi
+25 -47
View File
@@ -16,6 +16,7 @@
#include "GeoConst.h"
#include "CurveComposite.h"
#include "SurfFlatRegion.h"
#include "AdjustLoops.h"
#include "Voronoi.h"
#include "/EgtDev/Include/EGkOffsetCurve.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
@@ -36,7 +37,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
if ( nChunk == 0)
return nullptr ;
// se offset nullo, la nuova regione è la copia di quella attuale
// se offset nullo, la nuova regione è la copia di quella attuale
if ( abs( dDist) < 10 * EPS_SMALL)
return this->Clone() ;
@@ -70,7 +71,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
while ( bOk && ! IsNull( pOffs)) {
if ( pOffs->GetType() == CRV_COMPO) {
CurveComposite* pOffsCompo = GetBasicCurveComposite( pOffs) ;
// assegno proprietà
// assegno proprietà
pOffsCompo->SetTempProp( j, 1) ;
for ( int k = 0 ; k < pOffsCompo->GetCurveCount() ; ++k)
pOffsCompo->SetCurveTempProp( k, j, 1) ;
@@ -80,7 +81,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
}
else
pOffs->SetTempProp( j, 1) ;
// se prima curva esterna, è il primo contorno esterno della nuova regione
// se prima curva esterna, è il primo contorno esterno della nuova regione
if ( j == 0 && bFirstCurve) {
if ( ! pSfrChk->AddExtLoop( Release( pOffs)))
return nullptr ;
@@ -137,7 +138,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
// -------------------- OFFSET CON VORONOI -------------------------------------
else {
// verifico se oggetto Voronoi della superficie è definito
// verifico se oggetto Voronoi della superficie è definito
if ( m_pVoronoiObj == nullptr)
CalcVoronoiObject() ;
@@ -146,51 +147,28 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
if ( ! m_pVoronoiObj->CalcOffset( vOffs, dDist, nType))
return nullptr ;
// costruisco la superficie
if ( vOffs.size() > 0) {
BOOLVECTOR vbAddOrSub( vOffs.size(), true) ;
int nFirstId = -1 ;
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) {
// porto nel frame della flat region
PCRV_DEQUE vLoops ;
for ( int i = 0 ; i < int( vOffs.size()) ; i ++) {
vOffs[i]->ToLoc( m_frF) ;
// calcolo orientamento della curva
double dAreaXY ;
if ( ! vOffs[i]->GetAreaXY( dAreaXY))
return nullptr ;
vbAddOrSub[i] = ( dAreaXY > SQ_EPS_SMALL) ;
// verifico se è il primo loop esterno
if ( nFirstId == -1 && vbAddOrSub[i])
nFirstId = i ;
}
// inizializzo la superficie
if ( nFirstId != -1 && ! pSfr->AddExtLoop( Release( vOffs[nFirstId])))
return nullptr ;
if ( pSfr->IsValid()) {
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) {
// verifico non sia il primo loop esterno
if ( i == nFirstId)
continue ;
// costruisco la superficie associata
PtrOwner<SurfFlatRegion> pSrfCrv( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSrfCrv) || ! pSrfCrv->AddExtLoop( Release( vOffs[i])))
return nullptr ;
if ( ! pSrfCrv->IsValid())
continue ;
// aggiungo o sottraggo
if ( vbAddOrSub[i]) {
if ( ! pSfr->Add( *pSrfCrv))
return nullptr ;
}
else {
pSrfCrv->Invert() ;
if ( ! pSfr->Subtract( *pSrfCrv))
return nullptr ;
}
// rimuovo eventuali sovrapposizioni
ICURVEPLIST CrvLst ;
AdjustLoops( Release( vOffs[i]), CrvLst, true) ;
for ( auto pCrv : CrvLst) {
pCrv->SetExtrusion( Z_AX) ;
vLoops.emplace_back( pCrv) ;
}
}
// verifico di avere ancora dei loops
if ( vLoops.size() > 0) {
pSfr.Set( MyNewSurfFromLoops( vLoops)) ;
if ( IsNull( pSfr)) {
MyTestAndDelete( vLoops) ;
return nullptr ;
}
}
}
}
@@ -207,9 +185,9 @@ SurfFlatRegion::Offset( double dDist, int nType)
if ( nChunk == 0)
return false ;
// se offset nullo, non devo fare alcunchè
// se offset nullo, non devo fare alcunchè
if ( abs( dDist) < 10 * EPS_SMALL)
return this->Clone() ;
return true ;
// calcolo la superficie di offset
PtrOwner<SurfFlatRegion> pSfr( CreateOffsetSurf( dDist, nType)) ;
+64 -13
View File
@@ -16,6 +16,7 @@
#include "stdafx.h"
#include "SurfTriMesh.h"
#include "GeoObjFactory.h"
#include "GdbGeo.h"
#include "NgeWriter.h"
#include "NgeReader.h"
#include "SurfFlatRegion.h"
@@ -31,7 +32,7 @@
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <new>
#include <set>
#include <set>
using namespace std ;
@@ -41,8 +42,9 @@ 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_bFacEdged( false),
m_nTimeStamp( 0), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_nMaxTFlag( 0), m_nParts( -1), m_pHGrd3d( nullptr)
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bShowEdges( false), m_bOriented( false), m_bClosed( false),
m_bFaceted( false), m_bFacEdged( false), m_nTimeStamp( 0), m_nTempProp{0,0}, m_dTempParam{0,0},
m_nMaxTFlag( 0), m_nParts( -1), m_pHGrd3d( nullptr)
{
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
@@ -59,7 +61,7 @@ bool
SurfTriMesh::Init( int nNumVert, int nNumTria, int nNumFacet)
{
// imposto ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ;
m_OGrMgr.Clear() ;
ResetHashGrids3d() ;
// se superficie vuota
if ( nNumVert == 0 && nNumTria == 0 && nNumFacet == 0)
@@ -91,6 +93,12 @@ bool
SurfTriMesh::Clear( void)
{
m_nStatus = OK ;
m_dLinTol = STM_STD_LIN_TOL ;
m_dBoundaryAng = STM_STD_BOUNDARY_ANG ;
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
m_dSmoothAng = STM_STD_SMOOTH_ANG ;
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
m_bShowEdges = false ;
m_bOriented = false ;
m_bClosed = false ;
m_bFaceted = false ;
@@ -98,7 +106,13 @@ SurfTriMesh::Clear( void)
m_vVert.clear() ;
m_vTria.clear() ;
m_vFacet.clear() ;
m_OGrMgr.Clear() ;
ResetHashGrids3d() ;
m_nTimeStamp = 0 ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
m_dTempParam[0] = 0 ;
m_dTempParam[1] = 0 ;
m_nMaxTFlag = 0 ;
m_nParts = -1 ;
return true ;
@@ -875,7 +889,7 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
SurfTriMesh*
SurfTriMesh::CloneTriangle( int nT) const
{
// verifico validit superficie ed esistenza del triangolo
// verifico validità superficie ed esistenza del triangolo
if ( ! IsValid() || nT < 0 || nT >= GetTriangleSize() || m_vTria[nT].nIdVert[0] == SVT_DEL)
return nullptr ;
@@ -982,7 +996,7 @@ SurfTriMesh::GetLoops( POLYLINEVECTOR& vPL) const
if ( ! MarchAlongLoop( nT, 1, m_nTimeStamp, vPL.back()))
return false ;
}
// se il lato 0 di contorno
// se il lato 0 è di contorno
else if ( nAdjT[0] == SVT_NULL) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
@@ -994,7 +1008,7 @@ SurfTriMesh::GetLoops( POLYLINEVECTOR& vPL) const
if ( ! MarchAlongLoop( nT, 1, m_nTimeStamp, vPL.back()))
return false ;
}
// se il lato 1 di contorno
// se il lato 1 è di contorno
else if ( nAdjT[1] == SVT_NULL) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
@@ -1006,7 +1020,7 @@ SurfTriMesh::GetLoops( POLYLINEVECTOR& vPL) const
if ( ! MarchAlongLoop( nT, 2, m_nTimeStamp, vPL.back()))
return false ;
}
// se il lato 2 di contorno
// se il lato 2 è di contorno
else if ( nAdjT[2] == SVT_NULL) {
// ho trovato l'inizio di un loop
vPL.emplace_back() ;
@@ -1018,7 +1032,7 @@ SurfTriMesh::GetLoops( POLYLINEVECTOR& vPL) const
if ( ! MarchAlongLoop( nT, 0, m_nTimeStamp, vPL.back()))
return false ;
}
// altrimenti non c' contorno
// altrimenti non c'è contorno
else {
// marco il triangolo come verificato
m_vTria[nT].nTemp = m_nTimeStamp ;
@@ -1063,10 +1077,10 @@ SurfTriMesh::MarchOneTria( int& nT, int& nV, int nTimeStamp,
return false ;
// vertice di fine adiacenza e indice del successivo lato
int nAdjV = Next( nAdjS) ;
// verifico se il lato successivo un bordo
// verifico se il lato successivo è un bordo
int nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ;
if ( nNextT == SVT_NULL) {
// se gi recuperato
// se già recuperato
if ( m_vTria[nAdjT].nTemp == nTimeStamp) {
bEnd = true ;
return true ;
@@ -1197,6 +1211,7 @@ SurfTriMesh::CopyFrom( const SurfTriMesh& stmSrc)
m_dCosBndAng = stmSrc.m_dCosBndAng ;
m_dSmoothAng = stmSrc.m_dSmoothAng ;
m_dCosSmAng = stmSrc.m_dCosSmAng ;
m_bShowEdges = stmSrc.m_bShowEdges ;
m_bOriented = stmSrc.m_bOriented ;
m_bClosed = stmSrc.m_bClosed ;
m_bFaceted = stmSrc.m_bFaceted ;
@@ -1332,12 +1347,33 @@ SurfTriMesh::Save( NgeWriter& ngeOut) const
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::PreSave( GdbGeo& Wrapper) const
{
// salvo il flag di visualizzazione spigoli vivi anche in shading (default false)
if ( m_bShowEdges)
Wrapper.SetInfo( GDB_SI_SHOWEDGES, true) ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::PostSave( GdbGeo& Wrapper) const
{
// elimino eventuali info aggiunte nella PreSave
Wrapper.RemoveInfo( GDB_SI_SHOWEDGES) ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Load( NgeReader& ngeIn)
{
// imposto ricalcolo della grafica, della connessione e di hashgrids3d
m_OGrMgr.Reset() ;
m_OGrMgr.Clear() ;
m_nMaxTFlag = 0 ;
m_nParts = -1 ;
ResetHashGrids3d() ;
@@ -1434,6 +1470,20 @@ SurfTriMesh::Load( NgeReader& ngeIn)
return Validate() ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::PostLoad( GdbGeo& Wrapper)
{
// recupero eventuale flag di visualizzazione spigoli vivi anche in shading
bool bVal ;
if ( Wrapper.GetInfo( GDB_SI_SHOWEDGES, bVal)) {
m_bShowEdges = bVal ;
Wrapper.RemoveInfo( GDB_SI_SHOWEDGES) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Validate( bool bCorrect)
@@ -1960,7 +2010,7 @@ SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL)
PNTVECTOR vPnt ;
INTVECTOR vTria ;
Triangulate Tri ;
if ( ! Tri.Make( vPL, vPnt, vTria))
if ( ! Tri.MakeAdvanced( vPL, vPnt, vTria))
return false ;
// inizializzo la superficie
@@ -3643,6 +3693,7 @@ SurfTriMesh::ResetTFlags( void)
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i)
m_vTria[i].nTFlag = 0 ;
m_nMaxTFlag = 0 ;
m_OGrMgr.Clear() ;
return true ;
}
+9
View File
@@ -226,6 +226,9 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
{ m_dSmoothAng = std::max( dSmoothAngDeg, EPS_ANG_SMALL) ;
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
m_OGrMgr.Reset() ; }
void SetShowEdges( bool bShow) override
{ m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica
m_OGrMgr.Clear() ; }
int AddVertex( const Point3d& ptVert, double dU = -1, double dV = -1) override ;
bool MoveVertex( int nInd, const Point3d& ptNewVert) override ;
int AddTriangle( const int nIdVert[3], int nTFlag = 0) override ;
@@ -254,6 +257,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
{ return m_dLinTol ; }
double GetSmoothAngle( void) const override
{ return m_dSmoothAng ; }
bool GetShowEdges( void) const override
{ return m_bShowEdges ; }
bool GetVertex( int nId, Point3d& ptP) const override ;
bool GetVertexParam( int nId, double& dU, double& dV) const override ;
int GetFirstVertex( Point3d& ptP) const override ;
@@ -320,7 +325,10 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override ;
bool PostSave( GdbGeo& Wrapper) const override ;
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override ;
public :
SurfTriMesh( void) ;
@@ -413,6 +421,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
double m_dCosBndAng ; // coseno dell'angolo limite per considerare un lato un contorno
double m_dSmoothAng ; // angolo limite per mediare le normali (in gradi)
double m_dCosSmAng ; // coseno dell'angolo limite per mediare le normali
bool m_bShowEdges ; // flag di visualizzazione spigoli vivi
bool m_bOriented ; // la superficie è orientata consistentemente in tutte le sue parti
bool m_bClosed ; // la superficie racchiude un volume
bool m_bFaceted ; // flag di validità della sfaccettatura
+214 -140
View File
@@ -52,9 +52,10 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
if ( vnDegVec[nC] > 0)
++ nExistNotDeg ;
}
// Divido il loop di partenza in sotto-loop
int nIterationCount = 0 ;
while ( cvOpenChain.size() > 0) {
while ( cvOpenChain.size() > 0) { // per ogni catena aperta...
bool bLoopSplitted = false ;
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
if ( vnDegVec[nLastOpenLoopN] == 1) {
@@ -63,13 +64,24 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
int nLastOpenLoopPoint = max( int( cvOpenChain[nLastOpenLoopN].size()) - 1, 0) ;
Point3d ptOpenLoopStP = cvOpenChain[nLastOpenLoopN][0].ptSt ;
Point3d ptOpenLoopEnP = cvOpenChain[nLastOpenLoopN][nLastOpenLoopPoint].ptEn ;
// costruisco il primo e il secondo loop che si generano
// NB. il loop esterno è chiuso, mentre la catena aperta
// è la successione dei tratti lineari dovuti ai triangoli dell'altra superficie
PNTVECTOR Loop1, Loop2 ;
// cambio il punto iniziale del loop di bordo se non coincide già con ptStart della catena aperta
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
// splitto
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
if ( ! ( bChangedStart && bSplitted) ||
( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2)))
continue ;
continue ; // la catena aperta non è interna al loop chiuso attuale
// il loop 1 segue sempre la direzione della catena, il loop 2 ha dentro la catena invertita
// Ho sempre che il loop 1 è sempre interno ( la direzione della catena è determinata
// dalla normale dei triangoli che la formano; avendo chimatao la chian senza ammettere inversioni, sono
// curve tutte concordi ) e il loop 2 che è esterno
bLoopSplitted = true ;
// ricostrusico i due loop mediante concatenazione
Chain cvCounterChain ;
for ( int nPt = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nPt >= 0 ; -- nPt) {
IntSegment CurSeg ;
@@ -181,7 +193,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
// elimino i punti superflui prima
for ( int i = 0 ; i < nCvFirst ; ++ i)
cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin()) ;
// verifico se questo punto dalla parte valida o no
// verifico se questo punto è dalla parte valida o no
bool bC12 = ( ( ptM12 - ptProva) * vtVecProva < 0) ;
vbInOut[nLoop] = bC12 ;
}
@@ -192,7 +204,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
// elimino i punti superflui intermedi
for ( int i = nCvFirst + 2 ; i < nCvSecond ; ++ i)
cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin() + nCvFirst + 2) ;
// verifico se questo punto dalla parte valida o no
// verifico se questo punto è dalla parte valida o no
bool bC21 = ( ( ptM21 - ptProva) * vtVecProva < 0) ;
vbInOut[nLoop] = bC21 ;
}
@@ -234,9 +246,13 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// La superficie deve essere valida
if ( ! Surf.IsValid())
return false ;
// Ritriangolarizzo i triangoli
// itero sulla unorderd_map
for ( auto it = LoopLines.begin() ; it != LoopLines.end() ; ++ it) {
// itero sulle catene ( secondo parametro della mappa)
for ( int nS1 = 0 ; nS1 < int( it->second.size()) - 1 ; ++ nS1) {
// tolgo i tratti degeneri ad un punto
for ( int nS2 = nS1 + 1 ; nS2 < int( it->second.size()) ; ++ nS2) {
if ( AreSamePointApprox( it->second[nS1].ptSt, it->second[nS2].ptEn) &&
AreSamePointApprox( it->second[nS1].ptEn, it->second[nS2].ptSt) &&
@@ -248,22 +264,21 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
}
// se non resta nulla, allora passo alla mappa successiva
if ( int( it->second.size()) == 0)
continue ;
// Se il triangolo è stato sottoposto a ritriangolazione, le sue componenti sono classificabili come dentro-fuori.
// Lo tolgo dall'insieme dei triangoli ambigui (intersezione edge-edge)
else {
auto itS = Ambiguos.find( it->first) ;
if ( itS != Ambiguos.end()) {
Ambiguos.erase( itS) ;
}
}
auto itS = Ambiguos.find( it->first) ;
if ( itS != Ambiguos.end())
Ambiguos.erase( itS) ;
// Creo i loop
// CREAZIONE DEI LOOP ---------------------------------------------
// Chain
ChainCurves LoopCreator ;
LoopCreator.Init( false, 2 * EPS_SMALL, int( it->second.size()), 10 * BOOLEAN_SCALE) ;
// Carico le curve per concatenarle
// Recupero le curve ( gli estremi dei tratti lineari) per concatenarle
for ( int nCv = 0 ; nCv < int( it->second.size()); ++ nCv) {
Point3d ptSt = it->second[nCv].ptSt ;
Point3d ptEn = it->second[nCv].ptEn ;
@@ -277,15 +292,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
CHAINVECTOR vChain ;
while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) {
Chain chTemp ;
for ( auto i : vIds) {
// Aggiungo la linea alla curva composta.
for ( auto i : vIds) // Aggiungo la linea alla curva composta
chTemp.emplace_back( it->second[i - 1]) ;
}
vChain.emplace_back( chTemp) ;
}
// Lavoro su loop e catene per regolarizzarle
int nChainCnt = int( vChain.size()) ;
// unisco eventuali catene estreme che sono parte di una stessa catena
// 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()) ;
@@ -298,7 +312,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
-- nChainCnt ;
}
}
// semplifico catene formate da punti degeneri
// Semplifico catene formate da punti degeneri
for ( int nCh = 0 ; nCh < nChainCnt ; ++ nCh) {
if ( vChain[nCh].size() == 2 && ( vChain[nCh][0].bDegenerate || vChain[nCh][1].bDegenerate)) {
vChain[nCh][0].ptEn = vChain[nCh][1].ptEn ;
@@ -377,6 +391,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
}
// Chiudo i loop costruiti a partire dalle catene
for ( int nC = 0 ; nC < nChainCnt ; ++ nC) {
int nChainLastSegPos = int( vChain[nC].size()) - 1 ;
@@ -463,7 +478,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[2] = 0 ;
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
bModif = true ;
}
int nNewCoupleId1[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 1) % 3)), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)) } ;
@@ -472,7 +487,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[2] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
bModif = true ;
}
int nNewCoupleId2[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)), Surf.AddVertex( ptIntEn) } ;
@@ -481,27 +496,32 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[2] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
bModif = true ;
}
continue ;
}
}
}
// -------------------------------------------------------------------------------------------
// 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.
// 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;
// creo una matrice di punti ; ogni riga corrisponde ad una sequenza di punti che indentificano un loop
PNTMATRIX cvBoundClosedLoopVec ;
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
// vettore per indicare se il loop è interno/esterno all'altra superficie
BOOLVECTOR vbInOut ;
vbInOut.push_back( true) ;
// Divido il loop usando le catene
if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) {
if ( cvBoundClosedLoopVec.size() == 1 && cvOpenChain.size() == 2) {
@@ -556,7 +576,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[it->first].nTempPart = 0 ;
continue ;
}
}
}
// Rimuovo il triangolo corrente
int nOldTriaCol = Surf.m_vTria[it->first].nTFlag ;
Surf.RemoveTriangle( it->first) ;
@@ -564,14 +584,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
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) {
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine)
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ;
}
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][0]) ;
// Assegno ai loop trovati i rispettivi interni
// Assumo che i loop interni a uno dei loop creati fino ad'ora siano tutti sullo stesso livello.
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
// loop è figlio del nodo corrispondente al loop che lo contiene.
INTVECTOR vInnerLoop ;
for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) {
@@ -692,7 +712,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
break ;
}
}
if ( vInnerLoop.size() == 0 || bDouble) {
// Eseguo triangolazione
PNTVECTOR vPt ;
@@ -710,7 +730,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( vbInOut[nLoop])
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
else
Surf.m_vTria[nNewTriaNum].nTempPart = - 1 ;
bModif = true ;
@@ -719,33 +739,32 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
else {
// se ho più loop, essi descrivono un poligono di n-lati
POLYLINEVECTOR vPolygons ;
vPolygons.emplace_back( vplPolyVec[nLoop]) ;
for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) {
// per ognuno di essi, ricavo la PolyLine dai punti
PolyLine CurLoop ;
for ( int nV = 0 ; nV < int( cvClosedChain[vInnerLoop[nL]].size()) ; ++ nV) {
for ( int nV = 0 ; nV < int( cvClosedChain[vInnerLoop[nL]].size()) ; ++ nV)
CurLoop.AddUPoint( 0., cvClosedChain[vInnerLoop[nL]][nV].ptSt) ;
}
CurLoop.AddUPoint( 0., cvClosedChain[vInnerLoop[nL]][0].ptSt) ;
vPolygons.emplace_back( CurLoop) ;
}
// poligono
Polygon3d pgPol ;
pgPol.FromPolyLine(vPolygons[1]) ;
pgPol.FromPolyLine( vPolygons[1]) ;
// controllo direzioni delle normali
bool bCodirectedNormals = trTria.GetN() * pgPol.GetVersN() > 0. ;
if ( bCodirectedNormals) {
for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) {
vPolygons[nL].Invert() ;
}
}
// Aggiungo al loop esterno i punti dei loop interni che si trovano su di esso
PNTULIST& ExternLoopList = vPolygons[0].GetUPointList() ;
// Ciclo sui segmenti del loop esterno
auto itSt = ExternLoopList.begin() ;
auto itEn = itSt ;
++ itEn ;
++ itEn ;
for ( ; itSt != ExternLoopList.end() && itEn != ExternLoopList.end() ; ++ itSt, ++ itEn) {
// Estremi del segmento corrente del loop esterno e scorrispondente vettore
Point3d ptSt = itSt->first ;
@@ -761,7 +780,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Point3d ptInnPoint ;
bool bIsFirst = true ;
bool bContinue = vPolygons[nInnPoly].GetFirstPoint( ptInnPoint) ;
while ( bContinue) {
while ( bContinue) {
DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ;
double dDist ;
DistCalculator.GetDist( dDist) ;
@@ -788,13 +807,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// Aggiungo i punti al loop esterno
for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) ; ++ nPi) {
itSt = ExternLoopList.emplace( itEn, vPointWithOrder[nPi]) ;
}
}
}
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( vPolygons, vPt, vTr)) {
// Inserisco i nuovi triangoli
// classifico i loop e ricavo la triangolazione di essi mediante classificazione
if ( Triangulate().MakeAdvanced( vPolygons, 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] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
@@ -817,7 +837,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// Divido i loop che si autointercettano
int nInitialLoopNum = int( vPolygons.size()) ;
for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) {
// Lista dei punti della PolyLine Loop corrente
// Lista dei punti della PolyLine Loop corrente
PNTULIST& LoopPointList = vPolygons[nL].GetUPointList() ;
// Ciclo sui segmenti
auto itSt2 = LoopPointList.begin() ;
@@ -841,7 +861,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
double dDist ;
DistCalculator.GetDist( dDist) ;
double dLongPos = ( ptP - ptSt) * vtSeg ;
if ( dDist < EPS_SMALL && dLongPos > 0. && dLongPos < dSegLen) {
if ( dDist < EPS_SMALL && dLongPos > EPS_SMALL && dLongPos < dSegLen - EPS_SMALL) {
POINTU NewPointU ;
NewPointU.first = ptP ;
NewPointU.second = dLongPos ;
@@ -911,43 +931,49 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
bool bReplaced = false ;
for ( int nl = 0 ; nl < int( vAuxPolygons.size()) ; ++ nl) {
if ( true) {
if ( ! bReplaced) {
vPolygons[nL].Clear() ;
Point3d ptP ;
bool bContinue = vAuxPolygons[nl].GetFirstPoint( ptP) ;
while ( bContinue) {
vPolygons[nL].AddUPoint( 0., ptP) ;
bContinue = vAuxPolygons[nl].GetNextPoint( ptP) ;
}
bReplaced = true ;
}
else {
vPolygons.emplace_back( vAuxPolygons[nl]) ;
if ( ! bReplaced) {
vPolygons[nL].Clear() ;
Point3d ptP ;
bool bContinue = vAuxPolygons[nl].GetFirstPoint( ptP) ;
while ( bContinue) {
vPolygons[nL].AddUPoint( 0., ptP) ;
bContinue = vAuxPolygons[nl].GetNextPoint( ptP) ;
}
bReplaced = true ;
}
else {
vPolygons.emplace_back( vAuxPolygons[nl]) ;
}
}
}
for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) {
vPolygons[nL].Invert() ;
if ( Triangulate().Make( vPolygons[nL], 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] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
Surf.AddVertex( vPt[nNewTriaVertId[1]]),
Surf.AddVertex( vPt[nNewTriaVertId[2]])} ;
int nNewTriaNum = Surf.AddTriangle( nNewId, nOldTriaCol) ;
if ( IsValidSvt( nNewTriaNum)) {
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( bCodirectedNormals)
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
else
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
bModif = true ;
}
// tolgo il loop esterno per triangolare solo i loop interni
vPolygons.erase( vPolygons.begin()) ;
// tolgo le PolyLine non valide ( rejected )
for ( int i = 0 ; i < int( vPolygons.size()) ; ) {
if ( ! vPolygons[i].IsClosed())
vPolygons.erase( vPolygons.begin() + i) ;
else
++ i ;
}
if ( Triangulate().MakeAdvanced( vPolygons, 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] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
Surf.AddVertex( vPt[nNewTriaVertId[1]]),
Surf.AddVertex( vPt[nNewTriaVertId[2]])} ;
int nNewTriaNum = Surf.AddTriangle( nNewId, nOldTriaCol) ;
if ( IsValidSvt( nNewTriaNum)) {
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( bCodirectedNormals)
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
else
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
bModif = true ;
}
}
}
@@ -1088,18 +1114,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
{
bool bModif = false ;
SurfTriMesh& SurfB = Other ;
// Le superfici devono essere valide
if ( m_nStatus != OK || ! SurfB.IsValid())
return false ;
// Unordered map dei segmenti di intersezione
CHAINMAP LineMapA ;
CHAINMAP LineMapB ;
// Unordered map dei triangoli ambigui (intersezione edge-edge)
TRIA3DVECTORMAP AmbiguosA ;
TRIA3DVECTORMAP AmbiguosB ;
// Ciclo sui triangoli delle mesh
int nTriaNumA = GetTriangleSize() ;
int nTriaNumB = SurfB.GetTriangleSize() ;
// Setto il triangolo come né fuori né dentro
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
m_vTria[nTA].nTempPart = 0 ;
@@ -1113,55 +1144,58 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
SurfB.m_vTria[nTB].nETempFlag[1] = 0 ;
SurfB.m_vTria[nTB].nETempFlag[2] = 0 ;
}
// Resetto e ricalcolo la HashGrid della superficie B
SurfB.ResetHashGrids3d() ;
// Scorro i triangoli della superficie A
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
// Se il triangolo A non è valido, continuo
Triangle3d trTriaA ;
if ( ! GetTriangle( nTA, trTriaA) || ! trTriaA.Validate( true))
continue ;
// Box del triangolo A
BBox3d b3dTriaA ;
trTriaA.GetLocalBBox( b3dTriaA) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ;
SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
// I scorro tutti i triangoli di B che intersecano il box di A
for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) {
// Se il triangolo B non è valido, continuo
Triangle3d trTriaB ;
if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true))
continue ;
// Interseco i triangoli
Point3d ptSegSt, ptSegEn ;
TRIA3DVECTOR vTria ;
int nIntType = IntersTriaTria( trTriaA, trTriaB, ptSegSt, ptSegEn, vTria) ;
if ( nIntType == ITTT_EDGE_EDGE_SEG ||
nIntType == ITTT_EDGE_INT ||
nIntType == ITTT_INT_EDGE ||
nIntType == ITTT_INT_INT_SEG) {
// Assegno i dati di intersezione
// se l'intersezione è identificabile con un segmento...
if ( nIntType == ITTT_EDGE_EDGE_SEG || nIntType == ITTT_EDGE_INT ||
nIntType == ITTT_INT_EDGE || nIntType == ITTT_INT_INT_SEG) {
// Assegno i dati di intersezione per la superficie A
IntSegment CurInters ;
if ( nIntType == ITTT_EDGE_EDGE_SEG || nIntType == ITTT_EDGE_INT ||
nIntType == ITTT_INT_EDGE || nIntType == ITTT_INT_INT_SEG) {
CurInters.ptSt = ptSegSt ;
CurInters.ptEn = ptSegEn ;
CurInters.bDegenerate = false ;
}
else {
CurInters.ptSt = ptSegSt ;
CurInters.ptEn = ptSegSt ;
CurInters.bDegenerate = true ;
}
CurInters.vtOuter = trTriaB.GetN() ;
CurInters.ptSt = ptSegSt ; // punto iniziale del segmento
CurInters.ptEn = ptSegEn ; // punto finale del segmento
CurInters.bDegenerate = false ; // segmento non degenere
CurInters.vtOuter = trTriaB.GetN() ; // perpendicolare alla tangente ( oritentata )
CurInters.vtOuter -= ( ( CurInters.vtOuter * trTriaA.GetN()) * trTriaA.GetN()) ;
CurInters.vtOuter.Normalize() ;
// Salvo intersezione per superficie A
bool bIntOnEndgeA = false ;
if ( nIntType != ITTT_EDGE_EDGE_SEG && nIntType != ITTT_EDGE_INT) {
// controllo se tale segmento non è già contenuto
auto itA = LineMapA.find( nTA) ;
if ( itA != LineMapA.end()) {
if ( itA != LineMapA.end())
itA->second.emplace_back( CurInters) ;
}
else {
Chain chTemp ;
chTemp.emplace_back( CurInters) ;
@@ -1171,6 +1205,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
else
bIntOnEndgeA = true ;
// Inverto i dati del segmento per intersezione con superficie B
swap( CurInters.ptSt, CurInters.ptEn) ;
CurInters.vtOuter = trTriaA.GetN() ;
CurInters.vtOuter -= ( ( CurInters.vtOuter * trTriaB.GetN()) * trTriaB.GetN()) ;
@@ -1179,10 +1214,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
// Salvo intersezione per superficie B
bool bIntOnEndgeB = false ;
if ( nIntType != ITTT_EDGE_EDGE_SEG && nIntType != ITTT_INT_EDGE) {
// controllo se tale segmento non è già contenuto
auto itB = LineMapB.find( vNearTria[nTB]) ;
if ( itB != LineMapB.end()) {
if ( itB != LineMapB.end())
itB->second.emplace_back( CurInters) ;
}
else {
Chain chTemp ;
chTemp.emplace_back( CurInters) ;
@@ -1191,8 +1226,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
else
bIntOnEndgeB = true ;
// Intersezione edge-interno
// caso di Intersezione edge-interno ( per superificie A con B)
if ( bIntOnEndgeA && ! bIntOnEndgeB) {
// calcolo la massima distanza e il tratto ad essa associato
double dMaxDist = 0. ;
int nSegMaxDist = - 1 ;
for ( int nVA = 0 ; nVA < 3 ; ++ nVA) {
@@ -1203,7 +1240,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
if ( nSegMaxDist >= 0) {
// Cerco qual'è il segmento di contatto per dichiararlo come invalicabile
// Cerco qual è il segmento di contatto per dichiararlo come invalicabile
int nVA ;
for ( nVA = 0 ; nVA < 3 ; ++ nVA) {
if ( abs( ( trTriaA.GetP( nVA) - trTriaB.GetP( 0)) * trTriaB.GetN()) < EPS_SMALL &&
@@ -1215,8 +1252,9 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
m_vTria[nTA].nETempFlag[nVA] = m_vTria[nTA].nTempPart ;
}
}
// Intersezione interno-edge
// caso di Intersezione interno-edge ( per superficie A con B)
else if ( ! bIntOnEndgeA && bIntOnEndgeB) {
// calcolo la massima distanza e il tratto ad essa associato
double dMaxDist = 0. ;
int nSegMaxDist = - 1 ;
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
@@ -1227,7 +1265,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
if ( nSegMaxDist >= 0) {
// Cerco qual'è il segmento di contatto per dichiararlo come invalicabile
// Cerco qual è il segmento di contatto per dichiararlo come invalicabile
int nVB ;
for ( nVB = 0 ; nVB < 3 ; ++ nVB) {
if ( abs( ( trTriaB.GetP( nVB) - trTriaA.GetP(0)) * trTriaA.GetN()) < EPS_SMALL &&
@@ -1266,11 +1304,11 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
}
// Ritriangolarizzo i triangoli delle superfici
RetriangulationForBooleanOperation( LineMapA, AmbiguosA, *this, bModif) ;
RetriangulationForBooleanOperation( LineMapB, AmbiguosB, SurfB, bModif) ;
// Se i triangoli delle superfici non si intersecano, una delle due è totalmente interna o esterna all'altra.
// non mi basta fare un controllo sulle bbox perché non so come sono orientate le superfici e che potrebbero anche non essere chiuse
bool bRetriangulated = true ;
@@ -1309,7 +1347,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = 1 ;
else if (nInOutNum == -1) {
else if ( nInOutNum == -1) {
bSame = false ;
break ;
}
@@ -1317,7 +1355,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = -1 ;
else if (nInOutNum == 1) {
else if ( nInOutNum == 1) {
bSame = false ;
break ;
}
@@ -1325,23 +1363,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
// se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino
// e ricalcolo l'informazione che mi dà la sua normale
if ( ! bSame ) {
if ( ! bSame) {
Point3d ptBar_tot ;
for (int nTriaNum : vnTriaNum) {
SurfB.GetTriangle( nTriaNum, trTriaB) ;
ptBar_tot += trTriaB.GetCentroid();
}
ptBar_tot /= (int)vnTriaNum.size() ;
for (int nTriaNum : vnTriaNum) {
ptBar_tot /= int( vnTriaNum.size()) ;
for ( int nTriaNum : vnTriaNum) {
SurfB.GetTriangle( nTriaNum, trTriaB) ;
Point3d ptInters1, ptInters2 ;
int nInters = IntersLineTria(ptFirstV, ptBar_tot, trTriaB, ptInters1, ptInters2, true) ;
if (nInters == ILTT_NO)
int nInters = IntersLineTria( ptFirstV, ptBar_tot, trTriaB, ptInters1, ptInters2, true) ;
if ( nInters == ILTT_NO)
continue ;
else if ( nInters == ILTT_IN ) {
if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL)
else if ( nInters == ILTT_IN) {
if ( ( ptFirstV - trTriaB.GetP( 0)) * trTriaB.GetN() < - EPS_SMALL)
nInOutNum = 1 ;
else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL)
else if ( ( ptFirstV - trTriaB.GetP( 0)) * trTriaB.GetN() > EPS_SMALL)
nInOutNum = -1 ;
break ;
}
@@ -1355,9 +1393,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
++ nVertNum ;
}
}
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA)
m_vTria[nTA].nTempPart = nInOutNum ;
}
nVertNum = 0 ;
nCurVert = SurfB.GetFirstVertex( ptFirstV) ;
nInOutNum = 0 ;
@@ -1374,7 +1413,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
DistCalculator.GetDist( dDist) ;
// potrei trovare più triangolo equidistanti, li salvo tutti
if ( DistPointTriangle( ptFirstV, trTriaA).GetDist( dDist)) {
if ( abs(dDist - dMinDist) < EPS_SMALL)
if ( abs( dDist - dMinDist) < EPS_SMALL)
vnTriaNum.push_back( nTA) ;
else if ( dDist < dMinDist){
vnTriaNum.clear() ;
@@ -1392,7 +1431,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() < - EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = 1 ;
else if (nInOutNum == -1) {
else if ( nInOutNum == -1) {
bSame = false ;
break ;
}
@@ -1400,7 +1439,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = -1 ;
else if (nInOutNum == 1) {
else if ( nInOutNum == 1) {
bSame = false ;
break ;
}
@@ -1408,23 +1447,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
// se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino
// e ricalcolo l'informazione che mi dà la sua normale
if ( ! bSame ) {
if ( ! bSame) {
Point3d ptBar_tot ;
for (int nTriaNum : vnTriaNum) {
for ( int nTriaNum : vnTriaNum) {
GetTriangle( nTriaNum, trTriaA) ;
ptBar_tot += trTriaA.GetCentroid();
}
ptBar_tot /= (int)vnTriaNum.size() ;
for (int nTriaNum : vnTriaNum) {
ptBar_tot /= int( vnTriaNum.size()) ;
for ( int nTriaNum : vnTriaNum) {
GetTriangle( nTriaNum, trTriaA) ;
Point3d ptInters1, ptInters2 ;
int nInters = IntersLineTria(ptFirstV, ptBar_tot, trTriaA, ptInters1, ptInters2, true) ;
if (nInters == ILTT_NO)
int nInters = IntersLineTria( ptFirstV, ptBar_tot, trTriaA, ptInters1, ptInters2, true) ;
if ( nInters == ILTT_NO)
continue ;
else if ( nInters == ILTT_IN ) {
if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() < - EPS_SMALL)
else if ( nInters == ILTT_IN) {
if ( ( ptFirstV - trTriaA.GetP( 0)) * trTriaA.GetN() < - EPS_SMALL)
nInOutNum = 1 ;
else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL)
else if ( ( ptFirstV - trTriaA.GetP( 0)) * trTriaA.GetN() > EPS_SMALL)
nInOutNum = -1 ;
break ;
}
@@ -1438,9 +1477,8 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
++ nVertNum ;
}
}
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB)
SurfB.m_vTria[nTB].nTempPart = nInOutNum ;
}
}
// Se c'è stata una ritriangolazione di almeno un triangolo, NON siamo nel caso di tutto dentro o tutto fuori.
@@ -1449,11 +1487,12 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
AmbiguosTriangleManager( AmbiguosA, *this) ;
AmbiguosTriangleManager( AmbiguosB, SurfB) ;
}
bool bContinue = true ;
// Se avvenuta modifica, aggiorno tutto
if ( bModif)
bContinue = ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ;
// Triangoli sovrapposti
if ( bContinue) {
int nTriaNum2A = GetTriangleSize() ;
@@ -1491,7 +1530,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
return true ;
}
return true ;
}
@@ -1620,48 +1659,83 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
return true ;
}
// Surf A è la superficie attuale ( this), SurfB è l'altra
SurfTriMesh SurfB ;
SurfB.CopyFrom( &Other) ;
// scalo la superficie
Frame3d frScalingRef ;
frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ;
Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
// ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo
IntersectTriMeshTriangle( SurfB) ;
// assegno un medesimo indice ai triangoli che non interferiscono con altri
IdentifyParts() ;
SurfB.IdentifyParts() ;
// rimozione dei triangoli di A con proprietà -1 e -2
int nTriaNumA = GetTriangleSize() ;
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
if ( m_vTria[nTA].nTempPart == - 1 || m_vTria[nTA].nTempPart == - 2)
RemoveTriangle( nTA) ;
}
// aggiunta dei triangoli di B con proprietà +1
int nPrevMaxTFlag = m_nMaxTFlag ;
int nTriaNumB = SurfB.GetTriangleSize() ;
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
if ( SurfB.m_vTria[nTB].nTempPart == 1) {
int nNewVert[3] ;
for ( int nV = 0 ; nV < 3 ; ++ nV) {
for ( int nV = 0 ; nV < 3 ; ++ nV)
nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ;
}
if ( nPrevMaxTFlag == m_nMaxTFlag)
++ m_nMaxTFlag ;
AddTriangle( nNewVert, m_nMaxTFlag) ;
}
}
// sistemazioni varie
bool bOk = ( AdjustVertices() && DoCompacting()) ;
bool bModified = false ;
bOk = bOk && RemoveDoubleTriangles( bModified) ;
if ( bModified)
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
bOk = bOk && RemoveTJunctions( bModified) ;
if ( bModified)
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
// rimuovo tutte le parti esterne all'intersezione
int nParts = GetPartCount() ;
if ( nParts > 1) {
for ( int i = 0 ; i < nParts ; ++ i) {
// recupero i triangoli della stessa Part
INTVECTOR vTriaPart ;
for ( int j = 0 ; j < int( m_vTria.size()) ; ++ j)
if ( m_vTria[j].nPart == i)
vTriaPart.push_back( j) ;
// controllo se il loro box interferisce con il box della superficie B
bool bErasePart = true ;
for ( int j = 0 ; j < int( vTriaPart.size()) && bErasePart ; ++ j) {
// Se il triangolo A non è valido, continuo
Triangle3d Tria ;
if ( ! GetTriangle( j, Tria) || ! Tria.Validate( true))
continue ;
// Box del triangolo A
BBox3d b3dTriaA ; Tria.GetLocalBBox( b3dTriaA) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ; SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
bErasePart = int( vNearTria.size() == 0) ;
}
if ( bErasePart)
RemovePart( i) ;
}
}
// scalo alle dimensioni originali
Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ;
if ( ! SimplifyFacets())
+1 -1
View File
@@ -901,7 +901,7 @@ SurfTriMesh::UpdateFacetEdging( void)
int nTAdj = Tria.nIdAdjac[nE] ;
if ( Tria.nETempFlag[nE] == 0) {
if ( nTAdj == SVT_NULL) {
m_vFacEdge.emplace_back( Tria.nIdVert[nE], Tria.nIdVert[nE2], Tria.nIdFacet, SVT_NULL, 0.) ;
m_vFacEdge.emplace_back( Tria.nIdVert[nE], Tria.nIdVert[nE2], Tria.nIdFacet, SVT_NULL, 180.) ;
}
else if ( Tria.nIdFacet != m_vTria[nTAdj].nIdFacet) {
// calcolo l'angolo tra le facce ( 0 = allineate, > 0 convesse, < 0 concave)
+1 -1
View File
@@ -531,7 +531,7 @@ SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
if ( AreSamePointApprox( OrigChain[nLastOrig], ChainToAdd[0].ptSt)) {
for ( int nPt = 1 ; nPt <= nLastToAdd ; ++ nPt) {
if ( nPt == nLastToAdd) {
if ( ! AreSamePointApprox(OrigChain[0], ChainToAdd[nPt].ptSt))
if ( ! AreSamePointApprox( OrigChain[0], ChainToAdd[nPt].ptSt))
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
}
else if ( nPt == 1) {
+387 -30
View File
@@ -30,7 +30,8 @@ using namespace std ;
//----------------------------------------------------------------------------
Tree::Tree( void)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}),
m_bSplitPatches( true), m_bTestMode( false)
{
Point3d ptBl( 0, 0), ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
Cell cRoot( ptBl, ptTr) ;
@@ -39,7 +40,8 @@ Tree::Tree( void)
//----------------------------------------------------------------------------
Tree::Tree( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d& ptMin, const Point3d& ptMax)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}),
m_bSplitPatches( true), m_bTestMode( false)
{
SetSurf( pSrfBz, bSplitPatches, ptMin, ptMax) ;
}
@@ -49,6 +51,15 @@ Tree::~Tree( void)
{
}
//----------------------------------------------------------------------------
Tree::Tree( const Point3d ptBl, const Point3d ptTr)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}),
m_bSplitPatches( true), m_bTestMode( false)
{
Cell cRoot( ptBl, ptTr) ;
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
}
//----------------------------------------------------------------------------
void
Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMin, const Point3d& ptMax)
@@ -62,6 +73,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
m_vPlApprox.clear() ;
m_vChunk.clear() ;
m_vPolygons.clear() ;
m_vPlLoop2D.clear() ;
m_pSrfBz = pSrfBz ;
m_bSplitPatches = bSplitPatches ;
@@ -219,16 +231,18 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
// devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti
// in caso devo fare uno split nell'altra direzione
bool bOk = false ;
bool bCapped0 = true, bCapped1 = true ;
Point3d ptV0, ptV1 ;
// controllo se tutti i punti sull'isoparametrica sono uguali
bool bPole0 = true, bPole1 = true ;
Point3d ptU0, ptU1 ;
// controllo se tutti i punti di controllo sull'isoparametrica sono uguali
for ( int i = 1 ; i < nDegV * nSpanV + 1 ; ++ i) {
ptV0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ;
bCapped0 = bCapped0 && AreSamePointApprox( ptP00, ptV0) ;
ptV1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ;
bCapped1 = bCapped1 && AreSamePointApprox( ptP10, ptV1) ;
ptU0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ;
bPole0 = bPole0 && AreSamePointApprox( ptP00, ptU0) ;
ptU1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ;
bPole1 = bPole1 && AreSamePointApprox( ptP10, ptU1) ;
}
if ( bCapped0 && bCapped1) {
m_vbPole[1] = bPole0 ;
m_vbPole[3] = bPole1 ;
if ( bPole0 && bPole1) {
m_mTree[0].SetSplitDirVert( true) ;
Split( 0) ;
m_mTree[1].SetSplitDirVert( true) ;
@@ -248,16 +262,18 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
// devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti
// in caso devo fare uno split nell'altra direzione
bool bOk = false ;
bool bCapped0 = true, bCapped1 = true ;
Point3d ptU0, ptU1 ;
bool bPole0 = true, bPole1 = true ;
Point3d ptV0, ptV1 ;
// controllo se tutti i punti sull'isoparametrica sono uguali
for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) {
ptU0 = m_pSrfBz->GetControlPoint( i, &bOk) ;
bCapped0 = bCapped0 && AreSamePointApprox( ptP00, ptU0) ;
ptU1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ;
bCapped1 = bCapped1 && AreSamePointApprox( ptP01, ptU1) ;
ptV0 = m_pSrfBz->GetControlPoint( i, &bOk) ;
bPole0 = bPole0 && AreSamePointApprox( ptP00, ptV0) ;
ptV1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ;
bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ;
}
if ( bCapped0 && bCapped1) {
m_vbPole[0] = bPole0 ;
m_vbPole[2] = bPole1 ;
if ( bPole0 && bPole1) {
m_mTree[0].SetSplitDirVert( false) ;
Split( 0) ;
m_mTree[1].SetSplitDirVert( false) ;
@@ -931,6 +947,7 @@ Tree::Balance()
void
Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
{
// le celle restituite sono ordinate per x crescente
if ( vTopNeighs.empty()) {
if ( m_mTree.at( nId).m_nTop == -2)
return ;
@@ -1000,6 +1017,7 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
vector<Cell> vCells ;
for ( int k : vTopNeighs)
vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per x crescente
sort( vCells.begin(), vCells.end(), Cell::minorX) ;
vTopNeighs.clear() ;
for ( Cell c : vCells)
@@ -1011,6 +1029,7 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
void
Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
{
// le celle restituite sono ordinate per x crescente
if ( vBottomNeighs.empty()) {
if ( m_mTree.at( nId).m_nBottom == -2)
return ;
@@ -1080,6 +1099,7 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
vector<Cell> vCells ;
for ( int k : vBottomNeighs)
vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per x crescente
sort( vCells.begin(), vCells.end(), Cell::minorX) ;
vBottomNeighs.clear() ;
for ( Cell c : vCells)
@@ -1090,6 +1110,7 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
void
Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
{
// le celle restituite sono ordinate per y crescente
if ( vLeftNeighs.empty()) {
if ( m_mTree.at( nId).m_nLeft == -2)
return ;
@@ -1159,6 +1180,7 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
vector<Cell> vCells ;
for ( int k : vLeftNeighs)
vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per y crescente
sort( vCells.begin(), vCells.end(), Cell::minorY) ;
vLeftNeighs.clear() ;
for ( Cell c : vCells)
@@ -1169,6 +1191,7 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
void
Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
{
// le celle restituite sono ordinate per y crescente
if ( vRightNeighs.empty()) {
if ( m_mTree.at( nId).m_nRight == -2)
return ;
@@ -1238,6 +1261,7 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
vector<Cell> vCells ;
for ( int k : vRightNeighs)
vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per y crescente
sort( vCells.begin(), vCells.end(), Cell::minorY) ;
vRightNeighs.clear() ;
for ( Cell c : vCells)
@@ -1372,6 +1396,12 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons)
else {
POLYLINEVECTOR vPolygonsBasic ;
GetPolygonsBasic( vPolygonsBasic) ;
// aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim
for ( int i = 0 ; i < 4 ; ++i) {
m_vCEdge2D.emplace_back() ;
m_vCEdge2D.back().second.Init( false, EPS_SMALL, 1) ;
}
// percorro i loop, trovo le intersezioni con le celle e le categorizzo
if ( ! TraceLoopLabelCell( vPolygonsBasic))
return false ;
// scorro sulle celle e costruisco i poligoni
@@ -1418,9 +1448,17 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons)
//----------------------------------------------------------------------------
bool
Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells)
{
if ( m_vPolygons.empty()) {
// condizioni per il calcolo dei poligoni di base
if ( m_vPolygons.empty() || // se non li ho mai calcolati
( ! m_vPolygons.empty() && ! vCells.empty()) || // se ho già calcolato dei poligoni ma ne sto chiedendo di un altro gruppo di celle
( vCells.empty() && m_vPolygons.size() != m_vnLeaves.size())) { // se sto chiedendo i poligoni di tutte le celle, ma i poligoni già calcolati sono meno delle celle
m_vPolygons.clear() ;
// se non ho dato un elenco di celle in input do per scontato che la chiamata sia per calcolare i poligoni di tutte le foglie
if ( vCells.empty())
vCells = m_vnLeaves ;
PNTVECTOR vVertices ;
INTVECTOR vNeigh ;
// setto le celle che sono sul LeftEdge e sul TopEdge
@@ -1440,7 +1478,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons)
bool bBottomRight , bTopLeft ;
// scorro lungo tutte le celle leaves e oltre agli angoli della cella aggiungo alla polyline della cella anche i vertici, delle celle adiacenti,
// che sono sui lati della cella corrente
for ( int nId : m_vnLeaves) {
// N.B. :i poligoni sono costruiti a partire dal ptBL !!!
for ( int nId : vCells) {
vVertices.clear() ;
vNeigh.clear() ;
vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ;
@@ -1776,6 +1815,40 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
return nCells ;
}
//----------------------------------------------------------------------------
bool
Tree::UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt)
{
Point3d ptLast ;
pl.GetLastPoint( ptLast) ;
if ( pl.AddUPoint( nCount, pt))
++ nCount ;
if ( pl.GetPointNbr() != 1 ) {
Vector3d vtDir = pt - ptLast ;
if ( ! vtDir.Normalize())
return false ;
// se sono allineato con gli edge della cella ROOT
int nEdge = -1 ;
if ( abs( vtDir.x) > 1 - EPS_SMALL) {
if ( pt.y < EPS_SMALL)
nEdge = 2 ;
else if ( m_nSpanV * SBZ_TREG_COEFF - pt.y < EPS_SMALL)
nEdge = 0 ;
}
else if ( abs( vtDir.y) > 1 - EPS_SMALL) {
if ( pt.x < EPS_SMALL )
nEdge = 1 ;
else if ( m_nSpanU * SBZ_TREG_COEFF - pt.x < EPS_SMALL )
nEdge = 3 ;
}
if ( nEdge != -1) {
m_vCEdge2D[nEdge].second.AddCurve( m_vCEdge2D[nEdge].first.size() + 1, ptLast, vtDir, pt, vtDir) ;
m_vCEdge2D[nEdge].first.emplace_back( BIPOINT( ptLast, pt)) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
@@ -1788,6 +1861,9 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
// percorro i loop trovando le interezioni con le celle e riempiendo i vettori m_vInters delle varie celle
for ( int i = 0 ; i < (int) m_vPlApprox.size() ; ++ i) {
PolyLine plLoop = get<0>( m_vPlApprox[i]) ;
// creo la polyline che aggiunge alla polyline originale degli split dove interseca le celle ( serve per ricostruire gli edge aperti della superficie)
PolyLine plLoopSplit ;
int nPtLoopSplit = 0 ;
// controllo se il loop è CCW o CW
bool bCCW = get<1>( m_vPlApprox[i]) ;
// trovo in quale cella è il ptStart
@@ -1799,14 +1875,17 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
advance( ptSecond, 1) ;
CurveLine clFirst ;
clFirst.Set( ptFirst->first, ptSecond->first) ;
// aggiorno la polyline splittata
UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptFirst->first) ;
// individuo la cella da cui parte il loop
INTVECTOR nCells = FindCell( ptStart, clFirst) ;
int nId ;
if ( ! nCells.empty())
nId = nCells.back() ;
else
// il loop è risultato fuori dallo spazio parametrico
return false ;
// il loop è risultato fuori dallo spazio parametrico // può capitare se ho una superficie trimmata con più chunk con bbox separate.
// ma potrebbe anche essere indicatore di un errore
continue ;
int nFirstCell = nId ;
// trovo quali punti della polyline sono nella cella e l'intersezione
PNTVECTOR vptInters ;
@@ -1862,9 +1941,13 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
m_mTree[nId].m_vInters.back().bCCW = bCCW ;
// salvo il chunk del loop
m_mTree[nId].m_vInters.back().nChunk = m_mChunk[i] ;
// aggiorno la polyline splittata
UpdateSplitLoop( plLoopSplit, nPtLoopSplit, vptInters.back()) ;
}
// aggiungo la fine del segmento nel vettore delle intersezioni
vptInters.push_back( ptCurr) ;
// aggiorno la polyline splittata
UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ;
}
if ( nId == nFirstCell)
vptInters.pop_back() ;
@@ -1913,6 +1996,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
m_mTree[nId].m_vInters[nPass].nOut = nOut ;
}
}
// salvo la polyline splittata
m_vPlLoop2D.emplace_back( plLoopSplit) ;
}
// riordino i vettori di intersezione per ogni cella e setto il flag RightEdgeIn
@@ -2077,14 +2162,14 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
// -1 se la curva è sempre dentro la cella
Point3d ptInters ;
int nEdge2 ;
//int nEdge2 ;
if ( ptEnd.y >= ptTR.y && ptEnd.x <= ptTR.x) {
nEdge = 0 ;
//nEdge = 0 ;
// lato sopra
clEdge.Set( ptTR, ptTl) ;
// lato sinistro
if ( ptEnd.x < ptBL.x) {
nEdge2 = 1 ;
//nEdge2 = 1 ;
clEdge2.Set( ptTl, ptBL) ;
}
}
@@ -2094,7 +2179,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
clEdge.Set( ptTl, ptBL) ;
// lato sotto
if ( ptEnd.y < ptBL.y) {
nEdge2 = 2 ;
//nEdge2 = 2 ;
clEdge2.Set( ptBL, ptBr) ;
}
}
@@ -2104,7 +2189,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
clEdge.Set( ptBL, ptBr) ;
// lato destro
if ( ptEnd.x > ptTR.x) {
nEdge2 = 3 ;
//nEdge2 = 3 ;
clEdge2.Set( ptBr, ptTR) ;
}
}
@@ -2114,7 +2199,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
clEdge.Set( ptBr, ptTR) ;
// lato sopra
if ( ptEnd.y > ptTR.y) {
nEdge2 = 0 ;
//nEdge2 = 0 ;
clEdge2.Set( ptTR, ptTl) ;
}
}
@@ -2917,12 +3002,12 @@ Tree::CheckIfBefore( const PolyLine& pl, int nEdge) const
bool
Tree::CheckIfBefore( const Inters& inA) const
{
// questa funzione è pensata in riferimento al lato 3, quindi nessuno dei due punti può stare su Edge = 3
// questa funzione è pensata in riferimento al lato 3, quindi nessuno dei due punti può stare su Edge = 3 ( funzione usata per definire RightEdgeIn)
// controllo se l'ingresso è prima dell'uscita
int nEdge1 = inA.nIn ;
int nEdge2 = inA.nOut ;
if ( nEdge1 == -1)
return false ;
return false ; // questo return è usato in modo improprio perché non fa capire che l'intersezione analizzata non era corretta
PolyLine pl ;
pl.AddUPoint( 0, inA.vpt.back()) ;
pl.AddUPoint( 1, inA.vpt[0]) ;
@@ -3520,3 +3605,275 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges)
{
// se la superficie non è trimmata ricostruisco dalle celle al bordo
if ( ! m_bTrimmed) {
INTMATRIX vEdges ; // le righe sono gli edge a partire dallo 0, le colonne sono le celle che compongono quell'edge
// recupero le celle sui quattro bordi
vEdges.emplace_back() ;
GetRootNeigh( 0, vEdges[0]) ;
// le celle sui bordi orizzontali sono ordinate per x o y crescente, ma i io voglio costruire gli edge in senso antiorario a partire dal ptTR,
// quindi devo invertire gli Edge 0 e 1
reverse( vEdges[0].begin(), vEdges[0].end()) ;
vEdges.emplace_back() ;
GetRootNeigh( 1, vEdges[1]) ;
reverse( vEdges[1].begin(), vEdges[1].end()) ;
vEdges.emplace_back() ;
GetRootNeigh( 2, vEdges[2]) ;
vEdges.emplace_back() ;
GetRootNeigh( 3, vEdges[3]) ;
// recupero i poligoni base delle celle sui bordi
POLYLINEMATRIX mPL ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[0], vEdges[0]) ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[1], vEdges[1]) ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[2], vEdges[2]) ;
mPL.emplace_back() ;
GetPolygonsBasic( mPL[3], vEdges[3]) ;
// scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato
for ( int i = 0 ; i < int( mPL.size()) ; ++i) {
mPLEdges.emplace_back() ;
mPLEdges.back().emplace_back() ;
int nPtCount = 0 ;
// scorro sui poligoni delle celle di un lato
for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) {
Point3d pt ; mPL[i][c].GetFirstPoint( pt) ;
Point3d pt3d ;
// a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato
if ( i == 0) {
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) {
continue ;
}
mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[2]) ;
++ nPtCount ;
// scorro fino alla fine di quel lato
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft())) {
m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ;
++ nPtCount ;
}
mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[3]) ;
++ nPtCount ;
}
else if ( i == 1 ) {
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) {
continue ;
}
mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[3]) ;
++ nPtCount ;
// scorro fino alla fine di quel lato
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) {
m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ;
++ nPtCount ;
}
mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[0]) ;
++ nPtCount ;
}
else if ( i == 2) {
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) {
continue ;
}
mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[0]) ;
++ nPtCount ;
// scorro fino alla fine di quel lato
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) {
m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ;
++ nPtCount ;
}
mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[1]) ;
++ nPtCount ;
}
else if ( i == 3) {
while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) {
continue ;
}
mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[1]) ;
++ nPtCount ;
// scorro fino alla fine di quel lato
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) {
m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ;
++ nPtCount ;
}
mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[2]) ;
++ nPtCount ;
}
}
}
}
// se la superficie è trimmata ricostruisco dai loop splittati ricostruiti durante il TraceLoop
else {
// per ogni edge creo le compo che compongono l'edge dopo i trim ( possono essere più compo separate tra loro)
for ( int i = 0 ; i < 4 ; ++i) {
mPLEdges.emplace_back() ;
INTVECTOR vId ;
Point3d ptNear = m_mTree.at(-1).GetBottomLeft() ;
while( m_vCEdge2D[i].second.GetChainFromNear(ptNear, false, vId) ) {
PolyLine pl3D ;
int nInd = abs( vId[0]) - 1 ;
Point3d pt2D = m_vCEdge2D[i].first[nInd].first ;
Point3d pt3D ; m_pSrfBz->GetPointD1D2( pt2D.x / SBZ_TREG_COEFF, pt2D.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ;
pl3D.AddUPoint( 0, pt3D) ;
int nCount = 1 ;
for ( int j = 1 ; j < int( vId.size()) ; ++j) {
nInd = abs( vId[j]) - 1 ;
pt2D = m_vCEdge2D[i].first[nInd].second ;
m_pSrfBz->GetPointD1D2( pt2D.x / SBZ_TREG_COEFF, pt2D.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ;
if ( pl3D.AddUPoint( nCount, pt3D))
++ nCount ;
}
// qui devo fare dei controlli prima di aggiungere questa polyline?
mPLEdges[i].emplace_back( pl3D) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts)
{
// questa funzione dà per scontato di stare lavorando sulla root di uno spazio parametrico di cui si sta solamente calcolando
// il Contour. La funzione da chiamare dopo questa è la CreateCellContour.
// i tagli sono sempre delle linee che tagliano da parte a parte la cella, quindi sono curve aperte
if ( m_mTree.size() > 1)
return false ;
int nRoot = -1 ;
for ( int i = 0 ; i < int( vCuts.size()); ++i) {
PolyLine pl = vCuts.at( i) ;
m_mTree.at( nRoot).m_vInters.emplace_back() ;
Point3d pt ; pl.GetFirstPoint( pt) ;
int nEdgeIn ;
// se non trovo il primo punto esattamente su un lato, estendo il primo tratto della polyline all'inditro finchè trovo un'intersezione con un lato
// questa intersezione diventa il nuovo primo punto del vettore intersezione
if ( ! OnWhichEdge(nRoot, pt, nEdgeIn) ) {
Point3d ptSecond ; pl.GetNextPoint( ptSecond) ;
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ; pCL->SetPVL( ptSecond, pt - ptSecond, 1e6) ;
PtrOwner<ICurveLine> pCL0( CreateCurveLine()) ; pCL0->Set( m_mTree.at(-1).GetTopRight(), m_mTree.at(-1).GetTopLeft()) ;
PtrOwner<ICurveLine> pCL1( CreateCurveLine()) ; pCL1->Set( m_mTree.at(-1).GetTopLeft(), m_mTree.at(-1).GetBottomLeft()) ;
PtrOwner<ICurveLine> pCL2( CreateCurveLine()) ; pCL2->Set( m_mTree.at(-1).GetBottomLeft(), m_mTree.at(-1).GetBottomRight()) ;
PtrOwner<ICurveLine> pCL3( CreateCurveLine()) ; pCL3->Set( m_mTree.at(-1).GetBottomRight(), m_mTree.at(-1).GetTopRight()) ;
IntersCurveCurve icc0( *pCL, *pCL0) ;
IntersCurveCurve icc1( *pCL, *pCL1) ;
IntersCurveCurve icc2( *pCL, *pCL2) ;
IntersCurveCurve icc3( *pCL, *pCL3) ;
IntCrvCrvInfo iccInfo ;
if (icc0.GetIntersCount() != 0)
icc0.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc1.GetIntersCount() != 0)
icc1.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc2.GetIntersCount() != 0)
icc2.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc3.GetIntersCount() != 0)
icc3.GetIntCrvCrvInfo( 0, iccInfo) ;
pt = iccInfo.IciA[0].ptI ;
if ( ! OnWhichEdge(nRoot, pt, nEdgeIn))
return false ;
}
m_mTree.at( nRoot).m_vInters.back().nIn = nEdgeIn ;
PNTVECTOR vInters ;
vInters.emplace_back( pt) ;
while ( pl.GetNextPoint( pt))
vInters.emplace_back( pt) ;
pl.GetLastPoint( pt) ;
int nEdgeOut ;
// se non trovo l'ultimo punto esattamente su un lato, estendo l'ultimo tratto della polyline in avnti finchè trovo un'intersezione con un lato
// questa intersezione diventa il nuovo ultimo punto del vettore intersezione
if ( ! OnWhichEdge(nRoot, pt, nEdgeOut) ) {
Point3d ptSecondToLast ; pl.GetNextPoint( ptSecondToLast) ;
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ; pCL->SetPVL( ptSecondToLast, pt - ptSecondToLast, 1e6) ;
PtrOwner<ICurveLine> pCL0( CreateCurveLine()) ; pCL0->Set( m_mTree.at(-1).GetTopRight(), m_mTree.at(-1).GetTopLeft()) ;
PtrOwner<ICurveLine> pCL1( CreateCurveLine()) ; pCL1->Set( m_mTree.at(-1).GetTopLeft(), m_mTree.at(-1).GetBottomLeft()) ;
PtrOwner<ICurveLine> pCL2( CreateCurveLine()) ; pCL2->Set( m_mTree.at(-1).GetBottomLeft(), m_mTree.at(-1).GetBottomRight()) ;
PtrOwner<ICurveLine> pCL3( CreateCurveLine()) ; pCL3->Set( m_mTree.at(-1).GetBottomRight(), m_mTree.at(-1).GetTopRight()) ;
IntersCurveCurve icc0( *pCL, *pCL0) ;
IntersCurveCurve icc1( *pCL, *pCL1) ;
IntersCurveCurve icc2( *pCL, *pCL2) ;
IntersCurveCurve icc3( *pCL, *pCL3) ;
IntCrvCrvInfo iccInfo ;
if (icc0.GetIntersCount() != 0)
icc0.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc1.GetIntersCount() != 0)
icc1.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc2.GetIntersCount() != 0)
icc2.GetIntCrvCrvInfo( 0, iccInfo) ;
else if (icc3.GetIntersCount() != 0)
icc3.GetIntCrvCrvInfo( 0, iccInfo) ;
pt = iccInfo.IciA[0].ptI ;
vInters.pop_back() ;
vInters.emplace_back( pt) ;
if ( ! OnWhichEdge(nRoot, pt, nEdgeOut))
return false ;
}
m_mTree.at( nRoot).m_vInters.back().vpt = vInters ;
m_mTree.at( nRoot).m_vInters.back().nOut = nEdgeOut ;
}
// chiamo una funzione per renderli coerenti
AdjustCuts() ;
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::AdjustCuts( void)
{
if ( int( m_mTree.at( -1).m_vInters.size()) == 1)
return true ;
// li riordino per ordine di quali taglio incontrerei percorrendo il bordo della cella a partire da ptTR
sort( m_mTree.at( -1).m_vInters.begin(), m_mTree.at( -1).m_vInters.end(), [](Inters& a, Inters& b){ return Inters::FirstEncounter(a,b) ;}) ;
// ora controllo che le intersezioni che trovo siano ingressi alternati ad uscite, sennò inverto l'intersezione
bool bPreviousWasStart = m_mTree.at( -1).m_vInters.at(0).bSortedbyStart ;
for ( int i = 0 ; i < int( m_mTree.at( -1).m_vInters.size()); ++i) {
if ( m_mTree.at( -1).m_vInters.at(i).bSortedbyStart == bPreviousWasStart) {
reverse( m_mTree.at( -1).m_vInters.at(i).vpt.begin(), m_mTree.at( -1).m_vInters.at(i).vpt.end()) ;
int nEdgeOutNew = m_mTree.at( -1).m_vInters.at(i).nIn ;
m_mTree.at( -1).m_vInters.at(i).nIn = m_mTree.at( -1).m_vInters.at(i).nOut ;
m_mTree.at( -1).m_vInters.at(i).nOut = nEdgeOutNew ;
bPreviousWasStart = m_mTree.at( -1).m_vInters.at(i).bSortedbyStart ;
}
else
bPreviousWasStart = ! m_mTree.at( -1).m_vInters.at(i).bSortedbyStart ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::CreateCellContour( POLYLINEMATRIX& vPolygons)
{
// questa funzione è pensata per essere chiamata dopo la AddCutsToRoot, per creare il poligono di un'unica cella a cui sono stati aggiunti dei tagli
if ( m_mTree.size() > 1)
return false ;
int nRoot = -1 ;
// preparo tutto per poter chiamare la createCellPolygon
m_vnLeaves.push_back( nRoot) ;
INTVECTOR vToCheck( (int) m_mTree.at(nRoot).m_vInters.size()) ;
generate_n( vToCheck.begin(), (int) m_mTree.at(nRoot).m_vInters.size(), generator()) ;
int nPoly = 0 ;
INTVECTOR vnParentChunk ;
PolyLine pl ;
pl.AddUPoint(0, m_mTree.at(nRoot).GetTopRight()) ;
pl.AddUPoint(1, m_mTree.at(nRoot).GetTopLeft()) ;
pl.AddUPoint(2, m_mTree.at(nRoot).GetBottomLeft()) ;
pl.AddUPoint(3, m_mTree.at(nRoot).GetBottomRight()) ;
pl.Close() ;
// ora posso creare il poligono della cella con i tagli
while( (int)vToCheck.size() != 0) {
int nPolyBefore = nPoly ;
CreateCellPolygons( 0, vPolygons, vToCheck, nPoly, vnParentChunk, pl) ;
if ( nPolyBefore == nPoly)
break ;
}
return true ;
}
+116 -33
View File
@@ -18,6 +18,7 @@
#include "GeoConst.h"
#include "CurveLine.h"
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include <map>
//----------------------------------------------------------------------------
@@ -27,11 +28,12 @@ struct Inters {
int nOut ;
bool bCCW ;
int nChunk ;
bool bSortedbyStart ;
// riordino le intersezioni per lato in senso antiorario dal top
// se ho pi intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
bool operator < ( Inters& b)
{
// trovo in che ordine stanno i due strat, tenendo conto anche della possibilit che siano vertici
// trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
const auto iter1 = find( vEdges.begin(), vEdges.end(), nIn) ;
int nPos1 = std::distance( vEdges.begin(), iter1) ;
@@ -52,7 +54,7 @@ struct Inters {
pl.Close() ;
pl.GetAreaXY( dAreaB) ;
}
// se nIn un vertice sistemo il valore
// se nIn è un vertice sistemo il valore
int nEdgeIn = nIn ;
if ( nIn > 3)
nEdgeIn = nIn - 4 ;
@@ -63,6 +65,67 @@ struct Inters {
( bEqIn && nEdgeIn == 2 && vpt[0].x < b.vpt[0].x) ||
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ;
}
static bool FirstEncounter ( Inters& a, Inters& b)
{
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
// nell'intersezione salvo se il taglio è stato ordinato guardando l'ingresso o l'uscita
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
// trovo i lati di ingresso e uscita
const auto iter1 = find( vEdges.begin(), vEdges.end(), a.nIn) ;
int nPos1 = std::distance( vEdges.begin(), iter1) ;
const auto iter2 = find( vEdges.begin(), vEdges.end(), a.nOut) ;
int nPos2 = std::distance( vEdges.begin(), iter2) ;
const auto iter3 = find( vEdges.begin(), vEdges.end(), b.nIn) ;
int nPos3 = std::distance( vEdges.begin(), iter3) ;
const auto iter4 = find( vEdges.begin(), vEdges.end(), b.nOut) ;
int nPos4 = std::distance( vEdges.begin(), iter4) ;
int nFirstA = 0 ;
int nFirstB = 0 ;
// salvo l'indice del primo punto dell'intersezione che ho incontrato scorrendo il bordo da ptTR
// salvo il lato che viene prima confrontando ingresso e uscita
if ( nPos2 < nPos1) {
nPos1 = nPos2 ;
nFirstA = int( a.vpt.size()) - 1 ;
}
// se ingresso e uscita sono sullo stesso lato allora confronto le coordinate per capire se viene prima l'ingresso o l'uscita
else if ( nPos2 == nPos1 ) {
if ( nPos1 == 0 )
nFirstA = a.vpt[0].x > a.vpt.back().x ? 0 : ( int( a.vpt.size()) - 1) ;
else if ( nPos1 == 1 )
nFirstA = a.vpt[0].y > a.vpt.back().y ? 0 : ( int( a.vpt.size()) - 1) ;
else if ( nPos1 == 2 )
nFirstA = a.vpt[0].x < a.vpt.back().x ? 0 : ( int( a.vpt.size()) - 1) ;
else if ( nPos1 == 3 )
nFirstA = a.vpt[0].y < a.vpt.back().y ? 0 : ( int( a.vpt.size()) - 1) ;
}
if ( nPos4 < nPos3) {
nPos3 = nPos4 ;
nFirstB = int( b.vpt.size()) - 1 ;
}
else if ( nPos4 == nPos3 ) {
if ( nPos3 == 0 )
nFirstB = b.vpt[0].x > b.vpt.back().x ? 0 : ( int( b.vpt.size()) - 1) ;
else if ( nPos3 == 1 )
nFirstB = b.vpt[0].y > b.vpt.back().y ? 0 : ( int( b.vpt.size()) - 1) ;
else if ( nPos3 == 2 )
nFirstB = b.vpt[0].x < b.vpt.back().x ? 0 : ( int( b.vpt.size()) - 1) ;
else if ( nPos3 == 3 )
nFirstB = b.vpt[0].y < b.vpt.back().y ? 0 : ( int( b.vpt.size()) - 1) ;
}
a.bSortedbyStart = nFirstA == 0 ;
b.bSortedbyStart = nFirstB == 0 ;
// se sono diversi ritorno il confronto
if ( nPos1 != nPos3)
return nPos1 < nPos3 ;
// se sono uguali devo valutare il punto di intersezione
return ( nPos1 == 0 && a.vpt[nFirstA].x > b.vpt[nFirstB].x) ||
( nPos1 == 1 && a.vpt[nFirstA].y > b.vpt[nFirstB].y) ||
( nPos1 == 2 && a.vpt[nFirstA].x < b.vpt[nFirstB].x) ||
( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ;
}
bool operator == ( Inters& b)
{
return AreSamePointExact( vpt[0], b.vpt[0]) ;
@@ -73,8 +136,8 @@ struct Inters {
}
} ;
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da l in senso antiorario
// -1 se la curva sempre dentro la cella
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
// -1 se la curva è sempre dentro la cella
//----------------------------------------------------------------------------
class Cell
@@ -116,6 +179,10 @@ class Cell
{ return m_ptPbl ; }
Point3d GetTopRight( void) const
{ return m_ptPtr ; }
Point3d GetTopLeft( void) const
{ return Point3d( m_ptPbl.x, m_ptPtr.y) ; }
Point3d GetBottomRight( void) const
{ return Point3d( m_ptPtr.x, m_ptPbl.y); }
double GetSplitValue( void) const
{ return m_dSplit ; }
bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, senn orizzontalmente
@@ -138,24 +205,24 @@ class Cell
int m_nLeft ; // cella adiacente al lato left
int m_nRight ; // cella adiacente al lato right
int m_nParent ; // cella genitore
int m_nDepth ; // profondit della cella rispetto a root
double m_dSplit ; // parametro a cui stata splittata la cella
int m_nDepth ; // profondità della cella rispetto a root
double m_dSplit ; // parametro a cui è stata splittata la cella
int m_nChild1 ; // prima cella figlio
int m_nChild2 ; // seconda cella figlio
int m_nFlag ; // falg che indica la caratterizzazione della cella rispetto ai loop di trim
// 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop
int m_nFlag2 ; // falg che indica se la cella stata attraversata durante l'ultima fase del labelling
int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 met e met
bool m_bOnLeftEdge ; // flag che indica se la cella sul lato sinistro ( per superfici chiuse sul parametro U)
bool m_bOnTopEdge ; // flag che indica se la cella sul lato top ( per superfici chiuse sul parametro V)
int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling
int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà
bool m_bOnLeftEdge ; // flag che indica se la cella è sul lato sinistro ( per superfici chiuse sul parametro U)
bool m_bOnTopEdge ; // flag che indica se la cella è sul lato top ( per superfici chiuse sul parametro V)
std::vector<Inters> m_vInters ; // vettore delle intersezioni della cella con i loop di trim
// ogni elemento del vettore l'insieme dei punti che caratterizza un atrtaversamento della cella
// ogni elemento del vettore è l'insieme dei punti che caratterizza un attraversamento della cella
private :
Point3d m_ptPbl ; // punto bottom left
Point3d m_ptPtr ; // punto top right
bool m_bProcessed ; // flag che indica se la cella stata processata
bool m_bSplitVert ; // flag che indica in quale direzione stata divisa la cella
bool m_bProcessed ; // flag che indica se la cella è stata processata
bool m_bSplitVert ; // flag che indica in quale direzione è stata divisa la cella
} ;
//----------------------------------------------------------------------------
@@ -165,16 +232,26 @@ class Tree
~Tree( void) ;
Tree( void) ;
Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
Tree( const Point3d ptBl, const Point3d ptTr) ; // creatore da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno
void SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini)
bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax il massimo per la dimensione maggiore di un triangolo della trimesh
// dSideMin lunghezza minima del lato di una cella nello spazio reale
bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ;
bool GetPolygons( POLYLINEMATRIX& vPolygons) ;
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
// ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
bool GetLeaves ( std::vector<Cell>& vLeaves) const ;
void SetTestMode( void) { m_bTestMode = true ;} ;
bool GetLeaves ( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero
bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline
bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle
{ for ( int i = 0 ; i < int( m_vPlLoop2D.size()); ++i) vPl.emplace_back( m_vPlLoop2D[i]) ; return true ; };
void SetTestMode( void) { m_bTestMode = true ;} ; // attivando la test mode, per la costruzione dell'albero viene usata la funzione BuiltTree_test e viene corretta di conseguenza la FindCell
// funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico
bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree
bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli
bool IsClosedU( void) const { return m_bClosedU ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro U
bool IsClosedV( void) const { return m_bClosedV ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro V
std::vector<bool> GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli
private :
bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert
@@ -193,40 +270,46 @@ class Tree
bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle
bool FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim
// resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto
bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell) ;
bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, INTVECTOR& vnParentChunk) ;
bool CheckIfBefore( const PolyLine& pl, int nEdge) const ;
bool CheckIfBefore( const Inters& inA) const ;
bool CheckIfBefore( int nEdge1, const Point3d& ptP1, int nEdge2, const Point3d& ptP2) const ; // punto 1 su edge 1 e punto 2 su edge 2, rispetto al lato 3
bool CheckIfBefore( int nEdge, const Point3d& ptP1, const Point3d& ptP2, int nEdge2 = -1) const ; // entrambi i punti sullo stesso lato, nEdge. nEdge2 serve come backup, in caso nEdge sia un vertice.
bool AreSameEdge( int nEdge1, int nEdge2) const ;
bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd) const ;
bool SetRightEdgeIn( int nId) ;
bool CategorizeCell( int nId) ;
bool CheckIfBetween( const Inters& inA, const Inters& inB) const ;
bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ;
bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni.
bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, INTVECTOR& vnParentChunk) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella
bool CheckIfBefore( const PolyLine& pl, int nEdge) const ; // controllo se ptEnd è prima di ptStart sul lato nEdge rispetto al senso antiorario
bool CheckIfBefore( const Inters& inA) const ; // controlla se l'ingresso è prima dell'uscita in senso antiorario a partire da ptTR.
bool CheckIfBefore( int nEdge1, const Point3d& ptP1, int nEdge2, const Point3d& ptP2) const ; // verifico quale punto viene prima tra pt1 e pt2 a partire da ptTR girando in senso CCW (punto 1 su edge 1 e punto 2 su edge 2, rispetto al lato 3)
bool CheckIfBefore( int nEdge, const Point3d& ptP1, const Point3d& ptP2, int nEdge2 = -1) const ; // sul lato nEdge controllo se ptP1 viene prima di ptP2.
bool AreSameEdge( int nEdge1, int nEdge2) const ; // indica se i due edge sono lo stesso. Un vertice adiacente ad un edge viene considerato uguale a questo edge
bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto
bool SetRightEdgeIn( int nId) ; // categorizza la cella in base all'edge destro per poter poi definire m_nFlag
bool CategorizeCell( int nId) ; // categorizza la cella in base al flag m_nFlag (dentro, fuori, intersecata)
bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW)
bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ; // indica a quale edge o vertice il punto è vicino entro EPS_SMALL
bool AdjustCuts( void) ;
bool UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) ;
private :
const SurfBezier* m_pSrfBz ; // superficie di bezier
DBLVECTOR m_vDim ; // distanze tra i vertici della superficie di bezier in 3d in ordine antiorario a partire da ptP00
bool m_bTrimmed ; // superficie trimmata
INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk
std::map<int,int> m_mChunk ;
std::map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim
ICURVEPOVECTOR m_vLoop ; // curve di loop
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ;
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
bool m_bBilinear ; // superficie bilineare
bool m_bMulti ; // superficie multi-patch
bool m_bClosedU ; // superficie chiusa lungo il parametro U
bool m_bClosedV ; // superficie chiusa lungo il parametro V
BOOLVECTOR m_vbPole ; // vettore che indica se i vari lati sono collassati in poli ( indici riferiti all'ordine degli edge)
bool m_bSplitPatches ; // flag che indica se le patches sono state divise prima della creazione dell'albero
int m_nDegU ; // grado della superficie nel parametro U
int m_nDegV ; // grado della superficie nel parametro V
int m_nSpanU ;
int m_nSpanV ;
int m_nSpanU ; // numero di span lungo il parametro U
int m_nSpanV ; // numero di span lungo il parametro V
POLYLINEMATRIX m_vPolygons ; // matrice dei poligoni del tree
std::map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 puntatore Null e -1 root
std::map<int,PNTVECTOR> m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id lo stesso che la cella ha in m_mTree
INTVECTOR m_vnLeaves ; // vettore delle foglie
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
bool m_bTestMode ; // bool che indica se la test mode è attiva
POLYLINEVECTOR m_vPlLoop2D ; // vettore che contiene le polyline che rappresentano i loop di trim tenendo conto della divisione in celle
std::vector<std::pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
} ;
+138
View File
@@ -21,6 +21,8 @@
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "CurveComposite.h"
#include "IntersCrvCompoCrvCompo.h"
#include <algorithm>
using namespace std ;
@@ -218,6 +220,142 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
return true ;
}
//---------------------------------------------------------------------------
bool
Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVECTOR& vTr)
{
vPt.clear() ;
vTr.clear() ;
// se non ho PolyLine, allora non faccio nulla
if ( int( vPLORIG.size()) == 0)
return true ;
// copio il vettore di PolyLine
POLYLINEVECTOR vPL ;
for ( int i = 0 ; i < int( vPLORIG.size()) ; ++ i)
vPL.push_back( vPLORIG[i]) ;
typedef std::pair<int,double> INDAREA ;
std::vector<INDAREA> m_vArea ;
// calcolo piano medio e area delle curve
m_vArea.reserve( vPL.size()) ;
Vector3d vtN0 ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// calcolo piano medio e area
Plane3d plPlane ;
double dArea ;
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
return false ;
// imposto la normale del primo contorno come riferimento
if ( i == 0)
vtN0 = plPlane.GetVersN() ;
// verifico che le normali siano molto vicine
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN0))
return false ;
// assegno il segno all'area secondo il verso della normale
if ( ( plPlane.GetVersN() * vtN0) > 0)
m_vArea.emplace_back( i, dArea) ;
else
m_vArea.emplace_back( i, - dArea) ;
}
// ordino in senso decrescente sull'area
sort( m_vArea.begin(), m_vArea.end(),
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
Frame3d frRef ; frRef.Set( ORIG, vtN0) ;
if ( ! frRef.IsValid())
return false ;
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vCrvCompo[i].Set( CreateCurveComposite()) ;
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
vCrvCompo[i]->ToLoc( frRef) ;
}
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
// successive i loop interni
INTMATRIX vnPLIndMat ;
// aggiungo le diverse curve
bool bFirstCrv ;
Plane3d plExtLoop ;
double dAreaExtLoop = 0. ;
do {
bFirstCrv = true ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
// recupero indice di percorso e verifico sia valido
int j = m_vArea[i].first ;
if ( j < 0)
continue ;
// lo inserisco come esterno...
if ( bFirstCrv) {
vnPLIndMat.push_back({ j}) ;
m_vArea[i].first = -1 ;
dAreaExtLoop = m_vArea[i].second ;
// inverto se necessario
if ( m_vArea[i].second < EPS_SMALL) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
dAreaExtLoop *= -1 ;
}
bFirstCrv = false ;
}
// ... altrimenti verifico se il loop è interno o no
else {
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
// esterno a tutti i loop già inseriti nella riga attuale.
// verifica rispetto loop esterno
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
bool bOk = true ;
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
}
}
if ( bOk) {
// inserisco nella matrice
vnPLIndMat.back().push_back( j) ;
m_vArea[i].first = -1 ;
// inverto se necessario
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
}
}
}
}
} while ( ! bFirstCrv) ;
// chiamo la Triangolazione per ogni riga della matrice ( quindi su ogni "Chunk")
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++ i) {
PNTVECTOR vPt_tmp ; INTVECTOR vTr_tmp ;
POLYLINEVECTOR vPL_tmp ;
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++ j)
vPL_tmp.push_back( vPL[vnPLIndMat[i][j]]) ;
if ( ! Make( vPL_tmp, vPt_tmp, vTr_tmp))
return false ;
int nSize = int( vPt.size()) ;
for ( int p = 0 ; p < int( vPt_tmp.size()) ; ++ p)
vPt.push_back( vPt_tmp[p]) ;
for ( int t = 0 ; t < int( vTr_tmp.size()) ; ++ t)
vTr.push_back( nSize + vTr_tmp[t]) ;
}
return true ;
}
//----------------------------------------------------------------------------
// Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0])
// Ear Clipping algorithm from mapbox
+1
View File
@@ -22,6 +22,7 @@ class Triangulate
public :
bool Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeAdvanced( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
private :
bool MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr) ;
+53 -12
View File
@@ -14,10 +14,11 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "VolZmap.h"
#include "DistPointLine.h"
#include "GeoObjFactory.h"
#include "GdbGeo.h"
#include "NgeWriter.h"
#include "NgeReader.h"
#include "DistPointLine.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkUiUnits.h"
@@ -34,7 +35,8 @@ GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
//----------------------------------------------------------------------------
VolZmap::VolZmap(void)
: m_nStatus( TO_VERIFY), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_dStep( 10.0), m_nMapNum( 0), m_nShape( GENERIC), m_nVoxNumPerBlock( N_VOXBLOCK),
: m_nStatus( TO_VERIFY), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_bShowEdges( false),
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),
m_dToolLinTol( LIN_TOL_STD), m_dToolAngTolDeg( ANG_TOL_APPROX_DEG)
{
@@ -60,8 +62,16 @@ bool
VolZmap::Clear( void)
{
m_nStatus = TO_VERIFY ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
m_dTempParam[0] = 0.0 ;
m_dTempParam[1] = 0.0 ;
m_bShowEdges = false ;
m_dStep = 10.0 ;
m_nMapNum = 0 ;
m_nShape = GENERIC ;
m_nVoxNumPerBlock = N_VOXBLOCK ;
m_nDexVoxRatio = 1 ;
m_nNumBlock = 0 ;
m_nConnectedCompoCount = 0 ;
m_MapFrame.Reset() ;
@@ -73,17 +83,12 @@ VolZmap::Clear( void)
m_dMaxZ[i] = 0 ;
m_Values[i].clear() ;
}
m_dStep = EPS_SMALL ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
m_dTempParam[0] = 0.0 ;
m_dTempParam[1] = 0.0 ;
m_vTool.resize( 1) ;
m_nCurrTool = 0 ;
m_dToolLinTol = LIN_TOL_STD ;
m_dToolAngTolDeg = ANG_TOL_APPROX_DEG ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// imposto ri-creazione della grafica
m_OGrMgr.Clear() ;
return true ;
}
@@ -150,6 +155,7 @@ VolZmap::CopyFrom( const VolZmap& vzmSrc)
m_nTempProp[1] = vzmSrc.m_nTempProp[1] ;
m_dTempParam[0] = vzmSrc.m_dTempParam[0] ;
m_dTempParam[1] = vzmSrc.m_dTempParam[1] ;
m_bShowEdges = vzmSrc.m_bShowEdges ;
// dimensiono membri legati ai blocchi
m_BlockToUpdate = vzmSrc.m_BlockToUpdate ;
@@ -175,7 +181,7 @@ VolZmap::CopyFrom( const VolZmap& vzmSrc)
bool
VolZmap::ResetGraphics( void)
{
m_OGrMgr.Reset() ;
m_OGrMgr.Clear() ;
for ( int nCount = 0 ; nCount < m_nNumBlock ; ++ nCount)
m_BlockToUpdate[nCount] = true ;
return true ;
@@ -318,6 +324,27 @@ VolZmap::Save( NgeWriter& ngeOut) const
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::PreSave( GdbGeo& Wrapper) const
{
// salvo il flag di visualizzazione spigoli vivi anche in shading (default false)
if ( m_bShowEdges)
Wrapper.SetInfo( GDB_SI_SHOWEDGES, true) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::PostSave( GdbGeo& Wrapper) const
{
// elimino eventuali info aggiunte nella PreSave
Wrapper.RemoveInfo( GDB_SI_SHOWEDGES) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::Load( NgeReader& ngeIn)
@@ -430,6 +457,20 @@ VolZmap::Load( NgeReader& ngeIn)
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::PostLoad( GdbGeo& Wrapper)
{
// recupero eventuale flag di visualizzazione spigoli vivi anche in shading
bool bVal ;
if ( Wrapper.GetInfo( GDB_SI_SHOWEDGES, bVal)) {
m_bShowEdges = bVal ;
Wrapper.RemoveInfo( GDB_SI_SHOWEDGES) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
@@ -1620,12 +1661,12 @@ VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
bool
VolZmap::IsMapPartABox( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, double& dMinZ, double& dMaxZ)
{
if ( ! m_bIsBox)
return true ;
dMinZ = m_dMaxZ[nMap] ;
dMaxZ = m_dMinZ[nMap] ;
for ( int i = nInfI ; i < nSupI ; ++ i) {
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
if ( ! m_bIsBox)
return true ;
int n = j * m_nNx[nMap] + i ;
int nSize = int( m_Values[nMap][n].size()) ;
if ( nSize > 1)
+44 -37
View File
@@ -17,12 +17,15 @@
#include "GeoObjRW.h"
#include "Tool.h"
#include "/EgtDev/Include/EGkVolZmap.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
#include <unordered_map>
#include <stack>
#include <mutex>
#include <atomic>
// ------------------------- FORWARD -------------------------------------------------------------
class IntersParLinesSurfTm ;
// ------------------------- STRUTTURE -----------------------------------------------------------
struct AppliedVector {
Point3d ptPApp ;
@@ -88,6 +91,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW
int GetResolution( void) const override
{ return m_nDexVoxRatio ; }
bool ChangeResolution( int nDexVoxRatio) override ;
void SetShowEdges( bool bShow) override
{ m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica
m_OGrMgr.Clear() ; }
bool GetShowEdges( void) const override
{ return m_bShowEdges ; }
bool SetToolTolerances( double dLinTol, double dAngTolDeg = 90) override ;
bool SetStdTool( const std::string& sToolName,
double dH, double dR, double dCornR, double dCutterH, int nFlag, bool bFirst) override ;
@@ -112,19 +120,17 @@ class VolZmap : public IVolZmap, public IGeoObjRW
const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) override ;
bool GetDepth( const Point3d& ptP, const Vector3d& vtD, double& dInLength, double& dOutLength, bool bExact) const override ;
bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const override ;
bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const override ;
bool AvoidBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, bool bPrecise = false) const override ;
bool AvoidSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bool bPrecise = false) const override ;
bool AvoidCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise = false) const override ;
bool AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop, double dHeight,
double dSafeDist, bool bPrecise = false) const override ;
bool AvoidRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight,
double dSafeDist, bool bPrecise = false) const override ;
bool AvoidTorus( const Frame3d& frTorus, double dRadMax, double dRadMin,
double dSafeDist, bool bPrecise = false) const override ;
bool AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise = false) const override ;
bool CDeBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, bool bPrecise = false) const override ;
bool CDeSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bool bPrecise = false) const override ;
bool CDeCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise = false) const override ;
bool CDeConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop, double dHeight,
double dSafeDist, bool bPrecise = false) const override ;
bool CDeRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight,
double dSafeDist, bool bPrecise = false) const override ;
bool CDeTorus( const Frame3d& frTorus, double dRadMax, double dRadMin,
double dSafeDist, bool bPrecise = false) const override ;
bool CDeSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise = false) const override ;
bool Cut( const Plane3d& plPlane) override ;
bool Compact( void) override ;
int GetPartCount( void) const override ;
@@ -138,7 +144,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
public : // IGeoObjRW
int GetNgeId( void) const override ;
bool Save( NgeWriter& ngeOut) const override ;
bool PreSave( GdbGeo& Wrapper) const override ;
bool PostSave( GdbGeo& Wrapper) const override ;
bool Load( NgeReader& ngeIn) override ;
bool PostLoad( GdbGeo& Wrapper) override ;
public :
VolZmap( void) ;
@@ -149,6 +158,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
{ if ( ! CopyFrom( stSrc))
LOG_ERROR( GetEGkLogger(), "VolZmap : copy error")
return *this ; }
bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const ;
bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const ;
private :
enum CubeType { VOX_EXTERN = 1,
@@ -189,22 +200,18 @@ class VolZmap : public IVolZmap, public IGeoObjRW
std::vector<BOOLVECTOR> vbFlipped ;
} ;
// Triangoli smooth
struct SmoothTriaStruct {
struct SmoothTriaStruct {
int i, j, k ;
TRIA3DEXVECTOR vTria ;
};
// Vettore di SharpTriaStruct con sharp feature
typedef std::vector<SharpTriaStruct> SharpTriHolder ;
// Vettore di SmoothTriaStruct con triangoli smooth
typedef std::vector<SmoothTriaStruct> SmoothTriHolder ;
// Vettore di SharpTriHolder con sharp feature: il primo indice individua il blocco, il secondo il voxel
typedef std::vector<SharpTriHolder> SharpTriaMatrix ;
// Vettore di SmoothTriHolder smooth: il primo indice individua il blocco, il secondo il voxel
typedef std::vector<SmoothTriHolder> SmoothTriaMatrix ;
} ;
// Matrice di SharpTriaStruct con sharp feature: il primo indice individua il blocco, il secondo il voxel
typedef std::vector<std::vector<SharpTriaStruct>> SharpTriaMatrix ;
// Matrice di SmoothTriaStruct con triangoli smooth: il primo indice individua il blocco, il secondo il voxel
typedef std::vector<std::vector<SmoothTriaStruct>> SmoothTriaMatrix ;
// Tavola hash di Voxel
typedef std::unordered_map <int, Voxel> VoxelContainer ;
typedef std::unordered_map<int, Voxel> VoxelContainer ;
// Unordered map per la coerenza topologica
typedef std::unordered_map <int, bool> InterVoxMatter ;
typedef std::unordered_map<int, bool> InterVoxMatter ;
private :
bool CopyFrom( const VolZmap& clSrc) ;
@@ -393,14 +400,14 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool ProcessIntervals( IntContainer& IntervalsToProcess) ;
bool IsMapPartABox( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, double& dMinZ, double& dMaxZ) ;
bool IsBox( void) ;
// Avoid semplici
bool AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPrecise = false) const ;
bool AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise = false) const ;
bool AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool bPrecise = false) const ;
bool AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double dMaxRad, double dHeight, bool bPrecise = false) const ;
bool AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight, bool bPrecise = false) const ;
bool AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise = false) const ;
// Collision Detection semplici
bool CDeSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPrecise = false) const ;
bool CDeSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise = false) const ;
bool CDeSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool bPrecise = false) const ;
bool CDeSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double dMaxRad, double dHeight, bool bPrecise = false) const ;
bool CDeSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight, bool bPrecise = false) const ;
bool CDeSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise = false) const ;
// Funzione per crezione solido in parallelo
bool CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
@@ -416,9 +423,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
Status m_nStatus ; // stato
int m_nTempProp[2] ; // vettore proprietà temporanee
double m_dTempParam[2] ; // vettore parametri temporanei
bool m_bShowEdges ; // flag di visualizzazione spigoli vivi
Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap
double m_dStep ; // passo delle griglie
int m_nMapNum ; // numero di griglie ( 1 o 3)
Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap
int m_nNx[N_MAPS] ; // dimensione di ciascuna griglia in X
int m_nNy[N_MAPS] ; // dimensione di ciascuna griglia in Y
int m_nDim[N_MAPS] ; // dimensione di ciascuna griglia ( X * Y)
@@ -436,7 +444,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
} ;
std::vector<std::vector<Data>> m_Values[N_MAPS] ; // dexel delle 3 griglie
int m_nShape ; // Forma : 0 generica, 1 box, 2 estrusione
int m_nShape ; // Forma : 0 generica, 1 box, 2 estrusione
int m_nVoxNumPerBlock ; // Numero di voxel per blocco
int m_nDexVoxRatio ; // Rapporto dexel voxel
@@ -462,7 +470,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
mutable std::vector<InterVoxMatter> m_SliceYZ ;
mutable std::mutex m_SliceMutex ;
mutable std::atomic<bool> m_bBreak ;
std::atomic<bool> m_bIsBox ;
int m_nCurrTool ;
+219 -194
View File
@@ -411,7 +411,7 @@ VolZmap::GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtD, double& dIn
//----------------------------------------------------------------------------
bool
VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPrecise) const
VolZmap::CDeSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPrecise) const
{
// BBox
BBox3d b3BoxL( ORIG, ORIG + vtDiag) ;
@@ -425,10 +425,10 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre
// Se non interferiscono, posso uscire
if ( ! b3Zmap.Overlaps( b3Box) || ! b3Zmap.Overlaps( frBoxInt, b3BoxL))
return true ;
return false ;
BBox3d b3Int ;
if ( ! b3Zmap.FindIntersection( b3Box, b3Int))
return true ;
return false ;
// Se verifico solo prima mappa
if ( ! bPrecise || m_nMapNum == 1) {
@@ -470,7 +470,7 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
return false ;
return true ;
}
}
}
@@ -533,7 +533,7 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre
// Se il segmento è interno all'intervallo d'intersezione, ho finito.
if ( dMaxU > m_Values[nMap][nPos][nIndex].dMin - EPS_SMALL &&
dMinU < m_Values[nMap][nPos][nIndex].dMax + EPS_SMALL)
return false ;
return true ;
}
}
}
@@ -541,32 +541,36 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre
}
}
return true ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AvoidBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, bool bPrecise) const
VolZmap::CDeBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, bool bPrecise) const
{
// Se il box non è ben definito non ha senso proseguire
if ( vtDiag.IsSmall())
return true ;
// Se distanza di sicurezza nulla
if ( dSafeDist < EPS_SMALL)
return AvoidSimpleBox( frBox, vtDiag, bPrecise) ;
return CDeSimpleBox( frBox, vtDiag, bPrecise) ;
// Verifica preliminare con box esteso
Frame3d frEst = frBox ; frEst.Translate( -dSafeDist * ( frBox.VersX() + frBox.VersY() + frBox.VersZ())) ;
if ( AvoidSimpleBox( frEst, vtDiag + 2 * Vector3d( dSafeDist, dSafeDist, dSafeDist), bPrecise))
return true ;
if ( ! CDeSimpleBox( frEst, vtDiag + 2 * Vector3d( dSafeDist, dSafeDist, dSafeDist), bPrecise))
return false ;
// Tre box aumentati con distanza di sicurezza in un sola dimensione
Frame3d frTmp = frBox ; frTmp.Translate( -dSafeDist * frBox.VersX()) ;
if ( ! AvoidSimpleBox( frTmp, vtDiag + 2 * dSafeDist * X_AX, bPrecise))
return false ;
if ( CDeSimpleBox( frTmp, vtDiag + 2 * dSafeDist * X_AX, bPrecise))
return true ;
frTmp = frBox ; frTmp.Translate( -dSafeDist * frBox.VersY()) ;
if ( ! AvoidSimpleBox( frTmp, vtDiag + 2 * dSafeDist * Y_AX, bPrecise))
return false ;
if ( CDeSimpleBox( frTmp, vtDiag + 2 * dSafeDist * Y_AX, bPrecise))
return true ;
frTmp = frBox ; frTmp.Translate( -dSafeDist * frBox.VersZ()) ;
if ( ! AvoidSimpleBox( frTmp, vtDiag + 2 * dSafeDist * Z_AX, bPrecise))
return false ;
if ( CDeSimpleBox( frTmp, vtDiag + 2 * dSafeDist * Z_AX, bPrecise))
return true ;
// Vertici del box
Point3d ptVert0 = frBox.Orig() ;
@@ -579,67 +583,67 @@ VolZmap::AvoidBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDis
Point3d ptVert7 = ptVert3 + vtDiag.z * frBox.VersZ() ;
// Sfere centrate negli otto vertici
if ( ! AvoidSimpleSphere( ptVert0, dSafeDist, bPrecise))
return false ;
if ( ! AvoidSimpleSphere( ptVert1, dSafeDist, bPrecise))
return false ;
if ( ! AvoidSimpleSphere( ptVert2, dSafeDist, bPrecise))
return false ;
if ( ! AvoidSimpleSphere( ptVert3, dSafeDist, bPrecise))
return false ;
if ( ! AvoidSimpleSphere( ptVert4, dSafeDist, bPrecise))
return false ;
if ( ! AvoidSimpleSphere( ptVert5, dSafeDist, bPrecise))
return false ;
if ( ! AvoidSimpleSphere( ptVert6, dSafeDist, bPrecise))
return false ;
if ( ! AvoidSimpleSphere( ptVert7, dSafeDist, bPrecise))
return false ;
if ( CDeSimpleSphere( ptVert0, dSafeDist, bPrecise))
return true ;
if ( CDeSimpleSphere( ptVert1, dSafeDist, bPrecise))
return true ;
if ( CDeSimpleSphere( ptVert2, dSafeDist, bPrecise))
return true ;
if ( CDeSimpleSphere( ptVert3, dSafeDist, bPrecise))
return true ;
if ( CDeSimpleSphere( ptVert4, dSafeDist, bPrecise))
return true ;
if ( CDeSimpleSphere( ptVert5, dSafeDist, bPrecise))
return true ;
if ( CDeSimpleSphere( ptVert6, dSafeDist, bPrecise))
return true ;
if ( CDeSimpleSphere( ptVert7, dSafeDist, bPrecise))
return true ;
// Cilindri centrati sui dodici spigoli
frTmp.Set( ptVert0, frBox.VersX()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
return true ;
frTmp.Set( ptVert2, frBox.VersX()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
return true ;
frTmp.Set( ptVert0, frBox.VersY()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
return true ;
frTmp.Set( ptVert1, frBox.VersY()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
return true ;
frTmp.Set( ptVert4, frBox.VersX()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
return true ;
frTmp.Set( ptVert6, frBox.VersX()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
return true ;
frTmp.Set( ptVert4, frBox.VersY()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
return true ;
frTmp.Set( ptVert5, frBox.VersY()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
return true ;
frTmp.Set( ptVert0, frBox.VersZ()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
return true ;
frTmp.Set( ptVert1, frBox.VersZ()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
return true ;
frTmp.Set( ptVert2, frBox.VersZ()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
return true ;
frTmp.Set( ptVert3, frBox.VersZ()) ;
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
return true ;
return true ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise) const
VolZmap::CDeSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise) const
{
// Porto la sfera nel riferimento intrinseco dello Zmap
Point3d ptC = ptCenter ;
@@ -655,7 +659,7 @@ VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise)
// Se non interferiscono, posso uscire
BBox3d b3Int ;
if ( ! b3Zmap.FindIntersection( b3Box, b3Int))
return true ;
return false ;
// Se verifico solo prima mappa
if ( ! bPrecise || m_nMapNum == 1) {
@@ -693,7 +697,7 @@ VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise)
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
return false ;
return true ;
}
}
}
@@ -765,7 +769,7 @@ VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise)
// Se il segmento è interno all'intervallo d'intersezione, ho finito.
if ( dMaxU > m_Values[nMap][nPos][nIndex].dMin - EPS_SMALL &&
dMinU < m_Values[nMap][nPos][nIndex].dMax + EPS_SMALL)
return false ;
return true ;
}
}
}
@@ -773,19 +777,23 @@ VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise)
}
}
return true ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AvoidSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bool bPrecise) const
VolZmap::CDeSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bool bPrecise) const
{
return AvoidSimpleSphere( ptCenter, dRad + max( 0., dSafeDist), bPrecise) ;
// Il raggio deve essere non nullo
if ( dRad < EPS_SMALL)
return true ;
return CDeSimpleSphere( ptCenter, dRad + max( 0., dSafeDist), bPrecise) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool bPrecise) const
VolZmap::CDeSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool bPrecise) const
{
// BBox del cilindro in locale
BBox3d b3CylL( Point3d( -dR, -dR, 0), Point3d( dR, dR, dH)) ;
@@ -799,7 +807,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b
// Se non interferiscono, posso uscire
if ( ! b3Zmap.Overlaps( b3CylI) || ! b3Zmap.Overlaps( frCylInt, b3CylL))
return true ;
return false ;
// BBox del cilindro ottimizzato nel riferimento intrinseco dello Zmap
Point3d ptMyCen = frCylInt.Orig() ;
@@ -822,7 +830,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b
// Se non interferiscono, posso uscire
BBox3d b3Int ;
if ( ! b3Zmap.FindIntersection( b3Cyl, b3Int))
return true ;
return false ;
// Se verifico solo prima mappa
if ( ! bPrecise || m_nMapNum == 1) {
@@ -866,7 +874,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
return false ;
return true ;
}
}
}
@@ -931,7 +939,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b
// Se il segmento è interno all'intervallo d'intersezione, ho finito.
if ( dMaxU > m_Values[nMap][nPos][nIndex].dMin - EPS_SMALL &&
dMinU < m_Values[nMap][nPos][nIndex].dMax + EPS_SMALL)
return false ;
return true ;
}
}
}
@@ -939,13 +947,17 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b
}
}
return true ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AvoidCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise) const
VolZmap::CDeCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise) const
{
// Il cilindro deve essere ben definito
if ( dR < EPS_SMALL || dH < EPS_SMALL)
return true ;
// Se altezza negativa, sposto riferimento da faccia sopra a quella sotto
Frame3d frMyCyl = frCyl ;
if ( dH < 0) {
@@ -955,34 +967,34 @@ VolZmap::AvoidCylinder( const Frame3d& frCyl, double dR, double dH, double dSafe
// Se distanza di sicurezza nulla
if ( dSafeDist < EPS_SMALL)
return AvoidSimpleCylinder( frMyCyl, dR, dH, bPrecise) ;
return CDeSimpleCylinder( frMyCyl, dR, dH, bPrecise) ;
// Verifica preliminare con cilindro esteso
Frame3d frEst = frMyCyl ; frEst.Translate( -dSafeDist * frMyCyl.VersZ()) ;
if ( AvoidSimpleCylinder( frEst, dR + dSafeDist, dH + 2 * dSafeDist, bPrecise))
return true ;
if ( ! CDeSimpleCylinder( frEst, dR + dSafeDist, dH + 2 * dSafeDist, bPrecise))
return false ;
// Cilindro allargato
if ( ! AvoidSimpleCylinder( frMyCyl, dR + dSafeDist, dH, bPrecise))
return false ;
if ( CDeSimpleCylinder( frMyCyl, dR + dSafeDist, dH, bPrecise))
return true ;
// Cilindro allungato
Frame3d frTmp = frMyCyl ; frTmp.Translate( - dSafeDist * frMyCyl.VersZ()) ;
if ( ! AvoidSimpleCylinder( frTmp, dR, dH + 2 * dSafeDist, bPrecise))
return false ;
if ( CDeSimpleCylinder( frTmp, dR, dH + 2 * dSafeDist, bPrecise))
return true ;
// Toro inferiore
if ( ! AvoidSimpleTorus( frMyCyl, dR, dSafeDist, bPrecise))
return false ;
if ( CDeSimpleTorus( frMyCyl, dR, dSafeDist, bPrecise))
return true ;
// Toro superiore
frTmp = frMyCyl ; frTmp.Translate( dH * frMyCyl.VersZ()) ;
if ( ! AvoidSimpleTorus( frTmp, dR, dSafeDist, bPrecise))
return false ;
if ( CDeSimpleTorus( frTmp, dR, dSafeDist, bPrecise))
return true ;
return true ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double dMaxRad, double dHeight, bool bPrecise) const
VolZmap::CDeSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double dMaxRad, double dHeight, bool bPrecise) const
{
// BBox del tronco di cono in locale
BBox3d b3ConeL( Point3d( -dMaxRad, -dMaxRad, 0), Point3d( dMaxRad, dMaxRad, dHeight)) ;
@@ -996,7 +1008,7 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d
// Se non interferiscono, posso uscire
if ( ! b3Zmap.Overlaps( b3ConeI) || ! b3Zmap.Overlaps( frConeInt, b3ConeL))
return true ;
return false ;
// BBox del tronco di cono ottimizzato nel riferimento intrinseco dello Zmap
Point3d ptRefPoint = frConeInt.Orig() ;
@@ -1025,7 +1037,7 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d
// Se non interferiscono, posso uscire
BBox3d b3Int ;
if ( ! b3Zmap.FindIntersection( b3Cone, b3Int))
return true ;
return false ;
// Uso solo la prima mappa
if ( ! bPrecise || m_nMapNum == 1) {
@@ -1068,7 +1080,7 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
return false ;
return true ;
}
}
}
@@ -1133,14 +1145,14 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d
// Se il segmento è interno all'intervallo d'intersezione, ho finito.
if ( dMaxU > m_Values[nMap][nPos][nIndex].dMin - EPS_SMALL &&
dMinU < m_Values[nMap][nPos][nIndex].dMax + EPS_SMALL)
return false ;
return true ;
}
}
}
}
}
}
return true ;
return false ;
}
//----------------------------------------------------------------------------
@@ -1149,12 +1161,16 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d
// Se è un tronco di cono l'origine è nel centro della base Bot e l'asse Z è diretto verso
// la base Top, a prescindere da quale base abbia raggio maggiore.
bool
VolZmap::AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop, double dHeight,
VolZmap::CDeConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop, double dHeight,
double dSafeDist, bool bPrecise) const
{
// Se il tronco di cono non è ben definito non ha senso proseguire
if ( max( dRadBot, dRadTop) < EPS_SMALL || dHeight < EPS_SMALL)
return true ;
// Se cilindro
if ( abs( dRadBot - dRadTop) < EPS_SMALL)
return AvoidCylinder( frCone, max( dRadBot, dRadTop), dHeight, dSafeDist, bPrecise) ;
return CDeCylinder( frCone, max( dRadBot, dRadTop), dHeight, dSafeDist, bPrecise) ;
// Verifico che la base minore sia in basso nel suo riferimento
Frame3d frMyCone = frCone ;
@@ -1167,7 +1183,7 @@ VolZmap::AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop
// Se distanza di sicurezza nulla
if ( dSafeDist < EPS_SMALL)
return AvoidSimpleConeFrustum( frMyCone, dMinRad, dMaxRad, dHeight, bPrecise) ;
return CDeSimpleConeFrustum( frMyCone, dMinRad, dMaxRad, dHeight, bPrecise) ;
// Se vero e proprio cono
if ( dMinRad < EPS_SMALL) {
@@ -1177,28 +1193,28 @@ VolZmap::AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop
double dRadExt = dMaxRad * dHeightExt / dHeight ;
Frame3d frFrame = frMyCone ;
frFrame.Translate( -dDeltaVert * frFrame.VersZ()) ;
if ( AvoidSimpleConeFrustum( frFrame, 0., dRadExt, dHeightExt, bPrecise))
return true ;
if ( ! CDeSimpleConeFrustum( frFrame, 0., dRadExt, dHeightExt, bPrecise))
return false ;
// Sfera nel vertice in basso
frFrame = frMyCone ;
if ( ! AvoidSimpleSphere( frMyCone.Orig(), dSafeDist, bPrecise))
return false ;
if ( CDeSimpleSphere( frMyCone.Orig(), dSafeDist, bPrecise))
return true ;
// Tronco di cono intermedio
double dHypo = sqrt( dMaxRad * dMaxRad + dHeight * dHeight ) ;
double dDeltaH = dSafeDist * dMaxRad / dHypo ;
double dDeltaR = dSafeDist * dHeight / dHypo ;
frFrame = frMyCone ; frFrame.Translate( -dDeltaH * frFrame.VersZ()) ;
if ( ! AvoidSimpleConeFrustum( frFrame, dDeltaR, dMaxRad + dDeltaR, dHeight, bPrecise))
return false ;
if ( CDeSimpleConeFrustum( frFrame, dDeltaR, dMaxRad + dDeltaR, dHeight, bPrecise))
return true ;
// Cilindro nel toro in alto
frFrame = frMyCone ; frFrame.Translate( ( dHeight - dSafeDist) * frFrame.VersZ()) ;
if ( ! AvoidSimpleCylinder( frFrame, dMaxRad, 2 * dSafeDist, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dMaxRad, 2 * dSafeDist, bPrecise))
return true ;
// Toro in alto
frFrame = frMyCone ; frFrame.Translate( dHeight * frFrame.VersZ()) ;
if ( ! AvoidSimpleTorus( frFrame, dMaxRad, dSafeDist, bPrecise))
return false ;
return true ;
if ( CDeSimpleTorus( frFrame, dMaxRad, dSafeDist, bPrecise))
return true ;
return false ;
}
// Tronco di cono
@@ -1210,33 +1226,33 @@ VolZmap::AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop
double dDeltaMaxRad = ( dDeltaVert + dSafeDist) * dDiffRad / dHeight ;
double dDeltaMinRad = ( dDeltaVert - dSafeDist) * dDiffRad / dHeight ;
Frame3d frFrame = frMyCone ; frFrame.Translate( -dSafeDist * frFrame.VersZ()) ;
if ( AvoidSimpleConeFrustum( frFrame, dMinRad + dDeltaMinRad, dMaxRad + dDeltaMaxRad, dHeight + 2 * dSafeDist, bPrecise))
return true ;
if ( ! CDeSimpleConeFrustum( frFrame, dMinRad + dDeltaMinRad, dMaxRad + dDeltaMaxRad, dHeight + 2 * dSafeDist, bPrecise))
return false ;
// Tronco di cono intermedio
double dHypo = sqrt( dDiffRad * dDiffRad + dHeight * dHeight ) ;
double dDeltaH = dSafeDist * dDiffRad / dHypo ;
double dDeltaR = dSafeDist * dHeight / dHypo ;
frFrame = frMyCone ; frFrame.Translate( -dDeltaH * frFrame.VersZ()) ;
if ( ! AvoidSimpleConeFrustum( frFrame, dMinRad + dDeltaR, dMaxRad + dDeltaR, dHeight, bPrecise))
return false ;
if ( CDeSimpleConeFrustum( frFrame, dMinRad + dDeltaR, dMaxRad + dDeltaR, dHeight, bPrecise))
return true ;
// Cilindro sotto
frFrame = frMyCone ; frFrame.Translate( - dSafeDist * frFrame.VersZ()) ;
if ( ! AvoidSimpleCylinder( frFrame, dMinRad, 2 * dSafeDist, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dMinRad, 2 * dSafeDist, bPrecise))
return true ;
// Cilindro sopra
frFrame.Translate( dHeight * frFrame.VersZ()) ;
if ( ! AvoidSimpleCylinder( frFrame, dMaxRad, 2 * dSafeDist, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dMaxRad, 2 * dSafeDist, bPrecise))
return true ;
// Toro sotto
frFrame = frMyCone ;
if ( ! AvoidSimpleTorus( frFrame, dMinRad, dSafeDist, bPrecise))
return false ;
if ( CDeSimpleTorus( frFrame, dMinRad, dSafeDist, bPrecise))
return true ;
// Toro sopra
frFrame.Translate( dHeight * frFrame.VersZ()) ;
if ( ! AvoidSimpleTorus( frFrame, dMaxRad, dSafeDist, bPrecise))
return false ;
if ( CDeSimpleTorus( frFrame, dMaxRad, dSafeDist, bPrecise))
return true ;
return true ;
return false ;
}
//----------------------------------------------------------------------------
@@ -1380,8 +1396,8 @@ RectPrismoidSegmentCollisionPlus( const Frame3d& frPrismoid, double dLenghtBaseX
//----------------------------------------------------------------------------
bool
VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight, bool bPrecise) const
VolZmap::CDeSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight, bool bPrecise) const
{
// Box del tronco di prismoide nel suo sistema locale
double dMaxLenX = max( dLenghtBaseX, dLenghtTopX) ;
@@ -1398,7 +1414,7 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX
// Se i box non interferiscono, posso uscire
if ( ! b3Zmap.Overlaps( b3PrismI) || ! b3Zmap.Overlaps( frPrismInt, b3PrismL))
return true ;
return false ;
// BBox del tronco di prismoide ottimizzato nel riferimento intrinseco dello Zmap
Point3d ptMyCen = frPrismInt.Orig() ;
@@ -1418,7 +1434,7 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX
// Se i box non interferiscono, posso uscire
BBox3d b3Int ;
if ( ! b3Zmap.FindIntersection( b3Prism, b3Int))
return true ;
return false ;
// Se verifico solo prima mappa
if ( ! bPrecise || m_nMapNum == 1) {
@@ -1456,7 +1472,7 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX
dHeight, ptSegSt, ptSegEn, dStU, dEnU)) {
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
if ( m_Values[0][nPos][nIndex].dMax >= dStU && m_Values[0][nPos][nIndex].dMin <= dEnU)
return false ;
return true ;
}
}
}
@@ -1523,30 +1539,30 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX
dHeight, ptSegSt, ptSegEn, dStU, dEnU)) {
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
if ( m_Values[nMap][nDex][nIndex].dMax >= dStU && m_Values[nMap][nDex][nIndex].dMin <= dEnU)
return false ;
return true ;
}
}
}
}
}
return true ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AvoidRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight,
double dSafeDist, bool bPrecise) const
VolZmap::CDeRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight,
double dSafeDist, bool bPrecise) const
{
// Se il tronco di piramide non è ben definito non procedo
if ( max( dLenghtBaseX, dLenghtTopX) < EPS_SMALL ||
max( dLenghtBaseY, dLenghtTopY) < EPS_SMALL ||
dHeight < EPS_SMALL)
return false ;
return true ;
// Se distanza di sicurezza nulla
if ( dSafeDist < EPS_SMALL)
return AvoidSimpleRectPrismoid( frPrismoid, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, dHeight, bPrecise) ;
return CDeSimpleRectPrismoid( frPrismoid, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, dHeight, bPrecise) ;
// Verifica preliminare con offset esteso
double dHDiffX = ( dLenghtBaseX - dLenghtTopX) / 2 ;
@@ -1560,9 +1576,9 @@ VolZmap::AvoidRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, doub
double dOffsBaseY = dSafeDist * ( dSecAy + dTgAy) ;
double dOffsTopY = dSafeDist * ( dSecAy - dTgAy) ;
Frame3d frFrame = frPrismoid ; frFrame.Translate( -dSafeDist * frFrame.VersZ()) ;
if ( AvoidSimpleRectPrismoid( frFrame, dLenghtBaseX + 2 * dOffsBaseX, dLenghtBaseY + 2 * dOffsBaseY,
if ( ! CDeSimpleRectPrismoid( frFrame, dLenghtBaseX + 2 * dOffsBaseX, dLenghtBaseY + 2 * dOffsBaseY,
dLenghtTopX + 2 * dOffsTopX, dLenghtTopY + 2 * dOffsTopY, dHeight + 2 * dSafeDist, bPrecise))
return true ;
return false ;
// Offset fine
// Sfere centrate nei vertici
@@ -1580,85 +1596,85 @@ VolZmap::AvoidRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, doub
Point3d( -dHalfTopX, dHalfTopY, dHeight)} ;
for ( auto& ptV : vVert) {
ptV.ToGlob( frPrismoid) ;
if ( ! AvoidSimpleSphere( ptV, dSafeDist, bPrecise))
return false ;
if ( CDeSimpleSphere( ptV, dSafeDist, bPrecise))
return true ;
}
// Cilindri con i segmenti come asse
frFrame.Set( vVert[0], frPrismoid.VersX()) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtBaseX, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtBaseX, bPrecise))
return true ;
frFrame.Set( vVert[1], frPrismoid.VersY()) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtBaseY, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtBaseY, bPrecise))
return true ;
frFrame.Set( vVert[2], -frPrismoid.VersX()) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtBaseX, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtBaseX, bPrecise))
return true ;
frFrame.Set( vVert[3], -frPrismoid.VersY()) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtBaseY, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtBaseY, bPrecise))
return true ;
frFrame.Set( vVert[4], frPrismoid.VersX()) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtTopX, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtTopX, bPrecise))
return true ;
frFrame.Set( vVert[5], frPrismoid.VersY()) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtTopY, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtTopY, bPrecise))
return true ;
frFrame.Set( vVert[6], -frPrismoid.VersX()) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtTopX, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtTopX, bPrecise))
return true ;
frFrame.Set( vVert[7], -frPrismoid.VersY()) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtTopY, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtTopY, bPrecise))
return true ;
Vector3d vtSeg04 = vVert[4] - vVert[0] ;
double dLenSeg04 = vtSeg04.Len() ;
frFrame.Set( vVert[0], vtSeg04) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenSeg04, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenSeg04, bPrecise))
return true ;
Vector3d vtSeg15 = vVert[5] - vVert[1] ;
double dLenSeg15 = vtSeg15.Len() ;
frFrame.Set( vVert[1], vtSeg15) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenSeg15, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenSeg15, bPrecise))
return true ;
Vector3d vtSeg26 = vVert[6] - vVert[2] ;
double dLenSeg26 = vtSeg26.Len() ;
frFrame.Set( vVert[2], vtSeg26) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenSeg26, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenSeg26, bPrecise))
return true ;
Vector3d vtSeg37 = vVert[7] - vVert[3] ;
double dLenSeg37 = vtSeg37.Len();
frFrame.Set( vVert[3], vtSeg37) ;
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenSeg37, bPrecise))
return false ;
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenSeg37, bPrecise))
return true ;
// Box sotto
frFrame = frPrismoid ; frFrame.Translate( -dSafeDist * frFrame.VersZ()) ;
if ( ! AvoidSimpleBox( frFrame, Vector3d( dLenghtBaseX, dLenghtBaseY, dSafeDist), bPrecise))
return false ;
if ( CDeSimpleBox( frFrame, Vector3d( dLenghtBaseX, dLenghtBaseY, dSafeDist), bPrecise))
return true ;
// Box sopra
frFrame = frPrismoid ; frFrame.Translate( dHeight * frFrame.VersZ()) ;
if ( ! AvoidSimpleBox( frFrame, Vector3d( dLenghtBaseX, dLenghtBaseY, dSafeDist), bPrecise))
return false ;
if ( CDeSimpleBox( frFrame, Vector3d( dLenghtBaseX, dLenghtBaseY, dSafeDist), bPrecise))
return true ;
// Prismoide allungato in X
double dHypoX = sqrt( dHDiffX * dHDiffX + dHeight * dHeight) ;
double dOffsX = dSafeDist * dHeight / dHypoX ;
double dMoveXZ = dSafeDist * dHDiffX / dHypoX ;
frFrame = frPrismoid ; frFrame.Translate( dMoveXZ * frFrame.VersZ()) ;
if ( ! AvoidSimpleRectPrismoid( frFrame, dLenghtBaseX + 2 * dOffsX, dLenghtBaseY,
if ( CDeSimpleRectPrismoid( frFrame, dLenghtBaseX + 2 * dOffsX, dLenghtBaseY,
dLenghtTopX + 2 * dOffsX, dLenghtTopY, dHeight, bPrecise))
return false ;
return true ;
// Prismoide allungato in Y
double dHypoY = sqrt( dHDiffY * dHDiffY + dHeight * dHeight) ;
double dOffsY = dSafeDist * dHeight / dHypoY ;
double dMoveYZ = dSafeDist * dHDiffY / dHypoY ;
frFrame = frPrismoid ; frFrame.Translate( dMoveYZ * frFrame.VersZ()) ;
if ( ! AvoidSimpleRectPrismoid( frFrame, dLenghtBaseX, dLenghtBaseY + 2 * dOffsY,
if ( CDeSimpleRectPrismoid( frFrame, dLenghtBaseX, dLenghtBaseY + 2 * dOffsY,
dLenghtTopX, dLenghtTopY + 2 * dOffsY, dHeight, bPrecise))
return false ;
return true ;
return true ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise) const
VolZmap::CDeSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise) const
{
// BBox del toro in locale
BBox3d b3TorusL( Point3d( -dMaxRad - dMinRad, -dMaxRad - dMinRad, -dMinRad),
@@ -1673,7 +1689,7 @@ VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRa
// Se non interferiscono, posso uscire
if ( ! b3Zmap.Overlaps( b3TorusI) || ! b3Zmap.Overlaps( frTorusInt, b3TorusL))
return true ;
return false ;
// BBox del toro ottimizzato nel riferimento intrinseco dello Zmap
Point3d ptMyCen = frTorusInt.Orig() ;
@@ -1698,7 +1714,7 @@ VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRa
// Se non interferiscono, posso uscire
BBox3d b3Int ;
if ( ! b3Zmap.FindIntersection( b3Torus, b3Int))
return true ;
return false ;
// Se verifico solo prima mappa
if ( ! bPrecise || m_nMapNum == 1) {
@@ -1736,13 +1752,13 @@ VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRa
int nIntType = SegmentTorus( ptSegSt, Z_AX, dParMax - dParMin, ptMyCen, vtMyAx, dMinRad, dMaxRad,
vbType, vdPar) ;
if ( nIntType == LinCompTorusIntersType::T_ERROR)
return false ;
return true ;
else if ( nIntType != LinCompTorusIntersType::T_NO_INT) {
double dUmin = vdPar.front() ;
double dUmax = vdPar.back() ;
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
if ( m_Values[0][nPos][nIndex].dMax >= dUmin && m_Values[0][nPos][nIndex].dMin <= dUmax)
return false ;
return true ;
}
}
}
@@ -1810,31 +1826,31 @@ VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRa
int nIntType = SegmentTorus( ptSegSt, vtLineDir, dParMax - dParMin, ptMyCen, vtMyAx, dMinRad, dMaxRad,
vbType, vdPar) ;
if ( nIntType == LinCompTorusIntersType::T_ERROR)
return false ;
return true ;
else if ( nIntType != LinCompTorusIntersType::T_NO_INT) {
double dUmin = vdPar.front() ;
double dUmax = vdPar.back() ;
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
if ( m_Values[nMap][nDex][nIndex].dMax >= dUmin && m_Values[nMap][nDex][nIndex].dMin <= dUmax)
return false ;
return true ;
}
}
}
}
}
return true ;
return false ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AvoidTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad,
VolZmap::CDeTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad,
double dSafeDist, bool bPrecise) const
{
// I raggi devono essere non nulli
if ( dMaxRad < EPS_SMALL || dMinRad < EPS_SMALL)
return true ;
return AvoidSimpleTorus( frTorus, dMaxRad, dMinRad + max( 0., dSafeDist), bPrecise) ;
return CDeSimpleTorus( frTorus, dMaxRad, dMinRad + max( 0., dSafeDist), bPrecise) ;
}
//----------------------------------------------------------------------------
@@ -1844,12 +1860,13 @@ VolZmap::AvoidTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad,
// quelli di intersezione segmento triangolo vengono eseguiti nel sistema locale. Questo perché
// è più veloce trasformare le coordinate degli estremi del segmento piuttosto che quelle del
// triangolo.
//----------------------------------------------------------------------------
bool
VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise) const
VolZmap::CDeSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise) const
{
// Controllo sulla validità della superficie ed eventualmente sulla sua chiusura
if ( ! ( tmSurf.IsValid() && tmSurf.IsClosed()))
return false ;
// Controllo sulla validità della superficie e sulla sua chiusura
if ( ! tmSurf.IsValid() || ! tmSurf.IsClosed())
return true ;
// Bounding box della superficie espresso nel sistema locale
BBox3d b3SurfBox ;
tmSurf.GetLocalBBox( b3SurfBox) ;
@@ -1862,7 +1879,7 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
// Box intersezione: se non c'è intersezione ho finito.
BBox3d b3IntBox ;
if ( ! b3ZmapBox.FindIntersection( b3SurfBox, b3IntBox))
return true ;
return false ;
// Recupero i triangoli della superficie che cadono nel box intersezione.
INTVECTOR vTriaIndex ;
tmSurf.GetAllTriaOverlapBox( b3IntBox, vTriaIndex) ;
@@ -1923,7 +1940,7 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
return false ;
return true ;
}
}
}
@@ -1939,7 +1956,7 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
return false ;
return true ;
}
}
}
@@ -2030,11 +2047,11 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
double dU1, dU2 ;
int nIntersType = SegmentSphere( ptSegSt, vtLineDir, dSegLen, ptVertP, dSafeDist, dU1, dU2) ;
if ( nIntersType != LinCompSphereIntersType::S_NO_INTERS)
return false ;
return true ;
nIntersType = IntersSegmentCylinder( ptSegSt, vtLineDir, dSegLen, ptVertP, vtEdgeV,
dSafeDist, dEdgeLen, dU1, dU2) ;
if ( nIntersType != LinCompCCIntersType::CC_NO_INTERS)
return false ;
return true ;
}
// Traslo il triangolo.
trNewTria.Translate( dSafeDist * trTria.GetN()) ;
@@ -2044,14 +2061,14 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
int nIntersType = IntersLineTria( ptSegSt, vtLineDir, dSegLen, trNewTria, ptInt, ptInt2) ;
// Collisione
if ( nIntersType != IntLineTriaType::ILTT_NO)
return false ;
return true ;
}
}
}
}
}
return true ;
return false ;
}
//----------------------------------------------------------------------------
@@ -2895,8 +2912,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
nNumVox, nB, ptLineTria1, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
}
// altrimenti ci sono due intersezioni
else {
@@ -2904,8 +2922,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
}
}
}
@@ -2931,8 +2950,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
nNumVox, nB, ptLineTria1, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
}
// altrimenti ci sono due intersezioni
else {
@@ -2940,8 +2960,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
}
}
}
@@ -2957,15 +2978,17 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
continue ;
// se altrimenti c'è una sola intersezione
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
-1, nB, ptLineTria1, trTria) ;
-1, nB, trTria, dCosDN, ptLineTria1) ;
}
// altrimenti ci sono due intersezioni
else {
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
-1, nB, ptLineTria1, ptLineTria2, trTria) ;
-1, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
}
}
}
@@ -2990,8 +3013,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
nNumVox, nB, ptLineTria1, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
}
// altrimenti ci sono due intersezioni
else {
@@ -2999,8 +3023,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
}
}
}
+1
View File
@@ -17,6 +17,7 @@
#include "CurveLine.h"
#include "VolZmap.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include <future>
+9 -13
View File
@@ -4673,23 +4673,19 @@ VolZmap::GetEdges( ICURVEPOVECTOR& vpCurve) const
PtrOwner<CurveComposite> pCrvCompo( CreateBasicCurveComposite()) ;
if ( IsNull( pCrvCompo))
return false ;
// recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita
// recupero gli estremi dei segmenti e li inserisco nella composita
for ( int i = 0 ; i < int( vId.size()) ; ++ i) {
// creo un segmento di retta
// recupero indice e flag di inversione
int nInd = abs( vId[i]) - 1 ;
bool bInvert = ( vId[i] < 0) ;
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
if ( IsNull( pLine) || ! pLine->Set( vBpt[nInd].first, vBpt[nInd].second))
continue ;
if ( bInvert)
pLine->Invert() ;
// lo accodo alla composita
if ( ! pCrvCompo->AddCurve( Release( pLine), true, 1.1 * dToler) &&
! AreSamePointApprox( ptNear, ( bInvert ? vBpt[nInd].first : vBpt[nInd].second)))
return false ;
// aggiorno il prossimo near
ptNear = ( bInvert ? vBpt[nInd].first : vBpt[nInd].second) ;
// se primo segmento, inserisco il punto iniziale
if ( i == 0)
pCrvCompo->AddPoint( ! bInvert ? vBpt[nInd].first : vBpt[nInd].second) ;
// aggiungo il punto finale
pCrvCompo->AddLine( ! bInvert ? vBpt[nInd].second : vBpt[nInd].first) ;
}
// aggiorno il prossimo near
pCrvCompo->GetEndPoint( ptNear) ;
// se lunghezza curva inferiore a 5 volte la tolleranza, la salto
double dCrvLen ;
if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5 * dToler)
+248 -131
View File
@@ -79,7 +79,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
if ( pCrv == nullptr)
return false ;
// verifico se è una linea
// verifico se è una linea
int nType = pCrv->GetType() ;
bool bIsLine = ( nType == CRV_LINE) ;
if ( nType == CRV_COMPO) {
@@ -92,7 +92,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
// verifico sia piana e trovo piano su cui giace
Plane3d plPlane ;
if ( bIsLine) {
// linea è sicuramente piana. Scelgo piano definito dall'estrusione ( se definita)
// linea è sicuramente piana. Scelgo piano definito dall'estrusione ( se definita)
Point3d ptS ; pCrv->GetStartPoint( ptS) ;
Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ;
if ( ! vtExtr.IsSmall())
@@ -110,30 +110,40 @@ Voronoi::AddCurve( const ICurve* pCrv)
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
}
else {
// altrimenti verifico sia complanare ad eventuali curve già presenti
// altrimenti verifico sia complanare ad eventuali curve già presenti
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), plPlane.GetVersN()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
return false ;
}
// verifico se oggetto vroni è stato inizializzato
if ( m_vroni == nullptr) {
m_vroni = new( nothrow) vroniObject() ;
m_vroni->apiInitializeProgram() ;
}
// creo una copia della curva e la porto in locale
PtrOwner<ICurve> pCrvLoc( pCrv->Clone()) ;
if ( IsNull( pCrvLoc))
return false ;
pCrvLoc->ToLoc( m_Frame) ;
// aggiungo la curva in locale all'oggetto vroni
if ( ! AddCurveToVroni( pCrvLoc))
try {
// verifico se oggetto vroni è stato inizializzato
if ( m_vroni == nullptr) {
m_vroni = new( nothrow) vroniObject() ;
if ( m_vroni == nullptr)
return false ;
m_vroni->apiInitializeProgram() ;
}
// aggiungo la curva in locale all'oggetto vroni
if ( ! AddCurveToVroni( pCrvLoc))
return false ;
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
return false ;
}
// aggiorno il box complessivo
BBox3d bBox ;
pCrvLoc->GetLocalBBox( bBox) ;
m_bBox.Add( bBox) ;
return true ;
}
@@ -155,28 +165,38 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
m_Frame.Set( ptCen, vtN) ;
}
else {
// verifico sia complanare ad eventuali curve già presenti
// verifico sia complanare ad eventuali curve già presenti
Plane3d plPlane ;
plPlane.Set( ptCen, pSfr->GetNormVersor()) ;
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), pSfr->GetNormVersor()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
return false ;
}
// verifico se oggetto vroni è stato inizializzato
if ( m_vroni == nullptr) {
m_vroni = new( nothrow) vroniObject() ;
m_vroni->apiInitializeProgram() ;
}
// aggiungo le curve di loop
for ( int i = 0 ; i < pSfr->GetChunkCount() ; i ++) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; j ++) {
PtrOwner<ICurve> pCrvLoc( pSfr->GetLoop( i, j)) ;
pCrvLoc->ToLoc( m_Frame) ;
if ( ! AddCurveToVroni( pCrvLoc))
try {
// verifico se oggetto vroni è stato inizializzato
if ( m_vroni == nullptr) {
m_vroni = new( nothrow) vroniObject() ;
if ( m_vroni == nullptr)
return false ;
}
}
m_vroni->apiInitializeProgram() ;
}
// aggiungo le curve di loop
for ( int i = 0 ; i < pSfr->GetChunkCount() ; i ++) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; j ++) {
PtrOwner<ICurve> pCrvLoc( pSfr->GetLoop( i, j)) ;
if ( IsNull( pCrvLoc))
return false ;
pCrvLoc->ToLoc( m_Frame) ;
if ( ! AddCurveToVroni( pCrvLoc))
return false ;
}
}
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage())
return false ;
}
// aggiorno il box complessivo
BBox3d bBox ;
@@ -184,7 +204,7 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
frSrf.Invert() ;
pSfr->GetBBox( frSrf, bBox) ;
m_bBox.Add( bBox) ;
return true ;
}
@@ -225,8 +245,9 @@ Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, i
{
if ( pLine == nullptr)
return false ;
// verifico se il punto finale viene forzato oppure deve essere ricavato dalla pLine
if ( ! ptEnd.IsValid()) {
// recupero end point
if ( ! pLine->GetEndPoint( ptEnd))
return false ;
}
@@ -260,8 +281,8 @@ Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int
m_vroni->AddArc( &nVroniCrv, ptStart.x, ptStart.y, ptCen.x, ptCen.y, nArcSiteType, {nLoopId, nCrvId}) ;
}
else {
// verifico se il punto finale viene forzato oppure deve essere ricavato dal pArc
if ( ! ptEnd.IsValid()) {
// recupero end point dalla curva
if ( ! pArc->GetEndPoint( ptEnd))
return false ;
}
@@ -294,7 +315,7 @@ Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLo
for ( int i = 0 ; i < pCopy->GetCurveCount() ; i++) {
Point3d ptForcedEnd = P_INVALID ;
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
if ( i == pCopy->GetCurveCount() - 1 && bClosed)
pCompo->GetStartPoint( ptForcedEnd) ;
@@ -338,7 +359,7 @@ Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoo
ICurve*
Voronoi::GetCurve( int nId) const
{
// verifico validità indice
// verifico validità indice
if ( nId < 0 || nId > ( int)m_vpCrvs.size() - 1)
return nullptr ;
// ne faccio una copia
@@ -354,20 +375,22 @@ Voronoi::GetCurve( int nId) const
bool
Voronoi::CalcVoronoi( int nBound)
{
// se già stato calcolato con lo stesso bound non devo fare nulla
// se già stato calcolato con lo stesso bound non devo fare nulla
if ( m_bVDComputed && nBound == m_nBound)
return true ;
// se già stato calcolato reset dei dati
// se già stato calcolato reset dei dati
if ( m_bVDComputed)
m_vroni->ResetVoronoiDiagram() ;
// come valore minimo per il bound considero quello standard di vroni
m_nBound = max( nBound, VORONOI_STD_BOUND) ;
// calcolo
m_nBound = nBound ;
m_bVDComputed = true ;
string sTmp = "" ;
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
return true ;
}
@@ -467,15 +490,24 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
if ( ! IsValid())
return false ;
// verifico se necessario calcolo Voronoi
if ( ! m_bVDComputed || nBound != m_nBound)
CalcVoronoi( nBound) ;
try {
// verifico se necessario calcolo Voronoi
if ( ! m_bVDComputed || nBound != m_nBound)
CalcVoronoi( nBound) ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// recupero la curva del bisettore
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid())
vCrvs.emplace_back( Release( pCrv)) ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// recupero la curva del bisettore
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid())
vCrvs.emplace_back( Release( pCrv)) ;
}
// libero la memoria di vroni utilizzata per calcolare bisettore
m_vroni->apiFreeBisectorBuffer() ;
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
return false ;
}
return true ;
@@ -489,10 +521,7 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
if ( ! IsValid())
return false ;
if ( ! m_bVDComputed)
CalcVoronoi() ;
// lato per il medial axis
bool bLeft = true ;
bool bRight = true ;
@@ -501,18 +530,31 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
else if ( nSide == WMAT_RIGHT)
bLeft = false ;
// calcolo medial axis
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// verifico se il lato appartiene al medial axis
if ( m_vroni->IsWMATEdge( i)) {
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid())
vCrvs.emplace_back( Release( pCrv)) ;
}
try {
if ( ! m_bVDComputed)
CalcVoronoi() ;
// calcolo medial axis
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
// verifico se il lato appartiene al medial axis
if ( m_vroni->IsWMATEdge( i)) {
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
if ( ! IsNull( pCrv) && pCrv->IsValid())
vCrvs.emplace_back( Release( pCrv)) ;
}
}
// libero la memoria di vroni utilizzata per calcolare bisettore
m_vroni->apiFreeBisectorBuffer() ;
}
return true ;
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
@@ -559,20 +601,21 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
if ( pCrv->IsValid()) {
// eventuale inversione
if ( dOffs > EPS_SMALL)
pCrv->Invert() ;
pCrv->Invert() ;
// sistemo i raccordi
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
IdentifyFillets( pCrv, dOffs) ;
AdjustCurveFillets( pCrv, dOffs, nType) ;
}
if ( bClosed) {
// forzo chiusura della curva per evitare piccole imprecisioni
pCrv->Close() ;
// sistemo il punto di inizio
AdjustOffsetStart( *pCrv) ;
}
// sistemo i raccordi
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
IdentifyFillets( pCrv, dOffs) ;
AdjustCurveFillets( pCrv, dOffs, nType) ;
}
// porto nel frame globale
pCrv->ToGlob( m_Frame) ;
// unisco le parti allineate
@@ -614,12 +657,12 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo
// sistemo i raccordi
if ( bClosed && bSquareMids) {
// se curva è chiusa tutti i raccordi rispondono a bSquareMids
// se curva è chiusa tutti i raccordi rispondono a bSquareMids
IdentifyFillets( pCrvOffs, dOffs) ;
AdjustCurveFillets( pCrvOffs, dOffs, ICurve::OFF_EXTEND) ;
}
else if ( ! bClosed && ( bSquareMids || bSquareEnds)) {
// se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e
// se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e
// modificare solo quelli richiesti
for ( int j = 0 ; j < pCrvOffs->GetCurveCount() ; j ++) {
int nOrigCrv ; pCrvOffs->GetCurveTempProp( j, nOrigCrv) ;
@@ -660,75 +703,84 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs, bool bRightOff
nOrigCrvCnt = pOrigCompo->GetCurveCount() ;
}
// reset di eventuali offset precedenti
m_vroni->apiResetOffsetData() ;
// verifico necessario calcolo o ricalcolo di Voronoi
UpdateVoronoi( dOffs) ;
string sTmp = "" ;
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, bLeftOffs, bRightOffs) ;
int nOffsCnt = m_vroni->GetOffsetCount() ;
if ( nOffsCnt == 0) {
// se non ho ottenuto offset ritento con valore leggermente diverso per le tolleranze di vroni
try {
// reset di eventuali offset precedenti
m_vroni->apiResetOffsetData() ;
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs - VRONI_OFFS_TOL, 0.0, false, bLeftOffs, bRightOffs) ;
nOffsCnt = m_vroni->GetOffsetCount() ;
}
// recupero le curve di offset da vroni
for ( int i = 0 ; i < nOffsCnt ; i++) {
PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ;
int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve
// verifico necessario calcolo o ricalcolo di Voronoi
UpdateVoronoi( dOffs) ;
for ( int j = 0 ; j < nCrvCnt ; j ++) {
// recupero la sottocurva da vroni
Point3d ptS, ptE, ptC ;
int nType ;
int nOrigCrv, nOrigLoop, nOrigPnt ; // sito
m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ;
if ( j == 0)
pCrvOffs->AddPoint( ptS) ;
bool bOk = false ;
if ( nType == t_site::SEG)
bOk = pCrvOffs->AddLine( ptE) ;
else {
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
pArc->Set2PRS( ptS, ptE, Dist( ptC, ptS), nType == CCW) ;
bOk = pCrvOffs->AddCurve( Release( pArc)) ;
}
// se la curva è stata aggiunta
if ( bOk) {
// setto come info la sottocurva da cui si è generata
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
// verifico se è raccordo relativo agli estremi della curva
if ( nOrigCrv == -1 && ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt))
pCrvOffs->SetCurveTempParam( nCurrCrvId, 1.0, 0) ;
}
string sTmp = "" ;
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, bLeftOffs, bRightOffs) ;
int nOffsCnt = m_vroni->GetOffsetCount() ;
if ( nOffsCnt == 0) {
// se non ho ottenuto offset ritento con valore leggermente diverso per le tolleranze di vroni
m_vroni->apiResetOffsetData() ;
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs - VRONI_OFFS_TOL, 0.0, false, bLeftOffs, bRightOffs) ;
nOffsCnt = m_vroni->GetOffsetCount() ;
}
// rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
// recupero le curve di offset da vroni
for ( int i = 0 ; i < nOffsCnt ; i++) {
PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ;
int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve
// aggiungo la curva alla lista degli offset
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid())
OffsList.push_back( Release( pCrvOffs)) ;
for ( int j = 0 ; j < nCrvCnt ; j ++) {
// recupero la sottocurva da vroni
Point3d ptS, ptE, ptC ;
int nType ;
int nOrigCrv, nOrigLoop, nOrigPnt ; // sito
m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ;
if ( j == 0)
pCrvOffs->AddPoint( ptS) ;
bool bOk = false ;
if ( nType == t_site::SEG)
bOk = pCrvOffs->AddLine( ptE) ;
else {
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
pArc->Set2PRS( ptS, ptE, Dist( ptC, ptS), nType == CCW) ;
bOk = pCrvOffs->AddCurve( Release( pArc)) ;
}
// se la curva è stata aggiunta
if ( bOk) {
// setto come info la sottocurva da cui si è generata
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
// verifico se è raccordo relativo agli estremi della curva
if ( nOrigCrv == -1 && ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt))
pCrvOffs->SetCurveTempParam( nCurrCrvId, 1.0, 0) ;
}
}
// rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
// aggiungo la curva alla lista degli offset
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid())
OffsList.push_back( Release( pCrvOffs)) ;
}
// libero la memoria di vroni dedicata agli offset
m_vroni->apiFreeOffsetData() ;
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Voronoi::UpdateVoronoi( double dOffs)
{
double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ;
// calcolo il bound necessario per l'offset desiderato
double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ;
if ( ! m_bVDComputed || dNeededBound > m_nBound) {
// aggiorno il valore del bound
int nBound = ( int)( ceil( dNeededBound) + 0.5) ;
@@ -737,7 +789,6 @@ Voronoi::UpdateVoronoi( double dOffs)
}
return true ;
}
//----------------------------------------------------------------------------
@@ -747,7 +798,7 @@ Voronoi::VerifyCurvesValidityForOffset()
if ( m_vpCrvs.size() == 1)
return true ;
// se ho più curve, devono essere tutte chiuse
// se ho più curve, devono essere tutte chiuse
for ( auto pCrv : m_vpCrvs) {
if ( ! pCrv->IsClosed())
return false ;
@@ -767,12 +818,29 @@ Voronoi::VerifyCurvesValidityForOffset()
// se curva con orientamento principale verifico sia esterna a tutte le altre curve con orientamento principale
if ( vArea[i] * dRefArea > EPS_SMALL) {
for ( int j = i + 1 ; j < ( int)vArea.size() ; j++) {
if ( vArea[i] * vArea[j] > EPS_SMALL) {
for ( int j = 0 ; j < ( int)vArea.size() ; j++) {
if ( j != i && vArea[i] * vArea[j] > EPS_SMALL) {
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ;
int nRes = ccInt.GetRegionCurveClassification() ;
if ( ( bRefCCW && nRes != CCREGC_OUT) || ( ! bRefCCW && nRes != CCREGC_IN1))
if ( nRes == CCREGC_NULL || nRes == CCREGC_SAME || nRes == CCREGC_INTERS)
return false ;
if ( ( bRefCCW && nRes == CCREGC_IN1) || ( ! bRefCCW && nRes == CCREGC_IN2)) {
// se è interna ad una curva con orientamento principale, verifico sia esterna ad almeno una curva con orientamento
// diverso dal principale
bool bFound = false ;
for ( int k = 0 ; k < ( int)vArea.size() ; k++) {
if ( k != i && vArea[i] * vArea[k] < EPS_SMALL) {
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[k]) ;
int nRes = ccInt.GetRegionCurveClassification() ;
if ( ( bRefCCW && nRes == CCREGC_OUT) || ( ! bRefCCW && nRes == CCREGC_IN1)) {
bFound = true ;
break ;
}
}
}
if ( ! bFound)
return false ;
}
}
}
}
@@ -842,7 +910,7 @@ Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs)
// mi posiziono dopo la junction
pCompo.ChangeStartPoint( vJunctions[0] + 1) ;
delete( pCompo.RemoveFirstOrLastCurve()) ;
// verifico validità della curva
// verifico validità della curva
int nSide = GetOffsetCurveSide( pCompo, 0) ;
if ( nSide == nSideRef) {
// scorro fino alla prima curva non valida ed elimino la curva da quel punto fino alla fine
@@ -853,7 +921,7 @@ Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs)
}
}
else {
// elimino finchè non trovo una curva valida
// elimino finchè non trovo una curva valida
while( nSide != nSideRef && pCompo.IsValid()) {
delete( pCompo.RemoveFirstOrLastCurve( false)) ;
if ( pCompo.IsValid())
@@ -906,3 +974,52 @@ Voronoi::AdjustOffsetStart( ICurveComposite& pCrv)
}
return true ;
}
//---------------------------------------------------------------------------
bool
Voronoi::Translate( const Vector3d & vtMove)
{
if ( ! IsValid())
return false ;
return m_Frame.Translate( vtMove) ;
}
//---------------------------------------------------------------------------
bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
{
if ( ! IsValid())
return false ;
return m_Frame.Rotate( ptAx, vtAx, dAngDeg) ;
}
//---------------------------------------------------------------------------
bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{
if ( ! IsValid())
return false ;
return m_Frame.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
}
//---------------------------------------------------------------------------
bool Voronoi::ToGlob( const Frame3d& frRef)
{
if ( ! IsValid())
return false ;
return m_Frame.ToGlob( frRef) ;
}
//---------------------------------------------------------------------------
bool Voronoi::ToLoc( const Frame3d& frRef)
{
if ( ! IsValid())
return false ;
return m_Frame.ToLoc( frRef) ;
}
//---------------------------------------------------------------------------
bool Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{
if ( ! IsValid())
return false ;
return m_Frame.LocToLoc( frOri, frDest) ;
}
+9 -2
View File
@@ -55,6 +55,13 @@ class Voronoi
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids) ;
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ;
bool Translate( const Vector3d& vtMove) ;
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) ;
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) ;
bool ToGlob( const Frame3d& frRef) ;
bool ToLoc( const Frame3d& frRef) ;
bool LocToLoc( const Frame3d& frOri, const Frame3d& frDest) ;
private :
bool Clear( void) ;
bool IsValid( void) const
@@ -76,10 +83,10 @@ class Voronoi
private :
vroniObject* m_vroni ; // oggetto base della libreria vroni
Frame3d m_Frame ; // frame in cui è espresso l'oggetto vroni
Frame3d m_Frame ; // frame in cui è espresso l'oggetto vroni
int m_nBound ; // bound associato al diagramma di Voronoi corrente
CICURVEPVECTOR m_vpCrvs ; // curve associate al Voronoi ( espresse rispetto a m_Frame)
BBox3d m_bBox ; // box degli oggetti associati al Voronoi
bool m_bVDComputed ; // indica se il diagramma di Voronoi è stato calcolato
bool m_bVDComputed ; // indica se il diagramma di Voronoi è stato calcolato
bool m_bAllowAdd ; // indica se possibile aggiungere altre curve/superifici dopo aver creato l'oggetto Voronoi
} ;