Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 104726c5ee | |||
| e2445c0a15 | |||
| 9880fa0173 | |||
| d276809906 | |||
| 4268da4a1f | |||
| 4f485d0e87 | |||
| d48348fa1c | |||
| 003dd0bdef | |||
| ec109908fa | |||
| 3630b85632 | |||
| fdce6e1853 | |||
| 8ffa9d7fb7 | |||
| 360484c9af | |||
| 47606bffcd | |||
| aea99a635f | |||
| ce139c6925 | |||
| 5dcf5f5616 | |||
| 451ef8356b | |||
| 6e810f050e | |||
| 6bfb5c619f | |||
| bd90fc2b59 | |||
| 5800093e53 | |||
| fae6a7cd78 | |||
| 65daddfced | |||
| 95915b16e5 | |||
| ddade325c4 | |||
| 46b91bb49d | |||
| c8ce0a242e | |||
| 8be2246249 | |||
| 47e79756d1 | |||
| 595421bcdd | |||
| 517a66b0fe | |||
| 56cff98cf3 | |||
| 3168bee865 | |||
| 3d2f8c1495 | |||
| 7cd83efd97 | |||
| 751ea085a6 | |||
| 15ed754512 |
+15
-5
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) ;
|
||||
|
||||
@@ -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) ;
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -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
@@ -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
@@ -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) ;
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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) ;
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -368,4 +368,4 @@ ClampSegmentOutPlane( const Plane3d& plPlane, Point3d& ptSegP, const Vector3d& v
|
||||
dSegLen -= dIntersLen ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -309,14 +309,26 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="CurveByApprox.cpp" />
|
||||
<ClCompile Include="CurveByInterp.cpp" />
|
||||
<ClCompile Include="CurveCompositeOffset.cpp" />
|
||||
<ClCompile Include="IntersCurveSurfTm.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersLineVolZmap.cpp" />
|
||||
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
||||
<ClCompile Include="PolygonElevation.cpp" />
|
||||
<ClCompile Include="RotationMinimizeFrame.cpp" />
|
||||
<ClCompile Include="Voronoi.cpp" />
|
||||
<ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkCDeConeFrustumClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkCDeConvexTorusClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkCDeRectPrismoidClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersCurveSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersLineBox.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneBox.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h" />
|
||||
<ClInclude Include="..\Include\EGkPolygonElevation.h" />
|
||||
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
|
||||
<ClInclude Include="CDeBoxTria.h" />
|
||||
@@ -449,6 +461,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="VolZmapGraphics.cpp" />
|
||||
<ClCompile Include="VolZmapVolume.cpp" />
|
||||
<ClCompile Include="VolZmap.cpp" />
|
||||
<ClInclude Include="RotationMinimizeFrame.h" />
|
||||
<ClInclude Include="Voronoi.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -43,15 +43,18 @@
|
||||
<Filter Include="File di origine\GeoOffset">
|
||||
<UniqueIdentifier>{f07670fd-9429-4b7e-ac6d-1c0022e756fb}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoCollision">
|
||||
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoProject">
|
||||
<UniqueIdentifier>{d96752da-1884-4a73-ba1b-5b20b606e469}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoElevation">
|
||||
<UniqueIdentifier>{4c6a9dc5-8fac-4ecd-bde6-3e37e056712e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoCollisionAvoid">
|
||||
<UniqueIdentifier>{ae52e402-3063-45e3-b9f7-1710035a1f56}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoCollisionDetection">
|
||||
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Vector3d.cpp">
|
||||
@@ -372,17 +375,8 @@
|
||||
<ClCompile Include="IntersLineSurfStd.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvToolTriangle.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvToolSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeBoxTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvSimpleSurfFrMove.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersSurfTmSurfTm.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
@@ -400,19 +394,19 @@
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeCylTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeBoxClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeCylClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeSpheTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeSpheClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SurfBezier.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
@@ -430,34 +424,34 @@
|
||||
<Filter>File di origine\GeoDist</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeTriaTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeConeTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeUtility.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeClosedSurfTmClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeConeFrustumClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeConeFrustumTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeConvexTorusClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeConvexTorusTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeRectPrismoidClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeRectPrismoidTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SurfTriMeshUtilities.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
@@ -469,7 +463,7 @@
|
||||
<Filter>File di origine\Base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeCapsTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Circle2P.cpp">
|
||||
<Filter>File di origine\GeoCreate</Filter>
|
||||
@@ -510,6 +504,27 @@
|
||||
<ClCompile Include="PolygonElevation.cpp">
|
||||
<Filter>File di origine\GeoElevation</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersCurveSurfTm.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvSimpleSurfFrMove.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvToolSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvToolTriangle.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersLineVolZmap.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersPlaneVolZmap.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RotationMinimizeFrame.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -1169,6 +1184,18 @@
|
||||
<ClInclude Include="Voronoi.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkIntersCurveSurfTm.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RotationMinimizeFrame.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
+1
-1
@@ -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 ;
|
||||
}*/
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersCurveSurfTm.cpp Data : 23.02.24 Versione : 2.6b4
|
||||
// Contenuto : Implementazione della intersezione curva/superficie trimesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 23.02.24 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurveSurfTm.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void
|
||||
UpdateInfoIntersCurveSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen, double dUs, double dUe,
|
||||
int nT, const Triangle3d& Tria, ICSIVECTOR& vInfo)
|
||||
{
|
||||
Point3d ptInt, ptInt2 ;
|
||||
int nRes = IntersLineTria( ptL, vtDir, dLen, Tria, ptInt, ptInt2, true) ;
|
||||
if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) {
|
||||
double dU = dUs + ( ptInt - ptL) * vtDir / dLen * ( dUe - dUs) ;
|
||||
double dCosDN = vtDir * Tria.GetN() ;
|
||||
vInfo.emplace_back( nRes, dU, nT, dCosDN, ptInt) ;
|
||||
}
|
||||
else if ( nRes == ILTT_SEGM || nRes == ILTT_SEGM_ON_EDGE) {
|
||||
double dU = dUs + ( ptInt - ptL) * vtDir / dLen * ( dUe - dUs) ;
|
||||
double dU2 = dUs + ( ptInt2 - ptL) * vtDir / dLen * ( dUe - dUs) ;
|
||||
double dCosDN = vtDir * Tria.GetN() ;
|
||||
vInfo.emplace_back( nRes, dU, dU2, nT, dCosDN, ptInt, ptInt2) ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void
|
||||
OrderInfoIntersCurveSurfTm( ICSIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
if ( vInfo.size() == 0)
|
||||
return ;
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
[]( const IntCrvStmInfo& a, const IntCrvStmInfo& b)
|
||||
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
return ( dUa < dUb) ; }) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una curva con una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurveSurfTm( const ICurve& Curve, const ISurfTriMesh& Stm, double dLinTol, ICSIVECTOR& vInfo)
|
||||
{
|
||||
// verifico i parametri ricevuti
|
||||
if ( & Curve == nullptr || &Stm == nullptr || &vInfo == nullptr)
|
||||
return false ;
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
vInfo.clear() ;
|
||||
|
||||
// approssimo la curva con una spezzata
|
||||
PolyLine PL ;
|
||||
if ( ! Curve.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return false ;
|
||||
|
||||
// per ogni segmento dell'approssimante cerco l'intersezione con la superficie
|
||||
double dParS, dParE ;
|
||||
Point3d ptStart, ptEnd ;
|
||||
bool bFound = PL.GetFirstULine( &dParS, &ptStart, &dParE, &ptEnd) ;
|
||||
while ( bFound) {
|
||||
Vector3d vtDir = ptEnd - ptStart ;
|
||||
double dLen = vtDir.Len() ;
|
||||
if ( dLen > EPS_SMALL) {
|
||||
vtDir /= dLen ;
|
||||
// cerco i triangoli intersecati dal segmento
|
||||
const double BOX_STEP = 10 ;
|
||||
int nStep = int( ceil( dLen / BOX_STEP)) ;
|
||||
Vector3d vtStep = dLen / nStep * vtDir ;
|
||||
INTVECTOR vPrevT ;
|
||||
for ( int i = 0 ; i < nStep ; ++ i) {
|
||||
BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ;
|
||||
INTVECTOR vT ;
|
||||
if ( Stm.GetAllTriaOverlapBox( b3Box, vT)) {
|
||||
for ( auto nT : vT) {
|
||||
// se triangolo non ancora intersecato
|
||||
if ( find( vPrevT.begin(), vPrevT.end(), nT) == vPrevT.end()) {
|
||||
vPrevT.emplace_back( nT) ;
|
||||
Triangle3d Tria ;
|
||||
Stm.GetTriangle( nT, Tria) ;
|
||||
// aggiorno info con intersezione
|
||||
UpdateInfoIntersCurveSurfTm( ptStart, vtDir, dLen, dParS, dParE, nT, Tria, vInfo) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// passo al segmento successivo
|
||||
bFound = PL.GetNextULine( &dParS, &ptStart, &dParE, &ptEnd) ;
|
||||
}
|
||||
|
||||
// ordino il vettore delle eventuali intersezioni secondo il senso crescente del parametro di linea
|
||||
OrderInfoIntersCurveSurfTm( vInfo) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurveSurfTmExt( const ICurve& Curve, const ISurfTriMesh& Stm, double dLinTol, INTDBLVECTOR& vInters)
|
||||
{
|
||||
ICSIVECTOR vInfo ;
|
||||
vInters.clear() ;
|
||||
return ( IntersCurveSurfTm( Curve, Stm, dLinTol, vInfo) && FilterCurveSurfTmInters( Curve, vInfo, vInters)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FilterCurveSurfTmInters( const ICurve& Curve, const ICSIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
{
|
||||
// verifico i parametri ricevuti
|
||||
if ( & Curve == nullptr || &vInfo == nullptr || &vInters == nullptr)
|
||||
return false ;
|
||||
vInters.clear() ;
|
||||
// info sulla curva
|
||||
bool bClosedCrv = Curve.IsClosed() ;
|
||||
double dParSCrv, dParECrv ;
|
||||
Curve.GetDomain( dParSCrv, dParECrv) ;
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
||||
int nFlag = CSIT_NONE ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = CSIT_IN_OUT ;
|
||||
else if ( Info.dCosDN < -EPS_ZERO)
|
||||
nFlag = CSIT_OUT_IN ;
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
vInters.emplace_back( CSIT_IN_ON, Info.dU) ;
|
||||
vInters.emplace_back( CSIT_ON_IN, Info.dU2) ;
|
||||
}
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
int nStart = ( bClosedCrv ? 0 : 1) ;
|
||||
for ( int j = nStart ; j < int( vInters.size()) ; ) {
|
||||
// intersezione precedente
|
||||
int i = ( j > 0 ? j - 1 : int( vInters.size()) - 1) ;
|
||||
// se hanno lo stesso parametro
|
||||
if ( abs( vInters[i].second - vInters[j].second) < EPS_PARAM ||
|
||||
( bClosedCrv && abs( vInters[i].second - dParECrv) < EPS_PARAM && abs( vInters[j].second - dParSCrv) < EPS_PARAM)) {
|
||||
// flag per eseguita cancellazione
|
||||
bool bSomeErased = false ;
|
||||
// se sono entrambe entranti o uscenti, elimino la seconda
|
||||
if ( ( vInters[i].first == CSIT_OUT_IN && vInters[j].first == CSIT_OUT_IN) ||
|
||||
( vInters[i].first == CSIT_IN_OUT && vInters[j].first == CSIT_IN_OUT)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una entrante e l'altra uscente, cambio in touch da fuori ed elimino la seconda
|
||||
else if ( vInters[i].first == CSIT_OUT_IN && vInters[j].first == CSIT_IN_OUT) {
|
||||
vInters[i].first = CSIT_OUT_OUT ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una uscente e l'altra entrante, cambio in touch da dentro ed elimino la seconda
|
||||
else if ( vInters[i].first == CSIT_IN_OUT && vInters[j].first == CSIT_OUT_IN) {
|
||||
vInters[i].first = CSIT_IN_IN ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una touch da fuori o da dentro e l'altra entrante o uscente, elimino la prima
|
||||
else if ( ( vInters[i].first == CSIT_OUT_OUT || vInters[i].first == CSIT_IN_IN) &&
|
||||
( vInters[j].first == CSIT_OUT_IN || vInters[j].first == CSIT_IN_OUT)) {
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una entrante o uscente e l'altra touch da fuori o da dentro, elimino la seconda
|
||||
else if ( ( vInters[i].first == CSIT_OUT_IN || vInters[i].first == CSIT_IN_OUT) &&
|
||||
( vInters[j].first == CSIT_OUT_OUT || vInters[j].first == CSIT_IN_IN)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
|
||||
else if ( ( vInters[i].first == CSIT_OUT_IN || vInters[i].first == CSIT_IN_OUT || vInters[i].first == CSIT_NONE) &&
|
||||
( vInters[j].first == CSIT_IN_ON || vInters[j].first == CSIT_OUT_ON)) {
|
||||
vInters[j].first = ( vInters[i].first == CSIT_IN_OUT ? CSIT_IN_ON : CSIT_OUT_ON) ;
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
|
||||
else if ( ( vInters[i].first == CSIT_ON_IN || vInters[i].first == CSIT_ON_OUT) &&
|
||||
( vInters[j].first == CSIT_OUT_IN || vInters[j].first == CSIT_IN_OUT || vInters[j].first == CSIT_NONE)) {
|
||||
vInters[i].first = ( vInters[j].first == CSIT_IN_OUT ? CSIT_ON_OUT : CSIT_ON_IN) ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
|
||||
else if ( ( vInters[i].first == CSIT_ON_IN || vInters[i].first == CSIT_ON_OUT) &&
|
||||
( vInters[j].first == CSIT_IN_ON || vInters[j].first == CSIT_OUT_ON)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
vInters.erase( vInters.begin() + ( j > 0 ? i : i - 1)) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
if ( bSomeErased) {
|
||||
if ( j > 0)
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
// passo alla successiva
|
||||
++ j ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
+1
-1
@@ -22,7 +22,7 @@ using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Linea e box allineato assi devono essere nel medesimo sistema di riferimento.
|
||||
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
// In caso di intersezione viene restituito true e i parametri lunghezza in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Linea e box allineato agli assi sono nel medesimo riferimento.
|
||||
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
// Con intersezione viene restituito true e i parametri lunghezza in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
|
||||
|
||||
+70
-5
@@ -21,7 +21,7 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
static void
|
||||
UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen,
|
||||
int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dL
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
static void
|
||||
OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
@@ -81,7 +81,7 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
// lo ingrandisco per non avere problemi con faccia piana su piani canonici
|
||||
b3Stm.Expand( 10 * EPS_SMALL) ;
|
||||
double dU1, dU2 ;
|
||||
if ( ! IntersLineBox( ptL, vtL, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2))
|
||||
if ( ! IntersLineBox( ptL, vtDir, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2))
|
||||
return true ;
|
||||
if ( bFinite) {
|
||||
dU1 = max( dU1, 0.) ;
|
||||
@@ -89,12 +89,12 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
if ( dU2 - dU1 < EPS_SMALL)
|
||||
return true ;
|
||||
}
|
||||
Point3d ptStart = ptL + dU1 * vtL ;
|
||||
Point3d ptStart = ptL + dU1 * vtDir ;
|
||||
double dLenEff = dU2 - dU1 ;
|
||||
// cerco i triangoli intersecati dalla linea
|
||||
const double BOX_STEP = 10 ;
|
||||
int nStep = int( ceil( dLenEff / BOX_STEP)) ;
|
||||
Vector3d vtStep = dLenEff / nStep * vtL ;
|
||||
Vector3d vtStep = dLenEff / nStep * vtDir ;
|
||||
INTVECTOR vPrevT ;
|
||||
for ( int i = 0 ; i < nStep ; ++ i) {
|
||||
BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ;
|
||||
@@ -189,3 +189,68 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
{
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
||||
int nFlag = LST_TOUCH ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = LST_OUT ;
|
||||
else if ( Info.dCosDN < -EPS_ZERO)
|
||||
nFlag = LST_IN ;
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
vInters.emplace_back( LST_TG_INI, Info.dU) ;
|
||||
vInters.emplace_back( LST_TG_FIN, Info.dU2) ;
|
||||
}
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
// intersezione precedente
|
||||
size_t i = j - 1 ;
|
||||
// se hanno lo stesso parametro
|
||||
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
|
||||
// se sono entrambe entranti o uscenti, elimino la seconda
|
||||
if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_IN) ||
|
||||
( vInters[i].first == LST_OUT && vInters[j].first == LST_OUT)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
|
||||
else if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_OUT) ||
|
||||
( vInters[i].first == LST_OUT && vInters[j].first == LST_IN)) {
|
||||
vInters[i].first = LST_TOUCH ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
|
||||
else if ( ( vInters[i].first == LST_IN || vInters[i].first == LST_OUT || vInters[i].first == LST_TOUCH) && vInters[j].first == LST_TG_INI) {
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
|
||||
else if ( vInters[i].first == LST_TG_FIN && ( vInters[j].first == LST_IN || vInters[j].first == LST_OUT || vInters[j].first == LST_TOUCH)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
|
||||
else if ( i > 0 && vInters[i].first == LST_TG_FIN && vInters[j].first == LST_TG_INI) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
// passo alla successiva
|
||||
++ j ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersLineVolZmap.cpp Data : 22.02.24 Versione : 2.6b4
|
||||
// Contenuto : Implementazione della intersezione linea/VolZmap.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 22.02.24 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "VolZmap.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una linea con la superficie di un solido VolZmap
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineVolZmap( const Point3d& ptL, const Vector3d& vtL, const IVolZmap& Vzm, ILZIVECTOR& vInfo)
|
||||
{
|
||||
// verifico linea
|
||||
Vector3d vtDir = vtL ;
|
||||
if ( ! vtDir.Normalize( EPS_ZERO))
|
||||
return false ;
|
||||
// verifico volume
|
||||
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
|
||||
if ( pVzm == nullptr)
|
||||
return false ;
|
||||
// verifico parametro di ritorno
|
||||
if ( &vInfo == nullptr)
|
||||
return false ;
|
||||
|
||||
// eseguo intersezione
|
||||
return pVzm->GetLineIntersection( ptL, vtL, vInfo) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FilterLineVolZmapInters( const ILZIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
{
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
||||
int nFlag = LZT_TOUCH ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = LZT_OUT ;
|
||||
else if ( Info.dCosDN < -EPS_ZERO)
|
||||
nFlag = LZT_IN ;
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
vInters.emplace_back( LZT_TG_INI, Info.dU) ;
|
||||
vInters.emplace_back( LZT_TG_FIN, Info.dU2) ;
|
||||
}
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
// intersezione precedente
|
||||
size_t i = j - 1 ;
|
||||
// se hanno lo stesso parametro
|
||||
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
|
||||
// se sono entrambe entranti o uscenti, elimino la seconda
|
||||
if ( ( vInters[i].first == LZT_IN && vInters[j].first == LZT_IN) ||
|
||||
( vInters[i].first == LZT_OUT && vInters[j].first == LZT_OUT)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
|
||||
else if ( ( vInters[i].first == LZT_IN && vInters[j].first == LZT_OUT) ||
|
||||
( vInters[i].first == LZT_OUT && vInters[j].first == LZT_IN)) {
|
||||
vInters[i].first = LZT_TOUCH ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
|
||||
else if ( ( vInters[i].first == LZT_IN || vInters[i].first == LZT_OUT || vInters[i].first == LZT_TOUCH) && vInters[j].first == LZT_TG_INI) {
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
|
||||
else if ( vInters[i].first == LZT_TG_FIN && ( vInters[j].first == LZT_IN || vInters[j].first == LZT_OUT || vInters[j].first == LZT_TOUCH)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
|
||||
else if ( i > 0 && vInters[i].first == LZT_TG_FIN && vInters[j].first == LZT_TG_INI) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
// passo alla successiva
|
||||
++ j ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersPlaneVolZmap.cpp Data : 22.02.24 Versione : 2.6b4
|
||||
// Contenuto : Implementazione della intersezione piano/VolZmap.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 22.02.24 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "VolZmap.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlaneVolZmap.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di unpiano con la superficie di un solido VolZmap
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR& vpLoop)
|
||||
{
|
||||
// verifico volume
|
||||
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
|
||||
if ( pVzm == nullptr)
|
||||
return false ;
|
||||
// verifico parametro di ritorno
|
||||
if ( &vpLoop == nullptr)
|
||||
return false ;
|
||||
|
||||
// eseguo intersezione
|
||||
return pVzm->GetPlaneIntersection( plPlane, vpLoop) ;
|
||||
}
|
||||
+3
-3
@@ -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
@@ -30,7 +30,9 @@ IdentifyFillets( ICurveComposite* pCrvCo, double dDist)
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
if ( IsFillet( pCrv, dDist))
|
||||
pCrvCo->SetCurveTempParam( i, 1.0) ;
|
||||
pCrvCo->SetCurveTempParam( i, 1.0) ;
|
||||
else
|
||||
pCrvCo->SetCurveTempParam( i, 0.0) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
+76
-55
@@ -721,15 +721,42 @@ PolyLine::AdjustForMaxSegmentLen( double dMaxLen)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool
|
||||
PointsInTolerance( const PNTVECTOR& vRPT, const Point3d& ptP1, const Point3d& ptP2, double dSqTol)
|
||||
DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const int nIndStart,
|
||||
const int nIndEnd, INTVECTOR& vInd)
|
||||
{
|
||||
for ( const auto& ptQ : vRPT) {
|
||||
double dSqDist ;
|
||||
if ( ! DistPointLine( ptQ, ptP1, ptP2).GetSqDist( dSqDist) || dSqDist > dSqTol)
|
||||
// se indici uguali, ritorno
|
||||
if ( nIndStart == nIndEnd)
|
||||
return true ;
|
||||
|
||||
// distanza massima e indice del punto associato
|
||||
double dMaxSqDist = 0. ;
|
||||
int nMaxInd = 0 ;
|
||||
|
||||
// scorro i punti intermedi tra nIndStart e nIndEnd
|
||||
for ( int i = nIndStart + 1 ; i < nIndEnd ; ++ i) {
|
||||
double dCurrSqDist = 0. ;
|
||||
// distanza tra il punto attuale e la retta tra i punti di indici nIndStart ed nIndEnd
|
||||
DistPointLine DPL( vPtU[i].first, vPtU[nIndStart].first, vPtU[nIndEnd].first) ;
|
||||
if ( DPL.GetSqDist( dCurrSqDist) && dCurrSqDist > dMaxSqDist) {
|
||||
// aggiorno i parametri
|
||||
dMaxSqDist = dCurrSqDist ;
|
||||
nMaxInd = i ;
|
||||
}
|
||||
}
|
||||
|
||||
// se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra
|
||||
// (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd)
|
||||
if ( dMaxSqDist > dSqTol) {
|
||||
// inserisco il punto
|
||||
vInd.push_back( nMaxInd) ;
|
||||
// split
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nIndStart, nMaxInd, vInd) ||
|
||||
! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, nIndEnd, vInd))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -743,59 +770,53 @@ PolyLine::RemoveAlignedPoints( double dToler)
|
||||
// controllo minimo valore di tolleranza
|
||||
dToler = max( dToler, LIN_TOL_MIN) ;
|
||||
double dSqTol = dToler * dToler ;
|
||||
// si analizza la distanza di un punto dal segmento che unisce precedente e successivo
|
||||
// punto precedente
|
||||
auto precP = m_lUPoints.begin() ;
|
||||
// punto corrente
|
||||
auto currP = next( precP) ;
|
||||
// punto successivo
|
||||
auto nextP = next( currP) ;
|
||||
// lista dei punti appena rimossi
|
||||
PNTVECTOR vRPT ; vRPT.reserve( 20) ;
|
||||
// mentre esiste un successivo
|
||||
while ( nextP != m_lUPoints.end()) {
|
||||
// distanza del punto corrente dal segmento che unisce gli adiacenti
|
||||
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
|
||||
double dSqDist ;
|
||||
// se da eliminare
|
||||
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vRPT, precP->first, nextP->first, dSqTol)) {
|
||||
// aggiungo il punto nella lista dei rimossi
|
||||
vRPT.emplace_back( currP->first) ;
|
||||
// elimino il punto
|
||||
m_lUPoints.erase( currP) ;
|
||||
// avanzo con corrente e successivo
|
||||
currP = nextP ;
|
||||
++ nextP ;
|
||||
}
|
||||
// altrimenti da tenere
|
||||
else {
|
||||
// cancello la lista dei rimossi
|
||||
vRPT.clear() ;
|
||||
// avanzo il terzetto di uno step
|
||||
precP = currP ;
|
||||
currP = nextP ;
|
||||
++ nextP ;
|
||||
}
|
||||
|
||||
// vettore contenente i punti della polyline
|
||||
PNTUVECTOR vPtU ; vPtU.reserve( m_lUPoints.size()) ;
|
||||
for ( const auto& ptCurr : m_lUPoints)
|
||||
vPtU.emplace_back( ptCurr) ;
|
||||
|
||||
// vettore indici dei punti rimanenti
|
||||
INTVECTOR vInd ; vInd.reserve( vPtU.size()) ;
|
||||
|
||||
// se aperta
|
||||
if ( ! IsClosed()) {
|
||||
// considero tutti i punti della PolyLine
|
||||
vInd.push_back( 0) ;
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vInd))
|
||||
return false ;
|
||||
vInd.push_back( vPtU.size() - 1) ;
|
||||
}
|
||||
// se curva chiusa con almeno 4 punti, devo analizzare il terzetto attorno alla chiusura
|
||||
if ( IsClosed() && m_lUPoints.size() >= 4) {
|
||||
// precP e currP sono già corretti
|
||||
// il primo punto ripete l'ultimo (geometricamente coincide con currP)
|
||||
auto firstP = m_lUPoints.begin() ;
|
||||
// questo è il vero successivo
|
||||
nextP = next( firstP) ;
|
||||
// distanza del punto corrente dal segmento che unisce gli adiacenti
|
||||
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
|
||||
double dSqDist ;
|
||||
// se da eliminare
|
||||
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vRPT, precP->first, nextP->first, dSqTol)) {
|
||||
// faccio coincidere il primo punto con il precedente
|
||||
firstP->first = precP->first ;
|
||||
// elimino il punto corrente
|
||||
m_lUPoints.erase( currP) ;
|
||||
// altrimenti chiusa
|
||||
else {
|
||||
// cerco il punto più distante dal primo
|
||||
double dMaxDist = 0. ;
|
||||
int nMaxInd = 0 ;
|
||||
for ( int i = 1 ; i < int( vPtU.size()) ; ++ i) {
|
||||
double dCurrDist = Dist( vPtU[0].first, vPtU[i].first) ;
|
||||
if ( dCurrDist > dMaxDist) {
|
||||
dMaxDist = dCurrDist ;
|
||||
nMaxInd = i ;
|
||||
}
|
||||
}
|
||||
// recupero due PolyLine di approssimazione
|
||||
vInd.push_back( 0) ;
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, nMaxInd, vInd))
|
||||
return false ;
|
||||
vInd.push_back( nMaxInd) ;
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vInd))
|
||||
return false ;
|
||||
vInd.push_back( vPtU.size() - 1) ;
|
||||
}
|
||||
|
||||
|
||||
// ordino in senso crescente
|
||||
sort( vInd.begin(), vInd.end()) ;
|
||||
|
||||
// rimetto in lista i soli punti rimasti
|
||||
m_lUPoints.clear() ;
|
||||
for ( auto Ind : vInd)
|
||||
m_lUPoints.push_back( vPtU[Ind]) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
+24
-13
@@ -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) {
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : RotationMinimizeFrame.cpp Data : 05.03.24 Versione : 2.6c1
|
||||
// Contenuto : Classe per RotationMinimizeFrame
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 05.03.24 RE Creazione modulo.
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "RotationMinimizeFrame.h"
|
||||
#include "GeoConst.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
RotationMinimizeFrame::RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start)
|
||||
{
|
||||
// assegno i parametri
|
||||
m_pCrv = pCrv->Clone() ;
|
||||
m_Frame0 = fr_Start ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
RotationMinimizeFrame::~RotationMinimizeFrame( void)
|
||||
{
|
||||
Clear() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::Clear( void)
|
||||
{
|
||||
// pulizia della curva
|
||||
if ( m_pCrv != nullptr)
|
||||
delete m_pCrv ;
|
||||
m_pCrv = nullptr ;
|
||||
|
||||
// reset del frame di partenza
|
||||
m_Frame0.Reset() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::IsValid()
|
||||
{
|
||||
// controllo validità della curva
|
||||
if ( m_pCrv == nullptr || ! m_pCrv->IsValid())
|
||||
return false ;
|
||||
|
||||
// controllo del frame iniziale
|
||||
if ( ! m_Frame0.IsValid())
|
||||
return false ;
|
||||
|
||||
// controllo che l'origine del frame sia sulla curva e che l'asse Z sia tangente alla curva
|
||||
Point3d ptS ;
|
||||
Vector3d vtZ ;
|
||||
if ( ! m_pCrv->GetPointD1D2( 0., ICurve::FROM_MINUS, ptS, &vtZ) ||
|
||||
! vtZ.Normalize() ||
|
||||
! AreSamePointApprox( ptS, m_Frame0.Orig()) ||
|
||||
! AreSameVectorEpsilon( vtZ, m_Frame0.VersZ(), 5 * EPS_SMALL))
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::GetFrameAtLength( const Frame3d& frAct, const double dLenNext, Frame3d& frNext)
|
||||
{
|
||||
|
||||
/*
|
||||
Double Reflection
|
||||
Computation of Rotation Minimizing Frame in Computer Graphics
|
||||
Wenping Wang Bert Juttler Dayue Zheng Yang Liu
|
||||
*/
|
||||
|
||||
// ricavo i parametri dal frame
|
||||
if ( ! frAct.IsValid())
|
||||
return false ;
|
||||
|
||||
// origine del frame e versori ( ptAct, [ vt_r, vt_s, vt_t])
|
||||
Point3d ptCurr = frAct.Orig() ;
|
||||
Vector3d vt_r = frAct.VersX() ;
|
||||
Vector3d vt_t = frAct.VersZ() ;
|
||||
// ( vt_s è implicito )
|
||||
|
||||
double dUNext ; // parametro sulla curva nello step successivo
|
||||
Point3d ptNext ; // punto sulla curva allo step successivo
|
||||
|
||||
// parametro (i+1)-esimo sulla curva
|
||||
if ( ! m_pCrv->GetParamAtLength( dLenNext, dUNext))
|
||||
return false ;
|
||||
|
||||
// punto (i+1)-esimo sulla curva e suo vettore tangente
|
||||
Vector3d vt_t_next ;
|
||||
if ( ! m_pCrv->GetPointD1D2( dUNext, ICurve::FROM_MINUS, ptNext, &vt_t_next) ||
|
||||
! vt_t_next.IsValid() || ! vt_t_next.Normalize()) // versore tangente
|
||||
return false ;
|
||||
|
||||
// controllo per casi degeneri
|
||||
if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste il piano R1
|
||||
abs(( ptNext - ptCurr) * ( vt_t_next + vt_t)) < EPS_ZERO) // non esiste il piano R2
|
||||
return false ;
|
||||
|
||||
// ricavo il vettore di riflessione rispetto al piano R1
|
||||
Vector3d vR1_norm = ptNext - ptCurr ;
|
||||
if ( ! vR1_norm.IsValid())
|
||||
return false ;
|
||||
|
||||
// parametro di riflessione per R1
|
||||
double dPar1 = vR1_norm * vR1_norm ;
|
||||
|
||||
// riflessione rispetto al piano R1 ( sistema sinistrorso L )
|
||||
Vector3d vt_r_L = vt_r - ( 2 / dPar1) * ( vR1_norm * vt_r) * vR1_norm ;
|
||||
Vector3d vt_t_L = vt_t - ( 2 / dPar1) * ( vR1_norm * vt_t) * vR1_norm ;
|
||||
|
||||
// ricavo il vettore di riflessione rispetto al piano R1
|
||||
Vector3d vR2_norm = vt_t_next - vt_t_L ;
|
||||
if ( ! vR2_norm.IsValid())
|
||||
return false ;
|
||||
|
||||
// parametro di riflessione per R2
|
||||
double dPar2 = vR2_norm * vR2_norm ;
|
||||
// versore r del nuovo frame
|
||||
Vector3d vt_r_next = vt_r_L - ( 2 / dPar2) * ( vR2_norm * vt_r_L) * vR2_norm ;
|
||||
// versore t del nuovo frame
|
||||
Vector3d vt_s_next = vt_t_next ^ vt_r_next ;
|
||||
|
||||
// imposto il nuovo frame
|
||||
frNext.Set( ptNext, vt_r_next, vt_s_next, vt_t_next) ;
|
||||
if ( ! frNext.IsValid()) { // il frame potrebbe non essere nelle tolleranze...
|
||||
// ... sistemo ricavando il versore "s" mediante "t" ed "r" ...
|
||||
frNext.Set( ptNext, vt_t_next, vt_r_next) ;
|
||||
if ( ! frNext.IsValid())
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::GetFramesByStep( FRAME3DVECTOR& vRMFrames, double dStep, bool bUniform)
|
||||
{
|
||||
// controllo sullo step
|
||||
dStep = max( 10 * EPS_SMALL, dStep) ;
|
||||
|
||||
// controllo validità
|
||||
if ( ! IsValid()) {
|
||||
Clear() ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// calcolo lunghezza della curva
|
||||
double dLen = 0. ;
|
||||
if ( ! m_pCrv->GetLength( dLen))
|
||||
return false ;
|
||||
|
||||
// in prima posizione viene inserito il frame iniziale
|
||||
vRMFrames.push_back( m_Frame0) ;
|
||||
|
||||
// ricavo il numero degli step
|
||||
int nStep = int( ceil( dLen / dStep)) ;
|
||||
if ( nStep == 0) // se non ho step allora serve sono il frame iniziale
|
||||
return true ;
|
||||
|
||||
// lunghezza della curva identificata dal punto successivo
|
||||
double dLenNext ;
|
||||
|
||||
// step corrente
|
||||
double dMyStep = dStep ;
|
||||
if ( bUniform)
|
||||
dMyStep = dLen / nStep ;
|
||||
|
||||
// ciclo sugli step in cui la curva è suddivisa
|
||||
for ( int i = 0 ; i < nStep ; ++ i) {
|
||||
// ricavo la lunghezza della curva relativo allo step (i+1)-esimo
|
||||
dLenNext = min( dLen - 10 * EPS_SMALL, ( i + 1) * dMyStep) ;
|
||||
// ricavo il frame alla lunghezza calcolata
|
||||
Frame3d frNext ;
|
||||
if ( ! GetFrameAtLength( vRMFrames[i], dLenNext, frNext))
|
||||
return false ;
|
||||
// aggiornamento vettore dei frame
|
||||
vRMFrames.push_back( frNext) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::GetFramesBySplit( FRAME3DVECTOR& vRMFrames, int nIntervals)
|
||||
{
|
||||
// controllo sul numero di intervalli
|
||||
nIntervals = max( 1, nIntervals) ;
|
||||
|
||||
// ricavo lo step associato
|
||||
double dLen = 0 ;
|
||||
if ( ! m_pCrv->GetLength( dLen))
|
||||
return false ;
|
||||
|
||||
// ricavo lo step associato
|
||||
double dStep = dLen / nIntervals ;
|
||||
|
||||
return GetFramesByStep( vRMFrames, dStep) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
RotationMinimizeFrame::GetFramesByTollerance( FRAME3DVECTOR& vRMFrames, double dTol)
|
||||
{
|
||||
// controllo sulla tolleranza
|
||||
dTol = max( EPS_SMALL, dTol) ;
|
||||
|
||||
// controllo validità
|
||||
if ( ! IsValid()) {
|
||||
Clear() ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// ricavo la PolyLine associata alla curva mediante tale tolleranza
|
||||
PolyLine PL ;
|
||||
if ( ! m_pCrv->ApproxWithLines( dTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return false ;
|
||||
|
||||
// ricavo la lunghezza della curva
|
||||
double dCrvLen = 0 ;
|
||||
if ( ! m_pCrv->GetLength( dCrvLen))
|
||||
return false ;
|
||||
|
||||
// devo calcolare il RMF su ogni punto ricavato dall'approssimazione
|
||||
Point3d ptCurr ;
|
||||
bool bPoint = PL.GetFirstPoint( ptCurr) ;
|
||||
bool bFirst = true ;
|
||||
while ( bPoint) {
|
||||
if ( bFirst) {
|
||||
// in prima posizione viene inserito il frame iniziale
|
||||
vRMFrames.push_back( m_Frame0) ;
|
||||
bFirst = false ;
|
||||
}
|
||||
else {
|
||||
// ricavo la lunghezza della curva al punto corrente
|
||||
double dLen = 0. ;
|
||||
if ( ! m_pCrv->GetLengthAtPoint( ptCurr, dLen))
|
||||
return false ;
|
||||
// per sicurezza controllo che sia minore della lunghezza complessiva
|
||||
dLen = min( dCrvLen - 10 * EPS_SMALL , dLen) ;
|
||||
// ricavo il Frame associato a tale lunghezza
|
||||
Frame3d frNext ;
|
||||
if ( ! GetFrameAtLength( vRMFrames.back(), dLen, frNext))
|
||||
return false ;
|
||||
vRMFrames.emplace_back( frNext) ;
|
||||
}
|
||||
// passo al punto successivo
|
||||
bPoint = PL.GetNextPoint( ptCurr) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : RotationMinimizeFrame.h Data : 05.03.24 Versione : 2.6c1
|
||||
// Contenuto : Dichiarazione della classe RotationMinimizeFrame
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 05.03.24 RE Creazione modulo.
|
||||
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkFrame3d.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include <vector>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
typedef std::vector<Frame3d> FRAME3DVECTOR ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class RotationMinimizeFrame
|
||||
{
|
||||
public :
|
||||
RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start) ;
|
||||
~RotationMinimizeFrame( void) ;
|
||||
|
||||
public :
|
||||
bool GetFramesByStep( FRAME3DVECTOR& vRMFrames, double dStep, bool bUniform = false) ;
|
||||
bool GetFramesBySplit( FRAME3DVECTOR& vRMFrames, int nIntervals) ;
|
||||
bool GetFramesByTollerance( FRAME3DVECTOR& vRMFrames, double dTol) ;
|
||||
|
||||
private :
|
||||
bool Clear( void) ;
|
||||
bool IsValid( void) ;
|
||||
bool GetFrameAtLength( const Frame3d& frAct, const double dLenNext, Frame3d& frNext) ;
|
||||
|
||||
private :
|
||||
ICurve* m_pCrv ; // curva per il calcolo del rotation minimize frame
|
||||
Frame3d m_Frame0 ; // frame iniziale della curva
|
||||
} ;
|
||||
|
||||
+581
-95
@@ -1,4 +1,4 @@
|
||||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2015
|
||||
//----------------------------------------------------------------------------
|
||||
// File : StmFromCurves.cpp Data : 01.02.15 Versione : 1.6b1
|
||||
@@ -19,13 +19,16 @@
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "Voronoi.h"
|
||||
#include "RotationMinimizeFrame.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <future>
|
||||
#include <EgtDev/Include/EGkIntersCurves.h>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -109,9 +112,9 @@ GetSurfTriMeshByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr,
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByExtrusion( PL, vtExtr))
|
||||
return nullptr ;
|
||||
// se da fare, metto i tappi sulle estremità
|
||||
// se da fare, metto i tappi sulle estremità
|
||||
if ( bDoCapEnds) {
|
||||
// creo la prima superficie di estremità
|
||||
// creo la prima superficie di estremità
|
||||
SurfTriMesh STM1 ;
|
||||
if ( ! STM1.CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
@@ -155,7 +158,7 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i)
|
||||
vPL[i].Invert() ;
|
||||
}
|
||||
// creo la prima superficie di estremità
|
||||
// creo la prima superficie di estremità
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
|
||||
return nullptr ;
|
||||
@@ -287,7 +290,7 @@ GetSurfTriMeshByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vecto
|
||||
return nullptr ;
|
||||
// se richiesti caps
|
||||
if ( bCapEnds) {
|
||||
// determino se la sezione è chiusa e piatta
|
||||
// determino se la sezione è chiusa e piatta
|
||||
Plane3d plPlane ; double dArea ;
|
||||
bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ;
|
||||
// determino non sia una semplice rivoluzione
|
||||
@@ -331,7 +334,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
|
||||
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
Vector3d vtNorm = plGuide.GetVersN() ;
|
||||
// determino se la guida è chiusa
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// curve di offset
|
||||
OffsetCurve OffsCrvR ;
|
||||
@@ -372,7 +375,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
|
||||
pSTM->SetSmoothAngle( 20) ;
|
||||
// se guida aperta e tappi piatti
|
||||
if ( ! bGuideClosed && nCapType == RSCAP_FLAT) {
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
return nullptr ;
|
||||
@@ -451,7 +454,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
|
||||
Point3d ptCen ;
|
||||
pGuide->GetStartPoint( ptCen) ;
|
||||
ptCen -= dDimV / 2 * vtNorm ;
|
||||
// determino se la guida è chiusa
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// curve di offset
|
||||
const int NUM_OFFS = 4 ;
|
||||
@@ -474,7 +477,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
|
||||
}
|
||||
}
|
||||
else {
|
||||
// se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo
|
||||
// se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo
|
||||
for ( int i = 0 ; i < NUM_OFFS && bOk ; ++ i)
|
||||
bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ;
|
||||
}
|
||||
@@ -551,7 +554,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
|
||||
StmFromTriangleSoup stmCapSoup ;
|
||||
if ( ! stmCapSoup.Start( nBuckets))
|
||||
return nullptr ;
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
return nullptr ;
|
||||
@@ -650,34 +653,450 @@ GetSurfTriMeshRectSwept( double dDimH, double dDimV, double dBevelH, double dBev
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol)
|
||||
GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol, Vector3d* vtStatic)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pSect == nullptr || pGuide == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// calcolo la polilinea che approssima la sezione
|
||||
PolyLine PL ;
|
||||
if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return nullptr ;
|
||||
// determino se la sezione è chiusa
|
||||
|
||||
// determino se la sezione è chiusa
|
||||
bool bSectClosed = PL.IsClosed() ;
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
|
||||
// definisco la superficie da restituire ( definendo la sua tolleranza )
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM))
|
||||
return nullptr ;
|
||||
pSTM->SetLinearTolerance( dLinTol) ;
|
||||
|
||||
// calcolo punto e versore tangente iniziale
|
||||
Point3d ptStart ; pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ; pGuide->GetStartDir( vtStart) ;
|
||||
// inizializzazione del frame iniziale ( viene definito a seconda dei casi )
|
||||
Frame3d frStart ;
|
||||
|
||||
/* GUIDA PIANA */
|
||||
|
||||
// verifico che la linea guida sia piana
|
||||
Plane3d plGuide ;
|
||||
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = pGuide->IsClosed() ;
|
||||
// riferimento all'inizio della linea guida
|
||||
Frame3d frStart ;
|
||||
Point3d ptStart ;
|
||||
pGuide->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ;
|
||||
pGuide->GetStartDir( vtStart) ;
|
||||
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) {
|
||||
|
||||
/*
|
||||
La guida non è piana, l'estrusione può essere definita mediante :
|
||||
( 1) un versore statico
|
||||
( 2) mediante l'algoritmo del Rotation Minimize Frame
|
||||
*/
|
||||
|
||||
// recupero la sezione dalla PolyLine approssimata come Curva
|
||||
PtrOwner<CurveComposite> pSecLocApprox( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pSecLocApprox) ||
|
||||
! pSecLocApprox->FromPolyLine( PL) ||
|
||||
! pSecLocApprox->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// recupero il frame iniziale sulla guida ( Origine sul punto iniziale e asse Z tangente )
|
||||
frStart.Set( ptStart, vtStart) ;
|
||||
if ( ! frStart.IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// tengo in memoria il frame nel punto iniziale e finale della guida in caso di caps
|
||||
Frame3d frCaps_start ;
|
||||
Frame3d frCaps_end ;
|
||||
|
||||
if ( vtStatic != nullptr) { // (1) versore statico
|
||||
|
||||
// creo il piano di proiezione con normale definita dal vettore
|
||||
Plane3d plProj ;
|
||||
plProj.Set( ORIG, *vtStatic) ;
|
||||
if ( ! plProj.IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// porto la sezione nel frame definito dalla guida, tenendo il versore X del frame nel piano
|
||||
// definito da vtStatic
|
||||
Vector3d vtX = vtStart ; // versore tangente alla curva
|
||||
vtX.Rotate( *vtStatic, 90) ; // ruoto di 90 gradi rispetto a vtStatic
|
||||
OrthoCompo( vtX, *vtStatic) ; // tengo la componente nel piano
|
||||
vtX.Normalize() ; // normalizzo
|
||||
Frame3d frInitial ; frInitial.Set( ptStart, vtStart, vtX) ; // creo il frame
|
||||
if ( ! frInitial.IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// porto la sezione nel riferimento
|
||||
pSecLocApprox->ToLoc( frInitial) ;
|
||||
PL.ToLoc( frInitial) ; //... porto anche la PolyLine del bordo della sezione
|
||||
|
||||
// approssimo la guida mediante la tolleranza richiesta
|
||||
PolyLine PL_G ;
|
||||
if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL_G))
|
||||
return nullptr ;
|
||||
|
||||
// punto attuale e punto successivo sulla guida su cui definire il frame
|
||||
Point3d ptCurr, ptSucc ;
|
||||
if ( ! PL_G.GetFirstPoint( ptCurr))
|
||||
return nullptr ;
|
||||
bool bNextPoint = PL_G.GetNextPoint( ptSucc) ;
|
||||
if ( ! bNextPoint)
|
||||
return nullptr ;
|
||||
|
||||
// parametro attuale e successivo riferito ai punti sulla guida
|
||||
double dParCurr = 0 ;
|
||||
double dParSucc ;
|
||||
|
||||
// versore attuale e successivo riferito ai punti sulla guida
|
||||
Vector3d vtTanCurr, vtTanSucc ;
|
||||
if ( ! pGuide->GetStartDir( vtTanCurr))
|
||||
return nullptr ;
|
||||
|
||||
// frame iniziale e successivo riferito alla curva
|
||||
Frame3d frCurr, frSucc ;
|
||||
|
||||
bool bFirstIter = true ; // per salvare il frame iniziale nel caso di caps
|
||||
while ( bNextPoint) { // finchè recupero un punto sucessivo...
|
||||
|
||||
// recupero il parametro successivo riferito alla guida
|
||||
if ( ! pGuide->GetParamAtPoint( ptSucc, dParSucc))
|
||||
return nullptr ;
|
||||
|
||||
// recupero il versore tangente riferito al punto successivo sulla guida
|
||||
if ( ! pGuide->GetPointD1D2( dParSucc, ICurve::FROM_MINUS, ptSucc, &vtTanSucc) ||
|
||||
! vtTanSucc.Normalize())
|
||||
return nullptr ;
|
||||
|
||||
// creazione del frame nel punto corrente
|
||||
Vector3d vtX_curr = vtTanCurr ;
|
||||
vtX_curr.Rotate( *vtStatic, 90) ;
|
||||
OrthoCompo( vtX_curr, *vtStatic) ;
|
||||
vtX_curr.Normalize() ;
|
||||
frCurr.Set( ptCurr, vtTanCurr, vtX_curr) ;
|
||||
if ( ! frCurr.IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// memorizzo il primo frame di caso di caps
|
||||
if ( bFirstIter) {
|
||||
frCaps_start = frCurr ;
|
||||
bFirstIter = false ;
|
||||
}
|
||||
|
||||
// creazione del frame nel punto successivo
|
||||
Vector3d vtX_succ = vtTanSucc ;
|
||||
vtX_succ.Rotate( *vtStatic, 90) ;
|
||||
OrthoCompo( vtX_curr, *vtStatic) ;
|
||||
vtX_succ.Normalize() ;
|
||||
frSucc.Set( ptSucc, vtTanSucc, vtX_succ) ;
|
||||
if ( ! frSucc.IsValid())
|
||||
return nullptr ;
|
||||
|
||||
|
||||
frCaps_end = frSucc ; // aggiorno il frame finale ad ogni step
|
||||
|
||||
// definisco la sezione allo step corrente
|
||||
PtrOwner<ICurve> pSecCurr( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// considero la sezione ( in locale ) come vista dal globale
|
||||
if ( ! pSecCurr->ToGlob( frCurr))
|
||||
return nullptr ;
|
||||
|
||||
// definisco la sezione allo step successivo
|
||||
PtrOwner<ICurve> pSecSucc( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecSucc) || ! pSecSucc->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// considero la sezione ( in locale ) come vista dal globale
|
||||
if ( ! pSecSucc->ToGlob( frSucc))
|
||||
return nullptr ;
|
||||
|
||||
// creo la rigata tra queste due sezioni
|
||||
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSr) || ! pSr->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// attacco la rigata alla superficie da restituire
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
|
||||
// aggiornamento dei parametri
|
||||
ptCurr = ptSucc ; // il punto corrente diventa il successivo
|
||||
bNextPoint = PL_G.GetNextPoint( ptSucc) ; // il successivo lo recupero dalla PolyLine
|
||||
vtTanCurr = vtTanSucc ; // il versore tangete corrente diventa il successivo
|
||||
}
|
||||
// la superficie definita dal RMF è invertita, il versore Z è diretto come la tangente della curva
|
||||
pSTM->Invert() ;
|
||||
|
||||
}
|
||||
else { // (2) Rotation Minimize Frame
|
||||
|
||||
// porto la PolyLine e la curva della sezione nel riferimento nel punto iniziale della guida
|
||||
pSecLocApprox->ToLoc( frStart) ;
|
||||
PL.ToLoc( frStart) ;
|
||||
|
||||
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
|
||||
RotationMinimizeFrame RMF( pGuide, frStart) ;
|
||||
FRAME3DVECTOR vRMF ;
|
||||
if ( ! RMF.GetFramesByTollerance( vRMF, dLinTol) || vRMF.empty())
|
||||
return nullptr ;
|
||||
|
||||
// per ogni RMF calcolato, la sezione va roto-traslata lungo la guida
|
||||
for ( int i = 0 ; i < int( vRMF.size()) - 1 ; ++ i) {
|
||||
|
||||
// definisco la sezione allo step corrente
|
||||
PtrOwner<ICurve> pSecCurr( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// considero la sezione ( in locale ) come vista dal globale
|
||||
if ( ! pSecCurr->ToGlob( vRMF[i]))
|
||||
return nullptr ;
|
||||
|
||||
// definisco la sezione allo step successivo
|
||||
PtrOwner<ICurve> pSecSucc( pSecLocApprox->Clone()) ;
|
||||
if ( IsNull( pSecSucc) || ! pSecSucc->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// considero la sezione ( in locale ) come vista dal globale
|
||||
if ( ! pSecSucc->ToGlob( vRMF[i+1]))
|
||||
return nullptr ;
|
||||
|
||||
// creo la rigata tra queste due sezioni
|
||||
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSr) || ! pSr->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// attacco la rigata alla superficie da restituire
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
}
|
||||
// la superficie definita dal RMF è invertita, il versore Z è diretto come la tangente della curva
|
||||
pSTM->Invert() ;
|
||||
|
||||
// assegno frame iniziale e finale per caps
|
||||
frCaps_start = vRMF[0] ;
|
||||
frCaps_end = vRMF.back() ;
|
||||
}
|
||||
|
||||
// se richiesti caps e sezione chiusa e guida aperta
|
||||
// (1) vtStatic, (2) Rotation Minimize Frame
|
||||
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
|
||||
// aggiungo il cap sull'inizio ( portandolo nel frame del punto iniziale della guida )
|
||||
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
pSci->ToGlob( frCaps_start) ;
|
||||
// unisco
|
||||
pSTM->DoSewing( *pSci) ;
|
||||
|
||||
// aggiungo il cap sulla fine ( portandolo nel frame del punto finale della guida )
|
||||
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
pSce->ToGlob( frCaps_end) ;
|
||||
|
||||
pSce->Invert() ; // il versore z è definito dalle tangenti alla curva
|
||||
|
||||
// unisco
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
}
|
||||
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
double dVol ;
|
||||
if ( pSTM->GetVolume( dVol) && dVol < 0)
|
||||
pSTM->Invert() ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
GUIDA PIANA
|
||||
La guida è piana, l'estrusione viene definita mediante Offset della guida sulla sezione
|
||||
*/
|
||||
|
||||
// il frame iniziale è definito dal versore tangente e dalla normale al piano
|
||||
// che contiene la guida
|
||||
Vector3d vtNorm = plGuide.GetVersN() ;
|
||||
frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
|
||||
|
||||
// porto la sezione in questo riferimento e ve la appiattisco
|
||||
if ( ! PL.ToLoc( frStart) || ! PL.Flatten())
|
||||
return nullptr ;
|
||||
|
||||
// superficie swept
|
||||
PtrOwner<ICurve> pPrevCrv ;
|
||||
Point3d ptP ;
|
||||
bool bPoint = PL.GetFirstPoint( ptP) ;
|
||||
while ( bPoint) {
|
||||
// nuova curva ( definita dall'Offset )
|
||||
OffsetCurve OffsCrv ;
|
||||
if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
PtrOwner<ICurve> pCurrCrv( OffsCrv.GetLongerCurve()) ;
|
||||
if ( IsNull( pCurrCrv))
|
||||
return nullptr ;
|
||||
pCurrCrv->Translate( ptP.y * frStart.VersY()) ;
|
||||
|
||||
// se esiste la curva precedente, costruisco la rigata ( di tipo minima distanza)
|
||||
if ( ! IsNull( pPrevCrv)) {
|
||||
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
if ( IsNull( pSr))
|
||||
return nullptr ;
|
||||
|
||||
// unisco
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
}
|
||||
|
||||
// salvo la curva come prossima precedente
|
||||
pPrevCrv.Set( pCurrCrv) ;
|
||||
|
||||
// prossimo punto
|
||||
bPoint = PL.GetNextPoint( ptP) ;
|
||||
}
|
||||
|
||||
// se richiesti caps e sezione chiusa e guida aperta
|
||||
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
return nullptr ;
|
||||
Plane3d plEnds ; double dArea ;
|
||||
if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
|
||||
// aggiungo il cap sull'inizio
|
||||
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
pSci->ToGlob( frStart) ;
|
||||
|
||||
// unisco
|
||||
pSTM->DoSewing( *pSci) ;
|
||||
|
||||
// riferimento alla fine della linea guida
|
||||
Frame3d frEnd ;
|
||||
Point3d ptEnd ;
|
||||
pGuide->GetEndPoint( ptEnd) ;
|
||||
Vector3d vtEnd ;
|
||||
pGuide->GetEndDir( vtEnd) ;
|
||||
frEnd.Set( ptEnd, -vtEnd, vtEnd ^ vtNorm) ;
|
||||
|
||||
// aggiungo il cap sulla fine
|
||||
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
pSce->Invert() ;
|
||||
pSce->ToGlob( frEnd) ;
|
||||
|
||||
// unisco
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
}
|
||||
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
double dVol ;
|
||||
if ( pSTM->GetVolume( dVol) && dVol < 0)
|
||||
pSTM->Invert() ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSTM) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, bool bCapEnds,
|
||||
double dLinTol, Vector3d* vtStatic)
|
||||
{
|
||||
// verifica dei parametri
|
||||
if ( pSfrSect == nullptr || pGuide == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// creo la Trimesh da restituire
|
||||
PtrOwner<ISurfTriMesh> pStmSwept( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pStmSwept) || ! pStmSwept->AdjustTopology())
|
||||
return nullptr ;
|
||||
|
||||
StmFromTriangleSoup StmSoup ;
|
||||
StmSoup.Start() ;
|
||||
// per ogni loop della superficie, creo una Swept
|
||||
for ( int c = 0 ; c < pSfrSect->GetChunkCount() ; ++ c) {
|
||||
for ( int l = 0 ; l < pSfrSect->GetLoopCount( c) ; ++ l) {
|
||||
// recupero il loop
|
||||
PtrOwner<ICurve> pCrvLoop( pSfrSect->GetLoop( c, l)) ;
|
||||
if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid())
|
||||
return nullptr ;
|
||||
// creo la Trimesh Swept
|
||||
PtrOwner<ISurfTriMesh> pStmLoopSwept( GetSurfTriMeshSwept( pCrvLoop, pGuide, false, dLinTol, vtStatic)) ;
|
||||
if ( IsNull( pStmLoopSwept) || ! pStmLoopSwept->IsValid())
|
||||
return nullptr ;
|
||||
// aggiungo la Swept ricavata al risultato finale ( come triangoli )
|
||||
StmSoup.AddSurfTriMesh( *pStmLoopSwept) ;
|
||||
}
|
||||
}
|
||||
StmSoup.End() ;
|
||||
if ( ! pStmSwept.Set( StmSoup.GetSurf()) || IsNull( pStmSwept) ||
|
||||
! pStmSwept->IsValid() || ! pStmSwept->AdjustTopology())
|
||||
return nullptr ;
|
||||
|
||||
|
||||
// se rischista chiusura...
|
||||
// NB. Controllo solo che al guida non sia chiusa, la sezione derivando da una Flatregion è chiusa per
|
||||
// definizione
|
||||
if ( bCapEnds && ! pGuide->IsClosed()) {
|
||||
// creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta )
|
||||
PtrOwner<ISurfTriMesh> pSci( pSfrSect->GetAuxSurf()->Clone()) ;
|
||||
if ( IsNull( pSci) || ! pSci->IsValid())
|
||||
return nullptr ;
|
||||
pStmSwept->DoSewing( *pSci) ;
|
||||
// recupero i loops alla fine
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pStmSwept->GetLoops( vPL))
|
||||
return nullptr ;
|
||||
// creo la superficie alla fine e la attacco
|
||||
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
|
||||
if ( ! pSce->CreateByRegion( vPL))
|
||||
return nullptr ;
|
||||
// attacco la superficie finale alla swept
|
||||
pSce->Invert() ;
|
||||
pStmSwept->DoSewing( *pSce) ;
|
||||
}
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
double dVol ;
|
||||
if ( pStmSwept->GetVolume( dVol) && dVol < 0)
|
||||
pStmSwept->Invert() ;
|
||||
|
||||
return Release( pStmSwept) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfTriMesh*
|
||||
GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pSect == nullptr || pGuide == nullptr)
|
||||
return nullptr ;
|
||||
// determino se la sezione è chiusa
|
||||
bool bSectClosed = pSect->IsClosed() ;
|
||||
// punto iniziale della sezione e vettore a inizio guida
|
||||
Point3d ptStart ;
|
||||
if ( ! pSect->GetStartPoint( ptStart))
|
||||
return nullptr ;
|
||||
Point3d ptGuide ;
|
||||
if ( ! pGuide->GetStartPoint( ptGuide))
|
||||
return nullptr ;
|
||||
Vector3d vtDelta = ptStart - ptGuide ;
|
||||
// calcolo la polilinea che approssima la guida
|
||||
PolyLine PLG ;
|
||||
if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLG))
|
||||
return nullptr ;
|
||||
// determino se la guida è chiusa
|
||||
bool bGuideClosed = PLG.IsClosed() ;
|
||||
// calcolo la superficie
|
||||
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSTM))
|
||||
@@ -687,19 +1106,16 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
|
||||
// superficie swept
|
||||
PtrOwner<ICurve> pPrevCrv ;
|
||||
Point3d ptP ;
|
||||
bool bPoint = PL.GetFirstPoint( ptP) ;
|
||||
bool bPoint = PLG.GetFirstPoint( ptP) ;
|
||||
while ( bPoint) {
|
||||
// nuova curva
|
||||
OffsetCurve OffsCrv ;
|
||||
if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() == 0)
|
||||
return nullptr ;
|
||||
PtrOwner<ICurve> pCurrCrv( OffsCrv.GetLongerCurve()) ;
|
||||
PtrOwner<ICurve> pCurrCrv( pSect->Clone()) ;
|
||||
if ( IsNull( pCurrCrv))
|
||||
return nullptr ;
|
||||
pCurrCrv->Translate( ptP.y * frStart.VersY()) ;
|
||||
pCurrCrv->Translate( ptP - ptStart + vtDelta) ;
|
||||
// se esiste la curva precedente, costruisco la rigata (di tipo minima distanza)
|
||||
if ( ! IsNull( pPrevCrv)) {
|
||||
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
|
||||
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_ISOPAR, dLinTol)) ;
|
||||
if ( IsNull( pSr))
|
||||
return nullptr ;
|
||||
pSTM->DoSewing( *pSr) ;
|
||||
@@ -707,39 +1123,33 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
|
||||
// salvo la curva come prossima precedente
|
||||
pPrevCrv.Set( pCurrCrv) ;
|
||||
// prossimo punto
|
||||
bPoint = PL.GetNextPoint( ptP) ;
|
||||
bPoint = PLG.GetNextPoint( ptP) ;
|
||||
}
|
||||
// se richiesti caps e sezione chiusa e guida aperta
|
||||
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
|
||||
// verifico che le due estremità siano chiuse e piatte
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
|
||||
// calcolo la polilinea che approssima la sezione
|
||||
PolyLine PLS ;
|
||||
if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLS))
|
||||
return nullptr ;
|
||||
Plane3d plEnds ; double dArea ;
|
||||
if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
|
||||
return nullptr ;
|
||||
// aggiungo il cap sull'inizio
|
||||
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
pSci->ToGlob( frStart) ;
|
||||
pSTM->DoSewing( *pSci) ;
|
||||
// riferimento alla fine della linea guida
|
||||
Frame3d frEnd ;
|
||||
Point3d ptEnd ;
|
||||
pGuide->GetEndPoint( ptEnd) ;
|
||||
Vector3d vtEnd ;
|
||||
pGuide->GetEndDir( vtEnd) ;
|
||||
frEnd.Set( ptEnd, -vtEnd, vtEnd ^ vtNorm) ;
|
||||
// aggiungo il cap sulla fine
|
||||
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
|
||||
return nullptr ;
|
||||
pSce->Invert() ;
|
||||
pSce->ToGlob( frEnd) ;
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
// verifico che la sezione sia chiusa e piatta
|
||||
Plane3d plSect ; double dArea ;
|
||||
if ( PLS.IsClosedAndFlat( plSect, dArea, 100 * EPS_SMALL)) {
|
||||
// aggiungo il cap sull'inizio
|
||||
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PLS))
|
||||
return nullptr ;
|
||||
pSci->Invert() ;
|
||||
Point3d ptGi ; PLG.GetFirstPoint( ptGi) ;
|
||||
pSci->Translate( ptGi - ptStart + vtDelta) ;
|
||||
pSTM->DoSewing( *pSci) ;
|
||||
// aggiungo il cap sulla fine
|
||||
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
|
||||
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PLS))
|
||||
return nullptr ;
|
||||
Point3d ptGe ; PLG.GetLastPoint( ptGe) ;
|
||||
pSce->Translate( ptGe - ptStart + vtDelta) ;
|
||||
pSTM->DoSewing( *pSce) ;
|
||||
}
|
||||
}
|
||||
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
|
||||
double dVol ;
|
||||
@@ -800,56 +1210,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 ;
|
||||
}
|
||||
|
||||
+25
-47
@@ -16,6 +16,7 @@
|
||||
#include "GeoConst.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "AdjustLoops.h"
|
||||
#include "Voronoi.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
@@ -36,7 +37,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
if ( nChunk == 0)
|
||||
return nullptr ;
|
||||
|
||||
// se offset nullo, la nuova regione è la copia di quella attuale
|
||||
// se offset nullo, la nuova regione è la copia di quella attuale
|
||||
if ( abs( dDist) < 10 * EPS_SMALL)
|
||||
return this->Clone() ;
|
||||
|
||||
@@ -70,7 +71,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
while ( bOk && ! IsNull( pOffs)) {
|
||||
if ( pOffs->GetType() == CRV_COMPO) {
|
||||
CurveComposite* pOffsCompo = GetBasicCurveComposite( pOffs) ;
|
||||
// assegno proprietà
|
||||
// assegno proprietà
|
||||
pOffsCompo->SetTempProp( j, 1) ;
|
||||
for ( int k = 0 ; k < pOffsCompo->GetCurveCount() ; ++k)
|
||||
pOffsCompo->SetCurveTempProp( k, j, 1) ;
|
||||
@@ -80,7 +81,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
}
|
||||
else
|
||||
pOffs->SetTempProp( j, 1) ;
|
||||
// se prima curva esterna, è il primo contorno esterno della nuova regione
|
||||
// se prima curva esterna, è il primo contorno esterno della nuova regione
|
||||
if ( j == 0 && bFirstCurve) {
|
||||
if ( ! pSfrChk->AddExtLoop( Release( pOffs)))
|
||||
return nullptr ;
|
||||
@@ -137,7 +138,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
|
||||
// -------------------- OFFSET CON VORONOI -------------------------------------
|
||||
else {
|
||||
// verifico se oggetto Voronoi della superficie è definito
|
||||
// verifico se oggetto Voronoi della superficie è definito
|
||||
if ( m_pVoronoiObj == nullptr)
|
||||
CalcVoronoiObject() ;
|
||||
|
||||
@@ -146,51 +147,28 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
if ( ! m_pVoronoiObj->CalcOffset( vOffs, dDist, nType))
|
||||
return nullptr ;
|
||||
|
||||
// costruisco la superficie
|
||||
if ( vOffs.size() > 0) {
|
||||
BOOLVECTOR vbAddOrSub( vOffs.size(), true) ;
|
||||
int nFirstId = -1 ;
|
||||
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) {
|
||||
// porto nel frame della flat region
|
||||
PCRV_DEQUE vLoops ;
|
||||
for ( int i = 0 ; i < int( vOffs.size()) ; i ++) {
|
||||
vOffs[i]->ToLoc( m_frF) ;
|
||||
// calcolo orientamento della curva
|
||||
double dAreaXY ;
|
||||
if ( ! vOffs[i]->GetAreaXY( dAreaXY))
|
||||
return nullptr ;
|
||||
vbAddOrSub[i] = ( dAreaXY > SQ_EPS_SMALL) ;
|
||||
// verifico se è il primo loop esterno
|
||||
if ( nFirstId == -1 && vbAddOrSub[i])
|
||||
nFirstId = i ;
|
||||
}
|
||||
|
||||
// inizializzo la superficie
|
||||
if ( nFirstId != -1 && ! pSfr->AddExtLoop( Release( vOffs[nFirstId])))
|
||||
return nullptr ;
|
||||
if ( pSfr->IsValid()) {
|
||||
|
||||
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) {
|
||||
// verifico non sia il primo loop esterno
|
||||
if ( i == nFirstId)
|
||||
continue ;
|
||||
// costruisco la superficie associata
|
||||
PtrOwner<SurfFlatRegion> pSrfCrv( CreateBasicSurfFlatRegion()) ;
|
||||
if ( IsNull( pSrfCrv) || ! pSrfCrv->AddExtLoop( Release( vOffs[i])))
|
||||
return nullptr ;
|
||||
if ( ! pSrfCrv->IsValid())
|
||||
continue ;
|
||||
|
||||
// aggiungo o sottraggo
|
||||
if ( vbAddOrSub[i]) {
|
||||
if ( ! pSfr->Add( *pSrfCrv))
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
pSrfCrv->Invert() ;
|
||||
if ( ! pSfr->Subtract( *pSrfCrv))
|
||||
return nullptr ;
|
||||
}
|
||||
// rimuovo eventuali sovrapposizioni
|
||||
ICURVEPLIST CrvLst ;
|
||||
AdjustLoops( Release( vOffs[i]), CrvLst, true) ;
|
||||
for ( auto pCrv : CrvLst) {
|
||||
pCrv->SetExtrusion( Z_AX) ;
|
||||
vLoops.emplace_back( pCrv) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// verifico di avere ancora dei loops
|
||||
if ( vLoops.size() > 0) {
|
||||
pSfr.Set( MyNewSurfFromLoops( vLoops)) ;
|
||||
if ( IsNull( pSfr)) {
|
||||
MyTestAndDelete( vLoops) ;
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,9 +185,9 @@ SurfFlatRegion::Offset( double dDist, int nType)
|
||||
if ( nChunk == 0)
|
||||
return false ;
|
||||
|
||||
// se offset nullo, non devo fare alcunchè
|
||||
// se offset nullo, non devo fare alcunchè
|
||||
if ( abs( dDist) < 10 * EPS_SMALL)
|
||||
return this->Clone() ;
|
||||
return true ;
|
||||
|
||||
// calcolo la superficie di offset
|
||||
PtrOwner<SurfFlatRegion> pSfr( CreateOffsetSurf( dDist, nType)) ;
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+192
-126
@@ -52,9 +52,10 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
||||
if ( vnDegVec[nC] > 0)
|
||||
++ nExistNotDeg ;
|
||||
}
|
||||
|
||||
// Divido il loop di partenza in sotto-loop
|
||||
int nIterationCount = 0 ;
|
||||
while ( cvOpenChain.size() > 0) {
|
||||
while ( cvOpenChain.size() > 0) { // per ogni catena aperta...
|
||||
bool bLoopSplitted = false ;
|
||||
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
|
||||
if ( vnDegVec[nLastOpenLoopN] == 1) {
|
||||
@@ -63,13 +64,24 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
||||
int nLastOpenLoopPoint = max( int( cvOpenChain[nLastOpenLoopN].size()) - 1, 0) ;
|
||||
Point3d ptOpenLoopStP = cvOpenChain[nLastOpenLoopN][0].ptSt ;
|
||||
Point3d ptOpenLoopEnP = cvOpenChain[nLastOpenLoopN][nLastOpenLoopPoint].ptEn ;
|
||||
// costruisco il primo e il secondo loop che si generano
|
||||
// NB. il loop esterno è chiuso, mentre la catena aperta
|
||||
// è la successione dei tratti lineari dovuti ai triangoli dell'altra superficie
|
||||
PNTVECTOR Loop1, Loop2 ;
|
||||
// cambio il punto iniziale del loop di bordo se non coincide già con ptStart della catena aperta
|
||||
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
|
||||
// splitto
|
||||
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
|
||||
if ( ! ( bChangedStart && bSplitted) ||
|
||||
( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2)))
|
||||
continue ;
|
||||
continue ; // la catena aperta non è interna al loop chiuso attuale
|
||||
|
||||
// il loop 1 segue sempre la direzione della catena, il loop 2 ha dentro la catena invertita
|
||||
// Ho sempre che il loop 1 è sempre interno ( la direzione della catena è determinata
|
||||
// dalla normale dei triangoli che la formano; avendo chimatao la chian senza ammettere inversioni, sono
|
||||
// curve tutte concordi ) e il loop 2 che è esterno
|
||||
bLoopSplitted = true ;
|
||||
// ricostrusico i due loop mediante concatenazione
|
||||
Chain cvCounterChain ;
|
||||
for ( int nPt = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nPt >= 0 ; -- nPt) {
|
||||
IntSegment CurSeg ;
|
||||
@@ -181,7 +193,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
||||
// elimino i punti superflui prima
|
||||
for ( int i = 0 ; i < nCvFirst ; ++ i)
|
||||
cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin()) ;
|
||||
// verifico se questo punto � dalla parte valida o no
|
||||
// verifico se questo punto è dalla parte valida o no
|
||||
bool bC12 = ( ( ptM12 - ptProva) * vtVecProva < 0) ;
|
||||
vbInOut[nLoop] = bC12 ;
|
||||
}
|
||||
@@ -192,7 +204,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
||||
// elimino i punti superflui intermedi
|
||||
for ( int i = nCvFirst + 2 ; i < nCvSecond ; ++ i)
|
||||
cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin() + nCvFirst + 2) ;
|
||||
// verifico se questo punto � dalla parte valida o no
|
||||
// verifico se questo punto è dalla parte valida o no
|
||||
bool bC21 = ( ( ptM21 - ptProva) * vtVecProva < 0) ;
|
||||
vbInOut[nLoop] = bC21 ;
|
||||
}
|
||||
@@ -234,9 +246,13 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
// La superficie deve essere valida
|
||||
if ( ! Surf.IsValid())
|
||||
return false ;
|
||||
// Ritriangolarizzo i triangoli
|
||||
|
||||
// itero sulla unorderd_map
|
||||
for ( auto it = LoopLines.begin() ; it != LoopLines.end() ; ++ it) {
|
||||
|
||||
// itero sulle catene ( secondo parametro della mappa)
|
||||
for ( int nS1 = 0 ; nS1 < int( it->second.size()) - 1 ; ++ nS1) {
|
||||
// tolgo i tratti degeneri ad un punto
|
||||
for ( int nS2 = nS1 + 1 ; nS2 < int( it->second.size()) ; ++ nS2) {
|
||||
if ( AreSamePointApprox( it->second[nS1].ptSt, it->second[nS2].ptEn) &&
|
||||
AreSamePointApprox( it->second[nS1].ptEn, it->second[nS2].ptSt) &&
|
||||
@@ -248,22 +264,21 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se non resta nulla, allora passo alla mappa successiva
|
||||
if ( int( it->second.size()) == 0)
|
||||
continue ;
|
||||
|
||||
// Se il triangolo è stato sottoposto a ritriangolazione, le sue componenti sono classificabili come dentro-fuori.
|
||||
// Lo tolgo dall'insieme dei triangoli ambigui (intersezione edge-edge)
|
||||
else {
|
||||
auto itS = Ambiguos.find( it->first) ;
|
||||
if ( itS != Ambiguos.end()) {
|
||||
Ambiguos.erase( itS) ;
|
||||
}
|
||||
}
|
||||
auto itS = Ambiguos.find( it->first) ;
|
||||
if ( itS != Ambiguos.end())
|
||||
Ambiguos.erase( itS) ;
|
||||
|
||||
// Creo i loop
|
||||
// CREAZIONE DEI LOOP ---------------------------------------------
|
||||
// Chain
|
||||
ChainCurves LoopCreator ;
|
||||
LoopCreator.Init( false, 2 * EPS_SMALL, int( it->second.size()), 10 * BOOLEAN_SCALE) ;
|
||||
// Carico le curve per concatenarle
|
||||
// Recupero le curve ( gli estremi dei tratti lineari) per concatenarle
|
||||
for ( int nCv = 0 ; nCv < int( it->second.size()); ++ nCv) {
|
||||
Point3d ptSt = it->second[nCv].ptSt ;
|
||||
Point3d ptEn = it->second[nCv].ptEn ;
|
||||
@@ -277,15 +292,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
CHAINVECTOR vChain ;
|
||||
while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) {
|
||||
Chain chTemp ;
|
||||
for ( auto i : vIds) {
|
||||
// Aggiungo la linea alla curva composta.
|
||||
for ( auto i : vIds) // Aggiungo la linea alla curva composta
|
||||
chTemp.emplace_back( it->second[i - 1]) ;
|
||||
}
|
||||
|
||||
vChain.emplace_back( chTemp) ;
|
||||
}
|
||||
// Lavoro su loop e catene per regolarizzarle
|
||||
int nChainCnt = int( vChain.size()) ;
|
||||
// unisco eventuali catene estreme che sono parte di una stessa catena
|
||||
// Unisco eventuali catene estreme che sono parte di una stessa catena
|
||||
if ( nChainCnt > 1) {
|
||||
if ( AreSamePointApprox( vChain[0].front().ptSt, vChain[nChainCnt - 1].back().ptEn)) {
|
||||
vChain[0].insert( vChain[0].begin(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ;
|
||||
@@ -298,7 +312,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
-- nChainCnt ;
|
||||
}
|
||||
}
|
||||
// semplifico catene formate da punti degeneri
|
||||
// Semplifico catene formate da punti degeneri
|
||||
for ( int nCh = 0 ; nCh < nChainCnt ; ++ nCh) {
|
||||
if ( vChain[nCh].size() == 2 && ( vChain[nCh][0].bDegenerate || vChain[nCh][1].bDegenerate)) {
|
||||
vChain[nCh][0].ptEn = vChain[nCh][1].ptEn ;
|
||||
@@ -377,6 +391,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Chiudo i loop costruiti a partire dalle catene
|
||||
for ( int nC = 0 ; nC < nChainCnt ; ++ nC) {
|
||||
int nChainLastSegPos = int( vChain[nC].size()) - 1 ;
|
||||
@@ -463,7 +478,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[2] = 0 ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
|
||||
bModif = true ;
|
||||
}
|
||||
int nNewCoupleId1[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 1) % 3)), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)) } ;
|
||||
@@ -472,7 +487,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[2] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
|
||||
bModif = true ;
|
||||
}
|
||||
int nNewCoupleId2[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)), Surf.AddVertex( ptIntEn) } ;
|
||||
@@ -481,27 +496,32 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[2] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
|
||||
bModif = true ;
|
||||
}
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
|
||||
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
|
||||
// I loop chiusi trovati precedentemente sono interni a uno dei sotto-loop
|
||||
// chiusi di cui è formato il perimetro.
|
||||
|
||||
// Creo il loop chiuso padre di tutti, il perimetro del triangolo. Questo viene diviso in sotto-loop
|
||||
// chiusi mediante quelli aperti. I loop chiusi trovati precedentemente sono interni a uno dei
|
||||
// sotto-loop chiusi di cui è formato il perimetro.
|
||||
PNTVECTOR cvFirstLoop ;
|
||||
cvFirstLoop.emplace_back( trTria.GetP( 0)) ;
|
||||
cvFirstLoop.emplace_back( trTria.GetP( 1)) ;
|
||||
cvFirstLoop.emplace_back( trTria.GetP( 2)) ;
|
||||
|
||||
PNTMATRIX cvBoundClosedLoopVec;
|
||||
// creo una matrice di punti ; ogni riga corrisponde ad una sequenza di punti che indentificano un loop
|
||||
PNTMATRIX cvBoundClosedLoopVec ;
|
||||
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
|
||||
|
||||
// vettore per indicare se il loop è interno/esterno all'altra superficie
|
||||
BOOLVECTOR vbInOut ;
|
||||
vbInOut.push_back( true) ;
|
||||
|
||||
// Divido il loop usando le catene
|
||||
if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) {
|
||||
if ( cvBoundClosedLoopVec.size() == 1 && cvOpenChain.size() == 2) {
|
||||
@@ -556,7 +576,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[it->first].nTempPart = 0 ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Rimuovo il triangolo corrente
|
||||
int nOldTriaCol = Surf.m_vTria[it->first].nTFlag ;
|
||||
Surf.RemoveTriangle( it->first) ;
|
||||
@@ -564,14 +584,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
POLYLINEVECTOR vplPolyVec ;
|
||||
vplPolyVec.resize( cvBoundClosedLoopVec.size()) ;
|
||||
for ( int nLoop = 0 ; nLoop < int( vplPolyVec.size()) ; ++ nLoop) {
|
||||
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine) {
|
||||
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine)
|
||||
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ;
|
||||
}
|
||||
|
||||
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][0]) ;
|
||||
|
||||
// Assegno ai loop trovati i rispettivi interni
|
||||
// Assumo che i loop interni a uno dei loop creati fino ad'ora siano tutti sullo stesso livello.
|
||||
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
|
||||
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
|
||||
// loop è figlio del nodo corrispondente al loop che lo contiene.
|
||||
INTVECTOR vInnerLoop ;
|
||||
for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) {
|
||||
@@ -692,7 +712,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( vInnerLoop.size() == 0 || bDouble) {
|
||||
// Eseguo triangolazione
|
||||
PNTVECTOR vPt ;
|
||||
@@ -710,7 +730,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
|
||||
if ( vbInOut[nLoop])
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
|
||||
else
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = - 1 ;
|
||||
bModif = true ;
|
||||
@@ -719,33 +739,32 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
else {
|
||||
// se ho più loop, essi descrivono un poligono di n-lati
|
||||
POLYLINEVECTOR vPolygons ;
|
||||
vPolygons.emplace_back( vplPolyVec[nLoop]) ;
|
||||
for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) {
|
||||
// per ognuno di essi, ricavo la PolyLine dai punti
|
||||
PolyLine CurLoop ;
|
||||
for ( int nV = 0 ; nV < int( cvClosedChain[vInnerLoop[nL]].size()) ; ++ nV) {
|
||||
for ( int nV = 0 ; nV < int( cvClosedChain[vInnerLoop[nL]].size()) ; ++ nV)
|
||||
CurLoop.AddUPoint( 0., cvClosedChain[vInnerLoop[nL]][nV].ptSt) ;
|
||||
}
|
||||
|
||||
CurLoop.AddUPoint( 0., cvClosedChain[vInnerLoop[nL]][0].ptSt) ;
|
||||
vPolygons.emplace_back( CurLoop) ;
|
||||
}
|
||||
|
||||
// poligono
|
||||
Polygon3d pgPol ;
|
||||
pgPol.FromPolyLine(vPolygons[1]) ;
|
||||
pgPol.FromPolyLine( vPolygons[1]) ;
|
||||
|
||||
// controllo direzioni delle normali
|
||||
bool bCodirectedNormals = trTria.GetN() * pgPol.GetVersN() > 0. ;
|
||||
if ( bCodirectedNormals) {
|
||||
for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) {
|
||||
vPolygons[nL].Invert() ;
|
||||
}
|
||||
}
|
||||
|
||||
// Aggiungo al loop esterno i punti dei loop interni che si trovano su di esso
|
||||
PNTULIST& ExternLoopList = vPolygons[0].GetUPointList() ;
|
||||
// Ciclo sui segmenti del loop esterno
|
||||
auto itSt = ExternLoopList.begin() ;
|
||||
auto itEn = itSt ;
|
||||
++ itEn ;
|
||||
++ itEn ;
|
||||
for ( ; itSt != ExternLoopList.end() && itEn != ExternLoopList.end() ; ++ itSt, ++ itEn) {
|
||||
// Estremi del segmento corrente del loop esterno e scorrispondente vettore
|
||||
Point3d ptSt = itSt->first ;
|
||||
@@ -761,7 +780,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Point3d ptInnPoint ;
|
||||
bool bIsFirst = true ;
|
||||
bool bContinue = vPolygons[nInnPoly].GetFirstPoint( ptInnPoint) ;
|
||||
while ( bContinue) {
|
||||
while ( bContinue) {
|
||||
DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ;
|
||||
double dDist ;
|
||||
DistCalculator.GetDist( dDist) ;
|
||||
@@ -788,13 +807,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
// Aggiungo i punti al loop esterno
|
||||
for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) ; ++ nPi) {
|
||||
itSt = ExternLoopList.emplace( itEn, vPointWithOrder[nPi]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
if ( Triangulate().Make( vPolygons, vPt, vTr)) {
|
||||
// Inserisco i nuovi triangoli
|
||||
// classifico i loop e ricavo la triangolazione di essi mediante classificazione
|
||||
if ( Triangulate().MakeAdvanced( vPolygons, vPt, vTr)) {
|
||||
// Inserisco i nuovi triangoli
|
||||
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
||||
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ;
|
||||
int nNewId[3] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
|
||||
@@ -817,7 +837,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
// Divido i loop che si autointercettano
|
||||
int nInitialLoopNum = int( vPolygons.size()) ;
|
||||
for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) {
|
||||
// Lista dei punti della PolyLine Loop corrente
|
||||
// Lista dei punti della PolyLine Loop corrente
|
||||
PNTULIST& LoopPointList = vPolygons[nL].GetUPointList() ;
|
||||
// Ciclo sui segmenti
|
||||
auto itSt2 = LoopPointList.begin() ;
|
||||
@@ -928,26 +948,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 +1106,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 +1136,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 +1197,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 +1206,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 +1218,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 +1232,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 +1244,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 +1257,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 +1296,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 +1339,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 +1347,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 +1355,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 +1385,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 +1405,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 +1423,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 +1431,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 +1439,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 +1469,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 +1479,12 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
AmbiguosTriangleManager( AmbiguosA, *this) ;
|
||||
AmbiguosTriangleManager( AmbiguosB, SurfB) ;
|
||||
}
|
||||
|
||||
|
||||
bool bContinue = true ;
|
||||
// Se avvenuta modifica, aggiorno tutto
|
||||
if ( bModif)
|
||||
bContinue = ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ;
|
||||
|
||||
// Triangoli sovrapposti
|
||||
if ( bContinue) {
|
||||
int nTriaNum2A = GetTriangleSize() ;
|
||||
@@ -1491,7 +1522,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -1620,48 +1651,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())
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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]) ;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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) ;
|
||||
|
||||
@@ -17,12 +17,15 @@
|
||||
#include "GeoObjRW.h"
|
||||
#include "Tool.h"
|
||||
#include "/EgtDev/Include/EGkVolZmap.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
|
||||
// ------------------------- FORWARD -------------------------------------------------------------
|
||||
class IntersParLinesSurfTm ;
|
||||
|
||||
// ------------------------- STRUTTURE -----------------------------------------------------------
|
||||
struct AppliedVector {
|
||||
Point3d ptPApp ;
|
||||
@@ -112,19 +115,17 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
|
||||
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) override ;
|
||||
bool GetDepth( const Point3d& ptP, const Vector3d& vtD, double& dInLength, double& dOutLength, bool bExact) const override ;
|
||||
bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const override ;
|
||||
bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const override ;
|
||||
bool AvoidBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool AvoidSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool AvoidCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop, double dHeight,
|
||||
double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool AvoidRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
|
||||
double dLenghtTopX, double dLenghtTopY, double dHeight,
|
||||
double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool AvoidTorus( const Frame3d& frTorus, double dRadMax, double dRadMin,
|
||||
double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool CDeBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool CDeSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool CDeCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool CDeConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop, double dHeight,
|
||||
double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool CDeRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
|
||||
double dLenghtTopX, double dLenghtTopY, double dHeight,
|
||||
double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool CDeTorus( const Frame3d& frTorus, double dRadMax, double dRadMin,
|
||||
double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool CDeSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool Cut( const Plane3d& plPlane) override ;
|
||||
bool Compact( void) override ;
|
||||
int GetPartCount( void) const override ;
|
||||
@@ -149,6 +150,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
{ if ( ! CopyFrom( stSrc))
|
||||
LOG_ERROR( GetEGkLogger(), "VolZmap : copy error")
|
||||
return *this ; }
|
||||
bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const ;
|
||||
bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const ;
|
||||
|
||||
private :
|
||||
enum CubeType { VOX_EXTERN = 1,
|
||||
@@ -393,14 +396,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) ;
|
||||
|
||||
+219
-194
@@ -411,7 +411,7 @@ VolZmap::GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtD, double& dIn
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPrecise) const
|
||||
VolZmap::CDeSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPrecise) const
|
||||
{
|
||||
// BBox
|
||||
BBox3d b3BoxL( ORIG, ORIG + vtDiag) ;
|
||||
@@ -425,10 +425,10 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre
|
||||
|
||||
// Se non interferiscono, posso uscire
|
||||
if ( ! b3Zmap.Overlaps( b3Box) || ! b3Zmap.Overlaps( frBoxInt, b3BoxL))
|
||||
return true ;
|
||||
return false ;
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Zmap.FindIntersection( b3Box, b3Int))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// Se verifico solo prima mappa
|
||||
if ( ! bPrecise || m_nMapNum == 1) {
|
||||
@@ -470,7 +470,7 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre
|
||||
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
|
||||
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
|
||||
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -533,7 +533,7 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre
|
||||
// Se il segmento è interno all'intervallo d'intersezione, ho finito.
|
||||
if ( dMaxU > m_Values[nMap][nPos][nIndex].dMin - EPS_SMALL &&
|
||||
dMinU < m_Values[nMap][nPos][nIndex].dMax + EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -541,32 +541,36 @@ VolZmap::AvoidSimpleBox( const Frame3d& frBox, const Vector3d& vtDiag, bool bPre
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, bool bPrecise) const
|
||||
VolZmap::CDeBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, bool bPrecise) const
|
||||
{
|
||||
// Se il box non è ben definito non ha senso proseguire
|
||||
if ( vtDiag.IsSmall())
|
||||
return true ;
|
||||
|
||||
// Se distanza di sicurezza nulla
|
||||
if ( dSafeDist < EPS_SMALL)
|
||||
return AvoidSimpleBox( frBox, vtDiag, bPrecise) ;
|
||||
return CDeSimpleBox( frBox, vtDiag, bPrecise) ;
|
||||
|
||||
// Verifica preliminare con box esteso
|
||||
Frame3d frEst = frBox ; frEst.Translate( -dSafeDist * ( frBox.VersX() + frBox.VersY() + frBox.VersZ())) ;
|
||||
if ( AvoidSimpleBox( frEst, vtDiag + 2 * Vector3d( dSafeDist, dSafeDist, dSafeDist), bPrecise))
|
||||
return true ;
|
||||
if ( ! CDeSimpleBox( frEst, vtDiag + 2 * Vector3d( dSafeDist, dSafeDist, dSafeDist), bPrecise))
|
||||
return false ;
|
||||
|
||||
// Tre box aumentati con distanza di sicurezza in un sola dimensione
|
||||
Frame3d frTmp = frBox ; frTmp.Translate( -dSafeDist * frBox.VersX()) ;
|
||||
if ( ! AvoidSimpleBox( frTmp, vtDiag + 2 * dSafeDist * X_AX, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleBox( frTmp, vtDiag + 2 * dSafeDist * X_AX, bPrecise))
|
||||
return true ;
|
||||
frTmp = frBox ; frTmp.Translate( -dSafeDist * frBox.VersY()) ;
|
||||
if ( ! AvoidSimpleBox( frTmp, vtDiag + 2 * dSafeDist * Y_AX, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleBox( frTmp, vtDiag + 2 * dSafeDist * Y_AX, bPrecise))
|
||||
return true ;
|
||||
frTmp = frBox ; frTmp.Translate( -dSafeDist * frBox.VersZ()) ;
|
||||
if ( ! AvoidSimpleBox( frTmp, vtDiag + 2 * dSafeDist * Z_AX, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleBox( frTmp, vtDiag + 2 * dSafeDist * Z_AX, bPrecise))
|
||||
return true ;
|
||||
|
||||
// Vertici del box
|
||||
Point3d ptVert0 = frBox.Orig() ;
|
||||
@@ -579,67 +583,67 @@ VolZmap::AvoidBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDis
|
||||
Point3d ptVert7 = ptVert3 + vtDiag.z * frBox.VersZ() ;
|
||||
|
||||
// Sfere centrate negli otto vertici
|
||||
if ( ! AvoidSimpleSphere( ptVert0, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( ! AvoidSimpleSphere( ptVert1, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( ! AvoidSimpleSphere( ptVert2, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( ! AvoidSimpleSphere( ptVert3, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( ! AvoidSimpleSphere( ptVert4, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( ! AvoidSimpleSphere( ptVert5, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( ! AvoidSimpleSphere( ptVert6, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( ! AvoidSimpleSphere( ptVert7, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleSphere( ptVert0, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
if ( CDeSimpleSphere( ptVert1, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
if ( CDeSimpleSphere( ptVert2, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
if ( CDeSimpleSphere( ptVert3, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
if ( CDeSimpleSphere( ptVert4, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
if ( CDeSimpleSphere( ptVert5, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
if ( CDeSimpleSphere( ptVert6, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
if ( CDeSimpleSphere( ptVert7, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
|
||||
// Cilindri centrati sui dodici spigoli
|
||||
frTmp.Set( ptVert0, frBox.VersX()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert2, frBox.VersX()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert0, frBox.VersY()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert1, frBox.VersY()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert4, frBox.VersX()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert6, frBox.VersX()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.x, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert4, frBox.VersY()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert5, frBox.VersY()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.y, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert0, frBox.VersZ()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert1, frBox.VersZ()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert2, frBox.VersZ()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
|
||||
return true ;
|
||||
frTmp.Set( ptVert3, frBox.VersZ()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dSafeDist, vtDiag.z, bPrecise))
|
||||
return true ;
|
||||
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise) const
|
||||
VolZmap::CDeSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise) const
|
||||
{
|
||||
// Porto la sfera nel riferimento intrinseco dello Zmap
|
||||
Point3d ptC = ptCenter ;
|
||||
@@ -655,7 +659,7 @@ VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise)
|
||||
// Se non interferiscono, posso uscire
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Zmap.FindIntersection( b3Box, b3Int))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// Se verifico solo prima mappa
|
||||
if ( ! bPrecise || m_nMapNum == 1) {
|
||||
@@ -693,7 +697,7 @@ VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise)
|
||||
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
|
||||
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
|
||||
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -765,7 +769,7 @@ VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise)
|
||||
// Se il segmento è interno all'intervallo d'intersezione, ho finito.
|
||||
if ( dMaxU > m_Values[nMap][nPos][nIndex].dMin - EPS_SMALL &&
|
||||
dMinU < m_Values[nMap][nPos][nIndex].dMax + EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -773,19 +777,23 @@ VolZmap::AvoidSimpleSphere( const Point3d& ptCenter, double dRad, bool bPrecise)
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bool bPrecise) const
|
||||
VolZmap::CDeSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bool bPrecise) const
|
||||
{
|
||||
return AvoidSimpleSphere( ptCenter, dRad + max( 0., dSafeDist), bPrecise) ;
|
||||
// Il raggio deve essere non nullo
|
||||
if ( dRad < EPS_SMALL)
|
||||
return true ;
|
||||
|
||||
return CDeSimpleSphere( ptCenter, dRad + max( 0., dSafeDist), bPrecise) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool bPrecise) const
|
||||
VolZmap::CDeSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool bPrecise) const
|
||||
{
|
||||
// BBox del cilindro in locale
|
||||
BBox3d b3CylL( Point3d( -dR, -dR, 0), Point3d( dR, dR, dH)) ;
|
||||
@@ -799,7 +807,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b
|
||||
|
||||
// Se non interferiscono, posso uscire
|
||||
if ( ! b3Zmap.Overlaps( b3CylI) || ! b3Zmap.Overlaps( frCylInt, b3CylL))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// BBox del cilindro ottimizzato nel riferimento intrinseco dello Zmap
|
||||
Point3d ptMyCen = frCylInt.Orig() ;
|
||||
@@ -822,7 +830,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b
|
||||
// Se non interferiscono, posso uscire
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Zmap.FindIntersection( b3Cyl, b3Int))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// Se verifico solo prima mappa
|
||||
if ( ! bPrecise || m_nMapNum == 1) {
|
||||
@@ -866,7 +874,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b
|
||||
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
|
||||
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
|
||||
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -931,7 +939,7 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b
|
||||
// Se il segmento è interno all'intervallo d'intersezione, ho finito.
|
||||
if ( dMaxU > m_Values[nMap][nPos][nIndex].dMin - EPS_SMALL &&
|
||||
dMinU < m_Values[nMap][nPos][nIndex].dMax + EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -939,13 +947,17 @@ VolZmap::AvoidSimpleCylinder( const Frame3d& frCyl, double dR, double dH, bool b
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise) const
|
||||
VolZmap::CDeCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise) const
|
||||
{
|
||||
// Il cilindro deve essere ben definito
|
||||
if ( dR < EPS_SMALL || dH < EPS_SMALL)
|
||||
return true ;
|
||||
|
||||
// Se altezza negativa, sposto riferimento da faccia sopra a quella sotto
|
||||
Frame3d frMyCyl = frCyl ;
|
||||
if ( dH < 0) {
|
||||
@@ -955,34 +967,34 @@ VolZmap::AvoidCylinder( const Frame3d& frCyl, double dR, double dH, double dSafe
|
||||
|
||||
// Se distanza di sicurezza nulla
|
||||
if ( dSafeDist < EPS_SMALL)
|
||||
return AvoidSimpleCylinder( frMyCyl, dR, dH, bPrecise) ;
|
||||
return CDeSimpleCylinder( frMyCyl, dR, dH, bPrecise) ;
|
||||
|
||||
// Verifica preliminare con cilindro esteso
|
||||
Frame3d frEst = frMyCyl ; frEst.Translate( -dSafeDist * frMyCyl.VersZ()) ;
|
||||
if ( AvoidSimpleCylinder( frEst, dR + dSafeDist, dH + 2 * dSafeDist, bPrecise))
|
||||
return true ;
|
||||
if ( ! CDeSimpleCylinder( frEst, dR + dSafeDist, dH + 2 * dSafeDist, bPrecise))
|
||||
return false ;
|
||||
|
||||
// Cilindro allargato
|
||||
if ( ! AvoidSimpleCylinder( frMyCyl, dR + dSafeDist, dH, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frMyCyl, dR + dSafeDist, dH, bPrecise))
|
||||
return true ;
|
||||
// Cilindro allungato
|
||||
Frame3d frTmp = frMyCyl ; frTmp.Translate( - dSafeDist * frMyCyl.VersZ()) ;
|
||||
if ( ! AvoidSimpleCylinder( frTmp, dR, dH + 2 * dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frTmp, dR, dH + 2 * dSafeDist, bPrecise))
|
||||
return true ;
|
||||
// Toro inferiore
|
||||
if ( ! AvoidSimpleTorus( frMyCyl, dR, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleTorus( frMyCyl, dR, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
// Toro superiore
|
||||
frTmp = frMyCyl ; frTmp.Translate( dH * frMyCyl.VersZ()) ;
|
||||
if ( ! AvoidSimpleTorus( frTmp, dR, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleTorus( frTmp, dR, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double dMaxRad, double dHeight, bool bPrecise) const
|
||||
VolZmap::CDeSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double dMaxRad, double dHeight, bool bPrecise) const
|
||||
{
|
||||
// BBox del tronco di cono in locale
|
||||
BBox3d b3ConeL( Point3d( -dMaxRad, -dMaxRad, 0), Point3d( dMaxRad, dMaxRad, dHeight)) ;
|
||||
@@ -996,7 +1008,7 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d
|
||||
|
||||
// Se non interferiscono, posso uscire
|
||||
if ( ! b3Zmap.Overlaps( b3ConeI) || ! b3Zmap.Overlaps( frConeInt, b3ConeL))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// BBox del tronco di cono ottimizzato nel riferimento intrinseco dello Zmap
|
||||
Point3d ptRefPoint = frConeInt.Orig() ;
|
||||
@@ -1025,7 +1037,7 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d
|
||||
// Se non interferiscono, posso uscire
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Zmap.FindIntersection( b3Cone, b3Int))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// Uso solo la prima mappa
|
||||
if ( ! bPrecise || m_nMapNum == 1) {
|
||||
@@ -1068,7 +1080,7 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d
|
||||
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
|
||||
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
|
||||
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1133,14 +1145,14 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d
|
||||
// Se il segmento è interno all'intervallo d'intersezione, ho finito.
|
||||
if ( dMaxU > m_Values[nMap][nPos][nIndex].dMin - EPS_SMALL &&
|
||||
dMinU < m_Values[nMap][nPos][nIndex].dMax + EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1149,12 +1161,16 @@ VolZmap::AvoidSimpleConeFrustum( const Frame3d& frCone, double dMinRad, double d
|
||||
// Se è un tronco di cono l'origine è nel centro della base Bot e l'asse Z è diretto verso
|
||||
// la base Top, a prescindere da quale base abbia raggio maggiore.
|
||||
bool
|
||||
VolZmap::AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop, double dHeight,
|
||||
VolZmap::CDeConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop, double dHeight,
|
||||
double dSafeDist, bool bPrecise) const
|
||||
{
|
||||
// Se il tronco di cono non è ben definito non ha senso proseguire
|
||||
if ( max( dRadBot, dRadTop) < EPS_SMALL || dHeight < EPS_SMALL)
|
||||
return true ;
|
||||
|
||||
// Se cilindro
|
||||
if ( abs( dRadBot - dRadTop) < EPS_SMALL)
|
||||
return AvoidCylinder( frCone, max( dRadBot, dRadTop), dHeight, dSafeDist, bPrecise) ;
|
||||
return CDeCylinder( frCone, max( dRadBot, dRadTop), dHeight, dSafeDist, bPrecise) ;
|
||||
|
||||
// Verifico che la base minore sia in basso nel suo riferimento
|
||||
Frame3d frMyCone = frCone ;
|
||||
@@ -1167,7 +1183,7 @@ VolZmap::AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop
|
||||
|
||||
// Se distanza di sicurezza nulla
|
||||
if ( dSafeDist < EPS_SMALL)
|
||||
return AvoidSimpleConeFrustum( frMyCone, dMinRad, dMaxRad, dHeight, bPrecise) ;
|
||||
return CDeSimpleConeFrustum( frMyCone, dMinRad, dMaxRad, dHeight, bPrecise) ;
|
||||
|
||||
// Se vero e proprio cono
|
||||
if ( dMinRad < EPS_SMALL) {
|
||||
@@ -1177,28 +1193,28 @@ VolZmap::AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop
|
||||
double dRadExt = dMaxRad * dHeightExt / dHeight ;
|
||||
Frame3d frFrame = frMyCone ;
|
||||
frFrame.Translate( -dDeltaVert * frFrame.VersZ()) ;
|
||||
if ( AvoidSimpleConeFrustum( frFrame, 0., dRadExt, dHeightExt, bPrecise))
|
||||
return true ;
|
||||
if ( ! CDeSimpleConeFrustum( frFrame, 0., dRadExt, dHeightExt, bPrecise))
|
||||
return false ;
|
||||
// Sfera nel vertice in basso
|
||||
frFrame = frMyCone ;
|
||||
if ( ! AvoidSimpleSphere( frMyCone.Orig(), dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleSphere( frMyCone.Orig(), dSafeDist, bPrecise))
|
||||
return true ;
|
||||
// Tronco di cono intermedio
|
||||
double dHypo = sqrt( dMaxRad * dMaxRad + dHeight * dHeight ) ;
|
||||
double dDeltaH = dSafeDist * dMaxRad / dHypo ;
|
||||
double dDeltaR = dSafeDist * dHeight / dHypo ;
|
||||
frFrame = frMyCone ; frFrame.Translate( -dDeltaH * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleConeFrustum( frFrame, dDeltaR, dMaxRad + dDeltaR, dHeight, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleConeFrustum( frFrame, dDeltaR, dMaxRad + dDeltaR, dHeight, bPrecise))
|
||||
return true ;
|
||||
// Cilindro nel toro in alto
|
||||
frFrame = frMyCone ; frFrame.Translate( ( dHeight - dSafeDist) * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dMaxRad, 2 * dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dMaxRad, 2 * dSafeDist, bPrecise))
|
||||
return true ;
|
||||
// Toro in alto
|
||||
frFrame = frMyCone ; frFrame.Translate( dHeight * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleTorus( frFrame, dMaxRad, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
return true ;
|
||||
if ( CDeSimpleTorus( frFrame, dMaxRad, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// Tronco di cono
|
||||
@@ -1210,33 +1226,33 @@ VolZmap::AvoidConeFrustum( const Frame3d& frCone, double dRadBot, double dRadTop
|
||||
double dDeltaMaxRad = ( dDeltaVert + dSafeDist) * dDiffRad / dHeight ;
|
||||
double dDeltaMinRad = ( dDeltaVert - dSafeDist) * dDiffRad / dHeight ;
|
||||
Frame3d frFrame = frMyCone ; frFrame.Translate( -dSafeDist * frFrame.VersZ()) ;
|
||||
if ( AvoidSimpleConeFrustum( frFrame, dMinRad + dDeltaMinRad, dMaxRad + dDeltaMaxRad, dHeight + 2 * dSafeDist, bPrecise))
|
||||
return true ;
|
||||
if ( ! CDeSimpleConeFrustum( frFrame, dMinRad + dDeltaMinRad, dMaxRad + dDeltaMaxRad, dHeight + 2 * dSafeDist, bPrecise))
|
||||
return false ;
|
||||
// Tronco di cono intermedio
|
||||
double dHypo = sqrt( dDiffRad * dDiffRad + dHeight * dHeight ) ;
|
||||
double dDeltaH = dSafeDist * dDiffRad / dHypo ;
|
||||
double dDeltaR = dSafeDist * dHeight / dHypo ;
|
||||
frFrame = frMyCone ; frFrame.Translate( -dDeltaH * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleConeFrustum( frFrame, dMinRad + dDeltaR, dMaxRad + dDeltaR, dHeight, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleConeFrustum( frFrame, dMinRad + dDeltaR, dMaxRad + dDeltaR, dHeight, bPrecise))
|
||||
return true ;
|
||||
// Cilindro sotto
|
||||
frFrame = frMyCone ; frFrame.Translate( - dSafeDist * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dMinRad, 2 * dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dMinRad, 2 * dSafeDist, bPrecise))
|
||||
return true ;
|
||||
// Cilindro sopra
|
||||
frFrame.Translate( dHeight * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dMaxRad, 2 * dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dMaxRad, 2 * dSafeDist, bPrecise))
|
||||
return true ;
|
||||
// Toro sotto
|
||||
frFrame = frMyCone ;
|
||||
if ( ! AvoidSimpleTorus( frFrame, dMinRad, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleTorus( frFrame, dMinRad, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
// Toro sopra
|
||||
frFrame.Translate( dHeight * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleTorus( frFrame, dMaxRad, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleTorus( frFrame, dMaxRad, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1380,8 +1396,8 @@ RectPrismoidSegmentCollisionPlus( const Frame3d& frPrismoid, double dLenghtBaseX
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
|
||||
double dLenghtTopX, double dLenghtTopY, double dHeight, bool bPrecise) const
|
||||
VolZmap::CDeSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
|
||||
double dLenghtTopX, double dLenghtTopY, double dHeight, bool bPrecise) const
|
||||
{
|
||||
// Box del tronco di prismoide nel suo sistema locale
|
||||
double dMaxLenX = max( dLenghtBaseX, dLenghtTopX) ;
|
||||
@@ -1398,7 +1414,7 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX
|
||||
|
||||
// Se i box non interferiscono, posso uscire
|
||||
if ( ! b3Zmap.Overlaps( b3PrismI) || ! b3Zmap.Overlaps( frPrismInt, b3PrismL))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// BBox del tronco di prismoide ottimizzato nel riferimento intrinseco dello Zmap
|
||||
Point3d ptMyCen = frPrismInt.Orig() ;
|
||||
@@ -1418,7 +1434,7 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX
|
||||
// Se i box non interferiscono, posso uscire
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Zmap.FindIntersection( b3Prism, b3Int))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// Se verifico solo prima mappa
|
||||
if ( ! bPrecise || m_nMapNum == 1) {
|
||||
@@ -1456,7 +1472,7 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX
|
||||
dHeight, ptSegSt, ptSegEn, dStU, dEnU)) {
|
||||
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
|
||||
if ( m_Values[0][nPos][nIndex].dMax >= dStU && m_Values[0][nPos][nIndex].dMin <= dEnU)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1523,30 +1539,30 @@ VolZmap::AvoidSimpleRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX
|
||||
dHeight, ptSegSt, ptSegEn, dStU, dEnU)) {
|
||||
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
|
||||
if ( m_Values[nMap][nDex][nIndex].dMax >= dStU && m_Values[nMap][nDex][nIndex].dMin <= dEnU)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
|
||||
double dLenghtTopX, double dLenghtTopY, double dHeight,
|
||||
double dSafeDist, bool bPrecise) const
|
||||
VolZmap::CDeRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
|
||||
double dLenghtTopX, double dLenghtTopY, double dHeight,
|
||||
double dSafeDist, bool bPrecise) const
|
||||
{
|
||||
// Se il tronco di piramide non è ben definito non procedo
|
||||
if ( max( dLenghtBaseX, dLenghtTopX) < EPS_SMALL ||
|
||||
max( dLenghtBaseY, dLenghtTopY) < EPS_SMALL ||
|
||||
dHeight < EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
|
||||
// Se distanza di sicurezza nulla
|
||||
if ( dSafeDist < EPS_SMALL)
|
||||
return AvoidSimpleRectPrismoid( frPrismoid, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, dHeight, bPrecise) ;
|
||||
return CDeSimpleRectPrismoid( frPrismoid, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, dHeight, bPrecise) ;
|
||||
|
||||
// Verifica preliminare con offset esteso
|
||||
double dHDiffX = ( dLenghtBaseX - dLenghtTopX) / 2 ;
|
||||
@@ -1560,9 +1576,9 @@ VolZmap::AvoidRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, doub
|
||||
double dOffsBaseY = dSafeDist * ( dSecAy + dTgAy) ;
|
||||
double dOffsTopY = dSafeDist * ( dSecAy - dTgAy) ;
|
||||
Frame3d frFrame = frPrismoid ; frFrame.Translate( -dSafeDist * frFrame.VersZ()) ;
|
||||
if ( AvoidSimpleRectPrismoid( frFrame, dLenghtBaseX + 2 * dOffsBaseX, dLenghtBaseY + 2 * dOffsBaseY,
|
||||
if ( ! CDeSimpleRectPrismoid( frFrame, dLenghtBaseX + 2 * dOffsBaseX, dLenghtBaseY + 2 * dOffsBaseY,
|
||||
dLenghtTopX + 2 * dOffsTopX, dLenghtTopY + 2 * dOffsTopY, dHeight + 2 * dSafeDist, bPrecise))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// Offset fine
|
||||
// Sfere centrate nei vertici
|
||||
@@ -1580,85 +1596,85 @@ VolZmap::AvoidRectPrismoid( const Frame3d& frPrismoid, double dLenghtBaseX, doub
|
||||
Point3d( -dHalfTopX, dHalfTopY, dHeight)} ;
|
||||
for ( auto& ptV : vVert) {
|
||||
ptV.ToGlob( frPrismoid) ;
|
||||
if ( ! AvoidSimpleSphere( ptV, dSafeDist, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleSphere( ptV, dSafeDist, bPrecise))
|
||||
return true ;
|
||||
}
|
||||
// Cilindri con i segmenti come asse
|
||||
frFrame.Set( vVert[0], frPrismoid.VersX()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtBaseX, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtBaseX, bPrecise))
|
||||
return true ;
|
||||
frFrame.Set( vVert[1], frPrismoid.VersY()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtBaseY, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtBaseY, bPrecise))
|
||||
return true ;
|
||||
frFrame.Set( vVert[2], -frPrismoid.VersX()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtBaseX, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtBaseX, bPrecise))
|
||||
return true ;
|
||||
frFrame.Set( vVert[3], -frPrismoid.VersY()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtBaseY, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtBaseY, bPrecise))
|
||||
return true ;
|
||||
frFrame.Set( vVert[4], frPrismoid.VersX()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtTopX, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtTopX, bPrecise))
|
||||
return true ;
|
||||
frFrame.Set( vVert[5], frPrismoid.VersY()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtTopY, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtTopY, bPrecise))
|
||||
return true ;
|
||||
frFrame.Set( vVert[6], -frPrismoid.VersX()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtTopX, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtTopX, bPrecise))
|
||||
return true ;
|
||||
frFrame.Set( vVert[7], -frPrismoid.VersY()) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenghtTopY, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenghtTopY, bPrecise))
|
||||
return true ;
|
||||
Vector3d vtSeg04 = vVert[4] - vVert[0] ;
|
||||
double dLenSeg04 = vtSeg04.Len() ;
|
||||
frFrame.Set( vVert[0], vtSeg04) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenSeg04, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenSeg04, bPrecise))
|
||||
return true ;
|
||||
Vector3d vtSeg15 = vVert[5] - vVert[1] ;
|
||||
double dLenSeg15 = vtSeg15.Len() ;
|
||||
frFrame.Set( vVert[1], vtSeg15) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenSeg15, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenSeg15, bPrecise))
|
||||
return true ;
|
||||
Vector3d vtSeg26 = vVert[6] - vVert[2] ;
|
||||
double dLenSeg26 = vtSeg26.Len() ;
|
||||
frFrame.Set( vVert[2], vtSeg26) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenSeg26, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenSeg26, bPrecise))
|
||||
return true ;
|
||||
Vector3d vtSeg37 = vVert[7] - vVert[3] ;
|
||||
double dLenSeg37 = vtSeg37.Len();
|
||||
frFrame.Set( vVert[3], vtSeg37) ;
|
||||
if ( ! AvoidSimpleCylinder( frFrame, dSafeDist, dLenSeg37, bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleCylinder( frFrame, dSafeDist, dLenSeg37, bPrecise))
|
||||
return true ;
|
||||
// Box sotto
|
||||
frFrame = frPrismoid ; frFrame.Translate( -dSafeDist * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleBox( frFrame, Vector3d( dLenghtBaseX, dLenghtBaseY, dSafeDist), bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleBox( frFrame, Vector3d( dLenghtBaseX, dLenghtBaseY, dSafeDist), bPrecise))
|
||||
return true ;
|
||||
// Box sopra
|
||||
frFrame = frPrismoid ; frFrame.Translate( dHeight * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleBox( frFrame, Vector3d( dLenghtBaseX, dLenghtBaseY, dSafeDist), bPrecise))
|
||||
return false ;
|
||||
if ( CDeSimpleBox( frFrame, Vector3d( dLenghtBaseX, dLenghtBaseY, dSafeDist), bPrecise))
|
||||
return true ;
|
||||
// Prismoide allungato in X
|
||||
double dHypoX = sqrt( dHDiffX * dHDiffX + dHeight * dHeight) ;
|
||||
double dOffsX = dSafeDist * dHeight / dHypoX ;
|
||||
double dMoveXZ = dSafeDist * dHDiffX / dHypoX ;
|
||||
frFrame = frPrismoid ; frFrame.Translate( dMoveXZ * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleRectPrismoid( frFrame, dLenghtBaseX + 2 * dOffsX, dLenghtBaseY,
|
||||
if ( CDeSimpleRectPrismoid( frFrame, dLenghtBaseX + 2 * dOffsX, dLenghtBaseY,
|
||||
dLenghtTopX + 2 * dOffsX, dLenghtTopY, dHeight, bPrecise))
|
||||
return false ;
|
||||
return true ;
|
||||
// Prismoide allungato in Y
|
||||
double dHypoY = sqrt( dHDiffY * dHDiffY + dHeight * dHeight) ;
|
||||
double dOffsY = dSafeDist * dHeight / dHypoY ;
|
||||
double dMoveYZ = dSafeDist * dHDiffY / dHypoY ;
|
||||
frFrame = frPrismoid ; frFrame.Translate( dMoveYZ * frFrame.VersZ()) ;
|
||||
if ( ! AvoidSimpleRectPrismoid( frFrame, dLenghtBaseX, dLenghtBaseY + 2 * dOffsY,
|
||||
if ( CDeSimpleRectPrismoid( frFrame, dLenghtBaseX, dLenghtBaseY + 2 * dOffsY,
|
||||
dLenghtTopX, dLenghtTopY + 2 * dOffsY, dHeight, bPrecise))
|
||||
return false ;
|
||||
return true ;
|
||||
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise) const
|
||||
VolZmap::CDeSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad, bool bPrecise) const
|
||||
{
|
||||
// BBox del toro in locale
|
||||
BBox3d b3TorusL( Point3d( -dMaxRad - dMinRad, -dMaxRad - dMinRad, -dMinRad),
|
||||
@@ -1673,7 +1689,7 @@ VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRa
|
||||
|
||||
// Se non interferiscono, posso uscire
|
||||
if ( ! b3Zmap.Overlaps( b3TorusI) || ! b3Zmap.Overlaps( frTorusInt, b3TorusL))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// BBox del toro ottimizzato nel riferimento intrinseco dello Zmap
|
||||
Point3d ptMyCen = frTorusInt.Orig() ;
|
||||
@@ -1698,7 +1714,7 @@ VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRa
|
||||
// Se non interferiscono, posso uscire
|
||||
BBox3d b3Int ;
|
||||
if ( ! b3Zmap.FindIntersection( b3Torus, b3Int))
|
||||
return true ;
|
||||
return false ;
|
||||
|
||||
// Se verifico solo prima mappa
|
||||
if ( ! bPrecise || m_nMapNum == 1) {
|
||||
@@ -1736,13 +1752,13 @@ VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRa
|
||||
int nIntType = SegmentTorus( ptSegSt, Z_AX, dParMax - dParMin, ptMyCen, vtMyAx, dMinRad, dMaxRad,
|
||||
vbType, vdPar) ;
|
||||
if ( nIntType == LinCompTorusIntersType::T_ERROR)
|
||||
return false ;
|
||||
return true ;
|
||||
else if ( nIntType != LinCompTorusIntersType::T_NO_INT) {
|
||||
double dUmin = vdPar.front() ;
|
||||
double dUmax = vdPar.back() ;
|
||||
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
|
||||
if ( m_Values[0][nPos][nIndex].dMax >= dUmin && m_Values[0][nPos][nIndex].dMin <= dUmax)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1810,31 +1826,31 @@ VolZmap::AvoidSimpleTorus( const Frame3d& frTorus, double dMaxRad, double dMinRa
|
||||
int nIntType = SegmentTorus( ptSegSt, vtLineDir, dParMax - dParMin, ptMyCen, vtMyAx, dMinRad, dMaxRad,
|
||||
vbType, vdPar) ;
|
||||
if ( nIntType == LinCompTorusIntersType::T_ERROR)
|
||||
return false ;
|
||||
return true ;
|
||||
else if ( nIntType != LinCompTorusIntersType::T_NO_INT) {
|
||||
double dUmin = vdPar.front() ;
|
||||
double dUmax = vdPar.back() ;
|
||||
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
|
||||
if ( m_Values[nMap][nDex][nIndex].dMax >= dUmin && m_Values[nMap][nDex][nIndex].dMin <= dUmax)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad,
|
||||
VolZmap::CDeTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad,
|
||||
double dSafeDist, bool bPrecise) const
|
||||
{
|
||||
// I raggi devono essere non nulli
|
||||
if ( dMaxRad < EPS_SMALL || dMinRad < EPS_SMALL)
|
||||
return true ;
|
||||
|
||||
return AvoidSimpleTorus( frTorus, dMaxRad, dMinRad + max( 0., dSafeDist), bPrecise) ;
|
||||
return CDeSimpleTorus( frTorus, dMaxRad, dMinRad + max( 0., dSafeDist), bPrecise) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1844,12 +1860,13 @@ VolZmap::AvoidTorus( const Frame3d& frTorus, double dMaxRad, double dMinRad,
|
||||
// quelli di intersezione segmento triangolo vengono eseguiti nel sistema locale. Questo perché
|
||||
// è più veloce trasformare le coordinate degli estremi del segmento piuttosto che quelle del
|
||||
// triangolo.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise) const
|
||||
VolZmap::CDeSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise) const
|
||||
{
|
||||
// Controllo sulla validità della superficie ed eventualmente sulla sua chiusura
|
||||
if ( ! ( tmSurf.IsValid() && tmSurf.IsClosed()))
|
||||
return false ;
|
||||
// Controllo sulla validità della superficie e sulla sua chiusura
|
||||
if ( ! tmSurf.IsValid() || ! tmSurf.IsClosed())
|
||||
return true ;
|
||||
// Bounding box della superficie espresso nel sistema locale
|
||||
BBox3d b3SurfBox ;
|
||||
tmSurf.GetLocalBBox( b3SurfBox) ;
|
||||
@@ -1862,7 +1879,7 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
|
||||
// Box intersezione: se non c'è intersezione ho finito.
|
||||
BBox3d b3IntBox ;
|
||||
if ( ! b3ZmapBox.FindIntersection( b3SurfBox, b3IntBox))
|
||||
return true ;
|
||||
return false ;
|
||||
// Recupero i triangoli della superficie che cadono nel box intersezione.
|
||||
INTVECTOR vTriaIndex ;
|
||||
tmSurf.GetAllTriaOverlapBox( b3IntBox, vTriaIndex) ;
|
||||
@@ -1923,7 +1940,7 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
|
||||
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
|
||||
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
|
||||
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1939,7 +1956,7 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
|
||||
for ( int nIndex = 0 ; nIndex < nSize ; nIndex += 1) {
|
||||
if ( dZmax > m_Values[0][nPos][nIndex].dMin - EPS_SMALL &&
|
||||
dZmin < m_Values[0][nPos][nIndex].dMax + EPS_SMALL)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2030,11 +2047,11 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
|
||||
double dU1, dU2 ;
|
||||
int nIntersType = SegmentSphere( ptSegSt, vtLineDir, dSegLen, ptVertP, dSafeDist, dU1, dU2) ;
|
||||
if ( nIntersType != LinCompSphereIntersType::S_NO_INTERS)
|
||||
return false ;
|
||||
return true ;
|
||||
nIntersType = IntersSegmentCylinder( ptSegSt, vtLineDir, dSegLen, ptVertP, vtEdgeV,
|
||||
dSafeDist, dEdgeLen, dU1, dU2) ;
|
||||
if ( nIntersType != LinCompCCIntersType::CC_NO_INTERS)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
// Traslo il triangolo.
|
||||
trNewTria.Translate( dSafeDist * trTria.GetN()) ;
|
||||
@@ -2044,14 +2061,14 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
|
||||
int nIntersType = IntersLineTria( ptSegSt, vtLineDir, dSegLen, trNewTria, ptInt, ptInt2) ;
|
||||
// Collisione
|
||||
if ( nIntersType != IntLineTriaType::ILTT_NO)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -2895,8 +2912,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
|
||||
int nNumVox ;
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
|
||||
nNumVox, nB, ptLineTria1, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
|
||||
}
|
||||
// altrimenti ci sono due intersezioni
|
||||
else {
|
||||
@@ -2904,8 +2922,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
|
||||
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
|
||||
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2931,8 +2950,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
|
||||
int nNumVox ;
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
|
||||
nNumVox, nB, ptLineTria1, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
|
||||
}
|
||||
// altrimenti ci sono due intersezioni
|
||||
else {
|
||||
@@ -2940,8 +2960,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
|
||||
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
|
||||
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2957,15 +2978,17 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
continue ;
|
||||
// se altrimenti c'è una sola intersezione
|
||||
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
|
||||
-1, nB, ptLineTria1, trTria) ;
|
||||
-1, nB, trTria, dCosDN, ptLineTria1) ;
|
||||
}
|
||||
// altrimenti ci sono due intersezioni
|
||||
else {
|
||||
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
|
||||
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
|
||||
-1, nB, ptLineTria1, ptLineTria2, trTria) ;
|
||||
-1, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2990,8 +3013,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
|
||||
int nNumVox ;
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
|
||||
nNumVox, nB, ptLineTria1, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
|
||||
}
|
||||
// altrimenti ci sono due intersezioni
|
||||
else {
|
||||
@@ -2999,8 +3023,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
|
||||
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
|
||||
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "CurveLine.h"
|
||||
#include "VolZmap.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <future>
|
||||
|
||||
|
||||
+199
-131
@@ -79,7 +79,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
|
||||
// verifico se è una linea
|
||||
// verifico se è una linea
|
||||
int nType = pCrv->GetType() ;
|
||||
bool bIsLine = ( nType == CRV_LINE) ;
|
||||
if ( nType == CRV_COMPO) {
|
||||
@@ -92,7 +92,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
||||
// verifico sia piana e trovo piano su cui giace
|
||||
Plane3d plPlane ;
|
||||
if ( bIsLine) {
|
||||
// linea è sicuramente piana. Scelgo piano definito dall'estrusione ( se definita)
|
||||
// linea è sicuramente piana. Scelgo piano definito dall'estrusione ( se definita)
|
||||
Point3d ptS ; pCrv->GetStartPoint( ptS) ;
|
||||
Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ;
|
||||
if ( ! vtExtr.IsSmall())
|
||||
@@ -110,30 +110,40 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
||||
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
|
||||
}
|
||||
else {
|
||||
// altrimenti verifico sia complanare ad eventuali curve già presenti
|
||||
// altrimenti verifico sia complanare ad eventuali curve già presenti
|
||||
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), plPlane.GetVersN()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// verifico se oggetto vroni è stato inizializzato
|
||||
if ( m_vroni == nullptr) {
|
||||
m_vroni = new( nothrow) vroniObject() ;
|
||||
m_vroni->apiInitializeProgram() ;
|
||||
}
|
||||
|
||||
// creo una copia della curva e la porto in locale
|
||||
PtrOwner<ICurve> pCrvLoc( pCrv->Clone()) ;
|
||||
if ( IsNull( pCrvLoc))
|
||||
return false ;
|
||||
pCrvLoc->ToLoc( m_Frame) ;
|
||||
|
||||
// aggiungo la curva in locale all'oggetto vroni
|
||||
if ( ! AddCurveToVroni( pCrvLoc))
|
||||
try {
|
||||
// verifico se oggetto vroni è stato inizializzato
|
||||
if ( m_vroni == nullptr) {
|
||||
m_vroni = new( nothrow) vroniObject() ;
|
||||
if ( m_vroni == nullptr)
|
||||
return false ;
|
||||
m_vroni->apiInitializeProgram() ;
|
||||
}
|
||||
|
||||
// aggiungo la curva in locale all'oggetto vroni
|
||||
if ( ! AddCurveToVroni( pCrvLoc))
|
||||
return false ;
|
||||
}
|
||||
catch (...) {
|
||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// aggiorno il box complessivo
|
||||
BBox3d bBox ;
|
||||
pCrvLoc->GetLocalBBox( bBox) ;
|
||||
m_bBox.Add( bBox) ;
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -155,28 +165,38 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
|
||||
m_Frame.Set( ptCen, vtN) ;
|
||||
}
|
||||
else {
|
||||
// verifico sia complanare ad eventuali curve già presenti
|
||||
// verifico sia complanare ad eventuali curve già presenti
|
||||
Plane3d plPlane ;
|
||||
plPlane.Set( ptCen, pSfr->GetNormVersor()) ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), pSfr->GetNormVersor()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// verifico se oggetto vroni è stato inizializzato
|
||||
if ( m_vroni == nullptr) {
|
||||
m_vroni = new( nothrow) vroniObject() ;
|
||||
m_vroni->apiInitializeProgram() ;
|
||||
}
|
||||
|
||||
// aggiungo le curve di loop
|
||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; i ++) {
|
||||
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; j ++) {
|
||||
PtrOwner<ICurve> pCrvLoc( pSfr->GetLoop( i, j)) ;
|
||||
pCrvLoc->ToLoc( m_Frame) ;
|
||||
if ( ! AddCurveToVroni( pCrvLoc))
|
||||
try {
|
||||
// verifico se oggetto vroni è stato inizializzato
|
||||
if ( m_vroni == nullptr) {
|
||||
m_vroni = new( nothrow) vroniObject() ;
|
||||
if ( m_vroni == nullptr)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
m_vroni->apiInitializeProgram() ;
|
||||
}
|
||||
|
||||
// aggiungo le curve di loop
|
||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; i ++) {
|
||||
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; j ++) {
|
||||
PtrOwner<ICurve> pCrvLoc( pSfr->GetLoop( i, j)) ;
|
||||
if ( IsNull( pCrvLoc))
|
||||
return false ;
|
||||
pCrvLoc->ToLoc( m_Frame) ;
|
||||
if ( ! AddCurveToVroni( pCrvLoc))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage())
|
||||
return false ;
|
||||
}
|
||||
|
||||
// aggiorno il box complessivo
|
||||
BBox3d bBox ;
|
||||
@@ -184,7 +204,7 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
|
||||
frSrf.Invert() ;
|
||||
pSfr->GetBBox( frSrf, bBox) ;
|
||||
m_bBox.Add( bBox) ;
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -225,8 +245,9 @@ Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, i
|
||||
{
|
||||
if ( pLine == nullptr)
|
||||
return false ;
|
||||
|
||||
// verifico se il punto finale viene forzato oppure deve essere ricavato dalla pLine
|
||||
if ( ! ptEnd.IsValid()) {
|
||||
// recupero end point
|
||||
if ( ! pLine->GetEndPoint( ptEnd))
|
||||
return false ;
|
||||
}
|
||||
@@ -260,8 +281,8 @@ Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int
|
||||
m_vroni->AddArc( &nVroniCrv, ptStart.x, ptStart.y, ptCen.x, ptCen.y, nArcSiteType, {nLoopId, nCrvId}) ;
|
||||
}
|
||||
else {
|
||||
// verifico se il punto finale viene forzato oppure deve essere ricavato dal pArc
|
||||
if ( ! ptEnd.IsValid()) {
|
||||
// recupero end point dalla curva
|
||||
if ( ! pArc->GetEndPoint( ptEnd))
|
||||
return false ;
|
||||
}
|
||||
@@ -294,7 +315,7 @@ Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLo
|
||||
for ( int i = 0 ; i < pCopy->GetCurveCount() ; i++) {
|
||||
Point3d ptForcedEnd = P_INVALID ;
|
||||
|
||||
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
|
||||
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
|
||||
if ( i == pCopy->GetCurveCount() - 1 && bClosed)
|
||||
pCompo->GetStartPoint( ptForcedEnd) ;
|
||||
|
||||
@@ -338,7 +359,7 @@ Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoo
|
||||
ICurve*
|
||||
Voronoi::GetCurve( int nId) const
|
||||
{
|
||||
// verifico validità indice
|
||||
// verifico validità indice
|
||||
if ( nId < 0 || nId > ( int)m_vpCrvs.size() - 1)
|
||||
return nullptr ;
|
||||
// ne faccio una copia
|
||||
@@ -354,20 +375,22 @@ Voronoi::GetCurve( int nId) const
|
||||
bool
|
||||
Voronoi::CalcVoronoi( int nBound)
|
||||
{
|
||||
// se già stato calcolato con lo stesso bound non devo fare nulla
|
||||
// se già stato calcolato con lo stesso bound non devo fare nulla
|
||||
if ( m_bVDComputed && nBound == m_nBound)
|
||||
return true ;
|
||||
|
||||
// se già stato calcolato reset dei dati
|
||||
// se già stato calcolato reset dei dati
|
||||
if ( m_bVDComputed)
|
||||
m_vroni->ResetVoronoiDiagram() ;
|
||||
|
||||
// come valore minimo per il bound considero quello standard di vroni
|
||||
m_nBound = max( nBound, VORONOI_STD_BOUND) ;
|
||||
|
||||
// calcolo
|
||||
m_nBound = nBound ;
|
||||
m_bVDComputed = true ;
|
||||
string sTmp = "" ;
|
||||
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
|
||||
|
||||
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -467,15 +490,24 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// verifico se necessario calcolo Voronoi
|
||||
if ( ! m_bVDComputed || nBound != m_nBound)
|
||||
CalcVoronoi( nBound) ;
|
||||
try {
|
||||
// verifico se necessario calcolo Voronoi
|
||||
if ( ! m_bVDComputed || nBound != m_nBound)
|
||||
CalcVoronoi( nBound) ;
|
||||
|
||||
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
|
||||
// recupero la curva del bisettore
|
||||
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
||||
if ( ! IsNull( pCrv) && pCrv->IsValid())
|
||||
vCrvs.emplace_back( Release( pCrv)) ;
|
||||
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
|
||||
// recupero la curva del bisettore
|
||||
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
||||
if ( ! IsNull( pCrv) && pCrv->IsValid())
|
||||
vCrvs.emplace_back( Release( pCrv)) ;
|
||||
}
|
||||
|
||||
// libero la memoria di vroni utilizzata per calcolare bisettore
|
||||
m_vroni->apiFreeBisectorBuffer() ;
|
||||
}
|
||||
catch (...) {
|
||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -489,10 +521,7 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
|
||||
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
if ( ! m_bVDComputed)
|
||||
CalcVoronoi() ;
|
||||
|
||||
|
||||
// lato per il medial axis
|
||||
bool bLeft = true ;
|
||||
bool bRight = true ;
|
||||
@@ -501,18 +530,31 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
|
||||
else if ( nSide == WMAT_RIGHT)
|
||||
bLeft = false ;
|
||||
|
||||
// calcolo medial axis
|
||||
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
|
||||
|
||||
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
|
||||
// verifico se il lato appartiene al medial axis
|
||||
if ( m_vroni->IsWMATEdge( i)) {
|
||||
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
||||
if ( ! IsNull( pCrv) && pCrv->IsValid())
|
||||
vCrvs.emplace_back( Release( pCrv)) ;
|
||||
}
|
||||
try {
|
||||
if ( ! m_bVDComputed)
|
||||
CalcVoronoi() ;
|
||||
|
||||
// calcolo medial axis
|
||||
m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ;
|
||||
|
||||
for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) {
|
||||
// verifico se il lato appartiene al medial axis
|
||||
if ( m_vroni->IsWMATEdge( i)) {
|
||||
PtrOwner<ICurve> pCrv( GetBisectorCurve( i)) ;
|
||||
if ( ! IsNull( pCrv) && pCrv->IsValid())
|
||||
vCrvs.emplace_back( Release( pCrv)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// libero la memoria di vroni utilizzata per calcolare bisettore
|
||||
m_vroni->apiFreeBisectorBuffer() ;
|
||||
}
|
||||
return true ;
|
||||
catch (...) {
|
||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -559,20 +601,21 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
|
||||
if ( pCrv->IsValid()) {
|
||||
// eventuale inversione
|
||||
if ( dOffs > EPS_SMALL)
|
||||
pCrv->Invert() ;
|
||||
|
||||
pCrv->Invert() ;
|
||||
|
||||
// sistemo i raccordi
|
||||
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
|
||||
IdentifyFillets( pCrv, dOffs) ;
|
||||
AdjustCurveFillets( pCrv, dOffs, nType) ;
|
||||
}
|
||||
|
||||
if ( bClosed) {
|
||||
// forzo chiusura della curva per evitare piccole imprecisioni
|
||||
pCrv->Close() ;
|
||||
// sistemo il punto di inizio
|
||||
AdjustOffsetStart( *pCrv) ;
|
||||
}
|
||||
|
||||
// sistemo i raccordi
|
||||
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
|
||||
IdentifyFillets( pCrv, dOffs) ;
|
||||
AdjustCurveFillets( pCrv, dOffs, nType) ;
|
||||
}
|
||||
|
||||
// porto nel frame globale
|
||||
pCrv->ToGlob( m_Frame) ;
|
||||
// unisco le parti allineate
|
||||
@@ -614,12 +657,12 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo
|
||||
|
||||
// sistemo i raccordi
|
||||
if ( bClosed && bSquareMids) {
|
||||
// se curva è chiusa tutti i raccordi rispondono a bSquareMids
|
||||
// se curva è chiusa tutti i raccordi rispondono a bSquareMids
|
||||
IdentifyFillets( pCrvOffs, dOffs) ;
|
||||
AdjustCurveFillets( pCrvOffs, dOffs, ICurve::OFF_EXTEND) ;
|
||||
}
|
||||
else if ( ! bClosed && ( bSquareMids || bSquareEnds)) {
|
||||
// se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e
|
||||
// se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e
|
||||
// modificare solo quelli richiesti
|
||||
for ( int j = 0 ; j < pCrvOffs->GetCurveCount() ; j ++) {
|
||||
int nOrigCrv ; pCrvOffs->GetCurveTempProp( j, nOrigCrv) ;
|
||||
@@ -660,75 +703,84 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs, bool bRightOff
|
||||
nOrigCrvCnt = pOrigCompo->GetCurveCount() ;
|
||||
}
|
||||
|
||||
// reset di eventuali offset precedenti
|
||||
m_vroni->apiResetOffsetData() ;
|
||||
|
||||
// verifico necessario calcolo o ricalcolo di Voronoi
|
||||
UpdateVoronoi( dOffs) ;
|
||||
|
||||
string sTmp = "" ;
|
||||
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, bLeftOffs, bRightOffs) ;
|
||||
int nOffsCnt = m_vroni->GetOffsetCount() ;
|
||||
if ( nOffsCnt == 0) {
|
||||
// se non ho ottenuto offset ritento con valore leggermente diverso per le tolleranze di vroni
|
||||
try {
|
||||
// reset di eventuali offset precedenti
|
||||
m_vroni->apiResetOffsetData() ;
|
||||
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs - VRONI_OFFS_TOL, 0.0, false, bLeftOffs, bRightOffs) ;
|
||||
nOffsCnt = m_vroni->GetOffsetCount() ;
|
||||
}
|
||||
|
||||
// recupero le curve di offset da vroni
|
||||
for ( int i = 0 ; i < nOffsCnt ; i++) {
|
||||
PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ;
|
||||
int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve
|
||||
// verifico necessario calcolo o ricalcolo di Voronoi
|
||||
UpdateVoronoi( dOffs) ;
|
||||
|
||||
for ( int j = 0 ; j < nCrvCnt ; j ++) {
|
||||
// recupero la sottocurva da vroni
|
||||
Point3d ptS, ptE, ptC ;
|
||||
int nType ;
|
||||
int nOrigCrv, nOrigLoop, nOrigPnt ; // sito
|
||||
m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ;
|
||||
|
||||
if ( j == 0)
|
||||
pCrvOffs->AddPoint( ptS) ;
|
||||
|
||||
bool bOk = false ;
|
||||
if ( nType == t_site::SEG)
|
||||
bOk = pCrvOffs->AddLine( ptE) ;
|
||||
else {
|
||||
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
|
||||
pArc->Set2PRS( ptS, ptE, Dist( ptC, ptS), nType == CCW) ;
|
||||
bOk = pCrvOffs->AddCurve( Release( pArc)) ;
|
||||
}
|
||||
|
||||
// se la curva è stata aggiunta
|
||||
if ( bOk) {
|
||||
// setto come info la sottocurva da cui si è generata
|
||||
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
|
||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
|
||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
|
||||
// verifico se è raccordo relativo agli estremi della curva
|
||||
if ( nOrigCrv == -1 && ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt))
|
||||
pCrvOffs->SetCurveTempParam( nCurrCrvId, 1.0, 0) ;
|
||||
}
|
||||
string sTmp = "" ;
|
||||
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs, 0.0, false, bLeftOffs, bRightOffs) ;
|
||||
int nOffsCnt = m_vroni->GetOffsetCount() ;
|
||||
if ( nOffsCnt == 0) {
|
||||
// se non ho ottenuto offset ritento con valore leggermente diverso per le tolleranze di vroni
|
||||
m_vroni->apiResetOffsetData() ;
|
||||
m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs - VRONI_OFFS_TOL, 0.0, false, bLeftOffs, bRightOffs) ;
|
||||
nOffsCnt = m_vroni->GetOffsetCount() ;
|
||||
}
|
||||
|
||||
// rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL
|
||||
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
|
||||
// recupero le curve di offset da vroni
|
||||
for ( int i = 0 ; i < nOffsCnt ; i++) {
|
||||
PtrOwner<CurveComposite> pCrvOffs ( CreateBasicCurveComposite()) ;
|
||||
int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve
|
||||
|
||||
// aggiungo la curva alla lista degli offset
|
||||
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid())
|
||||
OffsList.push_back( Release( pCrvOffs)) ;
|
||||
for ( int j = 0 ; j < nCrvCnt ; j ++) {
|
||||
// recupero la sottocurva da vroni
|
||||
Point3d ptS, ptE, ptC ;
|
||||
int nType ;
|
||||
int nOrigCrv, nOrigLoop, nOrigPnt ; // sito
|
||||
m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ;
|
||||
|
||||
if ( j == 0)
|
||||
pCrvOffs->AddPoint( ptS) ;
|
||||
|
||||
bool bOk = false ;
|
||||
if ( nType == t_site::SEG)
|
||||
bOk = pCrvOffs->AddLine( ptE) ;
|
||||
else {
|
||||
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
|
||||
pArc->Set2PRS( ptS, ptE, Dist( ptC, ptS), nType == CCW) ;
|
||||
bOk = pCrvOffs->AddCurve( Release( pArc)) ;
|
||||
}
|
||||
|
||||
// se la curva è stata aggiunta
|
||||
if ( bOk) {
|
||||
// setto come info la sottocurva da cui si è generata
|
||||
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
|
||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
|
||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
|
||||
// verifico se è raccordo relativo agli estremi della curva
|
||||
if ( nOrigCrv == -1 && ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt))
|
||||
pCrvOffs->SetCurveTempParam( nCurrCrvId, 1.0, 0) ;
|
||||
}
|
||||
}
|
||||
|
||||
// rimuovo tratti di lunghezza inferiore a 5 * EPS_SMALL
|
||||
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
|
||||
|
||||
// aggiungo la curva alla lista degli offset
|
||||
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid())
|
||||
OffsList.push_back( Release( pCrvOffs)) ;
|
||||
}
|
||||
|
||||
// libero la memoria di vroni dedicata agli offset
|
||||
m_vroni->apiFreeOffsetData() ;
|
||||
}
|
||||
catch (...) {
|
||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::UpdateVoronoi( double dOffs)
|
||||
{
|
||||
double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ;
|
||||
// calcolo il bound necessario per l'offset desiderato
|
||||
double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ;
|
||||
if ( ! m_bVDComputed || dNeededBound > m_nBound) {
|
||||
// aggiorno il valore del bound
|
||||
int nBound = ( int)( ceil( dNeededBound) + 0.5) ;
|
||||
@@ -737,7 +789,6 @@ Voronoi::UpdateVoronoi( double dOffs)
|
||||
}
|
||||
|
||||
return true ;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -747,7 +798,7 @@ Voronoi::VerifyCurvesValidityForOffset()
|
||||
if ( m_vpCrvs.size() == 1)
|
||||
return true ;
|
||||
|
||||
// se ho più curve, devono essere tutte chiuse
|
||||
// se ho più curve, devono essere tutte chiuse
|
||||
for ( auto pCrv : m_vpCrvs) {
|
||||
if ( ! pCrv->IsClosed())
|
||||
return false ;
|
||||
@@ -767,12 +818,29 @@ Voronoi::VerifyCurvesValidityForOffset()
|
||||
|
||||
// se curva con orientamento principale verifico sia esterna a tutte le altre curve con orientamento principale
|
||||
if ( vArea[i] * dRefArea > EPS_SMALL) {
|
||||
for ( int j = i + 1 ; j < ( int)vArea.size() ; j++) {
|
||||
if ( vArea[i] * vArea[j] > EPS_SMALL) {
|
||||
for ( int j = 0 ; j < ( int)vArea.size() ; j++) {
|
||||
if ( j != i && vArea[i] * vArea[j] > EPS_SMALL) {
|
||||
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ;
|
||||
int nRes = ccInt.GetRegionCurveClassification() ;
|
||||
if ( ( bRefCCW && nRes != CCREGC_OUT) || ( ! bRefCCW && nRes != CCREGC_IN1))
|
||||
if ( nRes == CCREGC_NULL || nRes == CCREGC_SAME || nRes == CCREGC_INTERS)
|
||||
return false ;
|
||||
if ( ( bRefCCW && nRes == CCREGC_IN1) || ( ! bRefCCW && nRes == CCREGC_IN2)) {
|
||||
// se è interna ad una curva con orientamento principale, verifico sia esterna ad almeno una curva con orientamento
|
||||
// diverso dal principale
|
||||
bool bFound = false ;
|
||||
for ( int k = 0 ; k < ( int)vArea.size() ; k++) {
|
||||
if ( k != i && vArea[i] * vArea[k] < EPS_SMALL) {
|
||||
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[k]) ;
|
||||
int nRes = ccInt.GetRegionCurveClassification() ;
|
||||
if ( ( bRefCCW && nRes == CCREGC_OUT) || ( ! bRefCCW && nRes == CCREGC_IN1)) {
|
||||
bFound = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! bFound)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -842,7 +910,7 @@ Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs)
|
||||
// mi posiziono dopo la junction
|
||||
pCompo.ChangeStartPoint( vJunctions[0] + 1) ;
|
||||
delete( pCompo.RemoveFirstOrLastCurve()) ;
|
||||
// verifico validità della curva
|
||||
// verifico validità della curva
|
||||
int nSide = GetOffsetCurveSide( pCompo, 0) ;
|
||||
if ( nSide == nSideRef) {
|
||||
// scorro fino alla prima curva non valida ed elimino la curva da quel punto fino alla fine
|
||||
@@ -853,7 +921,7 @@ Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// elimino finchè non trovo una curva valida
|
||||
// elimino finchè non trovo una curva valida
|
||||
while( nSide != nSideRef && pCompo.IsValid()) {
|
||||
delete( pCompo.RemoveFirstOrLastCurve( false)) ;
|
||||
if ( pCompo.IsValid())
|
||||
|
||||
Reference in New Issue
Block a user