Compare commits

...

14 Commits

Author SHA1 Message Date
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
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
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
Daniele Bariletti 47e79756d1 EgtGeomKernel :
- corretto bug nella triangolazione delle sup. di Bezier.
2024-02-12 12:53:57 +01:00
SaraP 595421bcdd EgtGeomKernel :
- gestone delle eccezioni di vroni
- correzioni varie.
2024-02-12 12:22:24 +01:00
Daniele Bariletti 517a66b0fe EgtGeomKernel :
- aggiunta di commenti al codice di triangolazione per le bezier.
2024-02-06 15:57:11 +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
41 changed files with 1001 additions and 604 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 ;
}
}
BIN
View File
Binary file not shown.
+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 ;
}*/
+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 ;
}
+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) {
+114 -37
View File
@@ -26,6 +26,7 @@
#include <algorithm>
#include <thread>
#include <future>
#include <EgtDev/Include/EGkIntersCurves.h>
using namespace std ;
@@ -800,56 +801,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 ;
}
+1 -1
View File
@@ -209,7 +209,7 @@ SurfFlatRegion::Offset( double dDist, int nType)
// 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)) ;
+2 -2
View File
@@ -31,7 +31,7 @@
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <new>
#include <set>
#include <set>
using namespace std ;
@@ -1960,7 +1960,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
+196 -126
View File
@@ -35,6 +35,7 @@
#include "/EgtDev/Include/EGkPolygon3d.h"
#include "/EgtDev/Include/EgtPerfCounter.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EGkGeoObjSave.h"
#include <algorithm>
using namespace std ;
@@ -52,9 +53,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 +65,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 +194,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 +205,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 +247,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 +265,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 +293,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 +313,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 +392,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 +479,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 +488,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 +497,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 +577,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 +585,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 +713,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
break ;
}
}
if ( vInnerLoop.size() == 0 || bDouble) {
// Eseguo triangolazione
PNTVECTOR vPt ;
@@ -710,7 +731,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 +740,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 +781,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 +808,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 +838,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() ;
@@ -928,26 +949,24 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
}
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 ;
}
vPolygons.erase( vPolygons.begin()) ;
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 +1107,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 +1137,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 +1198,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 +1207,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 +1219,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 +1233,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 +1245,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 +1258,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 +1297,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 +1340,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 +1348,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 +1356,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 +1386,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 +1406,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 +1424,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 +1432,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 +1440,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 +1470,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 +1480,15 @@ 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()) ;
SaveGeoObj( this, "C:\\Users\\riccardo.elitropi\\Desktop\\SurfA.nge") ;
SaveGeoObj( SurfB.Clone(), "C:\\Users\\riccardo.elitropi\\Desktop\\SurfB.nge") ;
// Triangoli sovrapposti
if ( bContinue) {
int nTriaNum2A = GetTriangleSize() ;
@@ -1491,7 +1526,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
return true ;
}
return true ;
}
@@ -1620,48 +1655,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
@@ -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) {
+11 -10
View File
@@ -1805,8 +1805,9 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
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 ;
@@ -2077,14 +2078,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 +2095,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 +2105,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 +2115,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 +2918,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]) ;
+18 -18
View File
@@ -173,8 +173,8 @@ class Tree
bool GetPolygons( POLYLINEMATRIX& vPolygons) ;
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons) ; // 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
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
private :
bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert
@@ -193,27 +193,27 @@ 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
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
bool m_bBilinear ; // superficie bilineare
bool m_bMulti ; // superficie multi-patch
bool m_bClosedU ; // superficie chiusa lungo il parametro U
@@ -221,8 +221,8 @@ class Tree
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
+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) ;
+19 -19
View File
@@ -114,17 +114,17 @@ class VolZmap : public IVolZmap, public IGeoObjRW
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 ;
@@ -393,14 +393,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) ;
+203 -186
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 ;
}
//----------------------------------------------------------------------------
+155 -113
View File
@@ -115,25 +115,35 @@ Voronoi::AddCurve( const ICurve* pCrv)
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 ;
}
@@ -162,21 +172,31 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
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 ;
}
@@ -362,8 +383,10 @@ Voronoi::CalcVoronoi( int nBound)
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) ;
@@ -467,15 +490,21 @@ 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)) ;
}
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
return false ;
}
return true ;
@@ -489,10 +518,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 +527,28 @@ 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)) ;
}
}
}
return true ;
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
@@ -559,20 +595,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
@@ -660,75 +697,81 @@ 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)) ;
}
}
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 +780,6 @@ Voronoi::UpdateVoronoi( double dOffs)
}
return true ;
}
//----------------------------------------------------------------------------