Compare commits

...

55 Commits

Author SHA1 Message Date
Riccardo Elitropi 8538bc2d30 Merge commit 'e490c173e84ed5bf576888ac4bc5f023c49680f7' into VmillAdditivo 2024-04-30 08:36:48 +02:00
Daniele Bariletti e490c173e8 EgtGeomKernel :
- svincolata la funzione GetSingleEdge della SurfBezier dalla creazione della trimesh.
2024-04-29 17:46:30 +02:00
Daniele Bariletti 7e165a6dea EgtGeomKernel :
- eliminati dei memory leaks.
2024-04-29 17:40:17 +02:00
Daniele Bariletti 49ff6e79a8 EgtGeomKernel :
- correzione nella gestione della conversione delle curve/superfici NURBS.
2024-04-29 17:20:30 +02:00
Daniele Bariletti b23df89cd3 EgtGeomKernel :
- tolto header di debug.
2024-04-24 10:48:58 +02:00
Daniele Bariletti cf9737a48e Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2024-04-24 10:47:54 +02:00
Daniele Bariletti ae52115bda EgtGeomKernel :
- aggiunto il contro OFFSET alla SetTrimRegion delle Bezier
- aggiunte funzioni varie al tree delle Bezier.
2024-04-24 10:47:50 +02:00
Riccardo Elitropi c0f7eb6727 EgtGeomKernel :
- piccola correzione booleane TriMesh.
2024-04-24 09:26:51 +02:00
Riccardo Elitropi faa2004c29 EgtGeomKernel :
- integrate modifiche vMill additivo dal ramo TempForVmill.
2024-04-22 13:21:37 +02:00
Dario Sassi c9a59dc5ea Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2024-04-22 10:50:40 +02:00
Dario Sassi aaaf951990 EgtGeomKernel :
- aggiunti alcuni controlli sulla validità dei parametri in Collision Avoid.
2024-04-22 10:49:34 +02:00
Daniele Bariletti cc263089ca EgtGeomKernel :
- aggiunta gestione ulteriore delle curve nurbs periodiche da formato .stp.
2024-04-22 09:15:49 +02:00
Daniele Bariletti d99b8f4c86 EgtGeomKernel :
- correzione alla conversione di curve NURBS.
- modifica del parametro per il metodo IsPlanar di SurfBezier.
2024-04-18 11:04:34 +02:00
Daniele Bariletti f5e5441469 EgtGeomKernel :
- aggiunto il metodo IsPlanar per la SurfBezier.
2024-04-17 16:00:30 +02:00
Daniele Bariletti 4206a4822f EgtGeomKernel :
- funzione CalcPoles chiamata direttamente all'inizio della funzione Cut.
2024-04-17 15:16:23 +02:00
Daniele Bariletti 788a5bc4eb EgtGeomKernel :
- correzioni nella gestione dei trim delle superfici di Bezier.
- correzioni varie alle superfici di Bezier.
2024-04-17 14:52:07 +02:00
Riccardo Elitropi a5a96c2bb5 EgtGeomKernel :
- piccola modifica tolleranza SurfFlatRegion.
2024-04-17 12:04:23 +02:00
Riccardo Elitropi 881691e678 Merge commit '80f4d64ad4008ade24e403eeb8831609f3623459' 2024-04-17 12:02:56 +02:00
Dario Sassi 80f4d64ad4 EgtGeomKernel :
- piccola miglioria alla conversione dell'orientazione dei riferimenti in quaternioni.
2024-04-17 06:51:05 +02:00
SaraP 7d9a641e39 EgtGeomKernel :
- in GetSurfTriMeshSwept nel calcolo del piano della curva guida nel caso di una linea viene considerata l'estrusione ( come viene fatto nel calcolo degli offset).
2024-04-16 08:46:59 +02:00
Dario Sassi d82ccd8947 EgtGeomKernel 2.6d4 :
- aggiunta della classe Quaternion.
2024-04-14 18:17:41 +02:00
Dario Sassi 318b1e4b2f EgtGeomKernel :
- separata da GetAuxSurf la funzione GetApproxSurf
- piccola miglioria ad AdjustLoop.
2024-04-13 17:09:17 +02:00
Riccardo Elitropi 583e30170a EgtGeomKernel :
- ricalcolo delle facce dopo scalatura per TriMesh
- Rimozione punti allineati nei contatti tra facce diverse.
2024-04-12 15:27:52 +02:00
SaraP fe46b8ebd2 EgtGeomKernel 2.6d3 :
- in Voronoi modificata la direzione dei bisettori per averli sempre orientati dal parametro minore al maggiore.
2024-04-12 14:53:00 +02:00
Daniele Bariletti 6a845e4f81 EgtGeomKernel :
- migliorato un controllo per la SurfTmByBezier.
2024-04-12 11:52:05 +02:00
Daniele Bariletti 46e18b3977 EgtGeomKernel :
- aggiunti parametri per ottenere la trimesh di una Bezier con precisione scelta.
2024-04-11 17:38:00 +02:00
Dario Sassi 20d146268b EgtGeomKernel :
- MakeUniform e OnWhichEdge da metodi di SurfBezier a funzioni globali di SurfAux.
2024-04-11 00:17:20 +02:00
Daniele Bariletti 5013fc2b6c EgtGeomKernel :
- funzioni MakeUniform e OnWhichEdge per Bezier spostate da converter e exch3dm a metodi della classe Bezier.
2024-04-10 16:17:39 +02:00
Daniele Bariletti 32a0e1d2b5 EgtGeomKernel :
- gestiti i loop di trim di sup di Bezier che escono dal parametrico.
- corretto un errore di triangolazione per sup di Bezier.
2024-04-10 09:21:49 +02:00
Daniele Bariletti 7ce9e7e26c EgtGeomKernel :
- resa pubblica la funzione per il SubType di ExtDim.
2024-04-10 09:17:19 +02:00
Daniele Bariletti 9a6e972521 EgtGeomKernel :
- gestita la forma periodica per curve NURBS da file .stp.
- gestione di regioni di trim di cui non si riesce a fare l'intersezione col parametrico.
2024-04-10 09:16:11 +02:00
Dario Sassi 8c008f36c2 EgtGeomKernel 2.6d2 :
- proiezione curva su superficie estesa a casi con guida un punto o una superficie
- ricompilazione per modifiche a EgtLock.
2024-04-09 14:47:25 +02:00
Dario Sassi eae29d4854 EgtGeomKernel :
- aggiunta funzione ProjectCurveOnSurfTm con parametro entità guida.
2024-04-08 09:43:17 +02:00
Dario Sassi 2bd53476ca EgtGeomKernel :
- modifiche per RotationMinimizingFrame e RotationXplaneFrame
- aggiornato calcolo superfici TriMesh da Swept di curva o di regione.
2024-04-05 16:55:20 +02:00
Dario Sassi 015065f3c8 Merge remote-tracking branch 'origin/RMF' 2024-04-04 14:50:44 +02:00
Dario Sassi 12862a6c76 EgtGeomKernel 2.6d1 :
- correzione nella triangolazione (da RiccardoE).
2024-04-04 12:13:48 +02:00
Daniele Bariletti 9d869411e8 EgtGeomKernel :
- eliminato memory leak nella classe Surf Bezier.
2024-04-03 10:10:36 +02:00
Dario Sassi 0c3c17e0f4 EgtGeomKernel :
- correzione a ProjectCurveOnSurfTm per assegnazione parametro punto proiettato su curva originale.
2024-04-03 08:11:35 +02:00
Dario Sassi 47f6eedd9c EgtGeomKernel :
- piccole modifiche stilistiche.
2024-03-27 17:27:01 +01:00
Daniele Bariletti b36adefd10 EgtGeomKernel :
- tolto header per il debug.
2024-03-27 11:10:03 +01:00
Daniele Bariletti 8cf8c0def5 Merge branch 'CmdCreateSurfBezier' 2024-03-27 11:08:29 +01:00
Daniele Bariletti 1e6a70c60d EgtGeomKernel :
- gestione della convenzione C3D per le curve NURBS periodiche.
2024-03-27 10:59:40 +01:00
SaraP 9712e8c526 EgtGeomKernel 2.6c3 :
- aggiornamento versione.
2024-03-27 10:04:08 +01:00
SaraP 6b1f932dfc EgtGeomKernel :
- modifiche al calcolo fillet per gestire curve con offset complessi.
2024-03-27 09:57:22 +01:00
Dario Sassi 9653ba8d53 EgtGeomKernel :
- aggiunte funzioni di Test tra solido e superficie speculari di quelle di Collision Detection degli stessi solidi con colido.
2024-03-25 09:03:13 +01:00
Daniele Bariletti ba66891539 EgtGeomKernel :
- corretto caso non gestito nelle dimensioni angolari.
2024-03-22 17:59:40 +01:00
Riccardo Elitropi 104726c5ee EgtGeomKernel :
- migliorie varie.
2024-03-19 09:01:46 +01:00
Riccardo Elitropi e2445c0a15 EgtGeomKernel :
- modifica Swept con vettore statico.
- aggiunta Swep con FlatRegion come sezione
- migliorie varie.
2024-03-18 13:20:35 +01:00
Riccardo Elitropi 9880fa0173 EgtGeomKernel :
- migliorie varie.
2024-03-15 13:17:41 +01:00
Riccardo Elitropi d276809906 EgtGeomKernel :
- Swept con o senza caps mediante RMF
- inizio stesura codice per frame statico
- migliorie varie.
2024-03-14 13:04:09 +01:00
Riccardo Elitropi 4268da4a1f EgtGeomKernel :
- primo codice di test con Caps per funzione Swept con guida non piana.
2024-03-11 13:22:37 +01:00
Riccardo Elitropi 4f485d0e87 EgtGeomKernel :
- primo codice di prova per creazione Swept.
2024-03-07 16:53:19 +01:00
Riccardo Elitropi d48348fa1c EgtGeomKernel :
- pulizia codice.
2024-03-07 10:51:59 +01:00
Riccardo Elitropi 003dd0bdef EgtGeomKernel :
- codice di prova per RMF.
2024-03-06 16:29:36 +01:00
Riccardo Elitropi ec109908fa EgtGeomKernel :
- inizio stesura codice per Rotation Minimize Frame.
2024-03-05 16:20:28 +01:00
41 changed files with 3796 additions and 662 deletions
+6
View File
@@ -104,6 +104,9 @@ CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Ve
// Se utensile non definito, errore // Se utensile non definito, errore
if ( m_Tool.GetType() == Tool::UNDEF) if ( m_Tool.GetType() == Tool::UNDEF)
return false ; return false ;
// Se direzioni non definite, errore
if ( vtDir.IsSmall() || vtMove.IsSmall())
return false ;
// Imposto il riferimento di movimento // Imposto il riferimento di movimento
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove)) if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
m_frMove.Set( ORIG, vtMove, vtDir) ; m_frMove.Set( ORIG, vtMove, vtDir) ;
@@ -122,6 +125,9 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
// Se utensile non definito, errore // Se utensile non definito, errore
if ( m_Tool.GetType() == Tool::UNDEF) if ( m_Tool.GetType() == Tool::UNDEF)
return false ; return false ;
// Se direzioni non definite, errore
if ( vtDir.IsSmall() || vtMove.IsSmall())
return false ;
// Se lista vuota, non devo fare alcunché // Se lista vuota, non devo fare alcunché
if ( lPntM.empty()) if ( lPntM.empty())
return true ; return true ;
+39 -2
View File
@@ -1,13 +1,14 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2016-2020 // EgalTech 2016-2024
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : CDBoxSurfTm.cpp Data : 09.01.20 Versione : 2.2a2 // File : CDeBoxClosedSurfTm.cpp Data : 24.03.24 Versione : 2.6c2
// Contenuto : Implementazione della verifica di collisione tra // Contenuto : Implementazione della verifica di collisione tra
// BoundingBox e Closed SurftriMesh. // BoundingBox e Closed SurftriMesh.
// //
// //
// Modifiche : 05.10.16 DS Creazione modulo. // Modifiche : 05.10.16 DS Creazione modulo.
// 09.01.20 DS Cambio nome alla funzione. // 09.01.20 DS Cambio nome alla funzione.
// 24.03.24 DS Aggiunta TestCylSurfTm.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -66,3 +67,39 @@ CDeBoxClosedSurfTm( const Frame3d& frBox, const Vector3d& vtDiag, const ISurfTri
// Se il box è interno c'è collisione // Se il box è interno c'è collisione
return DistBoxCenSurfCalc.IsPointInside() ; return DistBoxCenSurfCalc.IsPointInside() ;
} }
//----------------------------------------------------------------------------
// Verifica l'interferenza tra il box e la superficie : restituisce true in caso di interferenza.
//----------------------------------------------------------------------------
bool
TestBoxSurfTm( 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, non ha senso proseguire
if ( ! Stm.IsValid())
return true ;
// Recupero BBox del poliedro
BBox3d b3Poly = Stm.GetAllTriaBox() ;
// Calcolo il BBox del parallelepipedo
BBox3d b3BoxL( ORIG, ORIG + vtDiag) ;
if ( dSafeDist > EPS_SMALL)
b3BoxL.Expand( dSafeDist) ;
BBox3d b3Box = GetToGlob( b3BoxL, frBox) ;
// Se i BBox non interferiscono, non c'è collisione
if ( ! b3Poly.Overlaps( b3Box) || ! b3Poly.Overlaps( frBox, b3BoxL))
return false ;
// Verifico se il parallelepipedo interferisce con i triangoli del poliedro presenti nel suo BBox
INTVECTOR vT ;
Stm.GetAllTriaOverlapBox( b3Box, vT) ;
for ( int nT : vT) {
Triangle3d Tria ;
if ( Stm.GetTriangle( nT, Tria)) {
if ( CDeBoxTria( frBox, vtDiag, Tria, dSafeDist))
return true ;
}
}
// Non c'è interferenza
return false ;
}
+89 -3
View File
@@ -1,12 +1,12 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2020-2020 // EgalTech 2020-2024
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : CDeSurfTmSurfTm.h Data : 14.06.23 Versione : 2.5f3 // File : CDeClosedSurfTmClosedSurfTm.h Data : 24.03.24 Versione : 2.6c2
// Contenuto : Implementazione funzione verifica collisione tra // Contenuto : Implementazione funzione verifica collisione tra
// SurfTm e SurfTm. // SurfTm e SurfTm.
// //
// Modifiche : 13.11.20 LM Creazione modulo. // Modifiche : 13.11.20 LM Creazione modulo.
// // 24.03.24 DS Aggiunta TestSurfTmSurfTm.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -122,3 +122,89 @@ CDeClosedSurfTmClosedSurfTm( const ISurfTriMesh& SurfA, const ISurfTriMesh& Surf
DistPointSurfTm DistPoinBSrfA( ptPointB, *pSrfA) ; DistPointSurfTm DistPoinBSrfA( ptPointB, *pSrfA) ;
return ( DistPoinASrfB.IsPointInside() || DistPoinBSrfA.IsPointInside()) ; return ( DistPoinASrfB.IsPointInside() || DistPoinBSrfA.IsPointInside()) ;
} }
//----------------------------------------------------------------------------
// Verifica l'interferenza tra le due superfici : restituisce true in caso di interferenza.
//----------------------------------------------------------------------------
bool
TestSurfTmSurfTm( 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, non ha senso proseguire
if ( pSrfA == nullptr || ! pSrfA->IsValid() ||
pSrfB == nullptr || ! pSrfB->IsValid())
return true ;
// Se i box delle superfici non si intersecano, ho finito.
BBox3d b3BoxA, b3BoxB ;
pSrfA->GetLocalBBox( b3BoxA) ;
pSrfB->GetLocalBBox( b3BoxB) ;
// Se è necessario, espando il box di B di una costante additiva pari alla distanza di sicurezza.
if ( dSafeDist > EPS_SMALL)
b3BoxB.Expand( dSafeDist) ;
// Se i box non si sovrappongono, non c'è collisione. Ho finito.
if ( ! b3BoxA.Overlaps( b3BoxB))
return false ;
// Recupero i triangoli di A che interferiscono col box di B
INTVECTOR vTriaIndex ;
pSrfA->GetAllTriaOverlapBox( b3BoxB, vTriaIndex) ;
// Ciclo sui triangoli della superficie A che interferiscono col box della superficie B.
for ( int nTA : vTriaIndex) {
Triangle3d trTriaA ;
if ( ! ( pSrfA->GetTriangle( nTA, trTriaA) && trTriaA.Validate()))
continue ;
BBox3d b3BoxTriaA ;
trTriaA.GetLocalBBox( b3BoxTriaA) ;
// Se è necessario, espando il box di una costante additiva pari alla distanza di sicurezza.
if ( dSafeDist > EPS_SMALL)
b3BoxTriaA.Expand( dSafeDist) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ;
pSrfB->GetAllTriaOverlapBox( b3BoxTriaA, vNearTria) ;
// Settare tutti i triangoli come già processati.
// Al termine della chiamata i TempInt dei triangoli valgono 0.
pSrfB->ResetTempInts() ;
// Ciclo sui triangoli della superficie B che cadono nel box del triangolo corrente della Superficie A.
for ( int nTB : vNearTria) {
// Recupero il triangolo corrente della superficie B.
// Se triangolo non valido salto al successivo.
Triangle3d trTriaB ;
if ( ! ( pSrfB->GetTriangle( nTB, trTriaB) && trTriaB.Validate()))
continue ;
// Se necessario considero l'offset
if ( dSafeDist > EPS_SMALL) {
int nAdjTriaId[3] ;
pSrfB->GetTriangleAdjacencies( nTB, nAdjTriaId) ;
// Ciclo sui vertici del triangolo.
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
// Se il triangolo adiacente al triangolo corrente su questo edge
// non è stato processato, processo il vertice e l'edge.
int nAdjTriaTempFlag ;
if ( ! ( pSrfB->GetTempInt( nAdjTriaId[nVB], nAdjTriaTempFlag) || nAdjTriaTempFlag == 0))
continue ;
// Processo il vertice: se c'è collisione fra triangolo A e sfera ho finito.
if ( CDeSimpleSpheTria( trTriaB.GetP( nVB), dSafeDist, trTriaA))
return true ;
// Processo l'edge: se c'è collisione fra triangolo A e cilindro ho finito.
Vector3d vtEdgeV = trTriaB.GetP( ( nVB + 1) % 3) - trTriaB.GetP( nVB) ;
double dEdgeLen = vtEdgeV.Len() ;
vtEdgeV /= dEdgeLen ;
Frame3d frCyl ;
frCyl.Set( trTriaB.GetP( nVB), vtEdgeV) ;
if ( CDeSimpleCylTria( frCyl, dSafeDist, dEdgeLen, trTriaA))
return true ;
}
// Traslo il triangolo
trTriaB.Translate( dSafeDist * trTriaB.GetN()) ;
}
// Processo il triangolo: se i due triangoli collidono ho finito.
if ( CDeTriaTria( trTriaA, trTriaB))
return true ;
// Segno il triangolo come processato: nTemp = 1
pSrfB->SetTempInt( nTB, 1) ;
}
}
// Non c'è interferenza
return false ;
}
+43 -2
View File
@@ -1,12 +1,13 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2020-2020 // EgalTech 2020-2024
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : CDCylSurfTm.cpp Data : 09.11.20 Versione : // File : CDeConeFrustumClosedSurfTm.cpp Data : 24.031.24 Versione : 2.6c2
// Contenuto : Implementazione della verifica di collisione tra // Contenuto : Implementazione della verifica di collisione tra
// Cone e Closed SurftriMesh. // Cone e Closed SurftriMesh.
// //
// //
// Modifiche : 09.11.20 LM Creazione modulo. // Modifiche : 09.11.20 LM Creazione modulo.
// 24.03.24 DS Aggiunta TestConeFrustumSurfTm.
// //
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -70,3 +71,43 @@ CDeConeFrustumClosedSurfTm( const Frame3d& frCone, double dBaseRad, double dTopR
// Se il tronco di cono è interno c'è collisione // Se il tronco di cono è interno c'è collisione
return DistConeCenSurfCalc.IsPointInside() ; return DistConeCenSurfCalc.IsPointInside() ;
} }
//----------------------------------------------------------------------------
// Verifica l'interferenza tra il tronco di cono e la superficie : restituisce true in caso di interferenza.
//----------------------------------------------------------------------------
bool
TestConeFrustumSurfTm( const Frame3d& frCone, double dBaseRad, double dTopRad, double dHeight,
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 true ;
// Se superficie non valida, non ha senso proseguire
if ( ! Stm.IsValid())
return true ;
// Recupero BBox della trimesh
BBox3d b3Surf = Stm.GetAllTriaBox() ;
// Calcolo il BBox del tronco di cono
double dMaxRad = max( dBaseRad, dTopRad) ;
BBox3d b3ConeL( Point3d( -dMaxRad, -dMaxRad, 0),
Point3d( dMaxRad, dMaxRad, dHeight)) ;
if ( dSafeDist > EPS_SMALL)
b3ConeL.Expand( dSafeDist) ;
BBox3d b3Cone = GetToGlob( b3ConeL, frCone) ;
// Se i BBox non interferiscono, non c'è collisione
if ( ! b3Surf.Overlaps( b3Cone) || ! b3Surf.Overlaps( frCone, b3ConeL))
return false ;
// Recupero i triangoli che interferiscono con il box del cono
INTVECTOR vT ;
Stm.GetAllTriaOverlapBox( b3Cone, vT) ;
// Verifico se il tronco di cono interferisce con i triangoli del poliedro presenti nel suo BBox
for ( int nT : vT) {
Triangle3d trTria ;
if ( Stm.GetTriangle( nT, trTria)) {
if ( CDeConeFrustumTria( frCone, dBaseRad, dTopRad, dHeight, trTria, dSafeDist))
return true ;
}
}
// Non c'è interferenza
return false ;
}
+1 -1
View File
@@ -1,7 +1,7 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2020-2020 // EgalTech 2020-2020
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : CDeConTria.cpp Data : 28.10.20 Versione : 2.2k1 // File : CDeConeFrustumTria.h Data : 28.10.20 Versione : 2.2k1
// Contenuto : Dichiarazione della verifica di collisione tra // Contenuto : Dichiarazione della verifica di collisione tra
// Cone e Triangle3d. // Cone e Triangle3d.
// //
+42 -3
View File
@@ -1,12 +1,12 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2020-2020 // EgalTech 2020-2024
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : CDeConvexTorusTria.cpp Data : 18.11.20 Versione : // File : CDeConvexTorusTria.cpp Data : 24.03.24 Versione : 2.6c2
// Contenuto : Implementazione funzione verifica collisione tra // Contenuto : Implementazione funzione verifica collisione tra
// toro convesso e SurfTriMesh. // toro convesso e SurfTriMesh.
// //
// Modifiche : 18.11.20 LM Creazione modulo. // Modifiche : 18.11.20 LM Creazione modulo.
// // 24.03.24 DS Aggiunta TestConvexTorusSurfTm.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -66,3 +66,42 @@ CDeConvexTorusClosedSurfTm( const Frame3d& frTorus, double dRad1, double dRad2,
// Se il toro è interno c'è collisione // Se il toro è interno c'è collisione
return ( DistConeOrigSurfCalc.IsPointInside()) ; return ( DistConeOrigSurfCalc.IsPointInside()) ;
} }
//----------------------------------------------------------------------------
// Verifica l'interferenza tra il toro convesso e la superficie : restituisce true in caso di interferenza
//----------------------------------------------------------------------------
bool
TestConvexTorusSurfTm( const Frame3d& frTorus, double dRad1, double dRad2,
const ISurfTriMesh& Stm, double dSafeDist)
{
// I raggi devono essere non nulli
if ( dRad1 < EPS_SMALL || dRad2 < EPS_SMALL)
return true ;
// Se superficie non valida, non ha senso proseguire
if ( ! Stm.IsValid())
return true ;
// Box della superficie
BBox3d b3Surf = Stm.GetAllTriaBox() ;
// Box del toro (sempre completo)
BBox3d b3TorusL( Point3d( -dRad1 - dRad2, -dRad1 - dRad2, -dRad2),
Point3d( dRad1 + dRad2, dRad1 + dRad2, dRad2)) ;
if ( dSafeDist > EPS_SMALL)
b3TorusL.Expand( dSafeDist) ;
BBox3d b3Torus = GetToGlob( b3TorusL, frTorus) ;
// Se i BBox non interferiscono, non c'è collisione
if ( ! b3Surf.Overlaps( b3Torus) || ! b3Surf.Overlaps( frTorus, b3TorusL))
return false ;
// Recupero i triangoli che interferiscono con il box del toro
INTVECTOR vT ;
Stm.GetAllTriaOverlapBox( b3Torus, vT) ;
// Verifico se il toro interferisce con i triangoli del poliedro presenti nel suo BBox
for ( int nT : vT) {
Triangle3d trTria ;
if ( Stm.GetTriangle( nT, trTria)) {
if ( CDeConvexTorusTria( frTorus, dRad1, dRad2, CT_TOT, trTria, dSafeDist))
return true ;
}
}
// Non c'è interferenza
return false ;
}
+45 -2
View File
@@ -1,13 +1,13 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2020-2024 // EgalTech 2020-2024
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : CDCylSurfTm.cpp Data : 15.02.24 Versione : 2.6b2 // File : CDeCylClosedSurfTm.cpp Data : 24.03.24 Versione : 2.6c2
// Contenuto : Implementazione della verifica di collisione tra // Contenuto : Implementazione della verifica di collisione tra
// Cylinder e Closed SurftriMesh. // Cylinder e Closed SurftriMesh.
// //
// //
// Modifiche : 09.01.20 DS Creazione modulo. // Modifiche : 09.01.20 DS Creazione modulo.
// // 24.03.24 DS Aggiunta TestCylSurfTm.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -73,3 +73,46 @@ CDeCylClosedSurfTm( const Frame3d& frCyl, double dR, double dH, const ISurfTriMe
// Se il cilindro è interno c'è collisione // Se il cilindro è interno c'è collisione
return ( DistCylCenSurfCalc.IsPointInside()) ; return ( DistCylCenSurfCalc.IsPointInside()) ;
} }
//----------------------------------------------------------------------------
// Verifica l'interferenza tra il cilindro e la superficie : restituisce true in caso di interferenza
//----------------------------------------------------------------------------
bool
TestCylSurfTm( 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, non ha senso proseguire
if ( ! Stm.IsValid())
return true ;
// Recupero BBox della superficie poligonale
BBox3d b3Poly = Stm.GetAllTriaBox() ;
// Sistemazioni cilindro
Frame3d frMyCyl = frCyl ;
if ( dH < 0) {
frMyCyl.Translate( dH * frMyCyl.VersZ()) ;
dH = -dH ;
}
// Calcolo il BBox del cilindro
BBox3d b3CylL( Point3d( -dR, -dR, 0),
Point3d( dR, dR, dH)) ;
if ( dSafeDist > EPS_SMALL)
b3CylL.Expand( dSafeDist) ;
BBox3d b3Cyl = GetToGlob( b3CylL, frMyCyl) ;
// Se i BBox non interferiscono, non c'è interferenza
if ( ! b3Poly.Overlaps( b3Cyl) || ! b3Poly.Overlaps( frMyCyl, b3CylL))
return false ;
// Verifico se il cilindro interferisce con i triangoli del poliedro presenti nel suo BBox
INTVECTOR vT ;
Stm.GetAllTriaOverlapBox( b3Cyl, vT) ;
for ( int nT : vT) {
Triangle3d Tria ;
if ( Stm.GetTriangle( nT, Tria)) {
if ( CDeCylTria( frMyCyl, dR, dH, Tria, dSafeDist))
return true ;
}
}
// Non c'è interferenza
return false ;
}
+48 -3
View File
@@ -1,12 +1,12 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2020-2020 // EgalTech 2020-2024
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : CDePyramidClosedSurfTm.h Data : 09.11.20 Versione : // File : CDeRectPrismoidClosedSurfTm.h Data : 24.03.24 Versione : 2.6c2
// Contenuto : Implementazione funzione verifica collisione tra // Contenuto : Implementazione funzione verifica collisione tra
// Prismoide a basi rettangolari e Closed SurfTriMesh. // Prismoide a basi rettangolari e Closed SurfTriMesh.
// //
// Modifiche : 09.11.20 LM Creazione modulo. // Modifiche : 09.11.20 LM Creazione modulo.
// // 24.03.24 DS Aggiunta TestRectPrismoidSurfTm.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -74,3 +74,48 @@ CDeRectPrismoidClosedSurfTm( const Frame3d& frPrismoid, double dLenghtBaseX, dou
// C'è collisione se il tronco di piramide è interno // C'è collisione se il tronco di piramide è interno
return ( DistPyrCenSurfCalc.IsPointInside()) ; return ( DistPyrCenSurfCalc.IsPointInside()) ;
} }
//----------------------------------------------------------------------------
// Verifica l'interferenza tra il Prismoide a basi rettangolari e la superficie : restituisce true in caso di interferenza.
//----------------------------------------------------------------------------
bool
TestRectPrismoidSurfTm( const Frame3d& frPrismoid, double dLenghtBaseX, double dLenghtBaseY,
double dLenghtTopX, double dLenghtTopY, double dHeight,
const ISurfTriMesh& Stm, double dSafeDist)
{
// 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)
return true ;
// Se superficie non valida, non ha senso proseguire
if ( ! Stm.IsValid())
return true ;
// Recupero BBox della trimesh
BBox3d b3Surf = Stm.GetAllTriaBox() ;
// Calcolo il BBox del tronco di piramide
double dMaxLenX = max( dLenghtBaseX, dLenghtTopX) ;
double dMaxLenY = max( dLenghtBaseY, dLenghtTopY) ;
BBox3d b3PyrL( Point3d( -dMaxLenX / 2, -dMaxLenY / 2, 0.),
Point3d( dMaxLenX / 2, dMaxLenY / 2, dHeight)) ;
if ( dSafeDist > EPS_SMALL)
b3PyrL.Expand( dSafeDist) ;
BBox3d b3Pyr = GetToGlob( b3PyrL, frPrismoid) ;
// Se i BBox non interferiscono, non c'è collisione
if ( ! b3Surf.Overlaps( b3Pyr) || ! b3Surf.Overlaps( frPrismoid, b3PyrL))
return false ;
// Recupero i triangoli che interferiscono con il box del tronco di piramide.
INTVECTOR vT ;
Stm.GetAllTriaOverlapBox( b3Pyr, vT) ;
// Verifico se il tronco di piramide interferisce con i triangoli del poliedro presenti nel suo BBox
for ( int nT : vT) {
Triangle3d trTria ;
if ( Stm.GetTriangle( nT, trTria)) {
if ( CDeRectPrismoidTria( frPrismoid, dLenghtBaseX, dLenghtBaseY, dLenghtTopX, dLenghtTopY, dHeight,
trTria, dSafeDist))
return true ;
}
}
// Non c'è interferenza
return false ;
}
+38 -3
View File
@@ -1,13 +1,13 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2020-2020 // EgalTech 2020-2024
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : CDCylSurfTm.cpp Data : 09.01.20 Versione : 2.2a2 // File : CDCylSurfTm.cpp Data : 24.03.24 Versione : 2.6c2
// Contenuto : Implementazione della verifica di collisione tra // Contenuto : Implementazione della verifica di collisione tra
// Sphere e Closed SurftriMesh. // Sphere e Closed SurftriMesh.
// //
// //
// Modifiche : 09.01.20 DS Creazione modulo. // Modifiche : 09.01.20 DS Creazione modulo.
// // 24.03.24 DS Aggiunta TestSpheSurfTm.
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -60,3 +60,38 @@ CDeSpheClosedSurfTm( const Point3d& ptCen, double dR, const ISurfTriMesh& Stm, d
// C'è collisione se la sfera è interna. // C'è collisione se la sfera è interna.
return ( DistCenSurfCalc.IsPointInside()) ; return ( DistCenSurfCalc.IsPointInside()) ;
} }
//----------------------------------------------------------------------------
// Verifica l'interferenza tra la sfera e la superficie : restituisce true in caso di interferenza
//----------------------------------------------------------------------------
bool
TestSpheSurfTm( 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, non ha senso proseguire
if ( ! Stm.IsValid())
return true ;
// Recupero BBox del poliedro
BBox3d b3Poly = Stm.GetAllTriaBox() ;
// Calcolo il BBox della sfera
BBox3d b3Sphe( ptCen, dR) ;
if ( dSafeDist > EPS_SMALL)
b3Sphe.Expand( dSafeDist) ;
// Se i BBox non interferiscono, non c'è collisione
if ( ! b3Sphe.Overlaps( b3Poly))
return false ;
// Verifico se la sfera interferisce con i triangoli del poliedro presenti nel suo BBox
INTVECTOR vT ;
Stm.GetAllTriaOverlapBox( b3Sphe, vT) ;
for ( int nT : vT) {
Triangle3d Tria ;
if ( Stm.GetTriangle( nT, Tria)) {
if ( CDeSpheTria( ptCen, dR, Tria, dSafeDist))
return true ;
}
}
// Non c'è interferenza
return false ;
}
+75
View File
@@ -524,6 +524,81 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// se periodica // se periodica
if ( cnData.bPeriodic || ! cnData.bClamped) { if ( cnData.bPeriodic || ! cnData.bClamped) {
// se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva
// wrap della curva su se stessa
if ( cnData.bPeriodic ) {
bool bRepetead = true ;
for ( int i = 0 ; i < cnData.nDeg ; ++i) {
if ( ! AreSamePointApprox( cnData.vCP[i], cnData.vCP.end()[-cnData.nDeg + i]) ) {
bRepetead = false ;
break ;
}
}
if ( ! bRepetead){
// salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped
DBLVECTOR vU = cnData.vU ;
// se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo
if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back()) ) {
cnData.vCP.push_back( cnData.vCP[0]) ;
if ( cnData.bRat)
cnData.vW.push_back( cnData.vW[0]) ;
}
// se effettivamente ho dei nodi in più da togliere allora li tolgo
if ( int( cnData.vU.size()) != int(cnData.vCP.size()) + cnData.nDeg - 1) {
// devo poi anche togliere i nodi di troppo // presuppongo che la convenzione sia che i nodi di troppo sono alla fine del vettore dei nodi
cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ;
// controllo eventualmente anche i nodi extra
// se ne ho due in più ne tolgo uno in cima e uno in fondo
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
// se ne ho solo uno in più lo tolgo in cima
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg)
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
}
// controllo se il vettore dei nodi ha la giusta molteplicità all'inizio e alla fine, sennò ha comunque bisogno di essere resa non periodica
double dU0 = cnData.vU[0] ;
double dULast = cnData.vU.back() ;
bool bSame = true ;
for ( int i = 1 ; i < cnData.nDeg ; ++i ) {
bSame = bSame && abs(cnData.vU[i] - dU0) < EPS_SMALL ;
bSame = bSame && abs(cnData.vU.end()[-( i+ 1)] - dULast) < EPS_SMALL ;
}
if ( bSame) {
cnData.bPeriodic = false ;
return true ;
}
else {
// aggiungo i punti ripetuti ( il primo l'ho già aggiunto)
for ( int i = 1 ; i < cnData.nDeg ; ++i ) {
cnData.vCP.push_back( cnData.vCP[i]) ;
if ( cnData.bRat)
cnData.vW.push_back( cnData.vW[i]) ;
}
// recupero il vettore dei nodi
cnData.vU = vU ;
// verifico se ho nodi extra
// se ne ho due in più ne tolgo uno in cima e uno in fondo
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
// se ne ho solo uno in più lo tolgo in cima
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg)
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
}
}
}
// qui aggiungo un controllo se la curva è collassata in un punto ( ho un polo), lascio stare
bool bCollapsed = true ;
Point3d ptFirst = cnData.vCP.front() ;
for( int i = 1 ; i < int( cnData.vCP.size()) ; ++i) {
if ( ! AreSamePointApprox( ptFirst, cnData.vCP[i])) {
bCollapsed = false ;
break ;
}
}
if ( bCollapsed)
return false ;
// va trasformata in non-periodica (clamped) // va trasformata in non-periodica (clamped)
// bisogna aumentare la molteplicità dei nodi u_p-1 e u_(m-p+1) fino ad arrivare al grado della nurbs // bisogna aumentare la molteplicità dei nodi u_p-1 e u_(m-p+1) fino ad arrivare al grado della nurbs
// e poi scartare nodi e punti fuori dalla regione clamped ( al di fuori della regione u_p-1 -> u_(m-p+1)) // e poi scartare nodi e punti fuori dalla regione clamped ( al di fuori della regione u_p-1 -> u_(m-p+1))
BIN
View File
Binary file not shown.
+6 -1
View File
@@ -319,6 +319,9 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="IntersPlaneVolZmap.cpp" /> <ClCompile Include="IntersPlaneVolZmap.cpp" />
<ClCompile Include="IntersLineSurfBez.cpp" /> <ClCompile Include="IntersLineSurfBez.cpp" />
<ClCompile Include="PolygonElevation.cpp" /> <ClCompile Include="PolygonElevation.cpp" />
<ClCompile Include="Quaternion.cpp" />
<ClCompile Include="RotationMinimizingFrame.cpp" />
<ClCompile Include="RotationXplaneFrame.cpp" />
<ClCompile Include="SbzStandard.cpp" /> <ClCompile Include="SbzStandard.cpp" />
<ClCompile Include="Voronoi.cpp" /> <ClCompile Include="Voronoi.cpp" />
<ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" /> <ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" />
@@ -331,6 +334,9 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EGkIntersPlaneBox.h" /> <ClInclude Include="..\Include\EGkIntersPlaneBox.h" />
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h" /> <ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h" />
<ClInclude Include="..\Include\EGkPolygonElevation.h" /> <ClInclude Include="..\Include\EGkPolygonElevation.h" />
<ClInclude Include="..\Include\EGkQuaternion.h" />
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h" />
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" /> <ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
<ClInclude Include="CDeBoxTria.h" /> <ClInclude Include="CDeBoxTria.h" />
<ClInclude Include="CDeCapsTria.h" /> <ClInclude Include="CDeCapsTria.h" />
@@ -462,7 +468,6 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="VolZmapGraphics.cpp" /> <ClCompile Include="VolZmapGraphics.cpp" />
<ClCompile Include="VolZmapVolume.cpp" /> <ClCompile Include="VolZmapVolume.cpp" />
<ClCompile Include="VolZmap.cpp" /> <ClCompile Include="VolZmap.cpp" />
<ClInclude Include="IntersLineSurfBez.h" />
<ClInclude Include="Voronoi.h" /> <ClInclude Include="Voronoi.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+18
View File
@@ -528,6 +528,15 @@
<ClCompile Include="SbzStandard.cpp"> <ClCompile Include="SbzStandard.cpp">
<Filter>File di origine\GeoCreate</Filter> <Filter>File di origine\GeoCreate</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="RotationMinimizingFrame.cpp">
<Filter>File di origine\Base</Filter>
</ClCompile>
<ClCompile Include="RotationXplaneFrame.cpp">
<Filter>File di origine\Base</Filter>
</ClCompile>
<ClCompile Include="Quaternion.cpp">
<Filter>File di origine\Base</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="stdafx.h"> <ClInclude Include="stdafx.h">
@@ -1196,6 +1205,15 @@
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h"> <ClInclude Include="..\Include\EGkIntersLineVolZmap.h">
<Filter>File di intestazione\Include</Filter> <Filter>File di intestazione\Include</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkQuaternion.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc"> <ResourceCompile Include="EgtGeomKernel.rc">
+18 -2
View File
@@ -28,6 +28,7 @@
#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EGkCurve.h" #include "/EgtDev/Include/EGkCurve.h"
#include <new> #include <new>
#include <algorithm>
using namespace std ; using namespace std ;
@@ -319,8 +320,23 @@ ExtDimension::SetAngularEx( const Point3d& ptV1, const Point3d& ptP1,
dLenDir = m_vtDir.Len() ; dLenDir = m_vtDir.Len() ;
} }
// assegno gli altri punti notevoli della quotatura // assegno gli altri punti notevoli della quotatura
m_ptP1 = ptV1 - ( ptV1 - m_ptP6) * m_vtN * m_vtN ; // se i ptV concidono con l'intersezione tra le linee le sposto leggermente verso l'altro punto di quel lato
m_ptP2 = ptV2 - ( ptV2 - m_ptP6) * m_vtN * m_vtN ; Point3d ptV1New = ptV1 ;
Point3d ptV2New = ptV2 ;
if ( AreSamePointApprox( ptV1, ptV)) {
Vector3d vtDir1 ; Line1.GetStartDir( vtDir1) ;
double dLen ; Line1.GetLength( dLen) ;
dLen = max( min( 1., dLen/ 10), 0.01) ;
ptV1New = ptV1 + vtDir1 * dLen ;
}
if ( AreSamePointApprox( ptV2, ptV)) {
Vector3d vtDir2 ; Line2.GetStartDir( vtDir2) ;
double dLen ; Line2.GetLength( dLen) ;
dLen = max( min( 1., dLen/ 10), 0.01) ;
ptV2New = ptV2 + vtDir2 * dLen ;
}
m_ptP1 = ptV1New - ( ptV1New - m_ptP6) * m_vtN * m_vtN ;
m_ptP2 = ptV2New - ( ptV2New - m_ptP6) * m_vtN * m_vtN ;
m_ptP5 = m_ptP6 + vtLine1 * dLenDir ; m_ptP5 = m_ptP6 + vtLine1 * dLenDir ;
double dLen1 = Dist( m_ptP6, m_ptP1) ; double dLen1 = Dist( m_ptP6, m_ptP1) ;
m_ptP3 = m_ptP6 + vtLine1 * ( dLenDir + m_dExtLineLen * ( dLen1 < dLenDir ? 1 : -1)) ; m_ptP3 = m_ptP6 + vtLine1 * ( dLenDir + m_dExtLineLen * ( dLen1 < dLenDir ? 1 : -1)) ;
+1 -1
View File
@@ -108,6 +108,7 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
{ return m_dTextHeight ; } { return m_dTextHeight ; }
bool GetMidPoint( Point3d& ptMid) const override ; bool GetMidPoint( Point3d& ptMid) const override ;
bool GetCenterPoint( Point3d& ptCen) const override ; bool GetCenterPoint( Point3d& ptCen) const override ;
const std::string& GetSubType( void) const override ;
bool ApproxWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST& lstPL) const override ; bool ApproxWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST& lstPL) const override ;
public : // IGeoObjRW public : // IGeoObjRW
@@ -130,7 +131,6 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
private : private :
bool CopyFrom( const ExtDimension& gpSrc) ; bool CopyFrom( const ExtDimension& gpSrc) ;
const std::string& GetSubType( void) const ;
bool Update( void) const ; bool Update( void) const ;
double GetTextHalfDist( const Point3d& ptText, bool bUseRot = true) const ; double GetTextHalfDist( const Point3d& ptText, bool bUseRot = true) const ;
bool GetArrowHead( const Point3d& ptTip, const Vector3d& vtDir, PolyLine& PL) const ; bool GetArrowHead( const Point3d& ptTip, const Vector3d& vtDir, PolyLine& PL) const ;
+48 -12
View File
@@ -18,6 +18,7 @@
#include "/EgtDev/Include/EGkFilletChamfer.h" #include "/EgtDev/Include/EGkFilletChamfer.h"
#include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkIntersCurves.h" #include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EgkOffsetCurve.h"
#include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ; using namespace std ;
@@ -40,13 +41,21 @@ CalcForFillet( const ICurve& cCrv1, const Point3d& ptNear1,
if ( ! dPC1.GetSideAtMinDistPoint( 0, vtNorm, nSide1)) if ( ! dPC1.GetSideAtMinDistPoint( 0, vtNorm, nSide1))
return false ; return false ;
double dOffs1 = ( nSide1 == MDS_RIGHT ? dRadius : - dRadius) ; double dOffs1 = ( nSide1 == MDS_RIGHT ? dRadius : - dRadius) ;
// calcolo l'offset nel piano locale e dal lato opportuno di una copia della curva 1 // calcolo gli offset nel piano locale e dal lato opportuno di una copia della curva 1
PtrOwner<ICurve> pCopy1( cCrv1.Clone()) ; PtrOwner<ICurve> pCopy1( cCrv1.Clone()) ;
if ( IsNull( pCopy1)) if ( IsNull( pCopy1))
return false ; return false ;
pCopy1->ToLoc( frIntr) ; pCopy1->ToLoc( frIntr) ;
pCopy1->SetExtrusion( Z_AX) ; pCopy1->SetExtrusion( Z_AX) ;
if ( ! pCopy1->SimpleOffset( dOffs1, ICurve::OFF_FILLET)) OffsetCurve OffsCrv1 ;
OffsCrv1.Make( pCopy1, dOffs1, ICurve::OFF_FILLET) ;
ICURVEPOVECTOR vOffs1 ;
ICurve* pCrv = OffsCrv1.GetLongerCurve() ;
while ( pCrv != nullptr) {
vOffs1.emplace_back( pCrv) ;
pCrv = OffsCrv1.GetLongerCurve() ;
}
if ( vOffs1.empty())
return false ; return false ;
// determino il lato di offset della curva 2 // determino il lato di offset della curva 2
@@ -54,23 +63,50 @@ CalcForFillet( const ICurve& cCrv1, const Point3d& ptNear1,
if ( ! dPC2.GetSideAtMinDistPoint( 0, vtNorm, nSide2)) if ( ! dPC2.GetSideAtMinDistPoint( 0, vtNorm, nSide2))
return false ; return false ;
double dOffs2 = ( nSide2 == MDS_RIGHT ? dRadius : - dRadius) ; double dOffs2 = ( nSide2 == MDS_RIGHT ? dRadius : - dRadius) ;
// calcolo l'offset nel piano locale e dal lato opportuno di una copia della curva 2 // calcolo gli offset nel piano locale e dal lato opportuno di una copia della curva 2
PtrOwner<ICurve> pCopy2( cCrv2.Clone()) ; PtrOwner<ICurve> pCopy2( cCrv2.Clone()) ;
if ( IsNull( pCopy2)) if ( IsNull( pCopy2))
return false ; return false ;
pCopy2->ToLoc( frIntr) ; pCopy2->ToLoc( frIntr) ;
pCopy2->SetExtrusion( Z_AX) ; pCopy2->SetExtrusion( Z_AX) ;
if ( ! pCopy2->SimpleOffset( dOffs2, ICurve::OFF_FILLET)) OffsetCurve OffsCrv2 ;
OffsCrv2.Make( pCopy2, dOffs2, ICurve::OFF_FILLET) ;
ICURVEPOVECTOR vOffs2 ;
pCrv = OffsCrv2.GetLongerCurve() ;
while ( pCrv != nullptr) {
vOffs2.emplace_back( pCrv) ;
pCrv = OffsCrv2.GetLongerCurve() ;
}
if ( vOffs2.empty())
return false ; return false ;
// calcolo l'intersezione tra le due curve // calcolo le intersezioni tra tutte le curve di offset e seleziono quella più vicina ai punti passati
Point3d ptInt1, ptInt2 ; Point3d ptInt1 = P_INVALID, ptInt2 = P_INVALID ;
Point3d ptNearI = Media( ptNear1, ptNear2) ; Point3d ptNearI = Media( ptNear1, ptNear2) ;
ptNearI.ToLoc( frIntr) ; ptNearI.ToLoc( frIntr) ;
IntersCurveCurve intCC( *pCopy1, *pCopy2) ; double dMinDist = INFINITO ;
if ( ! intCC.GetIntersPointNearTo( 0, ptNearI, ptInt1) || for ( int i = 0 ; i < int( vOffs1.size()) ; i++) {
! intCC.GetIntersPointNearTo( 1, ptNearI, ptInt2)) for ( int j = 0 ; j < int( vOffs2.size()) ; j ++) {
IntersCurveCurve intCC( *vOffs1[i], *vOffs2[j]) ;
if ( intCC.GetIntersCount() == 0)
continue ;
Point3d ptInt1Curr, ptInt2Curr ;
if ( ! intCC.GetIntersPointNearTo( 0, ptNearI, ptInt1Curr) ||
! intCC.GetIntersPointNearTo( 1, ptNearI, ptInt2Curr))
return false ;
Point3d ptCenCurr = Media( ptInt1Curr, ptInt2Curr) ;
double dDist = Dist( ptNearI, ptCenCurr) ;
if ( dDist < dMinDist - EPS_SMALL) {
dMinDist = dDist ;
ptInt1 = ptInt1Curr ;
ptInt2 = ptInt2Curr ;
}
}
}
// se non sono state trovate intersezioni esco
if ( ! ptInt1.IsValid() || ! ptInt2.IsValid())
return false ; return false ;
ptInt1.ToGlob( frIntr) ; ptInt1.ToGlob( frIntr) ;
ptInt2.ToGlob( frIntr) ; ptInt2.ToGlob( frIntr) ;
ptCen = Media( ptInt1, ptInt2) ; ptCen = Media( ptInt1, ptInt2) ;
@@ -105,7 +141,7 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
const ICurve& cCrv2, const Point3d& ptNear2, const ICurve& cCrv2, const Point3d& ptNear2,
const Vector3d& vtNorm, double dRadius, double& dPar1, double& dPar2) const Vector3d& vtNorm, double dRadius, double& dPar1, double& dPar2)
{ {
// verifico validità parametri ricevuti // verifico validità parametri ricevuti
if ( &cCrv1 == nullptr || &ptNear1 == nullptr || if ( &cCrv1 == nullptr || &ptNear1 == nullptr ||
&cCrv2 == nullptr || &ptNear2 == nullptr || &cCrv2 == nullptr || &ptNear2 == nullptr ||
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr) &vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
@@ -119,7 +155,7 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
ptCen, ptTg1, ptTg2, nSide1, nSide2, dSinA, dTgPar1, dTgPar2)) ptCen, ptTg1, ptTg2, nSide1, nSide2, dSinA, dTgPar1, dTgPar2))
return nullptr ; return nullptr ;
// se tangenti parallele al contatto con fillet, ricalcolo con raggio più piccolo // se tangenti parallele al contatto con fillet, ricalcolo con raggio più piccolo
bool bParallel = ( abs( dSinA) < EPS_SMALL) ; bool bParallel = ( abs( dSinA) < EPS_SMALL) ;
if ( bParallel) { if ( bParallel) {
Point3d ptQQQ, ptQQ1, ptQQ2 ; Point3d ptQQQ, ptQQ1, ptQQ2 ;
@@ -165,7 +201,7 @@ CreateChamfer( const ICurve& cCrv1, const Point3d& ptNear1,
const ICurve& cCrv2, const Point3d& ptNear2, const ICurve& cCrv2, const Point3d& ptNear2,
const Vector3d& vtNorm, double dDist, double& dPar1, double& dPar2) const Vector3d& vtNorm, double dDist, double& dPar1, double& dPar2)
{ {
// verifico validità parametri ricevuti // verifico validità parametri ricevuti
if ( &cCrv1 == nullptr || &ptNear1 == nullptr || if ( &cCrv1 == nullptr || &ptNear1 == nullptr ||
&cCrv2 == nullptr || &ptNear2 == nullptr || &cCrv2 == nullptr || &ptNear2 == nullptr ||
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr) &vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
+15 -41
View File
@@ -22,13 +22,14 @@
using namespace std ; using namespace std ;
//---------------------- //----------------------------------------------------------------------------
bool static bool
RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool bFinite, RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool bFinite,
const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz) { const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz)
// la funzione raffina la posisione del punto ptSP, minimizzando la distanza dalla retta e restituisce il punto di intersezione ptIBz {
// la funzione raffina la posisione del punto ptSP, minimizzando la distanza dalla retta e restituisce il punto di intersezione ptIBz
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ; pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
// usando un algoritmo di newton cerco di avvicinarmi il più possibile alla retta // usando un algoritmo di newton cerco di avvicinarmi il più possibile alla retta
DistPointLine dpl( ptIBz, ptL, vtL, dLen, bFinite) ; DistPointLine dpl( ptIBz, ptL, vtL, dLen, bFinite) ;
double dDistNew = 0, dDistPre = 0 ; double dDistNew = 0, dDistPre = 0 ;
dpl.GetDist(dDistNew) ; dpl.GetDist(dDistNew) ;
@@ -36,8 +37,8 @@ RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool b
int nCount = 0 ; int nCount = 0 ;
double dh = EPS_SMALL ; double dh = EPS_SMALL ;
pSurfBz->GetPointD1D2( ptSP.x, ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ; pSurfBz->GetPointD1D2( ptSP.x, ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
// metodo di newton in più dimensioni // metodo di newton in più dimensioni
// vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi. // vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi.
while ( dDistNew > EPS_SMALL && nCount < 100) { while ( dDistNew > EPS_SMALL && nCount < 100) {
dDistPre = dDistNew ; dDistPre = dDistNew ;
Point3d ptIBzNew1 ; Point3d ptIBzNew1 ;
@@ -50,48 +51,21 @@ RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool b
DistPointLine dplNewV( ptIBzNew2, ptL, vtL, dLen, bFinite) ; DistPointLine dplNewV( ptIBzNew2, ptL, vtL, dLen, bFinite) ;
dplNewV.GetDist( dDistNew) ; dplNewV.GetDist( dDistNew) ;
double dfdV = ( dDistNew - dDistPre) / dh ; double dfdV = ( dDistNew - dDistPre) / dh ;
//// opzione 0 // mi avvicino cercando di annullare la distanza in un colpo solo
////scelgo h1 e h2 separatamente e in modo da annullare f(x)
//// opzione 1
//// valore fisso
//double dr = EPS_SMALL ;
//if ( dDistPre > 1)
// dr = 1 ;
//else if ( dDistPre > 0.1)
// dr = 0.1 ;
//else if ( dDistPre > 0.01)
// dr = 0.01 ;
//// opzione 2
//// valore direttamente vincolato
//double dr = dDistPre ;
//// opzione 3
//// valuto la deformazione locale in base allo spostamento del punto sulla bezier // non serve
//double dh1 = Dist( ptIBz, ptIBzNew1) ;
//double dh2 = Dist( ptIBz, ptIBzNew2) ;
// potrei valutare il nuovo spostamento in base all'ultima variazione di dDist
// potrei anche vedere se sto uscendo dal triangolo ( definito nello spazio parametrico)
// mi avvicino cercando di annullare la distanza in un colpo solo
double dr = - dDistPre / ( dfdU + dfdV) ; double dr = - dDistPre / ( dfdU + dfdV) ;
pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptSP.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ; pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptSP.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
DistPointLine dplNew( ptIBz, ptL, vtL, dLen, bFinite) ; DistPointLine dplNew( ptIBz, ptL, vtL, dLen, bFinite) ;
dplNew.GetDist( dDistNew) ; dplNew.GetDist( dDistNew) ;
++nCount ; ++ nCount ;
} }
return nCount != 99 ; return ( nCount != 99) ;
} }
////----------------------------------------------------------------------------
//bool
//RefineIntersBisec( const Point3d& ptL, const Vector3d& vtL, double dLen, bool bFinite,
// const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz) {
//
//}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void static void
UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos, UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos,
const Point3d& ptSP2, const Point3d& ptIBz2, double dCos2, ILSBIVECTOR& vInfo) const Point3d& ptSP2, const Point3d& ptIBz2, double dCos2, ILSBIVECTOR& vInfo)
{ {
if ( nILT == ILTT_IN || nILT == ILTT_EDGE || nILT == ILTT_VERT) { if ( nILT == ILTT_IN || nILT == ILTT_EDGE || nILT == ILTT_VERT) {
double dU = ( ptIBz - ptL) * vtDir ; double dU = ( ptIBz - ptL) * vtDir ;
@@ -105,7 +79,7 @@ UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void static void
OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo) OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
{ {
// se non trovati, esco // se non trovati, esco
@@ -120,7 +94,7 @@ OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Intersezione di una linea con una superficie TriMesh // Intersezione di una linea con una superficie di Bezier
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz, IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
-1
View File
@@ -1 +0,0 @@
#pragma once
+307 -56
View File
@@ -15,6 +15,8 @@
#include "stdafx.h" #include "stdafx.h"
#include "DistPointLine.h" #include "DistPointLine.h"
#include "GeoConst.h" #include "GeoConst.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkProjectCurveSurfTm.h" #include "/EgtDev/Include/EGkProjectCurveSurfTm.h"
@@ -33,63 +35,9 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool static bool
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen, RemovePointsInExcess( PNT5AXVECTOR& vMyPt5ax, 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 = min( dMaxSegmLen, 1.) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie
Frame3d frRefLine ;
if ( ! frRefLine.Set( ORIG, vtDir))
return false ;
IntersParLinesSurfTm intPLSTM( frRefLine, tmSurf) ;
// Vettore locale dei punti risultanti
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie
double dU ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dU, &ptP) ;
while ( bFound) {
Point3d ptL = GetToLoc( ptP, frRefLine) ;
ILSIVECTOR vIntRes ;
intPLSTM.GetInters( ptL, 1, vIntRes, false) ;
if ( vIntRes.size() > 0) {
// calcolo il punto
int nI = int( vIntRes.size()) - 1 ;
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
return false ;
Vector3d vtN ;
double dU, dV, dW ;
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
if ( ! vtN.Normalize())
vtN = trTria.GetN() ;
// aggiungo al vettore dei proiettati
vMyPt5ax.emplace_back( ptInt, vtN, dU, 1) ;
}
bFound = PL.GetNextUPoint( &dU, &ptP) ;
}
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo // rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ; double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ;
double dSqTol = dLinTol * dLinTol ; double dSqTol = dLinTol * dLinTol ;
@@ -130,6 +78,309 @@ ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vec
++ nNext ; ++ nNext ;
} }
} }
return true ;
}
//----------------------------------------------------------------------------
bool
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 = min( dMaxSegmLen, 1.) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Oggetto per calcolo massivo intersezioni tra linee di proiezione e superficie
Frame3d frRefLine ;
if ( ! frRefLine.Set( ORIG, vtDir))
return false ;
IntersParLinesSurfTm intPLSTM( frRefLine, tmSurf) ;
// Vettore locale dei punti risultanti
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
Point3d ptL = GetToLoc( ptP, frRefLine) ;
ILSIVECTOR vIntRes ;
intPLSTM.GetInters( ptL, 1, vIntRes, false) ;
if ( ! vIntRes.empty()) {
// calcolo il punto
int nI = int( vIntRes.size()) - 1 ;
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
return false ;
Vector3d vtN ;
double dU, dV, dW ;
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
if ( ! vtN.Normalize())
vtN = trTria.GetN() ;
// aggiungo al vettore dei proiettati
vMyPt5ax.emplace_back( ptInt, vtN, dPar, 1) ;
}
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
// copio i punti rimasti nel vettore di ritorno
vPt5ax.clear() ;
for ( const auto& Pt5ax : vMyPt5ax) {
if ( Pt5ax.nFlag != -1)
vPt5ax.emplace_back( Pt5ax) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const IGeoPoint3d& gpRef,
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 = min( dMaxSegmLen, 1.) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Vettore locale dei punti risultanti
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione data dal punto di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// punto di riferimento
Point3d ptMin = gpRef.GetPoint() ;
// intersezione della retta di minima distanza con la superficie
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ;
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
if ( vIntRes.size() > 0) {
// calcolo il punto
int nI = int( vIntRes.size()) - 1 ;
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
return false ;
Vector3d vtN ;
double dU, dV, dW ;
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
if ( ! vtN.Normalize())
vtN = trTria.GetN() ;
// aggiungo al vettore dei proiettati
vMyPt5ax.emplace_back( ptInt, vtN, vtLine, dPar, 1) ;
}
}
}
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
// copio i punti rimasti nel vettore di ritorno
vPt5ax.clear() ;
for ( const auto& Pt5ax : vMyPt5ax) {
if ( Pt5ax.nFlag != -1)
vPt5ax.emplace_back( Pt5ax) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ICurve& crRef,
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 = min( dMaxSegmLen, 1.) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Vettore locale dei punti risultanti
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// punto sulla curva a minima distanza
DistPointCurve dPC( ptP, crRef) ;
Point3d ptMin ;
int nFlag ;
if ( dPC.GetMinDistPoint( 0, ptMin, nFlag)) {
// intersezione della retta di minima distanza con la superficie
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ;
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
if ( vIntRes.size() > 0) {
// calcolo il punto
int nI = int( vIntRes.size()) - 1 ;
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
return false ;
Vector3d vtN ;
double dU, dV, dW ;
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
if ( ! vtN.Normalize())
vtN = trTria.GetN() ;
// aggiungo al vettore dei proiettati
vMyPt5ax.emplace_back( ptInt, vtN, vtLine, dPar, 1) ;
}
}
}
}
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
// copio i punti rimasti nel vettore di ritorno
vPt5ax.clear() ;
for ( const auto& Pt5ax : vMyPt5ax) {
if ( Pt5ax.nFlag != -1)
vPt5ax.emplace_back( Pt5ax) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const ISurfTriMesh& tmRef,
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 = min( dMaxSegmLen, 1.) ;
if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN))
return false ;
// Vettore locale dei punti risultanti
PNT5AXVECTOR vMyPt5ax ;
vMyPt5ax.reserve( PL.GetPointNbr()) ;
// proietto i punti della polilinea sulla superficie con direzione normale alla curva di riferimento
double dPar ;
Point3d ptP ;
bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ;
while ( bFound) {
// punto sulla superficie guida a minima distanza
DistPointSurfTm dPS( ptP, tmRef) ;
Point3d ptMin ;
int nTriaMin ;
if ( dPS.GetMinDistPoint( ptMin) && dPS.GetMinDistTriaIndex ( nTriaMin)) {
// intersezione della retta di minima distanza con la superficie
Vector3d vtLine = ptP - ptMin ;
double dLineLen = vtLine.Len() ;
if ( dLineLen > EPS_SMALL) {
vtLine /= dLineLen ;
ILSIVECTOR vIntRes ;
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, tmSurf, vIntRes, false)) {
if ( vIntRes.size() > 0) {
// calcolo il punto
int nI = int( vIntRes.size()) - 1 ;
Point3d ptInt ;
if ( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE)
ptInt = vIntRes[nI].ptI2 ;
else
ptInt = vIntRes[nI].ptI ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! tmSurf.GetTriangle( vIntRes[nI].nT, trTria))
return false ;
Vector3d vtN ;
double dU, dV, dW ;
if ( BarycentricCoord( ptInt, trTria, dU, dV, dW))
vtN = dU * trTria.GetVertexNorm( 0) + dV * trTria.GetVertexNorm( 1) + dW * trTria.GetVertexNorm( 2) ;
if ( ! vtN.Normalize())
vtN = trTria.GetN() ;
// calcolo la normale della superficie guida
Triangle3dEx trGuide ;
if ( ! tmRef.GetTriangle( nTriaMin, trGuide))
return false ;
Vector3d vtN2 ;
double dU2, dV2, dW2 ;
if ( BarycentricCoord( ptMin, trGuide, dU2, dV2, dW2))
vtN2 = dU2 * trGuide.GetVertexNorm( 0) + dV2 * trGuide.GetVertexNorm( 1) + dW2 * trGuide.GetVertexNorm( 2) ;
if ( ! vtN2.Normalize())
vtN2 = trGuide.GetN() ;
// aggiungo al vettore dei proiettati
vMyPt5ax.emplace_back( ptInt, vtN, vtN2, dPar, 1) ;
}
}
}
}
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
}
// rimuovo i punti allineati entro la tolleranza e non più lontani tra loro del massimo
RemovePointsInExcess( vMyPt5ax, dLinTol, dMaxSegmLen) ;
// copio i punti rimasti nel vettore di ritorno // copio i punti rimasti nel vettore di ritorno
vPt5ax.clear() ; vPt5ax.clear() ;
+158
View File
@@ -0,0 +1,158 @@
//----------------------------------------------------------------------------
// EgalTech 2024-2024
//----------------------------------------------------------------------------
// File : Quaternion.cpp Data : 13.04.24 Versione : 2.6d4
// Contenuto : Funzioni della classe Quaternion.
//
//
//
// Modifiche : 13.04.24 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "\EgtDev\Include\EGkQuaternion.h"
//----------------------------------------------------------------------------
// Lunghezza o Modulo
//----------------------------------------------------------------------------
double
Quaternion::Len( void) const
{
if ( abs( x) < EPS_ZERO && abs( y) < EPS_ZERO && abs( z) < EPS_ZERO)
return abs( w) ;
if ( abs( w) < EPS_ZERO && abs( y) < EPS_ZERO && abs( z) < EPS_ZERO)
return abs( x) ;
if ( abs( w) < EPS_ZERO && abs( z) < EPS_ZERO && abs( x) < EPS_ZERO)
return abs( y) ;
if ( abs( w) < EPS_ZERO && abs( x) < EPS_ZERO && abs( y) < EPS_ZERO)
return abs( z) ;
return sqrt( w * w + x * x + y * y + z * z) ;
}
//----------------------------------------------------------------------------
// Normalizzazione
//----------------------------------------------------------------------------
bool
Quaternion::Normalize( double dEps)
{
// se già normalizzato, ok
double dSqLen = w * w + x * x + y * y + z * z ;
if ( abs( 1.0 - dSqLen) < ( 2 * 1000 * DBL_EPSILON))
return true ;
// se troppo piccolo, errore
if ( dSqLen < ( dEps * dEps))
return false ;
// eseguo la normalizzazione
double dLen = sqrt( dSqLen) ;
*this /= dLen ;
return true ;
}
//----------------------------------------------------------------------------
Quaternion
FromAxisAngle( const Vector3d& vtAx, double dAngDeg)
{
if ( abs( dAngDeg) < EPS_ANG_ZERO)
return Q_UNIT ;
double dLen = vtAx.Len() ;
if ( dLen < EPS_ZERO)
return Q_NULL ;
double dDenom = 1 / dLen ;
double dHCos = cos( dAngDeg / 2 * DEGTORAD) ;
double dHSin = sin( dAngDeg / 2 * DEGTORAD) ;
return Quaternion( dHCos, dHSin * vtAx.x * dDenom, dHSin * vtAx.y * dDenom, dHSin * vtAx.z * dDenom) ;
}
//----------------------------------------------------------------------------
bool
ToAxisAngle( const Quaternion& qtQ, Vector3d& vtAx, double& dAngDeg)
{
if ( ! qtQ.IsNormalized())
return false ;
if ( qtQ.IsUnit() || (-qtQ).IsUnit()) {
dAngDeg = 0 ;
vtAx = Z_AX ;
}
else {
dAngDeg = 2 * acos( qtQ.w) * RADTODEG ;
double dDenom = 1 / sqrt( 1 - qtQ.w * qtQ.w) ;
vtAx.x = qtQ.x * dDenom ;
vtAx.y = qtQ.y * dDenom ;
vtAx.z = qtQ.z * dDenom ;
}
return true ;
}
//----------------------------------------------------------------------------
Quaternion
FromFrame( const Frame3d& frRef)
{
// verifico il riferimento
if ( ! frRef.IsValid())
return Q_NULL ;
// eseguo il calcolo
Quaternion qtQ ;
// traccia della matrice di rotazione
double dTr = frRef.VersX().x + frRef.VersY().y + frRef.VersZ().z ;
// se traccia positiva o nulla
if ( dTr > - 10 * EPS_ZERO) {
double dS = sqrt( 1 + dTr) ;
qtQ.w = dS / 2 ;
dS = 1 / ( 2 * dS) ;
qtQ.x = ( frRef.VersY().z - frRef.VersZ().y) * dS ;
qtQ.y = ( frRef.VersZ().x - frRef.VersX().z) * dS ;
qtQ.z = ( frRef.VersX().y - frRef.VersY().x) * dS ;
}
// altrimenti traccia negativa
else {
if ( frRef.VersX().x > frRef.VersY().y - 10 * EPS_ZERO && frRef.VersX().x > frRef.VersZ().z - 10 * EPS_ZERO) {
double dS = sqrt( 1 + frRef.VersX().x - ( frRef.VersY().y + frRef.VersZ().z)) ;
qtQ.x = dS / 2 ;
dS = 1 / ( 2 * dS) ;
qtQ.y = ( frRef.VersY().x + frRef.VersX().y) * dS ;
qtQ.z = ( frRef.VersX().z + frRef.VersZ().x) * dS ;
qtQ.w = ( frRef.VersY().z - frRef.VersZ().y) * dS ;
}
else if ( frRef.VersY().y > frRef.VersZ().z - 10 * EPS_ZERO && frRef.VersY().y > frRef.VersX().x - 10 * EPS_ZERO) {
double dS = sqrt( 1 + frRef.VersY().y - ( frRef.VersZ().z + frRef.VersX().x)) ;
qtQ.y = dS / 2 ;
dS = 1 / ( 2 * dS) ;
qtQ.z = ( frRef.VersZ().y + frRef.VersY().z) * dS ;
qtQ.x = ( frRef.VersY().x + frRef.VersX().y) * dS ;
qtQ.w = ( frRef.VersZ().x - frRef.VersX().z) * dS ;
}
else {
double dS = sqrt( 1 + frRef.VersZ().z - ( frRef.VersX().x + frRef.VersY().y)) ;
qtQ.z = dS / 2 ;
dS = 1 / ( 2 * dS) ;
qtQ.x = ( frRef.VersX().z + frRef.VersZ().x) * dS ;
qtQ.y = ( frRef.VersZ().y + frRef.VersY().z) * dS ;
qtQ.w = ( frRef.VersX().y - frRef.VersY().x) * dS ;
}
}
return qtQ ;
}
//----------------------------------------------------------------------------
bool
ToFrame( const Quaternion& qtQ, Frame3d& frRef)
{
double dNrm = qtQ.Len() ;
double dS = ( dNrm > EPS_ZERO ? 2 / dNrm : 0) ;
double dXs = qtQ.x * dS, dYs = qtQ.y * dS, dZs = qtQ.z * dS ;
double dWx = qtQ.w * dXs, dWy = qtQ.w * dYs, dWz = qtQ.w * dZs ;
double dXx = qtQ.x * dXs, dXy = qtQ.x * dYs, dXz = qtQ.x * dZs ;
double dYy = qtQ.y * dYs, dYz = qtQ.y * dZs, dZz = qtQ.z * dZs ;
Vector3d vtX( 1 - ( dYy + dZz), dXy + dWz, dXz - dWy) ;
Vector3d vtY( dXy - dWz, 1 - ( dXx + dZz), dYz + dWx) ;
Vector3d vtZ( dXz + dWy, dYz - dWx, 1 - ( dXx + dYy)) ;
return frRef.Set( ORIG, vtX, vtY, vtZ) ;
}
+231
View File
@@ -0,0 +1,231 @@
//----------------------------------------------------------------------------
// EgalTech 2024-2024
//----------------------------------------------------------------------------
// File : RotationMinimizingFrame.cpp Data : 05.03.24 Versione : 2.6d1
// Contenuto : Classe per RotationMinimizeFrame
//
//
//
// Modifiche : 05.03.24 RE Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
using namespace std ;
//----------------------------------------------------------------------------
bool
RotationMinimizingFrame::Set( const ICurve* pCrv, const Frame3d& fr_Start)
{
// pulisco
Clear() ;
// verifico i parametri
if ( pCrv == nullptr || ! pCrv->IsValid() ||
! fr_Start.IsValid())
return false ;
// assegno i parametri
m_pCrv = pCrv->Clone() ;
m_Frame0 = fr_Start ;
return true ;
}
//----------------------------------------------------------------------------
bool
RotationMinimizingFrame::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
RotationMinimizingFrame::IsValid( void)
{
// 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
RotationMinimizingFrame::GetFrameAtParam( const Frame3d& frAct, const double dParNext, 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 ( ptCurr, [ vtCurrR, vtCurrS, vtCurrT])
Point3d ptCurr = frAct.Orig() ;
Vector3d vtCurrR = frAct.VersX() ;
Vector3d vtCurrT = frAct.VersZ() ;
// punto i-esimo sulla curva e suo vettore tangente
Point3d ptNext ;
Vector3d vtNextT ;
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNext, &vtNextT) ||
! vtNextT.Normalize())
return false ;
// controllo per casi degeneri
if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste il piano R1
abs( ( ptNext - ptCurr) * ( vtNextT + vtCurrT)) < 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 = vtCurrR - ( 2 / dPar1) * ( vR1_norm * vtCurrR) * vR1_norm ;
Vector3d vt_t_L = vtCurrT - ( 2 / dPar1) * ( vR1_norm * vtCurrT) * vR1_norm ;
// ricavo il vettore di riflessione rispetto al piano R1
Vector3d vR2_norm = vtNextT - 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 ;
// imposto il nuovo frame
return frNext.Set( ptNext, vtNextT, vt_r_next) ;
}
//----------------------------------------------------------------------------
bool
RotationMinimizingFrame::GetFramesByStep( double dStep, bool bUniform, FRAME3DVECTOR& vRMFrames)
{
// controllo validità
if ( ! IsValid())
return false ;
// controllo sullo step
dStep = max( 10 * EPS_SMALL, dStep) ;
// lunghezza della curva
double dCrvLen = 0. ;
if ( ! m_pCrv->GetLength( dCrvLen) || dCrvLen < 10 * EPS_SMALL)
return false ;
// ricavo il numero degli step
int nStep = int( ceil( dCrvLen / dStep)) ;
double dMyStep = ( bUniform ? dCrvLen / nStep : dStep) ;
// inserisco il frame iniziale nel vettore dei riferimenti
vRMFrames.clear() ;
vRMFrames.reserve( nStep + 1) ;
vRMFrames.push_back( m_Frame0) ;
// ciclo sugli step in cui la curva è suddivisa
for ( int i = 1 ; i <= nStep ; ++ i) {
// ricavo il parametro della curva allo step i-esimo
double dParNext ;
if ( ! m_pCrv->GetParamAtLength( min( i * dMyStep, dCrvLen - EPS_SMALL), dParNext))
return false ;
// ricavo il frame alla posizione calcolata
Frame3d frNext ;
if ( ! GetFrameAtParam( vRMFrames[i-1], dParNext, frNext))
return false ;
// inserisco nuovo frame nel vettore dei riferimenti
vRMFrames.push_back( frNext) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
RotationMinimizingFrame::GetFramesBySplit( int nIntervals, FRAME3DVECTOR& vRMFrames)
{
// controllo validità
if ( ! IsValid())
return false ;
// controllo sul numero di intervalli
nIntervals = max( 1, nIntervals) ;
// ricavo lo step
double dLen = 0 ;
if ( ! m_pCrv->GetLength( dLen))
return false ;
double dStep = dLen / nIntervals ;
return GetFramesByStep( dStep, true, vRMFrames) ;
}
//----------------------------------------------------------------------------
bool
RotationMinimizingFrame::GetFramesByTolerance( double dTol, FRAME3DVECTOR& vRMFrames)
{
// controllo validità
if ( ! IsValid())
return false ;
// controllo sulla tolleranza
dTol = max( EPS_SMALL, dTol) ;
// 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 ;
int nStep = PL.GetLineNbr() ;
// inserisco il frame iniziale nel vettore dei riferimenti
vRMFrames.clear() ;
vRMFrames.reserve( nStep + 1) ;
vRMFrames.push_back( m_Frame0) ;
// eseguo il calcolo dei frame su ogni punto ricavato dall'approssimazione
Point3d ptCurr ;
PL.GetFirstPoint( ptCurr) ;
double dParNext ;
Point3d ptNext ;
while ( PL.GetNextUPoint( &dParNext, &ptNext)) {
// ricavo il Frame associato a questa posizione
Frame3d frNext ;
if ( ! GetFrameAtParam( vRMFrames.back(), dParNext, frNext))
return false ;
vRMFrames.emplace_back( frNext) ;
}
return true ;
}
+223
View File
@@ -0,0 +1,223 @@
//----------------------------------------------------------------------------
// EgalTech 2024-2024
//----------------------------------------------------------------------------
// File : RotationXplaneFrame.cpp Data : 05.04.24 Versione : 2.6d1
// Contenuto : Classe per RotationXplaneFrame.
//
//
//
// Modifiche : 05.04.24 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkRotationXplaneFrame.h"
using namespace std ;
//----------------------------------------------------------------------------
bool
RotationXplaneFrame::Set( const ICurve* pCrv, const Vector3d& vtNorm, const Vector3d& vtNearX)
{
// pulisco
Clear() ;
// verifico i parametri
if ( pCrv == nullptr || ! pCrv->IsValid() ||
! vtNorm.IsValid() || vtNorm.IsSmall() || ! vtNearX.IsValid())
return false ;
// assegno i parametri
m_pCrv = pCrv->Clone() ;
m_vtNorm = vtNorm ;
m_vtNearX = vtNearX ;
return true ;
}
//----------------------------------------------------------------------------
bool
RotationXplaneFrame::Clear( void)
{
// pulizia della curva
if ( m_pCrv != nullptr)
delete m_pCrv ;
m_pCrv = nullptr ;
// reset dei vettori
m_vtNorm = V_NULL ;
m_vtNearX = V_NULL ;
return true ;
}
//----------------------------------------------------------------------------
bool
RotationXplaneFrame::IsValid( void)
{
// controllo validità della curva
if ( m_pCrv == nullptr || ! m_pCrv->IsValid())
return false ;
// controllo della normale al piano
if ( m_vtNorm.IsSmall())
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
RotationXplaneFrame::GetFrameAtParam( const Frame3d& frAct, const double dParNext, Frame3d& frNext)
{
// verifico il riferimento corrente
if ( ! frAct.IsValid())
return false ;
// recupero punto e tangente nel nuovo punto
Point3d ptNext ;
Vector3d vtNext ;
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNext, &vtNext) ||
! vtNext.Normalize())
return false ;
// calcolo il nuovo riferimento
Vector3d vtAxX = m_vtNorm ^ vtNext ;
if ( vtAxX.IsSmall())
vtAxX = frAct.VersX() ;
else if ( vtAxX * frAct.VersX() < 0)
vtAxX.Invert() ;
// lo imposto
return frNext.Set( ptNext, vtNext, vtAxX) ;
}
//----------------------------------------------------------------------------
bool
RotationXplaneFrame::GetFramesByStep( double dStep, bool bUniform, FRAME3DVECTOR& vRXFrames)
{
// controllo validità
if ( ! IsValid())
return false ;
// controllo sullo step
dStep = max( 10 * EPS_SMALL, dStep) ;
// lunghezza della curva
double dCrvLen = 0. ;
if ( ! m_pCrv->GetLength( dCrvLen) || dCrvLen < 10 * EPS_SMALL)
return false ;
// numero e lunghezza effettiva di ogni step
int nStep = int( ceil( dCrvLen / dStep)) ;
double dMyStep = ( bUniform ? dCrvLen / nStep : dStep) ;
// calcolo il riferimento iniziale
Point3d ptStart ; m_pCrv->GetStartPoint( ptStart) ;
Vector3d vtStart ; m_pCrv->GetStartDir( vtStart) ;
Vector3d vtAxX = m_vtNorm ^ vtStart ;
if ( vtAxX.IsSmall()) {
vtAxX = OrthoCompo( m_vtNearX, m_vtNorm) ;
if ( vtAxX.IsSmall()) {
vtAxX = FromUprightOrtho( m_vtNorm) ;
vtAxX.Rotate( m_vtNorm, 0, 1) ;
}
}
Frame3d frStart ;
if ( ! frStart.Set( ptStart, vtStart, vtAxX))
return false ;
// inserisco questo frame nel vettore dei riferimenti
vRXFrames.clear() ;
vRXFrames.reserve( nStep + 1) ;
vRXFrames.push_back( frStart) ;
// ciclo sugli step in cui la curva è suddivisa
for ( int i = 1 ; i <= nStep ; ++ i) {
// ricavo il parametro della curva allo step i-esimo
double dParNext ;
if ( ! m_pCrv->GetParamAtLength( min( i * dMyStep, dCrvLen - EPS_SMALL), dParNext))
return false ;
// ricavo il frame alla posizione calcolata
Frame3d frNext ;
if ( ! GetFrameAtParam( vRXFrames[i-1], dParNext, frNext))
return false ;
// inserisco nuovo frame nel vettore dei riferimenti
vRXFrames.push_back( frNext) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
RotationXplaneFrame::GetFramesBySplit( int nIntervals, FRAME3DVECTOR& vRXFrames)
{
// controllo validità
if ( ! IsValid())
return false ;
// controllo sul numero di intervalli
nIntervals = max( 1, nIntervals) ;
// ricavo lo step
double dLen = 0 ;
if ( ! m_pCrv->GetLength( dLen))
return false ;
double dStep = dLen / nIntervals ;
return GetFramesByStep( dStep, true, vRXFrames) ;
}
//----------------------------------------------------------------------------
bool
RotationXplaneFrame::GetFramesByTolerance( double dTol, FRAME3DVECTOR& vRXFrames)
{
// controllo validità
if ( ! IsValid())
return false ;
// controllo sulla tolleranza
dTol = max( EPS_SMALL, dTol) ;
// 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 ;
int nStep = PL.GetLineNbr() ;
// calcolo il riferimento iniziale
Point3d ptStart ; m_pCrv->GetStartPoint( ptStart) ;
Vector3d vtStart ; m_pCrv->GetStartDir( vtStart) ;
Vector3d vtAxX = m_vtNorm ^ vtStart ;
if ( vtAxX.IsSmall()) {
vtAxX = OrthoCompo( m_vtNearX, m_vtNorm) ;
if ( vtAxX.IsSmall()) {
vtAxX = FromUprightOrtho( m_vtNorm) ;
vtAxX.Rotate( m_vtNorm, 0, 1) ;
}
}
Frame3d frStart ;
if ( ! frStart.Set( ptStart, vtStart, vtAxX))
return false ;
// inserisco questo frame nel vettore dei riferimenti
vRXFrames.clear() ;
vRXFrames.reserve( nStep + 1) ;
vRXFrames.push_back( frStart) ;
// eseguo il calcolo dei frame sui punti della polyline approssimante
Point3d ptCurr ;
PL.GetFirstPoint( ptCurr) ;
double dParNext ;
Point3d ptNext ;
while ( PL.GetNextUPoint( &dParNext, &ptNext)) {
// ricavo il Frame associato a questa posizione
Frame3d frNext ;
if ( ! GetFrameAtParam( vRXFrames.back(), dParNext, frNext))
return false ;
vRXFrames.emplace_back( frNext) ;
}
return true ;
}
+293 -46
View File
@@ -1,4 +1,4 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2015-2015 // EgalTech 2015-2015
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : StmFromCurves.cpp Data : 01.02.15 Versione : 1.6b1 // File : StmFromCurves.cpp Data : 01.02.15 Versione : 1.6b1
@@ -19,14 +19,15 @@
#include "CurveComposite.h" #include "CurveComposite.h"
#include "SurfTriMesh.h" #include "SurfTriMesh.h"
#include "Voronoi.h" #include "Voronoi.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EGkOffsetCurve.h" #include "/EgtDev/Include/EGkOffsetCurve.h"
#include "/EgtDev/Include/EGkStmFromCurves.h" #include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h" #include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
#include "/EgtDev/Include/EGkRotationXplaneFrame.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EgtPointerOwner.h"
#include <algorithm>
#include <thread>
#include <future> #include <future>
#include <EgtDev/Include/EGkIntersCurves.h>
using namespace std ; using namespace std ;
@@ -110,9 +111,9 @@ GetSurfTriMeshByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr,
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ; PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByExtrusion( PL, vtExtr)) if ( IsNull( pSTM) || ! pSTM->CreateByExtrusion( PL, vtExtr))
return nullptr ; return nullptr ;
// se da fare, metto i tappi sulle estremità // se da fare, metto i tappi sulle estremità
if ( bDoCapEnds) { if ( bDoCapEnds) {
// creo la prima superficie di estremità // creo la prima superficie di estremità
SurfTriMesh STM1 ; SurfTriMesh STM1 ;
if ( ! STM1.CreateByFlatContour( PL)) if ( ! STM1.CreateByFlatContour( PL))
return nullptr ; return nullptr ;
@@ -156,7 +157,7 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) for ( int i = 0 ; i < int( vPL.size()) ; ++ i)
vPL[i].Invert() ; vPL[i].Invert() ;
} }
// creo la prima superficie di estremità // creo la prima superficie di estremità
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ; PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL)) if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
return nullptr ; return nullptr ;
@@ -288,7 +289,7 @@ GetSurfTriMeshByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vecto
return nullptr ; return nullptr ;
// se richiesti caps // se richiesti caps
if ( bCapEnds) { if ( bCapEnds) {
// determino se la sezione è chiusa e piatta // determino se la sezione è chiusa e piatta
Plane3d plPlane ; double dArea ; Plane3d plPlane ; double dArea ;
bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ; bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ;
// determino non sia una semplice rivoluzione // determino non sia una semplice rivoluzione
@@ -332,7 +333,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
return nullptr ; return nullptr ;
Vector3d vtNorm = plGuide.GetVersN() ; Vector3d vtNorm = plGuide.GetVersN() ;
// determino se la guida è chiusa // determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ; bool bGuideClosed = pGuide->IsClosed() ;
// curve di offset // curve di offset
OffsetCurve OffsCrvR ; OffsetCurve OffsCrvR ;
@@ -373,7 +374,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
pSTM->SetSmoothAngle( 20) ; pSTM->SetSmoothAngle( 20) ;
// se guida aperta e tappi piatti // se guida aperta e tappi piatti
if ( ! bGuideClosed && nCapType == RSCAP_FLAT) { 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 ; POLYLINEVECTOR vPL ;
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
return nullptr ; return nullptr ;
@@ -452,7 +453,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
Point3d ptCen ; Point3d ptCen ;
pGuide->GetStartPoint( ptCen) ; pGuide->GetStartPoint( ptCen) ;
ptCen -= dDimV / 2 * vtNorm ; ptCen -= dDimV / 2 * vtNorm ;
// determino se la guida è chiusa // determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ; bool bGuideClosed = pGuide->IsClosed() ;
// curve di offset // curve di offset
const int NUM_OFFS = 4 ; const int NUM_OFFS = 4 ;
@@ -475,7 +476,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
} }
} }
else { 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) for ( int i = 0 ; i < NUM_OFFS && bOk ; ++ i)
bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ; bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ;
} }
@@ -552,7 +553,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
StmFromTriangleSoup stmCapSoup ; StmFromTriangleSoup stmCapSoup ;
if ( ! stmCapSoup.Start( nBuckets)) if ( ! stmCapSoup.Start( nBuckets))
return nullptr ; return nullptr ;
// verifico che le due estremità siano chiuse e piatte // verifico che le due estremità siano chiuse e piatte
POLYLINEVECTOR vPL ; POLYLINEVECTOR vPL ;
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
return nullptr ; return nullptr ;
@@ -650,47 +651,42 @@ GetSurfTriMeshRectSwept( double dDimH, double dDimV, double dBevelH, double dBev
} }
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
ISurfTriMesh* static ISurfTriMesh*
GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol) GetSurfTriMeshSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol)
{ {
// verifica parametri // determino se la sezione è chiusa
if ( pSect == nullptr || pGuide == nullptr) bool bSectClosed = pSect->IsClosed() ;
return nullptr ; // determino se la guida è chiusa
// 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
bool bSectClosed = PL.IsClosed() ;
// 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() ; bool bGuideClosed = pGuide->IsClosed() ;
// riferimento all'inizio della linea guida // riferimento all'inizio della linea guida
Frame3d frStart ; Frame3d frStart ;
Point3d ptStart ; Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ; pGuide->GetStartPoint( ptStart) ;
Vector3d vtStart ; Vector3d vtStart ;
pGuide->GetStartDir( vtStart) ; pGuide->GetStartDir( vtStart) ;
Vector3d vtNorm = plGuide.GetVersN() ;
frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ; frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
// porto la sezione in questo riferimento e ve la appiattisco
// calcolo la polilinea che approssima la sezione
PolyLine PL ;
if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
return nullptr ;
// porto la sezione in questo riferimento e ve la appiattisco
if ( ! PL.ToLoc( frStart) || ! PL.Flatten()) if ( ! PL.ToLoc( frStart) || ! PL.Flatten())
return nullptr ; return nullptr ;
// calcolo la superficie
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ; // preparo collettore delle superfici componenti
if ( IsNull( pSTM)) StmFromTriangleSoup StmFts ;
if ( ! StmFts.Start())
return nullptr ; return nullptr ;
// salvo tolleranza lineare usata
pSTM->SetLinearTolerance( dLinTol) ;
// superficie swept // superficie swept
PtrOwner<ICurve> pPrevCrv ; PtrOwner<ICurve> pPrevCrv ;
Point3d ptP ; Point3d ptP ;
bool bPoint = PL.GetFirstPoint( ptP) ; bool bPoint = PL.GetFirstPoint( ptP) ;
while ( bPoint) { while ( bPoint) {
// nuova curva // nuova curva ( definita dall'Offset )
OffsetCurve OffsCrv ; OffsetCurve OffsCrv ;
if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() == 0) if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() == 0)
return nullptr ; return nullptr ;
@@ -698,21 +694,32 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
if ( IsNull( pCurrCrv)) if ( IsNull( pCurrCrv))
return nullptr ; return nullptr ;
pCurrCrv->Translate( ptP.y * frStart.VersY()) ; pCurrCrv->Translate( ptP.y * frStart.VersY()) ;
// se esiste la curva precedente, costruisco la rigata (di tipo minima distanza) // se esiste la curva precedente, costruisco la rigata ( di tipo minima distanza)
if ( ! IsNull( pPrevCrv)) { if ( ! IsNull( pPrevCrv)) {
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ; PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
if ( IsNull( pSr)) if ( IsNull( pSr))
return nullptr ; return nullptr ;
pSTM->DoSewing( *pSr) ; // inserisco nel collettore
StmFts.AddSurfTriMesh( *pSr) ;
} }
// salvo la curva come prossima precedente // salvo la curva come prossima precedente
pPrevCrv.Set( pCurrCrv) ; pPrevCrv.Set( pCurrCrv) ;
// prossimo punto // prossimo punto
bPoint = PL.GetNextPoint( ptP) ; bPoint = PL.GetNextPoint( ptP) ;
} }
// recupero la supeficie risultante
if ( ! StmFts.End())
return nullptr ;
PtrOwner<SurfTriMesh> pSTM( GetBasicSurfTriMesh( StmFts.GetSurf())) ;
if ( IsNull( pSTM))
return nullptr ;
// salvo tolleranza lineare usata
pSTM->SetLinearTolerance( dLinTol) ;
// se richiesti caps e sezione chiusa e guida aperta // se richiesti caps e sezione chiusa e guida aperta
if ( bCapEnds && bSectClosed && ! bGuideClosed) { if ( bCapEnds && bSectClosed && ! bGuideClosed) {
// verifico che le due estremità siano chiuse e piatte // verifico che le due estremità siano chiuse e piatte
POLYLINEVECTOR vPL ; POLYLINEVECTOR vPL ;
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
return nullptr ; return nullptr ;
@@ -726,6 +733,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL)) if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
return nullptr ; return nullptr ;
pSci->ToGlob( frStart) ; pSci->ToGlob( frStart) ;
// unisco
pSTM->DoSewing( *pSci) ; pSTM->DoSewing( *pSci) ;
// riferimento alla fine della linea guida // riferimento alla fine della linea guida
Frame3d frEnd ; Frame3d frEnd ;
@@ -740,6 +748,7 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
return nullptr ; return nullptr ;
pSce->Invert() ; pSce->Invert() ;
pSce->ToGlob( frEnd) ; pSce->ToGlob( frEnd) ;
// unisco
pSTM->DoSewing( *pSce) ; pSTM->DoSewing( *pSce) ;
} }
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno // se superficie risultante chiusa, verifico che la normale sia verso l'esterno
@@ -750,6 +759,244 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
return Release( pSTM) ; return Release( pSTM) ;
} }
//-------------------------------------------------------------------------------
static ISurfTriMesh*
GetSurfTriMeshSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx, bool bCapEnds, double dLinTol)
{
// determino se la sezione è chiusa
bool bSectClosed = pSect->IsClosed() ;
// determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ;
// determino algoritmo da usare per calcolare i riferimenti lungo la curva
bool bRMF = vtAx.IsSmall() ;
// riferimento all'inizio della linea guida
Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ;
Vector3d vtStart ;
pGuide->GetStartDir( vtStart) ;
Frame3d frStart ;
if ( bRMF) {
if ( ! frStart.Set( ptStart, vtStart))
return nullptr ;
}
else {
Vector3d vtAxX = vtAx ^ vtStart ;
if ( vtAxX.IsSmall()) {
vtAxX = FromUprightOrtho( vtAx) ;
vtAxX.Rotate( vtAx, 0, 1) ;
}
if ( ! frStart.Set( ptStart, vtStart, vtAxX))
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 ;
// recupero la sezione dalla PolyLine approssimata come Curva
PtrOwner<CurveComposite> pSecLocApprox( CreateBasicCurveComposite()) ;
if ( IsNull( pSecLocApprox) ||
! pSecLocApprox->FromPolyLine( PL) ||
! pSecLocApprox->IsValid())
return nullptr ;
// porto la PolyLine e la curva della sezione nel riferimento nel punto iniziale della guida
PL.ToLoc( frStart) ;
pSecLocApprox->ToLoc( frStart) ;
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
FRAME3DVECTOR vFrames ;
if ( bRMF) {
RotationMinimizingFrame RMF ;
if ( ! RMF.Set( pGuide, frStart) ||
! RMF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
return nullptr ;
}
else {
RotationXplaneFrame RXF ;
if ( ! RXF.Set( pGuide, vtAx, frStart.VersX()) ||
! RXF.GetFramesByTolerance( dLinTol, vFrames) || vFrames.empty())
return nullptr ;
}
// preparo collettore delle superfici componenti
StmFromTriangleSoup StmFts ;
if ( ! StmFts.Start())
return nullptr ;
// per ogni Frame calcolato, la sezione va roto-traslata lungo la guida
for ( int i = 0 ; i < int( vFrames.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( vFrames[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( vFrames[i+1]))
return nullptr ;
// creo la rigata tra queste due sezioni
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_ISOPAR_SMOOTH, dLinTol)) ;
if ( IsNull( pSr) || ! pSr->IsValid())
return nullptr ;
// la inverto
pSr->Invert() ;
// inserisco la superficie nel collettore
StmFts.AddSurfTriMesh( *pSr) ;
}
// se richiesti caps e sezione chiusa e guida aperta
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( vFrames.front()) ;
// aggiungo
StmFts.AddSurfTriMesh( *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( vFrames.back()) ;
// inverto
pSce->Invert() ;
// aggiungo
StmFts.AddSurfTriMesh( *pSce) ;
}
// recupero la supeficie risultante
if ( ! StmFts.End())
return nullptr ;
PtrOwner<SurfTriMesh> pSTM( GetBasicSurfTriMesh( StmFts.GetSurf())) ;
if ( IsNull( pSTM))
return nullptr ;
// salvo tolleranza lineare usata
pSTM->SetLinearTolerance( dLinTol) ;
// 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 ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx,
bool bCapEnds, double dLinTol)
{
// verifica parametri
if ( pSect == nullptr || pGuide == nullptr)
return nullptr ;
bool bIsLine = false ;
if ( pGuide->GetType() == CRV_LINE)
bIsLine = true ;
else {
const CurveComposite* pCompo = GetBasicCurveComposite( pGuide) ;
Point3d ptStart, ptEnd ;
if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd))
bIsLine = true ;
}
// se la guida è piana
Plane3d plGuide ;
if ( pGuide->IsFlat( plGuide, bIsLine, 10 * EPS_SMALL))
return GetSurfTriMeshSweptInPlane( pSect, pGuide, plGuide.GetVersN(), bCapEnds, dLinTol) ;
// altrimenti swept 3d
return GetSurfTriMeshSwept3d( pSect, pGuide, vtAx, bCapEnds, dLinTol) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, const Vector3d& vtAx,
bool bCapEnds, double dLinTol)
{
// verifica dei parametri
if ( pSfrSect == nullptr || pGuide == nullptr)
return nullptr ;
// predispongo collettore superfici componenti
StmFromTriangleSoup StmSoup ;
StmSoup.Start() ;
// per ogni loop della superficie, creo una Swept
for ( int nC = 0 ; nC < pSfrSect->GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < pSfrSect->GetLoopCount( nC) ; ++ nL) {
// recupero il loop
PtrOwner<ICurve> pCrvLoop( pSfrSect->GetLoop( nC, nL)) ;
if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid())
return nullptr ;
// creo la Trimesh Swept
PtrOwner<ISurfTriMesh> pStmLoopSwept( GetSurfTriMeshSwept( pCrvLoop, pGuide, vtAx, false, dLinTol)) ;
if ( IsNull( pStmLoopSwept) || ! pStmLoopSwept->IsValid())
return nullptr ;
// aggiungo la Swept ricavata al risultato finale ( come triangoli )
StmSoup.AddSurfTriMesh( *pStmLoopSwept) ;
}
}
// Recupero la superficie
if ( ! StmSoup.End())
return nullptr ;
PtrOwner<ISurfTriMesh> pStmSwept( StmSoup.GetSurf()) ;
if ( IsNull( pStmSwept))
return nullptr ;
// se rischiesta chiusura...
// Controllo solo che la guida non sia chiusa, la sezione derivando da una Flatregion è sempre chiusa
if ( bCapEnds && ! pGuide->IsClosed()) {
// recupero i loop all'inizio (dalla regione e apportunamente approssimati)
POLYLINEVECTOR vPLi ;
for ( int nC = 0 ; nC < pSfrSect->GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < pSfrSect->GetLoopCount( nC) ; ++ nL) {
vPLi.emplace_back() ;
if ( ! pSfrSect->ApproxLoopWithLines( nC, nL, dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPLi.back()))
return nullptr ;
}
}
// creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta)
PtrOwner<ISurfTriMesh> pSci( CreateSurfTriMesh()) ;
if ( ! pSci->CreateByRegion( vPLi))
return nullptr ;
pStmSwept->DoSewing( *pSci) ;
// recupero i loops alla fine
POLYLINEVECTOR vPLe ;
if ( ! pStmSwept->GetLoops( vPLe))
return nullptr ;
// creo la superficie alla fine e la attacco
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
if ( ! pSce->CreateByRegion( vPLe))
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* ISurfTriMesh*
GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol) GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol)
@@ -757,7 +1004,7 @@ GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEn
// verifica parametri // verifica parametri
if ( pSect == nullptr || pGuide == nullptr) if ( pSect == nullptr || pGuide == nullptr)
return nullptr ; return nullptr ;
// determino se la sezione è chiusa // determino se la sezione è chiusa
bool bSectClosed = pSect->IsClosed() ; bool bSectClosed = pSect->IsClosed() ;
// punto iniziale della sezione e vettore a inizio guida // punto iniziale della sezione e vettore a inizio guida
Point3d ptStart ; Point3d ptStart ;
@@ -771,7 +1018,7 @@ GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEn
PolyLine PLG ; PolyLine PLG ;
if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLG)) if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLG))
return nullptr ; return nullptr ;
// determino se la guida è chiusa // determino se la guida è chiusa
bool bGuideClosed = PLG.IsClosed() ; bool bGuideClosed = PLG.IsClosed() ;
// calcolo la superficie // calcolo la superficie
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ; PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
@@ -937,7 +1184,7 @@ CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
vCrvCompo[i]->ToLoc( frRef) ; 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 // 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 // successive i loop interni
INTMATRIX vnPLIndMat ; INTMATRIX vnPLIndMat ;
@@ -970,10 +1217,10 @@ CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
} }
bFirstCrv = false ; bFirstCrv = false ;
} }
// ... altrimenti verifico se il loop è interno o no // ... altrimenti verifico se il loop è interno o no
else { else {
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo // 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. // esterno a tutti i loop già inseriti nella riga attuale.
// verifica rispetto loop esterno // verifica rispetto loop esterno
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ; IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
CRVCVECTOR ccClass ; CRVCVECTOR ccClass ;
+226 -47
View File
@@ -20,12 +20,14 @@
#include "CurveBezier.h" #include "CurveBezier.h"
#include "CurveComposite.h" #include "CurveComposite.h"
#include "SurfBezier.h" #include "SurfBezier.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Include/EGkSurf.h" #include "/EgtDev/Include/EGkSurf.h"
#include "/EgtDev/Include/EGkSurfAux.h" #include "/EgtDev/Include/EGkSurfAux.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ; using namespace std ;
//----------------------------------------------------------------------------
bool bool
NurbsSurfaceCanonicalize( SNurbsSurfData& snData) NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
{ {
@@ -60,11 +62,12 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
nuCurve.vCP = vPtCtrl ; nuCurve.vCP = vPtCtrl ;
nuCurve.vW = vWeCtrl ; nuCurve.vW = vWeCtrl ;
// i punti dell' oggetto nuCurve devono essere in forma non omogenea // i punti dell' oggetto nuCurve devono essere in forma non omogenea
NurbsCurveCanonicalize( nuCurve) ; if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie
for ( int i = 0 ; i < snData.nCPU ; ++i) { for ( int i = 0 ; i < snData.nCPU ; ++i) {
snData.mCP[i][j] = nuCurve.vCP[i] ; snData.mCP[i][j] = nuCurve.vCP[i] ;
}
snData.vU = nuCurve.vU ;
} }
snData.vU = nuCurve.vU ;
} }
snData.bPeriodicU = false ; snData.bPeriodicU = false ;
} }
@@ -97,37 +100,36 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
nuCurve.vCP = vPtCtrl ; nuCurve.vCP = vPtCtrl ;
nuCurve.vW = vWeCtrl ; nuCurve.vW = vWeCtrl ;
// i punti dell' oggetto nuCurve devono essere in forma non omogenea // i punti dell' oggetto nuCurve devono essere in forma non omogenea
NurbsCurveCanonicalize( nuCurve) ; if ( NurbsCurveCanonicalize( nuCurve)) { // se NurbsCurveCanonicalize ha restituito false (la curva potrebbe esserre un punto di polo) allora non modifico i punti e il vettore dei nodi della superficie
for ( int j = 0 ; j < snData.nCPV ; ++j ) { for ( int j = 0 ; j < snData.nCPV ; ++j ) {
snData.mCP[i][j] = nuCurve.vCP[j] ; snData.mCP[i][j] = nuCurve.vCP[j] ;
}
snData.vV = nuCurve.vU ;
} }
snData.vV = nuCurve.vU ;
} }
snData.bPeriodicV = false ; snData.bPeriodicV = false ;
} }
return true; return true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
ISurf* ISurf*
NurbsToBezierSurface(const SNurbsSurfData& snData) NurbsToBezierSurface(const SNurbsSurfData& snData)
{ {
// la superficie Nurbs deve essere in forma canonica // la superficie Nurbs deve essere in forma canonica
if ( snData.bPeriodicU || snData.bPeriodicV || snData.bExtraKnotes ) if ( snData.bPeriodicU || snData.bPeriodicV || snData.bExtraKnotes )
return nullptr ; return nullptr ;
// controllo sul numero dei nodi // controllo sul numero dei nodi
int nU = snData.nCPU + snData.nDegU - 1 ; int nU = snData.nCPU + snData.nDegU - 1 ;
int nV = snData.nCPV + snData.nDegV - 1 ; int nV = snData.nCPV + snData.nDegV - 1 ;
// controllo nodi e punti di controllo // controllo nodi e punti di controllo
//if ( nU != int( snData.vU.size()) || nV != int( snData.vV.size()) || snData.nCPU * snData.nCPV != int( snData.vCP.size()))
if ( nU != int(snData.vU.size()) || nV != int(snData.vV.size())) { if ( nU != int(snData.vU.size()) || nV != int(snData.vV.size())) {
return nullptr ; return nullptr ;
} }
// verifico le condizioni agli estremi sui nodi (i primi nDeg nodi e gli ultimi nDeg nodi devono essere uguali tra loro) // verifico le condizioni agli estremi sui nodi (i primi nDeg nodi e gli ultimi nDeg nodi devono essere uguali tra loro)
bool bOk = true ; bool bOk = true ;
// direzione U // direzione U
for ( int i = 1 ; i < snData.nDegU ; ++ i) { for ( int i = 1 ; i < snData.nDegU ; ++ i) {
if ( abs( snData.vU[i] - snData.vU[0]) >= EPS_ZERO) if ( abs( snData.vU[i] - snData.vU[0]) >= EPS_ZERO)
bOk = false ; bOk = false ;
@@ -136,7 +138,7 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
if ( abs( snData.vU[nU - 1 - i] - snData.vU[nU - 1]) >= EPS_ZERO) if ( abs( snData.vU[nU - 1 - i] - snData.vU[nU - 1]) >= EPS_ZERO)
bOk = false ; bOk = false ;
} }
// direzione V // direzione V
for ( int i = 1 ; i < snData.nDegV ; ++ i) { for ( int i = 1 ; i < snData.nDegV ; ++ i) {
if ( abs( snData.vV[i] - snData.vV[0]) >= EPS_ZERO) if ( abs( snData.vV[i] - snData.vV[0]) >= EPS_ZERO)
bOk = false ; bOk = false ;
@@ -148,8 +150,8 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
if ( ! bOk) if ( ! bOk)
return nullptr ; return nullptr ;
// algoritmo 5.7 del libro "The NURBS book"////////////////////////////////////////////////////////////////////////////////////////////////////////////// // algoritmo 5.7 del libro "The NURBS book"
// creazione delle strips nella direzione U ( trasformo le curve iso con U costante in bezier) // creazione delle strips nella direzione U ( trasformo le curve iso con U costante in bezier)
int a = snData.nDegU - 1 ; int a = snData.nDegU - 1 ;
int b = snData.nDegU ; int b = snData.nDegU ;
int nb = 0 ; // numero di strisce in U ( lunghezza con U costante) int nb = 0 ; // numero di strisce in U ( lunghezza con U costante)
@@ -164,14 +166,14 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
DBLVECTOR vAlpha ; DBLVECTOR vAlpha ;
vAlpha.resize( snData.nDegU - 1) ; vAlpha.resize( snData.nDegU - 1) ;
if ( ! snData.bRat ) { if ( ! snData.bRat ) {
for ( int i = 0 ; i <= snData.nDegU ; ++i ) { for ( int i = 0 ; i <= snData.nDegU ; ++i) {
for ( int row = 0 ; row < snData.nCPV ; ++row ) { for ( int row = 0 ; row < snData.nCPV ; ++row ) {
mBC[i][row] = snData.mCP[i][row] ; mBC[i][row] = snData.mCP[i][row] ;
} }
} }
} }
else { else {
for ( int i = 0 ; i <= snData.nDegU ; ++i ) { for ( int i = 0 ; i <= snData.nDegU ; ++i) {
for (int row = 0 ; row < snData.nCPV ; ++ row) { for (int row = 0 ; row < snData.nCPV ; ++ row) {
mW[i][row] = snData.mW[i][row] ; mW[i][row] = snData.mW[i][row] ;
mBC[i][row] = snData.mCP[i][row] * snData.mW[i][row] ; mBC[i][row] = snData.mCP[i][row] * snData.mW[i][row] ;
@@ -185,25 +187,25 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
while ( b < nU - 1 && abs( snData.vU[b+1] - snData.vU[b]) < EPS_ZERO) while ( b < nU - 1 && abs( snData.vU[b+1] - snData.vU[b]) < EPS_ZERO)
++ b ; ++ b ;
int mult = b - i + 1 ; int mult = b - i + 1 ;
if ( mult < snData.nDegU ) { if ( mult < snData.nDegU) {
bRef = true ; bRef = true ;
// calcolo numeratore e alpha // calcolo numeratore e alpha
double numer = snData.vU[b] - snData.vU[a] ; double numer = snData.vU[b] - snData.vU[a] ;
for ( int j = snData.nDegU ; j > mult ; -- j) for ( int j = snData.nDegU ; j > mult ; -- j)
vAlpha[j-mult-1] = numer / ( snData.vU[a+j] - snData.vU[a]) ; vAlpha[j-mult-1] = numer / ( snData.vU[a+j] - snData.vU[a]) ;
int r = snData.nDegU - mult ; int r = snData.nDegU - mult ;
for ( int j = 1 ; j <= snData.nDegU - mult ; ++j ) { for ( int j = 1 ; j <= snData.nDegU - mult ; ++j) {
int save = r - j ; int save = r - j ;
int s = mult + j ; int s = mult + j ;
if ( ! snData.bRat ) { if ( ! snData.bRat ) {
for ( int k = snData.nDegU ; k >= s ; --k ) { for ( int k = snData.nDegU ; k >= s ; --k) {
for ( int row = 0 ; row < snData.nCPV ; ++row) { for ( int row = 0 ; row < snData.nCPV ; ++row) {
mBC[k][row] = vAlpha[k-s] * mBC[k][row] + ( 1 - vAlpha[k-s]) * mBC[k-1][row] ; mBC[k][row] = vAlpha[k-s] * mBC[k][row] + ( 1 - vAlpha[k-s]) * mBC[k-1][row] ;
} }
} }
} }
else { else {
for ( int k = snData.nDegU ; k >= s ; --k ) { for ( int k = snData.nDegU ; k >= s ; --k) {
for ( int row = 0 ; row < snData.nCPV ; ++row) { for ( int row = 0 ; row < snData.nCPV ; ++row) {
mBC[k][row] = vAlpha[k-s] * mBC[k][row] + ( 1 - vAlpha[k-s]) * mBC[k-1][row] ; mBC[k][row] = vAlpha[k-s] * mBC[k][row] + ( 1 - vAlpha[k-s]) * mBC[k-1][row] ;
mW[k][row] = vAlpha[k-s] * mW[k][row] + ( 1 - vAlpha[k-s]) * mW[k-1][row] ; mW[k][row] = vAlpha[k-s] * mW[k][row] + ( 1 - vAlpha[k-s]) * mW[k-1][row] ;
@@ -222,26 +224,26 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
} }
} }
} }
mPC_strip.resize( snData.nDegU * ( nb + 1) + 1 , vCPV) ; mPC_strip.resize( snData.nDegU * ( nb + 1) + 1, vCPV) ;
mW_strip.resize( snData.nDegU * ( nb + 1) + 1, vV_W) ; mW_strip.resize( snData.nDegU * ( nb + 1) + 1, vV_W) ;
if ( ! snData.bRat) if ( ! snData.bRat)
for ( int i = 0 ; i <= snData.nDegU ; ++i) { for ( int i = 0 ; i <= snData.nDegU ; ++i) {
for ( int row = 0 ; row < snData.nCPV ; ++row ) { for ( int row = 0 ; row < snData.nCPV ; ++row) {
mPC_strip[i+ nb * snData.nDegU][row] = mBC[i][row] ; mPC_strip[i+ nb * snData.nDegU][row] = mBC[i][row] ;
} }
} }
else { else {
for ( int i = 0 ; i <= snData.nDegU ; ++i) { for ( int i = 0 ; i <= snData.nDegU ; ++i) {
for ( int row = 0 ; row < snData.nCPV ; ++row ) { for ( int row = 0 ; row < snData.nCPV ; ++row) {
mPC_strip[i+ nb * snData.nDegU][row] = mBC[i][row]/mW[i][row] ; mPC_strip[i+ nb * snData.nDegU][row] = mBC[i][row]/mW[i][row] ;
mW_strip[i+ nb * snData.nDegU][row] = mW[i][row] ; mW_strip[i+ nb * snData.nDegU][row] = mW[i][row] ;
} }
} }
} }
// ho finito di definire la patch di Bezier attuale e passo alla successiva
++ nb ; ++ nb ;
// ho finito di definire la patch di Bezier attuale e passo alla successiva
// aggiorno mBC con i valori della prossima pezza di Bezier // corrisponde a nb = nb + 1 // aggiorno mBC con i valori della prossima pezza di Bezier // corrisponde a nb = nb + 1
if ( ! snData.bRat){ if ( ! snData.bRat){
for (int i = 0 ; i < snData.nDegU - 1 ; ++ i) { for (int i = 0 ; i < snData.nDegU - 1 ; ++ i) {
for ( int row = 0 ; row < snData.nCPV ; ++row) { for ( int row = 0 ; row < snData.nCPV ; ++row) {
@@ -283,7 +285,7 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
} }
} }
// se non ho raffinato allora tutti i nodi avevano gi? molteplicit? massima. Converto direttamente in Bezier la dir U // se non ho raffinato allora tutti i nodi avevano gi? molteplicit? massima. Converto direttamente in Bezier la dir U
int nCPU_ref ; // numero dei punti di controllo in U dopo il raffinamento int nCPU_ref ; // numero dei punti di controllo in U dopo il raffinamento
if ( ! bRef ) { if ( ! bRef ) {
nCPU_ref = snData.nCPU ; nCPU_ref = snData.nCPU ;
@@ -308,8 +310,8 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
else else
nCPU_ref = snData.nDegU * nb + 1 ; // numero dei punti di controllo in U dopo il raffinamento nCPU_ref = snData.nDegU * nb + 1 ; // numero dei punti di controllo in U dopo il raffinamento
// ora ho ottenuto le strisce nDegU x nCPV // ora ho ottenuto le strisce nDegU x nCPV
// devo ripetere la procedura, sulla dir V, per ottenere le patch nDegU x nDegV // devo ripetere la procedura, sulla dir V, per ottenere le patch nDegU x nDegV
a = snData.nDegV - 1 ; a = snData.nDegV - 1 ;
b = snData.nDegV ; b = snData.nDegV ;
int nc = 0 ; // numero di strisce in V ( lunghezza con V costante) int nc = 0 ; // numero di strisce in V ( lunghezza con V costante)
@@ -325,14 +327,14 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
vector<vector<Point3d>> mPC_tot( nCPU_ref, vDegV) ; vector<vector<Point3d>> mPC_tot( nCPU_ref, vDegV) ;
vector<DBLVECTOR> mW_tot( nCPU_ref, vV1_W) ; vector<DBLVECTOR> mW_tot( nCPU_ref, vV1_W) ;
if ( ! snData.bRat ) { if ( ! snData.bRat ) {
for ( int i = 0 ; i < nCPU_ref ; ++i ) { for ( int i = 0 ; i < nCPU_ref ; ++i) {
for ( int row = 0 ; row <= snData.nDegV ; ++row ) { for ( int row = 0 ; row <= snData.nDegV ; ++row ) {
m_BC1[i][row] = mPC_strip[i][row] ; m_BC1[i][row] = mPC_strip[i][row] ;
} }
} }
} }
else { else {
for ( int i = 0 ; i < nCPU_ref ; ++i ) { for ( int i = 0 ; i < nCPU_ref ; ++i) {
for (int row = 0 ; row <= snData.nDegV ; ++ row) { for (int row = 0 ; row <= snData.nDegV ; ++ row) {
mW1[i][row] = mW_strip[i][row] ; mW1[i][row] = mW_strip[i][row] ;
m_BC1[i][row] = mPC_strip[i][row] * mW_strip[i][row] ; m_BC1[i][row] = mPC_strip[i][row] * mW_strip[i][row] ;
@@ -348,24 +350,24 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
int mult = b - i + 1 ; int mult = b - i + 1 ;
if ( mult < snData.nDegV ) { if ( mult < snData.nDegV ) {
bRef = true ; bRef = true ;
// calcolo numeratore e alpha // calcolo numeratore e alpha
double numer = snData.vV[b] - snData.vV[a] ; double numer = snData.vV[b] - snData.vV[a] ;
for ( int j = snData.nDegV ; j > mult ; -- j) for ( int j = snData.nDegV ; j > mult ; -- j)
vAlpha1[j-mult-1] = numer / ( snData.vV[a+j] - snData.vV[a]) ; vAlpha1[j-mult-1] = numer / ( snData.vV[a+j] - snData.vV[a]) ;
int r = snData.nDegV - mult ; int r = snData.nDegV - mult ;
for ( int j = 1 ; j <= snData.nDegV - mult ; ++j ) { for ( int j = 1 ; j <= snData.nDegV - mult ; ++j) {
int save = r - j ; int save = r - j ;
int s = mult + j ; int s = mult + j ;
if ( ! snData.bRat) { if ( ! snData.bRat) {
for ( int k = 0 ; k < nCPU_ref ; ++k) { for ( int k = 0 ; k < nCPU_ref ; ++k) {
for ( int row = snData.nDegV ; row >= s ; --row ) { for ( int row = snData.nDegV ; row >= s ; --row) {
m_BC1[k][row] = vAlpha1[row-s] * m_BC1[k][row] + ( 1 - vAlpha1[row-s]) * m_BC1[k][row-1] ; m_BC1[k][row] = vAlpha1[row-s] * m_BC1[k][row] + ( 1 - vAlpha1[row-s]) * m_BC1[k][row-1] ;
} }
} }
} }
else { else {
for ( int k = 0 ; k < nCPU_ref ; ++k) { for ( int k = 0 ; k < nCPU_ref ; ++k) {
for ( int row = snData.nDegV ; row >= s ; --row ) { for ( int row = snData.nDegV ; row >= s ; --row) {
m_BC1[k][row] = vAlpha1[row-s] * m_BC1[k][row] + ( 1 - vAlpha1[row-s]) * m_BC1[k][row-1] ; m_BC1[k][row] = vAlpha1[row-s] * m_BC1[k][row] + ( 1 - vAlpha1[row-s]) * m_BC1[k][row-1] ;
mW1[k][row] = vAlpha1[row-s] * mW1[k][row] + ( 1 - vAlpha1[row-s]) * mW1[k][row-1] ; mW1[k][row] = vAlpha1[row-s] * mW1[k][row] + ( 1 - vAlpha1[row-s]) * mW1[k][row-1] ;
} }
@@ -388,28 +390,28 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
} }
} }
int nRef = snData.nDegV * ( nc + 1) + 1 ; int nRef = snData.nDegV * ( nc + 1) + 1 ;
for ( int k = 0 ; k < nCPU_ref; ++k){ for ( int k = 0 ; k < nCPU_ref; ++k) {
mPC_tot[k].resize( nRef) ; mPC_tot[k].resize( nRef) ;
mW_tot[k].resize( nRef) ; mW_tot[k].resize( nRef) ;
} }
if ( ! snData.bRat) if ( ! snData.bRat)
for ( int i = 0 ; i < nCPU_ref ; ++i) { for ( int i = 0 ; i < nCPU_ref ; ++i) {
for ( int row = 0 ; row <= snData.nDegV ; ++row ) { for ( int row = 0 ; row <= snData.nDegV ; ++row) {
mPC_tot[i][row + nc * snData.nDegV] = m_BC1[i][row] ; mPC_tot[i][row + nc * snData.nDegV] = m_BC1[i][row] ;
} }
} }
else { else {
for ( int i = 0 ; i < nCPU_ref ; ++i) { for ( int i = 0 ; i < nCPU_ref ; ++i) {
for ( int row = 0 ; row <= snData.nDegV ; ++row ) { for ( int row = 0 ; row <= snData.nDegV ; ++row) {
mPC_tot[i][row + nc * snData.nDegV] = m_BC1[i][row]/mW1[i][row] ; mPC_tot[i][row + nc * snData.nDegV] = m_BC1[i][row] / mW1[i][row] ;
mW_tot[i][row + nc * snData.nDegV] = mW1[i][row] ; mW_tot[i][row + nc * snData.nDegV] = mW1[i][row] ;
} }
} }
} }
// ho finito di definire la patch di Bezier attuale e passo alla successiva
++ nc ; ++ nc ;
// ho finito di definire la patch di Bezier attuale e passo alla successiva
// aggiorno mBC con i valori della prossima pezza di Bezier // corrisponde a nc = nc + 1 // aggiorno mBC con i valori della prossima pezza di Bezier // corrisponde a nc = nc + 1
if ( ! snData.bRat){ if ( ! snData.bRat){
for (int i = 0 ; i < nCPU_ref ; ++ i) { for (int i = 0 ; i < nCPU_ref ; ++ i) {
for ( int row = 0 ; row < snData.nDegV - 1 ; ++row) { for ( int row = 0 ; row < snData.nDegV - 1 ; ++row) {
@@ -450,7 +452,7 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
++b ; ++b ;
} }
} }
// se non ho raffinato allora aggiungo direttamente alle matrici della superficie totale // se non ho raffinato allora aggiungo direttamente alle matrici della superficie totale
int nCPV_ref ; // numero dei punti di controllo in V dopo il raffinamento int nCPV_ref ; // numero dei punti di controllo in V dopo il raffinamento
if ( ! bRef) { if ( ! bRef) {
nCPV_ref = snData.nCPV ; nCPV_ref = snData.nCPV ;
@@ -477,7 +479,7 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
else else
nCPV_ref = snData.nDegV * nc + 1 ; nCPV_ref = snData.nDegV * nc + 1 ;
// finalmente setto la superficie di bezier totale divisa in nb patch in U e nc patch in V // finalmente setto la superficie di bezier totale divisa in nb patch in U e nc patch in V
PtrOwner<SurfBezier> pSrfBz( CreateBasicSurfBezier()) ; PtrOwner<SurfBezier> pSrfBz( CreateBasicSurfBezier()) ;
if ( IsNull( pSrfBz)) if ( IsNull( pSrfBz))
return nullptr ; return nullptr ;
@@ -498,3 +500,180 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
} }
return Release( pSrfBz) ; return Release( pSrfBz) ;
} }
//----------------------------------------------------------------------------
bool
MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, const DBLVECTOR& vV0,
int nDegU, int nDegV, double dScaleU, double dScaleV, bool bRetry)
{
// la superficie in input arriva già scalata
bool bRescaledU = false ;
bool bRescaledV = false ;
int nSpanU = 1, nSpanV = 1 ;
PtrOwner<ISurfFlatRegion> pRescaledSfr( CreateSurfFlatRegion()) ;
for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
// vettore dei nodi
DBLVECTOR vU ;
int nExtraKnots = 0 ;
// controllo in U
if ( nDir == 0) {
if ( nDegU > 1) {
nExtraKnots = nDegU - 1 ;
}
for ( int i = nExtraKnots ; i < int( vU0.size()) - nExtraKnots ; ++i ) {
double dKnot = vU0[i] * SBZ_TREG_COEFF ;
// lo aggiungo solo se è diverso dal precedente
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
vU.push_back( dKnot) ;
}
nSpanU = (int)vU.size() - 1 ;
}
// controllo in V
else if ( nDir == 1 ) {
if ( nDegV > 1) {
nExtraKnots = nDegV - 1 ;
}
for ( int i = nExtraKnots ; i < int( vV0.size()) - nExtraKnots ; ++i ) {
double dKnot = vV0[i] * SBZ_TREG_COEFF ;
// lo aggiungo solo se è diverso dal precedente
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
vU.push_back( dKnot) ;
}
nSpanV = (int)vU.size() - 1 ;
}
// controllo se il vettore dei nodi è uniforme
int a = 0, b = 1 ;
double d0 = abs( vU[b] - vU[a]), d1 = d0 ;
// il vettore è uniforme quando la distanza tra nodi consecutivi è sempre zero o un valore costante
while ( b < (int)vU.size() && ( ( d1 < d0 + EPS_SMALL && d1 > d0 - EPS_SMALL) || d1 < EPS_SMALL)) {
a = b ;
++b ;
if ( b < (int)vU.size())
d1 = abs( vU[b] - vU[a]) ;
}
if ( b != (int)vU.size()) {
nDir == 0 ? bRescaledU = true : bRescaledV = true ;
pRescaledSfr.Set( CreateSurfFlatRegion()) ;
if ( IsNull( pRescaledSfr))
return false ;
for ( int p = 0 ; p < (int)vU.size() - 1 ; ++p) {
PtrOwner<ISurfFlatRegion> pSfr_copy( pSfr->Clone()) ;
if ( IsNull( pSfr_copy))
return false ;
double dLenStrip = abs( vU[p+1] - vU[p]) ;
if ( dLenStrip < EPS_SMALL)
continue ;
// creo la maschera per tagliare la superficie originale e ottenere una striscia
PtrOwner<ISurfFlatRegion> pSfrTrim( CreateSurfFlatRegion()) ;
// ricavo la maschera del trim, con cui poi farò l'intersezione con la sfr iniziale
Vector3d vtTrim ;
if ( nDir == 0) {
pSfrTrim.Set( GetSurfFlatRegionRectangle( dLenStrip, dScaleV + 2)) ;
vtTrim.Set( abs(vU[p] - vU.front()), - 1, 0) ;
}
else{
pSfrTrim.Set( GetSurfFlatRegionRectangle( dScaleU + 2, dLenStrip)) ;
vtTrim.Set( - 1, abs(vU[p] - vU.front()), 0) ;
}
pSfrTrim->Translate( vtTrim) ;
if ( ! pSfr_copy->Intersect( *pSfrTrim))
return false ;
// aggiungo la nuova striscia solo se è valida
if ( pSfr_copy->IsValid() ) {
if ( nDir == 0)
pSfr_copy->Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
else
pSfr_copy->Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
// prima di riunire la striscia al resto devo traslarla sul bordo destro della superificie che sto ricostruendo
Point3d pt ;
nDir == 0 ? pt.Set( abs(vU[p] - vU.front()), 0, 0) : pt.Set( 0,abs(vU[p] - vU.front()), 0) ;
if ( nDir == 0)
pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
else
pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
Vector3d vtJoin ;
if ( nDir == 0)
vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ;
else
vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ;
pSfr_copy->Translate( vtJoin) ;
// se sto ritentando MakeUniform, allora faccio anche OFFSET e controOFFSET
if ( bRetry)
pSfr_copy->Offset( 10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // OFFSET
if ( pRescaledSfr->IsValid()) {
if ( ! pRescaledSfr->Add( *pSfr_copy))
return false ;
}
else
pRescaledSfr.Set( pSfr_copy) ;
}
}
if ( nDir == 0) {
dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ;
if ( pRescaledSfr->IsValid()) {
if ( bRetry)
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; //contro OFFSET
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
}
}
else
dScaleV = ((int)vU.size() - 1) * SBZ_TREG_COEFF ;
}
}
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
if ( bRetry)
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // contro OFFSET
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
}
if ( ! bRescaledU && ! bRescaledV)
pSfr->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ;
else if ( bRescaledU && ! bRescaledV)
pSfr->Scale( GLOB_FRM, 1, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ;
else if ( ! bRescaledU && bRescaledV)
pSfr->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, 1, 1) ;
bRescaled = ( bRescaledU || bRescaledV) ;
return true ;
}
//----------------------------------------------------------------------------
bool
OnWhichEdge( double u0, double u1, double v0, double v1, const Point3d& ptToAssign, int& nEdge)
{
Point3d ptTR( u1, v1) ;
Point3d ptTl( u0, v1) ;
Point3d ptBL( u0, v0) ;
Point3d ptBr( u1, v0) ;
double dEps = 0.1 ;
if ( AreSamePointEpsilon( ptToAssign, ptTR, dEps))
nEdge = 7 ;
else if ( AreSamePointEpsilon( ptToAssign, ptTl, dEps))
nEdge = 4 ;
else if ( AreSamePointEpsilon( ptToAssign, ptBL, dEps))
nEdge = 5 ;
else if ( AreSamePointEpsilon( ptToAssign, ptBr, dEps))
nEdge = 6 ;
else if ( ptToAssign.x > ptBL.x - dEps && ptToAssign.x < ptTR.x + dEps && abs( ptToAssign.y - ptTR.y) < dEps)
nEdge = 0 ;
else if ( ptToAssign.y > ptBL.y - dEps && ptToAssign.y < ptTR.y + dEps && abs( ptToAssign.x - ptBL.x) < dEps)
nEdge = 1 ;
else if ( ptToAssign.x > ptBL.x - dEps && ptToAssign.x < ptTR.x + dEps && abs( ptToAssign.y - ptBL.y) < dEps)
nEdge = 2 ;
else if ( ptToAssign.y > ptBL.y - dEps && ptToAssign.y < ptTR.y + dEps && abs( ptToAssign.x - ptTR.x) < dEps)
nEdge = 3 ;
else
return false ;
return true ;
}
+104 -27
View File
@@ -33,12 +33,11 @@
#include "/EgtDev/Include/EGkChainCurves.h" #include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Include/EGkIntersLineSurfBez.h" #include "/EgtDev/Include/EGkIntersLineSurfBez.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Extern/Eigen/Dense"
#include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkCurveComposite.h"
#include <limits>
#include "/EgtDev/Include/EGkGeoObjSave.h"
#include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Extern/Eigen/Dense"
#include <limits>
using namespace std ; using namespace std ;
@@ -153,13 +152,23 @@ SurfBezier::SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtrac
PtrOwner< ISurfFlatRegion> pSfrTrim( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; PtrOwner< ISurfFlatRegion> pSfrTrim( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ;
// bIntersectOrSubtract == true per ottenere lo spazio parametrico trimmato devo fare l'INTERSEZIONE tra il rettangolo totale e l'area passata // bIntersectOrSubtract == true per ottenere lo spazio parametrico trimmato devo fare l'INTERSEZIONE tra il rettangolo totale e l'area passata
if ( bIntersectOrSubtract) { if ( bIntersectOrSubtract) {
if ( IsNull( pSfrTrim) || ! pSfrTrim->Intersect( sfrTrimReg) || ! pSfrTrim->IsValid()) if ( IsNull( pSfrTrim) || ! pSfrTrim->Intersect( sfrTrimReg) || ! pSfrTrim->IsValid()) {
return false ; // provo a offsettare il rettangolo parametrico ( ingrandendolo) per vedere se risolvo problemi di intersezione
pSfrTrim->Offset( 10* EPS_SMALL, ICurve::OFF_EXTEND) ;
if ( ! pSfrTrim->Intersect( sfrTrimReg) || ! pSfrTrim->IsValid())
return false ;
pSfrTrim->Offset( -10* EPS_SMALL, ICurve::OFF_EXTEND) ;
}
} }
// bIntersectOrSubtract == false per ottenere lo spazio parametrico trimmato devo fare la SOTTRAZIONE tra il rettangolo totale e l'area passata // bIntersectOrSubtract == false per ottenere lo spazio parametrico trimmato devo fare la SOTTRAZIONE tra il rettangolo totale e l'area passata
else { else {
if ( IsNull( pSfrTrim) || ! pSfrTrim->Subtract( sfrTrimReg) || ! pSfrTrim->IsValid()) if ( IsNull( pSfrTrim) || ! pSfrTrim->Subtract( sfrTrimReg) || ! pSfrTrim->IsValid()) {
return false ; // provo a offsettare il rettangolo parametrico ( ingrandendolo) per vedere se risolvo problemi di sottrazione
pSfrTrim->Offset( 10* EPS_SMALL, ICurve::OFF_EXTEND) ;
if ( ! pSfrTrim->Subtract( sfrTrimReg) || ! pSfrTrim->IsValid())
return false ;
pSfrTrim->Offset( -10* EPS_SMALL, ICurve::OFF_EXTEND) ;
}
} }
ResetAuxSurf() ; ResetAuxSurf() ;
// assegno la regione di trim // assegno la regione di trim
@@ -1487,21 +1496,41 @@ SurfBezier::GetAuxSurf( void) const
// se già calcolata, la restituisco // se già calcolata, la restituisco
if ( m_pSTM != nullptr) if ( m_pSTM != nullptr)
return m_pSTM ; return m_pSTM ;
// eseguo calcolo
m_pSTM = GetApproxSurf( 50 * EPS_SMALL, 100 * EPS_SMALL) ;
return m_pSTM ;
}
//----------------------------------------------------------------------------
SurfTriMesh*
SurfBezier::GetApproxSurf( double dTol, double dSideMin) const
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return nullptr ;
// se c'è ausiliaria e richiesta con gli stessi parametri, ne restituisco una copia
if ( m_pSTM != nullptr &&
abs( dTol - 50 * EPS_SMALL) < EPS_SMALL && abs( dSideMin - 100 * EPS_SMALL) < EPS_SMALL)
return m_pSTM->Clone() ;
// costruttore della superficie // costruttore della superficie
POLYLINEMATRIX vvPL ; POLYLINEMATRIX vvPL ;
//POLYLINEVECTOR vPL ; // per usare i polygon basic //POLYLINEVECTOR vPL ; // per usare i polygon basic
Tree Tree( this, true) ; //Tree Tree( this, true) ;
Tree Tree ;
if ( ! Tree.SetSurf( this, true))
return nullptr ;
BIPNTVECTOR vTrees ; BIPNTVECTOR vTrees ;
Tree.GetIndependentTrees( vTrees) ; Tree.GetIndependentTrees( vTrees) ;
bool bTest = false ; // per debug bool bTest = false ; // per debug
// resetto il vettore degli edge // resetto il vettore degli edge
m_mCCEdge.clear() ; m_mCCEdge.clear() ;
m_mCCEdge = vector<ICRVCOMPOPVECTOR>(4) ; m_mCCEdge = vector<ICRVCOMPOPOVECTOR>(4) ;
m_vCCLoop.clear() ; m_vCCLoop.clear() ;
for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) { for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) {
Point3d ptMin = std::get<0>( vTrees[i]) ; Point3d ptMin = get<0>( vTrees[i]) ;
Point3d ptMax = std::get<1>( vTrees[i]) ; Point3d ptMax = get<1>( vTrees[i]) ;
Tree.SetSurf( this, true, ptMin, ptMax) ; Tree.SetSurf( this, true, ptMin, ptMax) ;
if ( bTest) { if ( bTest) {
Tree.BuildTree_test() ; // per debug Tree.BuildTree_test() ; // per debug
@@ -1509,17 +1538,20 @@ SurfBezier::GetAuxSurf( void) const
Tree.SetTestMode() ; Tree.SetTestMode() ;
} }
else { else {
Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ; //Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ;
Tree.BuildTree( dTol, dSideMin) ;
} }
Tree.GetPolygons( vvPL) ; if ( ! Tree.GetPolygons( vvPL))
continue ;
//Tree.GetPolygonsBasic( vPL) ; // per usare i polygon basic //Tree.GetPolygonsBasic( vPL) ; // per usare i polygon basic
// aggiorno la chiusura della superficie // aggiorno la chiusura della superficie
m_bClosedU = m_bClosedU || Tree.IsClosedU() ; m_bClosedU = m_bClosedU || Tree.IsClosedU() ;
m_bClosedV = m_bClosedV || Tree.IsClosedV() ; m_bClosedV = m_bClosedV || Tree.IsClosedV() ;
// salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria
UpdateEdgesFromTree( Tree) ; UpdateEdgesFromTree( Tree) ;
} }
//// per usare i polygon basic////////////////////// //// per usare i polygon basic//////////////////////
//for (int k = 0 ; k < (int)vPL.size(); ++k) { //for (int k = 0 ; k < (int)vPL.size(); ++k) {
// vvPL.emplace_back() ; // vvPL.emplace_back() ;
@@ -1527,9 +1559,8 @@ SurfBezier::GetAuxSurf( void) const
//} //}
//// per usare i polygon basic/////////////////// //// per usare i polygon basic///////////////////
if ( vvPL.empty())
if ( int(vvPL.size()) == 0) LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be triangulated") ;
LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be triangulated, hence wasn't drawn") ;
StmFromTriangleSoup stmSoup ; StmFromTriangleSoup stmSoup ;
if ( ! stmSoup.Start()) if ( ! stmSoup.Start())
@@ -1561,19 +1592,20 @@ SurfBezier::GetAuxSurf( void) const
} }
} }
// la salvo // termino
if ( ! stmSoup.End()) if ( ! stmSoup.End())
return nullptr ; return nullptr ;
m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ; // restituisco
return GetBasicSurfTriMesh( stmSoup.GetSurf()) ;
return m_pSTM ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
SurfBezier::GetLeaves( vector<tuple<int, Point3d, Point3d>>& vLeaves) const SurfBezier::GetLeaves( vector<tuple<int, Point3d, Point3d>>& vLeaves) const
{ {
Tree Tree( this, true) ; Tree Tree ;
if ( ! Tree.SetSurf( this, true))
return false ;
BIPNTVECTOR vTrees ; BIPNTVECTOR vTrees ;
Tree.GetIndependentTrees( vTrees) ; Tree.GetIndependentTrees( vTrees) ;
for ( int i = 0 ; i < int( vTrees.size()) ; ++ i) { for ( int i = 0 ; i < int( vTrees.size()) ; ++ i) {
@@ -1837,11 +1869,12 @@ SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR&
return true ; return true ;
} }
//----------------------------------------------------------------------------
typedef tuple<int,int,int> TRINT ; typedef tuple<int,int,int> TRINT ;
template<> template<>
struct hash<TRINT> { struct hash<TRINT> {
std::size_t operator()(const TRINT& t) const size_t operator()(const TRINT& t) const
{ {
// Compute individual hash values for first, second and third and combine them using XOR and bit shifting: // Compute individual hash values for first, second and third and combine them using XOR and bit shifting:
return ((hash<int>()(get<0>(t))) ^ (hash<int>()(get<1>(t)) << 1) >> 1) ^ (hash<int>()(get<2>(t)) << 1) ; return ((hash<int>()(get<0>(t))) ^ (hash<int>()(get<1>(t)) << 1) >> 1) ^ (hash<int>()(get<2>(t)) << 1) ;
@@ -1857,6 +1890,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
// le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim // le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim
// accorpo eventuali triangoli adiacenti ed estraggo i loop delle regioni ottenute; questi vengono poi portati in 2d e aggiunti alle curve di trim // accorpo eventuali triangoli adiacenti ed estraggo i loop delle regioni ottenute; questi vengono poi portati in 2d e aggiunti alle curve di trim
// se necessario calcolo i poli
if ( m_vbPole.empty())
CalcPoles() ;
PNTVECTOR vPnt ; PNTVECTOR vPnt ;
BIPNTVECTOR vBPnt ; BIPNTVECTOR vBPnt ;
TRIA3DVECTOR vTria ; TRIA3DVECTOR vTria ;
@@ -2047,7 +2084,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
// vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo // vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo
BOOLVECTOR vbAdded( vpCCOpen.size()) ; BOOLVECTOR vbAdded( vpCCOpen.size()) ;
std::fill( vbAdded.begin(), vbAdded.end(), false) ; fill( vbAdded.begin(), vbAdded.end(), false) ;
PtrOwner<ICurveComposite> pCCNewEdge( CreateCurveComposite()) ; PtrOwner<ICurveComposite> pCCNewEdge( CreateCurveComposite()) ;
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ; PtrOwner<ICurveLine> pCL( CreateCurveLine()) ;
TRINT tiFirstInters ; TRINT tiFirstInters ;
@@ -2480,7 +2517,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
return false ; return false ;
// trovo quale vertice è sull'edge di polo // trovo quale vertice è sull'edge di polo
BOOLVECTOR vbOn(3) ; BOOLVECTOR vbOn(3) ;
std::fill( vbOn.begin(), vbOn.end(), false) ; fill( vbOn.begin(), vbOn.end(), false) ;
for ( int p = 0 ; p < 3; ++p ) { for ( int p = 0 ; p < 3; ++p ) {
for ( int c = 0 ; c < 4; ++c) { for ( int c = 0 ; c < 4; ++c) {
for( int i = 0 ; int( m_mCCEdge[c].size()) ; ++i) { for( int i = 0 ; int( m_mCCEdge[c].size()) ; ++i) {
@@ -2686,7 +2723,7 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d
bool bool
SurfBezier::CalcPoles( void) SurfBezier::CalcPoles( void)
{ {
// controllo se uno o più lati sono in realtà dei poli // la funzione identifica se degli edge della superficie non trimmata sono in realtà dei poli
for ( int i = 0 ; i < 4 ; ++i) for ( int i = 0 ; i < 4 ; ++i)
m_vbPole.emplace_back( true) ; m_vbPole.emplace_back( true) ;
// scorro i punti di controllo e vedo subito // scorro i punti di controllo e vedo subito
@@ -3077,6 +3114,8 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con
ICurveComposite* ICurveComposite*
SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const
{ {
if ( m_mCCEdge.size() == 0 && bLineOrBezier)
GetAuxSurf() ;
// questa funzione dà per scontato che la superficie NON sia trimmata // questa funzione dà per scontato che la superficie NON sia trimmata
if ( nEdge < 0 || nEdge > 3 || m_bTrimmed) if ( nEdge < 0 || nEdge > 3 || m_bTrimmed)
return nullptr ; return nullptr ;
@@ -3170,3 +3209,41 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const
} }
return pCrvCompo ; return pCrvCompo ;
} }
//----------------------------------------------------------------------------
bool
SurfBezier::IsPlanar( void) const
{
// costruisco il contorno della superficie unendo gli edge e chiedo se la polyline è piana.
PtrOwner<ICurveComposite> pCCEdge( GetSingleEdge3D( false, 0)) ;
pCCEdge->AddCurve( GetSingleEdge3D( false, 1)) ;
pCCEdge->AddCurve( GetSingleEdge3D( false, 2)) ;
pCCEdge->AddCurve( GetSingleEdge3D( false, 3)) ;
PolyLine plApprox ;
pCCEdge->ApproxWithLines( 0.01, 15, 0, plApprox) ;
Plane3d plPlane ;
if ( ! plApprox.IsFlat( plPlane, 2 * EPS_SMALL))
return false ;
// in questo caso se è grado 1 in U e V e ho un unica Patch allora sono sicuro sia piana
if ( m_nDegU == 1 && m_nSpanU == 1 && m_nDegV == 1 && m_nSpanV == 1) // questa condizione da sola non è sufficiente ( posso avere superfici torte anche se i lati sono segmenti)
return true ;
double dULast ; plApprox.GetLastU( dULast) ;
++ dULast ;
// altrimenti devo verificare anche all'interno della superficie, prendendo dei punti campione
DBLVECTOR vSampling { 0.2, 0.4, 0.6, 0.8} ;
for ( double i : vSampling) {
for ( double j : vSampling) {
Point3d ptBez ;
GetPointD1D2( i * m_nSpanU, j * m_nSpanV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ;
if ( plApprox.AddUPoint( dULast, ptBez))
++ dULast ;
}
}
plPlane.Reset() ;
if ( plApprox.IsFlat( plPlane, 2 * EPS_SMALL))
return true ;
// nel dubbio restituisco false
return false ;
}
+5 -4
View File
@@ -19,7 +19,6 @@
#include "CurveComposite.h" #include "CurveComposite.h"
#include "SurfTriMesh.h" #include "SurfTriMesh.h"
#include "SurfFlatRegion.h" #include "SurfFlatRegion.h"
//#include "Tree.h"
#include "/EgtDev/Include/EGkSurfBezier.h" #include "/EgtDev/Include/EGkSurfBezier.h"
#include "/EgtDev/Include/EGkGeoCollection.h" #include "/EgtDev/Include/EGkGeoCollection.h"
@@ -114,6 +113,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ; bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ;
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ; bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
const SurfTriMesh* GetAuxSurf( void) const override ; const SurfTriMesh* GetAuxSurf( void) const override ;
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL) const override ;
// funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione. // funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione.
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ; bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ; bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ;
@@ -130,14 +130,13 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
// funzione per tagliare una superficie di bezier con un piano ( cancello la parte dal lato positivo della normale del piano). // funzione per tagliare una superficie di bezier con un piano ( cancello la parte dal lato positivo della normale del piano).
// bSaveOnEq indica se tenere i triangoli (della trimesh associata) che sono sul piano // bSaveOnEq indica se tenere i triangoli (della trimesh associata) che sono sul piano
bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ; bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ;
// funzione che calcola se gli edge sono collassati in poli. DEVE ESSERE STATA CHIAMATA PRIMA DI UN CUT
bool CalcPoles( void) override ;
// funzioni per incrementare le coordinate restando dentro lo spazio parametrico // funzioni per incrementare le coordinate restando dentro lo spazio parametrico
bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ; bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ;
bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ; bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ;
// funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier // funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier
// se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate // se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ;
bool IsPlanar( void) const override ;
public : // IGeoObjRW public : // IGeoObjRW
int GetNgeId( void) const override ; int GetNgeId( void) const override ;
@@ -193,6 +192,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
// restituisce il singolo edge della superficie non trimmata // restituisce il singolo edge della superficie non trimmata
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ; ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
bool UpdateEdgesFromTree( Tree& tr) const ; bool UpdateEdgesFromTree( Tree& tr) const ;
// funzione che calcola se gli edge sono collassati in poli
bool CalcPoles( void) ;
private : private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
@@ -212,7 +213,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
int m_nTempProp[2] ; // vettore proprietà temporanee int m_nTempProp[2] ; // vettore proprietà temporanee
double m_dTempParam[2] ; // vettore parametri temporanei double m_dTempParam[2] ; // vettore parametri temporanei
mutable vector<ICRVCOMPOPVECTOR> m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D mutable vector<ICRVCOMPOPOVECTOR> m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D
mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata
} ; } ;
+2 -2
View File
@@ -146,7 +146,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
else { else {
// verifico che il piano della curva coincida con quello XY intrinseco // verifico che il piano della curva coincida con quello XY intrinseco
plPlane.ToLoc( m_frF) ; plPlane.ToLoc( m_frF) ;
if ( ! plPlane.GetVersN().IsZ() || abs( plPlane.GetDist()) > EPS_SMALL) if ( ! plPlane.GetVersN().IsZEpsilon( 2 * EPS_ZERO) || abs( plPlane.GetDist()) > EPS_SMALL)
return false ; return false ;
// sistemo il senso di rotazione (deve essere CCW -> area > 0) // sistemo il senso di rotazione (deve essere CCW -> area > 0)
if ( ( plPlane.GetVersN().z > 0 && dArea < 0) || if ( ( plPlane.GetVersN().z > 0 && dArea < 0) ||
@@ -288,7 +288,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
Plane3d plPlane ; Plane3d plPlane ;
if ( ! pMyCrv->GetArea( plPlane, dArea)) if ( ! pMyCrv->GetArea( plPlane, dArea))
return false ; return false ;
if ( ! plPlane.GetVersN().IsZ() || abs( plPlane.GetDist()) > EPS_SMALL) if ( ! plPlane.GetVersN().IsZEpsilon( 2 * EPS_ZERO) || abs( plPlane.GetDist()) > EPS_SMALL)
return false ; return false ;
// sistemo il senso di rotazione (deve essere CW -> se N==Z+ area < 0, se N==Z- area > 0) // sistemo il senso di rotazione (deve essere CW -> se N==Z+ area < 0, se N==Z- area > 0)
if ( ( plPlane.GetVersN().z > 0 && dArea > 0) || ( plPlane.GetVersN().z < 0 && dArea < 0)) if ( ( plPlane.GetVersN().z > 0 && dArea > 0) || ( plPlane.GetVersN().z < 0 && dArea < 0))
+2 -6
View File
@@ -3244,7 +3244,6 @@ SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double
bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ; bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ;
// aggiorno le facce // aggiorno le facce
bool bRecalc = ( abs( dCoeffX) < EPS_ZERO || abs( dCoeffY) < EPS_ZERO || abs( dCoeffZ) < EPS_ZERO) ;
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
if ( m_vTria[i].nIdVert[0] != SVT_DEL) { if ( m_vTria[i].nIdVert[0] != SVT_DEL) {
// se c'è mirror, devo invertire la faccia // se c'è mirror, devo invertire la faccia
@@ -3254,15 +3253,12 @@ SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double
if ( ! CalcTriangleNormal( i)) { if ( ! CalcTriangleNormal( i)) {
// elimino il triangolo // elimino il triangolo
RemoveTriangle( i) ; RemoveTriangle( i) ;
// richiedo ricalcolo vertici e topologia
bRecalc = true ;
} }
} }
} }
if ( bRecalc)
return DoCompacting() ;
return true ; return DoCompacting() ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
+20 -7
View File
@@ -76,10 +76,9 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2))) ( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2)))
continue ; // la catena aperta non è interna al loop chiuso attuale 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 // il loop 2 segue sempre la direzione della catena, il loop 1 ha dentro la catena invertita
// Ho sempre che il loop 1 è sempre interno ( la direzione della catena è determinata // ( la direzione della catena è determinata dalla normale dei triangoli che la formano;
// dalla normale dei triangoli che la formano; avendo chimatao la chian senza ammettere inversioni, sono // avendo chiamato la chain senza ammettere inversioni, sono curve tutte concordi )
// curve tutte concordi ) e il loop 2 che è esterno
bLoopSplitted = true ; bLoopSplitted = true ;
// ricostrusico i due loop mediante concatenazione // ricostrusico i due loop mediante concatenazione
Chain cvCounterChain ; Chain cvCounterChain ;
@@ -584,6 +583,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
POLYLINEVECTOR vplPolyVec ; POLYLINEVECTOR vplPolyVec ;
vplPolyVec.resize( cvBoundClosedLoopVec.size()) ; vplPolyVec.resize( cvBoundClosedLoopVec.size()) ;
for ( int nLoop = 0 ; nLoop < int( vplPolyVec.size()) ; ++ nLoop) { 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][nLine]) ;
@@ -591,7 +591,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// Assegno ai loop trovati i rispettivi interni // 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. // 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 nodo corrispondente a un
// loop è figlio del nodo corrispondente al loop che lo contiene. // loop è figlio del nodo corrispondente al loop che lo contiene.
INTVECTOR vInnerLoop ; INTVECTOR vInnerLoop ;
for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) { for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) {
@@ -742,6 +742,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// se ho più loop, essi descrivono un poligono di n-lati // se ho più loop, essi descrivono un poligono di n-lati
POLYLINEVECTOR vPolygons ; POLYLINEVECTOR vPolygons ;
vPolygons.emplace_back( vplPolyVec[nLoop]) ; vPolygons.emplace_back( vplPolyVec[nLoop]) ;
for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) { for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) {
// per ognuno di essi, ricavo la PolyLine dai punti // per ognuno di essi, ricavo la PolyLine dai punti
PolyLine CurLoop ; PolyLine CurLoop ;
@@ -955,11 +956,22 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
vPolygons.erase( vPolygons.begin() + i) ; vPolygons.erase( vPolygons.begin() + i) ;
else else
++ i ; ++ i ;
}
bool bCordirectedNormals_intLoop = bCodirectedNormals ;
if ( ! vPolygons.empty()) {
Polygon3d pgPol ;
pgPol.FromPolyLine( vPolygons[0]) ;
// controllo direzioni delle normali
bCordirectedNormals_intLoop = trTria.GetN() * pgPol.GetVersN() > 0. ;
if ( ! bCordirectedNormals_intLoop)
vPolygons[0].Invert() ;
} }
if ( Triangulate().MakeAdvanced( vPolygons, vPt, vTr)) { if ( Triangulate().MakeAdvanced( vPolygons, vPt, vTr)) {
// Inserisco i nuovi triangoli // Inserisco i nuovi triangoli
for (int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) { for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ; int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ;
int nNewId[3] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]), int nNewId[3] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
Surf.AddVertex( vPt[nNewTriaVertId[1]]), Surf.AddVertex( vPt[nNewTriaVertId[1]]),
@@ -969,7 +981,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ; Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ; Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ; Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( bCodirectedNormals) if ( bCordirectedNormals_intLoop)
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ; Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
else else
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ; Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
@@ -1767,6 +1779,7 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other)
SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
IntersectTriMeshTriangle( SurfB) ; IntersectTriMeshTriangle( SurfB) ;
IdentifyParts() ; IdentifyParts() ;
SurfB.IdentifyParts() ; SurfB.IdentifyParts() ;
+50 -29
View File
@@ -2,7 +2,7 @@
// EgalTech 2021-2021 // EgalTech 2021-2021
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : SurfTriMeshUtilities.cpp Data : 01.11.21 Versione : 2.3k1 // File : SurfTriMeshUtilities.cpp Data : 01.11.21 Versione : 2.3k1
// Contenuto : Implementazione funzioni di utilità di Superfici TriMesh. // Contenuto : Implementazione funzioni di utilità di Superfici TriMesh.
// //
// //
// //
@@ -123,7 +123,7 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
// Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro // Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) { for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
// Se il triangolo non è valido, passo al successivo // Se il triangolo non è valido, passo al successivo
Triangle3d trTria ; Triangle3d trTria ;
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
continue ; continue ;
@@ -138,7 +138,7 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
for ( int nSeg = 0 ; nSeg < 3 ; ++ nSeg) { for ( int nSeg = 0 ; nSeg < 3 ; ++ nSeg) {
// aggiungo al vettore il vertice iniziale del lato // aggiungo al vettore il vertice iniziale del lato
vVertOtl.emplace_back( m_vTria[nT].nIdVert[nSeg]) ; vVertOtl.emplace_back( m_vTria[nT].nIdVert[nSeg]) ;
// Se in questo lato il triangolo è adiacente a un altro, lo salto. // Se in questo lato il triangolo è adiacente a un altro, lo salto.
if ( m_vTria[nT].nIdAdjac[nSeg] != SVT_DEL && m_vTria[nT].nIdAdjac[nSeg] != SVT_NULL) if ( m_vTria[nT].nIdAdjac[nSeg] != SVT_DEL && m_vTria[nT].nIdAdjac[nSeg] != SVT_NULL)
continue ; continue ;
int nPrevSize = int( vVertOtl.size()) ; int nPrevSize = int( vVertOtl.size()) ;
@@ -152,7 +152,7 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
vtSeg /= dSegLen ; vtSeg /= dSegLen ;
// Ciclo sui triangoli vicini // Ciclo sui triangoli vicini
for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) { for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) {
// Salto il triangolo se è quello di riferimento // Salto il triangolo se è quello di riferimento
if ( vNearTria[nI] == nT) if ( vNearTria[nI] == nT)
continue ; continue ;
// Cerco i vertici che stanno sul lato del triangolo // Cerco i vertici che stanno sul lato del triangolo
@@ -175,11 +175,11 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
} ; } ;
sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVertices) ; sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVertices) ;
} }
// Se ci sono più di 3 vertici // Se ci sono più di 3 vertici
if ( vVertOtl.size() > 3) { if ( vVertOtl.size() > 3) {
// Elimino i vertici ripetuti // Elimino i vertici ripetuti
vVertOtl.erase( unique( vVertOtl.begin(), vVertOtl.end()), vVertOtl.end()) ; vVertOtl.erase( unique( vVertOtl.begin(), vVertOtl.end()), vVertOtl.end()) ;
// Se ci sono ancora più di 3 vertici, inserisco nel Map // Se ci sono ancora più di 3 vertici, inserisco nel Map
if ( vVertOtl.size() > 3) if ( vVertOtl.size() > 3)
TriaMap.emplace( nT, vVertOtl) ; TriaMap.emplace( nT, vVertOtl) ;
} }
@@ -191,7 +191,7 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
int nT = itT->first ; int nT = itT->first ;
// Vettore degli altri vertici sul perimetro // Vettore degli altri vertici sul perimetro
const INTVECTOR& vVertOtl = itT->second ; const INTVECTOR& vVertOtl = itT->second ;
// Se il triangolo non è valido, passo al successivo // Se il triangolo non è valido, passo al successivo
Triangle3d trTria ; Triangle3d trTria ;
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true)) if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
continue ; continue ;
@@ -207,7 +207,7 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
int nLastNewTria = SVT_NULL ; int nLastNewTria = SVT_NULL ;
// Se ci sono 4 vertici, inserisco due triangoli // Se ci sono 4 vertici, inserisco due triangoli
if ( vVertOtl.size() == 4) { if ( vVertOtl.size() == 4) {
// se 1-2-3 è triangolo (e quindi 0-1-3) // se 1-2-3 è triangolo (e quindi 0-1-3)
int nNew1Id[3] = { vVertOtl[1], vVertOtl[2], vVertOtl[3]} ; int nNew1Id[3] = { vVertOtl[1], vVertOtl[2], vVertOtl[3]} ;
int nNew1Tria = AddTriangle( nNew1Id, nTFlag) ; int nNew1Tria = AddTriangle( nNew1Id, nTFlag) ;
if ( nNew1Tria != SVT_NULL && nNew1Tria != SVT_DEL) { if ( nNew1Tria != SVT_NULL && nNew1Tria != SVT_DEL) {
@@ -285,13 +285,13 @@ IsVertex( PNTULIST& PointList, PNTULIST::const_iterator itCurr)
static bool static bool
ChooseGoodStartPoint( PNTULIST& PointList) ChooseGoodStartPoint( PNTULIST& PointList)
{ {
// se il punto iniziale è un vertice, non devo fare alcunché // se il punto iniziale è un vertice, non devo fare alcunché
if ( IsVertex( PointList, PointList.begin())) if ( IsVertex( PointList, PointList.begin()))
return true ; return true ;
// altrimenti cerco il vertice più vicino // altrimenti cerco il vertice più vicino
for ( auto it = next( PointList.begin()) ; it != PointList.end() ; ++it) { for ( auto it = next( PointList.begin()) ; it != PointList.end() ; ++it) {
if ( IsVertex( PointList, it)) { if ( IsVertex( PointList, it)) {
// se ultimo punto non devo fare alcunché // se ultimo punto non devo fare alcunché
if ( next( it) == PointList.end()) if ( next( it) == PointList.end())
return false ; return false ;
// cancello ultimo punto ( coincide con primo) // cancello ultimo punto ( coincide con primo)
@@ -317,11 +317,32 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
// Se dal punto corrente inizia un segmento adiacente a un'altra faccia // Se dal punto corrente inizia un segmento adiacente a un'altra faccia
if ( itLast->second != it->second) { if ( itLast->second != it->second) {
// Elimino i punti interni // Raccolgo i punti in una polyline
auto itNextToLast = next( itLast) ; PolyLine PL ;
for ( auto itInn = itNextToLast ; itInn != it ; ) { int nPar = -1 ;
itInn = PointList.erase( itInn) ; for ( auto itInn = itLast ; itInn != it ; ) {
bModif = true ; PL.AddUPoint( ++nPar, itInn->first) ;
itInn = next( itInn) ;
}
PL.AddUPoint( ++nPar, it->first) ;
// Provo ad eliminare i punti allineati
PL.RemoveAlignedPoints( 50 * EPS_SMALL) ;
if ( PL.GetPointNbr() < nPar + 1) {
// rimuovo dalla lista dei punti gli eliminati (salto gli estremi)
int nUCurr = 1 ;
for ( auto itInn = next( itLast) ; itInn != it ; ) {
bool bFound = false ;
double dU ;
for ( bool bOk = PL.GetFirstU( dU) ; bOk && ! bFound ; bOk = PL.GetNextU( dU))
bFound = abs( dU - nUCurr) < EPS_SMALL ;
if ( ! bFound) {
itInn = PointList.erase( itInn) ;
bModif = true ;
}
else
itInn = next( itInn) ;
++ nUCurr ;
}
} }
// Se la lunghezza del segmento supera il limite imposto // Se la lunghezza del segmento supera il limite imposto
double dSegLen = Dist( it->first, itLast->first) ; double dSegLen = Dist( it->first, itLast->first) ;
@@ -354,7 +375,7 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
} }
// Se i punti sono allineati // Se i punti sono allineati
if ( bAreAligned) { if ( bAreAligned) {
// Verifico se il successivo punto non è più allineato // Verifico se il successivo punto non è più allineato
auto itNextToCurr = next( it) ; auto itNextToCurr = next( it) ;
if ( itNextToCurr != PointList.end()) { if ( itNextToCurr != PointList.end()) {
for ( auto itInn = itNextToLast ; itInn != itNextToCurr && bAreAligned ; ++ itInn) { for ( auto itInn = itNextToLast ; itInn != itNextToCurr && bAreAligned ; ++ itInn) {
@@ -402,7 +423,7 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
// La trimesh deve essere valida // La trimesh deve essere valida
if ( ! IsValid()) if ( ! IsValid())
return false ; return false ;
// Se la lunghezza massima del lato del triangolo sul bordo della faccia è nulla e non forzata, non devo fare alcunché // Se la lunghezza massima del lato del triangolo sul bordo della faccia è nulla e non forzata, non devo fare alcunché
if ( dMaxEdgeLen < EPS_SMALL && ! bForced) if ( dMaxEdgeLen < EPS_SMALL && ! bForced)
return true ; return true ;
@@ -505,7 +526,7 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
} }
} }
// dichiaro necessità ricalcolo della grafica e di hashgrids3d // dichiaro necessità ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ; m_OGrMgr.Reset() ;
ResetHashGrids3d() ; ResetHashGrids3d() ;
@@ -517,13 +538,13 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
bool bool
SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
{ {
// Se la catena da aggiungere è vuota, non devo fare alcunchè // Se la catena da aggiungere è vuota, non devo fare alcunchè
if ( ChainToAdd.size() == 0) if ( ChainToAdd.size() == 0)
return true ; return true ;
// Se la catena originale è vuota, non è possibile aggiungere nulla // Se la catena originale è vuota, non è possibile aggiungere nulla
if ( OrigChain.size() == 0) if ( OrigChain.size() == 0)
return false ; return false ;
// Se la catena originale è chiusa non posso aggiungere nulla // Se la catena originale è chiusa non posso aggiungere nulla
int nLastOrig = max( int( OrigChain.size()) - 1, 0) ; int nLastOrig = max( int( OrigChain.size()) - 1, 0) ;
if ( AreSamePointApprox( OrigChain[0], OrigChain[nLastOrig])) if ( AreSamePointApprox( OrigChain[0], OrigChain[nLastOrig]))
return false ; return false ;
@@ -562,11 +583,11 @@ SurfTriMesh::DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec,
return false ; return false ;
double dDistPtPl = DistPointPlane( ptP, plPlane) ; double dDistPtPl = DistPointPlane( ptP, plPlane) ;
Point3d ptProjP = ptP + dDistPtPl * plPlane.GetVersN() ; Point3d ptProjP = ptP + dDistPtPl * plPlane.GetVersN() ;
// Verifico se il punto proiettato è esterno al loop esterno // Verifico se il punto proiettato è esterno al loop esterno
int nPtOut = -1 ; int nPtOut = -1 ;
if ( ! IsPointInsidePolyLine( ptProjP, vPolyVec[0], EPS_SMALL)) if ( ! IsPointInsidePolyLine( ptProjP, vPolyVec[0], EPS_SMALL))
nPtOut = 0 ; nPtOut = 0 ;
// Verifico se il punto proiettato è interno ai loop interni (quindi esterno alla faccia) // Verifico se il punto proiettato è interno ai loop interni (quindi esterno alla faccia)
for ( int nLoop = 1 ; nLoop < int( vPolyVec.size()) && nPtOut < 0 ; ++ nLoop) { for ( int nLoop = 1 ; nLoop < int( vPolyVec.size()) && nPtOut < 0 ; ++ nLoop) {
Plane3d plPlane ; Plane3d plPlane ;
double dArea ; double dArea ;
@@ -580,7 +601,7 @@ SurfTriMesh::DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec,
dPointFacetDist = abs( dDistPtPl) ; dPointFacetDist = abs( dDistPtPl) ;
return true ; return true ;
} }
// Altrimenti calcolo la minima distanza del punto dalla polilinea del contorno a cui è esterno // Altrimenti calcolo la minima distanza del punto dalla polilinea del contorno a cui è esterno
double dDist ; double dDist ;
if ( DistPointPolyLine( ptP, vPolyVec[nPtOut], dDist)) { if ( DistPointPolyLine( ptP, vPolyVec[nPtOut], dDist)) {
dPointFacetDist = dDist ; dPointFacetDist = dDist ;
@@ -593,7 +614,7 @@ SurfTriMesh::DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec,
bool bool
SurfTriMesh::ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop) SurfTriMesh::ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop)
{ {
// Cerco il tratto del loop chiuso più vicino al punto // Cerco il tratto del loop chiuso più vicino al punto
int nMinSeg = - 1 ; int nMinSeg = - 1 ;
double dMinSqDinst = DBL_MAX ; double dMinSqDinst = DBL_MAX ;
for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) { for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) {
@@ -657,7 +678,7 @@ SurfTriMesh::ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop)
bool bool
SurfTriMesh::SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2) SurfTriMesh::SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2)
{ {
// Cerco il tratto del loop chiuso più vicino al punto // Cerco il tratto del loop chiuso più vicino al punto
int nMinSeg = -1 ; int nMinSeg = -1 ;
double dMinSqDinst = DBL_MAX ; double dMinSqDinst = DBL_MAX ;
for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) { for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) {
@@ -679,13 +700,13 @@ SurfTriMesh::SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECT
// Verifico che il punto stia su un vertice, in tal caso non devo aggiungerlo // Verifico che il punto stia su un vertice, in tal caso non devo aggiungerlo
bool bFirst = AreSamePointApprox( Loop[nMinSeg], ptStop) ; bool bFirst = AreSamePointApprox( Loop[nMinSeg], ptStop) ;
bool bLast = AreSamePointApprox( Loop[( nMinSeg + 1) % int( Loop.size())], ptStop) ; bool bLast = AreSamePointApprox( Loop[( nMinSeg + 1) % int( Loop.size())], ptStop) ;
// Se il punto è sul vertice finale del segmento, aggiungo il vertice alla lista da inglobare al primo loop // Se il punto è sul vertice finale del segmento, aggiungo il vertice alla lista da inglobare al primo loop
if ( bLast) if ( bLast)
++ nMinSeg ; ++ nMinSeg ;
// Inglobo fino a nSeg nel primo loop // Inglobo fino a nSeg nel primo loop
for ( int nPt = 0 ; nPt <= nMinSeg && nPt < int( Loop.size()) ; ++ nPt) for ( int nPt = 0 ; nPt <= nMinSeg && nPt < int( Loop.size()) ; ++ nPt)
Loop1.emplace_back( Loop[nPt]) ; Loop1.emplace_back( Loop[nPt]) ;
// Se il punto è interno al segmento, lo inglobo in entrambi i loop // Se il punto è interno al segmento, lo inglobo in entrambi i loop
if ( ! ( bFirst || bLast)) { if ( ! ( bFirst || bLast)) {
Loop1.emplace_back( ptStop) ; Loop1.emplace_back( ptStop) ;
Loop2.emplace_back( ptStop) ; Loop2.emplace_back( ptStop) ;
+83
View File
@@ -580,3 +580,86 @@ Tool::SetChiselTool( const string& sToolName, double dH, double dW, double dTh,
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
Tool::SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRC, int nToolNum)
{
// Impostazioni generali
m_sName = sToolName ;
m_nCurrentNum = nToolNum ;
m_nType = UNDEF ;
m_Outline.Clear() ;
m_ArcLineApprox.Clear() ;
// verifica sulle minime dimensioni globali
if ( dH < EPS_SMALL || dR < EPS_SMALL || dRC < - EPS_SMALL)
return false ;
m_dHeight = dH ;
m_dRadius = dR ;
m_dRCorner = dRC ;
m_dTipHeight = 0 ;
m_dTipRadius = 0 ;
m_dRefRadius = 0 ;
m_dCutterHeight = dH ;
bool bToolDefined = true ;
double dSquareCornerRadProj = m_dRCorner * m_dRCorner - 0.25 * m_dHeight * m_dHeight ;
// Utensile sfiancato
if ( dSquareCornerRadProj > 0) {
double dCenX = m_dRadius - m_dRCorner ;
double dCylRad = dCenX + sqrt( dSquareCornerRadProj) ;
// Utensile mal definito
if ( dCylRad < EPS_SMALL)
return false ;
// Profilo
m_Outline.AddPoint( Point3d( 0, 0, 0)) ;
m_Outline.AddLine( Point3d( dCylRad, 0, 0)) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
CurveArc cvArc ;
cvArc.SetC2P( Point3d( dCenX, - 0.5 * m_dHeight, 0), Point3d( dCylRad, 0, 0), Point3d( dCylRad, - m_dHeight, 0)) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( Point3d( 0, - m_dHeight, 0)) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
bToolDefined = SetGenTool( sToolName, &m_Outline, nToolNum) ;
}
// Utensile cilindrico con eventuale raggio corner
else {
// Utensile mal definito
if ( m_dRadius - m_dRCorner < 0)
return false ;
// Utensile sferico
else if ( m_dRadius - m_dRCorner < EPS_SMALL)
;
// Raggio corner nullo: cilindro
else if ( m_dRCorner < EPS_SMALL) {
;
}
else {
// Profilo
m_Outline.AddPoint( Point3d( 0, 0, 0)) ;
m_Outline.AddLine( Point3d( m_dRadius - m_dRCorner, 0, 0)) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
CurveArc cvArc ;
cvArc.SetC2P( Point3d( m_dRadius - m_dRCorner, - m_dRCorner, 0), Point3d( m_dRadius - m_dRCorner, 0, 0), Point3d( m_dRadius, - m_dRCorner, 0)) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( Point3d( m_dRadius, - m_dHeight + m_dRCorner, 0)) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
cvArc.SetC2P( Point3d( m_dRadius - m_dRCorner, - m_dHeight + m_dRCorner, 0), Point3d( m_dRadius, - m_dHeight + m_dRCorner, 0), Point3d( m_dRadius - m_dRCorner, - m_dHeight, 0)) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( Point3d( 0, - m_dHeight, 0)) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
bToolDefined = SetGenTool( sToolName, &m_Outline, nToolNum) ;
}
}
m_nType = ADDITIVE ;
return bToolDefined ;
}
+3 -1
View File
@@ -33,6 +33,7 @@ class Tool
bool SetGenTool( const std::string& sToolName, const ICurveComposite* pToolOutline, int nToolNum) ; bool SetGenTool( const std::string& sToolName, const ICurveComposite* pToolOutline, int nToolNum) ;
bool SetMortiserTool( const std::string& sToolName, double dH, double dW, double dTh, double dRc, int nToolNum) ; bool SetMortiserTool( const std::string& sToolName, double dH, double dW, double dTh, double dRc, int nToolNum) ;
bool SetChiselTool( const std::string& sToolName, double dH, double dW, double dTh, int nToolNum) ; bool SetChiselTool( const std::string& sToolName, double dH, double dW, double dTh, int nToolNum) ;
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRC, int nToolNum) ;
bool SetToolNum( int nToolNum) bool SetToolNum( int nToolNum)
{ m_nCurrentNum = nToolNum ; return true ; } { m_nCurrentNum = nToolNum ; return true ; }
int GetType() const int GetType() const
@@ -70,7 +71,8 @@ class Tool
BULLNOSEMILL = 4, // Naso di toro BULLNOSEMILL = 4, // Naso di toro
CONEMILL = 5, // Con parte terminale conica CONEMILL = 5, // Con parte terminale conica
MORTISER = 6, // Mortasatrice MORTISER = 6, // Mortasatrice
CHISEL = 7} ; // Scalpello CHISEL = 7, // Scalpello
ADDITIVE = 8} ; // Additivo
private : private :
bool ModifyForCutterHeight( void) ; bool ModifyForCutterHeight( void) ;
+432 -63
View File
@@ -20,11 +20,14 @@
#include "CurveComposite.h" #include "CurveComposite.h"
#include "SurfFlatRegion.h" #include "SurfFlatRegion.h"
#include "IntersLineLine.h" #include "IntersLineLine.h"
#include "AdjustLoops.h"
#include "/EgtDev/Include/EGkPolyLine.h" #include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkCurve.h" #include "/EgtDev/Include/EGkCurve.h"
#include "DistPointCrvComposite.h" #include "DistPointCrvComposite.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include <algorithm> #include <algorithm>
#include <numeric>
using namespace std ; using namespace std ;
@@ -38,13 +41,13 @@ Tree::Tree( void)
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ; m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
} }
//---------------------------------------------------------------------------- ////----------------------------------------------------------------------------
Tree::Tree( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d& ptMin, const Point3d& ptMax) //Tree::Tree( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d& ptMin, const Point3d& ptMax)
: m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}), // : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}),
m_bSplitPatches( true), m_bTestMode( false) // m_bSplitPatches( true), m_bTestMode( false)
{ //{
SetSurf( pSrfBz, bSplitPatches, ptMin, ptMax) ; // SetSurf( pSrfBz, bSplitPatches, ptMin, ptMax) ;
} //}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
Tree::~Tree( void) Tree::~Tree( void)
@@ -61,17 +64,162 @@ Tree::Tree( const Point3d ptBl, const Point3d ptTr)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void bool
Tree::LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const
{
// //questo metodo NON VA BENE perchè tiene anche parte dei loop che stanno fuori dal parametrico e quindi il FINDCELL può fallire
//
//// creo la flat region di trim, quella del parametrico e li interseco
//PtrOwner<ISurfFlatRegion> pSfrTrim( GetSurfFlatRegionFromPolyLine( pl)) ;
//bool bInverted = false ;
//if ( ! pSfrTrim->GetNormVersor().IsZplus()) {
// pSfrTrim->Invert() ;
// bInverted = true ;
//}
//PtrOwner<ISurfFlatRegion> pParamTrim( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ;
//if ( ! pParamTrim->Intersect( *pSfrTrim) || ! pParamTrim->IsValid()) {
// if ( ! pParamTrim->Offset( 10 * EPS_SMALL, ICurve::OFF_EXTEND))
// return false ;
// if ( ! pParamTrim->Intersect( *pSfrTrim) || ! pParamTrim->IsValid())
// return false ;
// if ( ! pParamTrim->Offset( -10 * EPS_SMALL, ICurve::OFF_EXTEND))
// return false ;
//}
//// ricostruisco la curva tenendo solo le parti dentro lo spazio parametrico
//// devo recuperare la polyline dei bordi dei vari chunk creati
//for ( int c = 0 ; c < int( pParamTrim->GetChunkCount()) ; ++c) {
// for ( int l = 0 ; l < pParamTrim->GetLoopCount(c) ; ++l) {
// PtrOwner<ICurve> pCrv ( pParamTrim->GetLoop( c, l)) ;
// if ( bInverted)
// pCrv->Invert() ;
// PolyLine plApprox ;
// double dLinTol = 10 * EPS_SMALL, dAngTolDeg = 5 ;
// int nType = 0 ;
// pCrv->ApproxWithLines( dLinTol, dAngTolDeg, nType, plApprox) ;
// // aggiungo la polyline del chunk
// vPl.push_back( plApprox) ;
// }
//}
//// CON LE CURVE ( INTERSEZIONI CON BORDO PARAMETRICO)
PtrOwner<ICurveComposite> pCCEdge( CreateCurveComposite()) ;
pCCEdge->AddPoint( m_mTree.at(-1).GetTopRight()) ;
pCCEdge->AddLine( m_mTree.at(-1).GetTopLeft()) ;
pCCEdge->AddLine( m_mTree.at(-1).GetBottomLeft()) ;
pCCEdge->AddLine( m_mTree.at(-1).GetBottomRight()) ;
pCCEdge->Close() ;
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
pCC->FromPolyLine( pl) ;
ICURVEPLIST vCrv ;
AdjustLoops( Release( pCC), vCrv, false) ;
if ( vCrv.size() > 1)
VerifyLoopOrientation( vCrv, vbOrientation) ;
for ( auto itCrv = vCrv.begin() ; itCrv != vCrv.end() ; ++itCrv) {
IntersCurveCurve icc( *pCCEdge, *(*itCrv)) ;
CRVCVECTOR vCrvClass ;
ICRVCOMPOPOVECTOR vCC ;
if ( ! icc.GetCurveClassification( 1, 0.01, vCrvClass))
return false ; // se non riesco a calcolare la classificazione potrei provare a ricostruire a mano usando le intersezioni trovate
int nLast = 0 ;
if ( vCrvClass.size() > 1) {
for ( int i = 0 ; i < int( vCrvClass.size()) ; ++i) {
if ( vCrvClass[i].nClass != CRVC_OUT) {
// se continua la curva precedente allora la giunta
if ( vCC.size() != 0 && vCrvClass[i].dParS == vCrvClass[nLast].dParE)
vCC.back()->AddCurve( (*itCrv)->CopyParamRange( vCrvClass[i].dParS, vCrvClass[i].dParE)) ;
// sennò creo una nuova curva
else
vCC.emplace_back( GetCurveComposite( (*itCrv)->CopyParamRange( vCrvClass[i].dParS, vCrvClass[i].dParE))) ;
nLast = i ;
}
}
POLYLINEVECTOR vPL ;
// qui devo ricostruire la curva con i pezzi da tenere
for ( int i = 0 ; i < int( vCC.size()) ; ++i) {
PolyLine plApprox ;
vCC[i]->ApproxWithLines( 0.01,15, 0, plApprox) ;
vPL.push_back( plApprox) ;
}
PolyLine plNew ;
// ricostruzione col bordo
CloseOpenCuts( vPL, plNew) ;
vPl.push_back( plNew) ;
}
else {
PolyLine plApprox ; (*itCrv)->ApproxWithLines( 0.01, 15, 0, plApprox) ;
vPl.push_back( plApprox) ;
}
}
for ( auto it = vCrv.begin() ; it != vCrv.end() ; ++it)
delete (*it) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::VerifyLoopOrientation( ICURVEPLIST& vpCrv, BOOLVECTOR& vbOrientation) const
{
// verifico che il verso dei loop sia corretto controllando le relazioni tra loop
vpCrv.sort( []( ICurve* a, ICurve* b) { double AreaA, AreaB ; a->GetAreaXY( AreaA) ; b->GetAreaXY( AreaB) ; return abs(AreaA) > abs(AreaB) ;}) ;
auto it = vpCrv.begin() ;
for ( ++it ; it != vpCrv.end() ; ++it) {
bool bIdentified = false ;
for ( auto k = it ; k != vpCrv.begin() ;) {
--k ;
IntersCurveCurve icc( **k, **it) ;
int nRes = icc.GetRegionCurveClassification() ;
if ( nRes == CCREGC_IN1) {
bIdentified = true ;
vbOrientation.push_back( ! vbOrientation[ distance( vpCrv.begin(), k)]) ; // l'orientazione deve essere opposta alla prima curva che contiene la corrente
break ;
}
}
if ( ! bIdentified)
vbOrientation.push_back( vbOrientation[0]) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::AdjustLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const
{
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
pCC->FromPolyLine( pl) ;
ICURVEPLIST vCrv ;
AdjustLoops( Release( pCC), vCrv, false) ;
if ( vCrv.size() > 1)
VerifyLoopOrientation( vCrv, vbOrientation) ;
for ( auto itCrv = vCrv.begin() ; itCrv != vCrv.end() ; ++itCrv) {
PolyLine plApprox ; (*itCrv)->ApproxWithLines( 0.01, 15, 0, plApprox) ;
vPl.push_back( plApprox) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMin, const Point3d& ptMax) Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMin, const Point3d& ptMax)
{ {
if ( pSrfBz == nullptr || ! pSrfBz->IsValid())
return false ;
// pulisco i vettori membri // pulisco i vettori membri
m_mTree.clear() ;
m_vnLeaves.clear() ; m_vnLeaves.clear() ;
m_vnParents.clear() ; m_vnParents.clear() ;
m_mVert.clear() ; m_mVert.clear() ;
m_vLoop.clear() ; //m_vLoop.clear() ;
m_mChunk.clear() ; m_mChunk.clear() ;
m_vPlApprox.clear() ; m_vPlApprox.clear() ;
m_vChunk.clear() ;
m_vPolygons.clear() ; m_vPolygons.clear() ;
m_vPlLoop2D.clear() ; m_vPlLoop2D.clear() ;
@@ -90,11 +238,18 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
m_bBilinear = true ; m_bBilinear = true ;
if ( nSpanU * nSpanV != 1) if ( nSpanU * nSpanV != 1)
m_bMulti = true ; m_bMulti = true ;
// creo la cella Root
Point3d ptTop( nSpanU * SBZ_TREG_COEFF, nSpanV * SBZ_TREG_COEFF) ;
bool bLimited = false ;
if ( ! AreSamePointExact( ptMax,ORIG) && ! AreSamePointExact( ptMax,ptTop)) {
ptTop = ptMax ;
bLimited = true ;
}
Cell cRoot( ptMin, ptTop) ;
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
// recupero i loop di trim e li divido per chunk // recupero i loop di trim e li divido per chunk
if ( m_bTrimmed) { if ( m_bTrimmed) {
int nLoop = 0 ; int nLoop = 0 ;
INTVECTOR vChunk ;
// recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk // recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk
PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ; PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ;
double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico
@@ -102,7 +257,6 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) { for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) {
PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ; PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ;
for ( int j = 0 ; j < pChunk->GetLoopCount( 0) ; ++ j) { for ( int j = 0 ; j < pChunk->GetLoopCount( 0) ; ++ j) {
vChunk.push_back( nLoop) ;
// i chunk della falt region sono ancora flat region composte da 1 chunk // i chunk della falt region sono ancora flat region composte da 1 chunk
PtrOwner<ICurve> pLoop ( pChunk->GetLoop( 0, j)) ; PtrOwner<ICurve> pLoop ( pChunk->GetLoop( 0, j)) ;
// rimuovo i difetti dei loop prima di salvarli // rimuovo i difetti dei loop prima di salvarli
@@ -111,9 +265,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
pCrvCompo->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ; pCrvCompo->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ;
pCrvCompo->RemoveSmallParts( dLinTol, dAngTolDeg) ; pCrvCompo->RemoveSmallParts( dLinTol, dAngTolDeg) ;
PtrOwner<ICurve> pCrv( pCrvCompo->Clone()) ; PtrOwner<ICurve> pCrv( pCrvCompo->Clone()) ;
m_vLoop.emplace_back( Release( pLoop)) ;
m_mChunk[nLoop] = i ;
++ nLoop ;
// approssimo i loop di trim con delle spezzate // approssimo i loop di trim con delle spezzate
PolyLine plApprox ; PolyLine plApprox ;
int nType = 0 ; int nType = 0 ;
@@ -127,32 +279,23 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
bCCW = true ; bCCW = true ;
else else
bCCW = false ; bCCW = false ;
m_vPlApprox.push_back( tuple<PolyLine,bool>(plApprox,bCCW)) ;
POLYLINEVECTOR vPlAdjusted ;
BOOLVECTOR vbOrientation ;
vbOrientation.push_back( bCCW) ;
AdjustLoop( plApprox, vPlAdjusted, vbOrientation) ;
nLoop = int ( m_vPlApprox.size()) ;
for ( int k = 0 ; k < int( vPlAdjusted.size()) ; ++k )
m_vPlApprox.push_back( tuple<PolyLine,bool>(vPlAdjusted[k], vbOrientation[k])) ;
// aggiorno la mappa del chunk di appartenenza per tutti i loop aggiunti // do per scontato che siano tutti dello stesso chunk anche se li ho separati
//m_vLoop.emplace_back( Release( pLoop)) ;
for ( int k = nLoop ; k < int( m_vPlApprox.size()); ++k)
m_mChunk[k] = i ;
} }
// li riordino dal più grande al più piccolo
sort(vChunk.begin(), vChunk.end(), [this]( const int& a, const int& b) { double dArea1, dArea2 ;
m_vLoop[a]->GetAreaXY( dArea1) ;
m_vLoop[b]->GetAreaXY( dArea2) ;
return dArea1 > dArea2 ; }) ;
m_vChunk.push_back( vChunk) ;
vChunk.clear() ;
} }
// li riordino dal più grande al più piccolo
sort(m_vChunk.begin(), m_vChunk.end(), [this]( const INTVECTOR& a, const INTVECTOR& b) { double dArea1, dArea2 ;
m_vLoop[a[0]]->GetAreaXY( dArea1) ;
m_vLoop[b[0]]->GetAreaXY( dArea2) ;
return dArea1 > dArea2 ;}) ;
} }
// salvo i vertici 3d della cella root // salvo i vertici 3d della cella root
Point3d ptTop( nSpanU * SBZ_TREG_COEFF, nSpanV * SBZ_TREG_COEFF) ;
bool bLimited = false ;
if ( ! AreSamePointExact( ptMax,ORIG) && ! AreSamePointExact( ptMax,ptTop)) {
ptTop = ptMax ;
bLimited = true ;
}
m_mTree.clear() ;
Cell cRoot( ptMin, ptTop) ;
m_mTree.insert( pair< int, Cell>( -1, cRoot)) ;
Point3d ptP00, ptP10, ptP11, ptP01 ; Point3d ptP00, ptP10, ptP11, ptP01 ;
bool bOk = false ; bool bOk = false ;
if ( ! bLimited) { if ( ! bLimited) {
@@ -328,6 +471,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi
m_vDim.push_back( ( dLen1 > EPS_ZERO ? dLen1 : 1)) ; m_vDim.push_back( ( dLen1 > EPS_ZERO ? dLen1 : 1)) ;
m_vDim.push_back( ( dLen2 > EPS_ZERO ? dLen2 : 1)) ; m_vDim.push_back( ( dLen2 > EPS_ZERO ? dLen2 : 1)) ;
m_vDim.push_back( ( dLen3 > EPS_ZERO ? dLen3 : 1)) ; m_vDim.push_back( ( dLen3 > EPS_ZERO ? dLen3 : 1)) ;
return true ;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -1018,7 +1162,7 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const
for ( int k : vTopNeighs) for ( int k : vTopNeighs)
vCells.push_back( m_mTree.at( k)) ; vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per x crescente // le celle restituite sono ordinate per x crescente
sort( vCells.begin(), vCells.end(), Cell::minorX) ; std::sort( vCells.begin(), vCells.end(), Cell::minorX) ;
vTopNeighs.clear() ; vTopNeighs.clear() ;
for ( Cell c : vCells) for ( Cell c : vCells)
vTopNeighs.push_back( c.m_nId) ; vTopNeighs.push_back( c.m_nId) ;
@@ -1100,7 +1244,7 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const
for ( int k : vBottomNeighs) for ( int k : vBottomNeighs)
vCells.push_back( m_mTree.at( k)) ; vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per x crescente // le celle restituite sono ordinate per x crescente
sort( vCells.begin(), vCells.end(), Cell::minorX) ; std::sort( vCells.begin(), vCells.end(), Cell::minorX) ;
vBottomNeighs.clear() ; vBottomNeighs.clear() ;
for ( Cell c : vCells) for ( Cell c : vCells)
vBottomNeighs.push_back( c.m_nId) ; vBottomNeighs.push_back( c.m_nId) ;
@@ -1181,7 +1325,7 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const
for ( int k : vLeftNeighs) for ( int k : vLeftNeighs)
vCells.push_back( m_mTree.at( k)) ; vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per y crescente // le celle restituite sono ordinate per y crescente
sort( vCells.begin(), vCells.end(), Cell::minorY) ; std::sort( vCells.begin(), vCells.end(), Cell::minorY) ;
vLeftNeighs.clear() ; vLeftNeighs.clear() ;
for ( Cell c : vCells) for ( Cell c : vCells)
vLeftNeighs.push_back( c.m_nId) ; vLeftNeighs.push_back( c.m_nId) ;
@@ -1262,7 +1406,7 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const
for ( int k : vRightNeighs) for ( int k : vRightNeighs)
vCells.push_back( m_mTree.at( k)) ; vCells.push_back( m_mTree.at( k)) ;
// le celle restituite sono ordinate per y crescente // le celle restituite sono ordinate per y crescente
sort( vCells.begin(), vCells.end(), Cell::minorY) ; std::sort( vCells.begin(), vCells.end(), Cell::minorY) ;
vRightNeighs.clear() ; vRightNeighs.clear() ;
for ( Cell c : vCells) for ( Cell c : vCells)
vRightNeighs.push_back( c.m_nId) ; vRightNeighs.push_back( c.m_nId) ;
@@ -1366,15 +1510,15 @@ Tree::GetDepth( int nId, int nRef = -2) const
return i ; return i ;
} }
//---------------------------------------------------------------------------- ////----------------------------------------------------------------------------
struct generator //struct generator
{ //{
int value ; // int value ;
generator( void) // generator( void)
{ value = -1 ; } // { value = -1 ; }
int operator() () // int operator() ()
{ return ++value ; } // { return ++value ; }
} ; //} ;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
@@ -1397,6 +1541,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons)
POLYLINEVECTOR vPolygonsBasic ; POLYLINEVECTOR vPolygonsBasic ;
GetPolygonsBasic( vPolygonsBasic) ; GetPolygonsBasic( vPolygonsBasic) ;
// aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim // aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim
m_vCEdge2D.clear() ;
for ( int i = 0 ; i < 4 ; ++i) { for ( int i = 0 ; i < 4 ; ++i) {
m_vCEdge2D.emplace_back() ; m_vCEdge2D.emplace_back() ;
m_vCEdge2D.back().second.Init( false, EPS_SMALL, 1) ; m_vCEdge2D.back().second.Init( false, EPS_SMALL, 1) ;
@@ -1422,7 +1567,8 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons)
INTVECTOR vnParentChunk ; INTVECTOR vnParentChunk ;
// vettore in cui salvo i loop che non appartengono al poligono che sto cotruendo nel ciclo attuale e da cui ripasserò dopo // vettore in cui salvo i loop che non appartengono al poligono che sto cotruendo nel ciclo attuale e da cui ripasserò dopo
INTVECTOR vToCheck( (int) m_mTree[nId].m_vInters.size()) ; INTVECTOR vToCheck( (int) m_mTree[nId].m_vInters.size()) ;
generate_n( vToCheck.begin(), (int) m_mTree[nId].m_vInters.size(), generator()) ; //generate_n( vToCheck.begin(), (int) m_mTree[nId].m_vInters.size(), generator()) ;
iota (vToCheck.begin(), vToCheck.end(), 0) ;
// numero di poligoni aggiunti // numero di poligoni aggiunti
int nPoly = 0 ; int nPoly = 0 ;
// scorro sui vettori intersezione della cella nId e sui suoi vertici // scorro sui vettori intersezione della cella nId e sui suoi vertici
@@ -1528,7 +1674,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells)
vNeigh.clear() ; vNeigh.clear() ;
vVertices.push_back( m_mTree.at( nId).GetTopRight()) ; vVertices.push_back( m_mTree.at( nId).GetTopRight()) ;
GetTopNeigh ( nId, vNeigh) ; GetTopNeigh ( nId, vNeigh) ;
reverse( vNeigh.begin(), vNeigh.end()) ; std::reverse( vNeigh.begin(), vNeigh.end()) ;
// aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top // aggiungo i vertici che sono sul lato top, solo se ho più di un vicino top
if ( ! vNeigh.empty() && vNeigh.size() != 1) { if ( ! vNeigh.empty() && vNeigh.size() != 1) {
// se la superficie è chiusa lungo il parametro V e la cella è sul lato top // se la superficie è chiusa lungo il parametro V e la cella è sul lato top
@@ -1549,7 +1695,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells)
bTopLeft = false ; bTopLeft = false ;
vNeigh.clear() ; vNeigh.clear() ;
GetLeftNeigh ( nId, vNeigh) ; GetLeftNeigh ( nId, vNeigh) ;
reverse( vNeigh.begin(), vNeigh.end()) ; std::reverse( vNeigh.begin(), vNeigh.end()) ;
// aggiungo i vertici che sono sul lato left, solo se ho più di un vicino left // aggiungo i vertici che sono sul lato left, solo se ho più di un vicino left
if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) { if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) {
// se la superficie è chiusa lungo il parametro U e la cella è sul lato left // se la superficie è chiusa lungo il parametro U e la cella è sul lato left
@@ -2002,7 +2148,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
// riordino i vettori di intersezione per ogni cella e setto il flag RightEdgeIn // riordino i vettori di intersezione per ogni cella e setto il flag RightEdgeIn
for ( int nId : m_vnLeaves) { for ( int nId : m_vnLeaves) {
sort( m_mTree[nId].m_vInters.begin(), m_mTree[nId].m_vInters.end()) ; std::sort( m_mTree[nId].m_vInters.begin(), m_mTree[nId].m_vInters.end()) ;
SetRightEdgeIn( nId) ; SetRightEdgeIn( nId) ;
} }
@@ -2287,7 +2433,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
INTVECTOR vNeigh, vNeigh1 ; INTVECTOR vNeigh, vNeigh1 ;
if ( nEdge == 0) { if ( nEdge == 0) {
GetTopNeigh( nId, vNeigh) ; GetTopNeigh( nId, vNeigh) ;
reverse( vNeigh.begin(), vNeigh.end()) ; std::reverse( vNeigh.begin(), vNeigh.end()) ;
for ( int j : vNeigh) { for ( int j : vNeigh) {
if ( ptInters.x >= m_mTree[j].GetBottomLeft().x) { if ( ptInters.x >= m_mTree[j].GetBottomLeft().x) {
nId = j ; nId = j ;
@@ -2307,7 +2453,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool
} }
else if ( nEdge == 1) { else if ( nEdge == 1) {
GetLeftNeigh( nId, vNeigh) ; GetLeftNeigh( nId, vNeigh) ;
reverse( vNeigh.begin(), vNeigh.end()) ; std::reverse( vNeigh.begin(), vNeigh.end()) ;
for ( int j : vNeigh) { for ( int j : vNeigh) {
if ( ptInters.y >= m_mTree[j].GetBottomLeft().y) { if ( ptInters.y >= m_mTree[j].GetBottomLeft().y) {
nId = j ; nId = j ;
@@ -3509,8 +3655,16 @@ Tree::CheckIfBetween( const Inters& inA, const Inters& inB) const
} }
else if ( nEdge == 7) else if ( nEdge == 7)
nEdge = 0 ; nEdge = 0 ;
if ( AreSameEdge( inA.nIn, inA.nOut) && ! CheckIfBefore( inA.nIn, inA.vpt[0], inA.vpt.back(), nEdge))
vEdges.push_back( nEdge) ;
int nEdgeIn = inA.nIn ;
if ( nEdgeIn > 3 && nEdgeIn != 7) {
nEdgeIn = nEdgeIn - 4 ;
}
else if ( nEdgeIn == 7)
nEdgeIn = 0 ;
// creo la sequenza di Edges da scorrere per trovare i possibili validNextStart // creo la sequenza di Edges da scorrere per trovare i possibili validNextStart
while ( ! AreSameEdge( nEdge, inA.nIn) || (int) vEdges.size() == 0) { while ( ! AreSameEdge( nEdge, nEdgeIn) || (int) vEdges.size() == 0) {
vEdges.push_back( nEdge) ; vEdges.push_back( nEdge) ;
if ( nEdge == 3) if ( nEdge == 3)
nEdge = 0 ; nEdge = 0 ;
@@ -3601,6 +3755,8 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
nEdge = 2 ; nEdge = 2 ;
else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptTR.x) < EPS_SMALL) else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && abs( ptToAssign.x - ptTR.x) < EPS_SMALL)
nEdge = 3 ; nEdge = 3 ;
else if ( ptToAssign.y > ptBL.y && ptToAssign.y < ptTR.y && ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x)
nEdge = -1 ;
else else
return false ; return false ;
return true ; return true ;
@@ -3618,10 +3774,10 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges)
GetRootNeigh( 0, vEdges[0]) ; GetRootNeigh( 0, vEdges[0]) ;
// le celle sui bordi orizzontali sono ordinate per x o y crescente, ma i io voglio costruire gli edge in senso antiorario a partire dal ptTR, // le celle sui bordi orizzontali sono ordinate per x o y crescente, ma i io voglio costruire gli edge in senso antiorario a partire dal ptTR,
// quindi devo invertire gli Edge 0 e 1 // quindi devo invertire gli Edge 0 e 1
reverse( vEdges[0].begin(), vEdges[0].end()) ; std::reverse( vEdges[0].begin(), vEdges[0].end()) ;
vEdges.emplace_back() ; vEdges.emplace_back() ;
GetRootNeigh( 1, vEdges[1]) ; GetRootNeigh( 1, vEdges[1]) ;
reverse( vEdges[1].begin(), vEdges[1].end()) ; std::reverse( vEdges[1].begin(), vEdges[1].end()) ;
vEdges.emplace_back() ; vEdges.emplace_back() ;
GetRootNeigh( 2, vEdges[2]) ; GetRootNeigh( 2, vEdges[2]) ;
vEdges.emplace_back() ; vEdges.emplace_back() ;
@@ -3831,12 +3987,12 @@ Tree::AdjustCuts( void)
if ( int( m_mTree.at( -1).m_vInters.size()) == 1) if ( int( m_mTree.at( -1).m_vInters.size()) == 1)
return true ; return true ;
// li riordino per ordine di quali taglio incontrerei percorrendo il bordo della cella a partire da ptTR // li riordino per ordine di quali taglio incontrerei percorrendo il bordo della cella a partire da ptTR
sort( m_mTree.at( -1).m_vInters.begin(), m_mTree.at( -1).m_vInters.end(), [](Inters& a, Inters& b){ return Inters::FirstEncounter(a,b) ;}) ; std::sort( m_mTree.at( -1).m_vInters.begin(), m_mTree.at( -1).m_vInters.end(), [](Inters& a, Inters& b){ return Inters::FirstEncounter(a,b) ;}) ;
// ora controllo che le intersezioni che trovo siano ingressi alternati ad uscite, sennò inverto l'intersezione // ora controllo che le intersezioni che trovo siano ingressi alternati ad uscite, sennò inverto l'intersezione
bool bPreviousWasStart = m_mTree.at( -1).m_vInters.at(0).bSortedbyStart ; bool bPreviousWasStart = m_mTree.at( -1).m_vInters.at(0).bSortedbyStart ;
for ( int i = 0 ; i < int( m_mTree.at( -1).m_vInters.size()); ++i) { for ( int i = 0 ; i < int( m_mTree.at( -1).m_vInters.size()); ++i) {
if ( m_mTree.at( -1).m_vInters.at(i).bSortedbyStart == bPreviousWasStart) { if ( m_mTree.at( -1).m_vInters.at(i).bSortedbyStart == bPreviousWasStart) {
reverse( m_mTree.at( -1).m_vInters.at(i).vpt.begin(), m_mTree.at( -1).m_vInters.at(i).vpt.end()) ; std::reverse( m_mTree.at( -1).m_vInters.at(i).vpt.begin(), m_mTree.at( -1).m_vInters.at(i).vpt.end()) ;
int nEdgeOutNew = m_mTree.at( -1).m_vInters.at(i).nIn ; int nEdgeOutNew = m_mTree.at( -1).m_vInters.at(i).nIn ;
m_mTree.at( -1).m_vInters.at(i).nIn = m_mTree.at( -1).m_vInters.at(i).nOut ; m_mTree.at( -1).m_vInters.at(i).nIn = m_mTree.at( -1).m_vInters.at(i).nOut ;
m_mTree.at( -1).m_vInters.at(i).nOut = nEdgeOutNew ; m_mTree.at( -1).m_vInters.at(i).nOut = nEdgeOutNew ;
@@ -3859,7 +4015,8 @@ Tree::CreateCellContour( POLYLINEMATRIX& vPolygons)
// preparo tutto per poter chiamare la createCellPolygon // preparo tutto per poter chiamare la createCellPolygon
m_vnLeaves.push_back( nRoot) ; m_vnLeaves.push_back( nRoot) ;
INTVECTOR vToCheck( (int) m_mTree.at(nRoot).m_vInters.size()) ; INTVECTOR vToCheck( (int) m_mTree.at(nRoot).m_vInters.size()) ;
generate_n( vToCheck.begin(), (int) m_mTree.at(nRoot).m_vInters.size(), generator()) ; //generate_n( vToCheck.begin(), (int) m_mTree.at(nRoot).m_vInters.size(), generator()) ;
iota( vToCheck.begin(), vToCheck.end(), 0) ;
int nPoly = 0 ; int nPoly = 0 ;
INTVECTOR vnParentChunk ; INTVECTOR vnParentChunk ;
PolyLine pl ; PolyLine pl ;
@@ -3877,3 +4034,215 @@ Tree::CreateCellContour( POLYLINEMATRIX& vPolygons)
} }
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
Tree::CloseOpenCuts( POLYLINEVECTOR& vPL, PolyLine& plNew) const // da verificare e comunque funzione probabilmente inutile
{
if ( vPL.size() == 1 && vPL[0].IsClosed()) {
plNew = vPL[0] ;
return true ;
}
vector<Inters> vInters ;
for ( int i = 0 ; i < int( vPL.size()) ; ++i) {
vInters.emplace_back() ;
Point3d ptStart ; vPL[i].GetFirstPoint( ptStart) ;
OnWhichEdge( -1, ptStart, vInters.back().nIn) ;
Point3d ptEnd ; vPL[i].GetLastPoint( ptEnd) ;
OnWhichEdge( -1, ptEnd, vInters.back().nOut) ;
PNTULIST lPnt = vPL[i].GetUPointList() ;
for ( auto it = lPnt.begin() ; it != lPnt.end() ; ++it)
vInters.back().vpt.push_back( (*it).first) ;
}
std::sort( vInters.begin(), vInters.end(), [](Inters &left, Inters &right) { return left < right;}) ;
bool bNotCameBack = true ;
int nEdge = vInters[0].nOut ;
PNTULIST lPnt = vPL[0].GetUPointList() ;
for ( auto it = lPnt.begin() ; it != lPnt.end() ; ++it)
plNew.AddUPoint( (*it).second, (*it).first) ;
// se ero in un vertice passo all'edge successivo
if ( nEdge > 3 && nEdge != 7)
nEdge = nEdge - 4 ;
else if ( nEdge == 7)
nEdge = 0 ;
int nInters = 0 ;
while ( bNotCameBack) {
bool bAtNextStart = false ;
//PolyLine plEdge ;
double dCount ; plNew.GetLastU( dCount) ;
plNew.AddUPoint( dCount, vInters[nInters].vpt.back()) ;
++ dCount ;
++ nInters ;
if ( nInters == vInters.size())
nInters = 0 ;
// scorro tutti i lati finché non torno allo start del loop
while( ! bAtNextStart) {
Point3d ptToAdd ;
if ( nEdge == 0)
ptToAdd = m_mTree.at(-1).GetTopLeft() ;
else if ( nEdge == 1)
ptToAdd = m_mTree.at(-1).GetBottomLeft() ;
else if ( nEdge == 2)
ptToAdd = m_mTree.at(-1).GetBottomRight() ;
else if ( nEdge == 3)
ptToAdd = m_mTree.at(-1).GetTopRight() ;
if ( plNew.AddUPoint( dCount, ptToAdd))
++ dCount ;
if ( nEdge > 3 && nEdge != 7)
nEdge = nEdge - 4 ;
else if ( nEdge < 3)
++ nEdge ;
else
nEdge = 0 ;
if ( AreSameEdge(nEdge,vInters[nInters].nIn))
bAtNextStart = true ;
}
if ( nInters != 0 && nInters < int(vPL.size())) {
// aggiungo la polyline successiva
PNTULIST lPnt = vPL[nInters].GetUPointList() ;
double dLastU ; vPL[nInters-1].GetLastU( dLastU) ;
++ dLastU ;
for ( auto it = lPnt.begin() ; it != lPnt.end() ; ++it)
plNew.AddUPoint( dLastU + (*it).second, (*it).first) ;
}
if ( AreSameEdge(nEdge, vInters[0].nIn)) {
plNew.Close() ;
bNotCameBack = false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
Tree::CloseOpenCuts( void)
{
int nRoot = -1 ;
// tra i loop del parametrico seleziono quelli aperti
// creo il vettore inters, lo riordino e poi rendo chiusi i loop ( che possono restare indipendenti o unirsi ad altri loop aperti)
INTVECTOR vOpen ;
for ( int i = 0 ; i < int(m_vPlApprox.size()) ; ++i ) {
if ( ! get<0>(m_vPlApprox[i]).IsClosed()) {
m_mTree.at( nRoot).m_vInters.emplace_back() ;
Point3d ptStart ; get<0>(m_vPlApprox[i]).GetFirstPoint( ptStart) ;
OnWhichEdge( nRoot, ptStart, m_mTree.at( nRoot).m_vInters.back().nIn) ;
Point3d ptEnd ; get<0>(m_vPlApprox[i]).GetLastPoint( ptEnd) ;
OnWhichEdge( nRoot, ptEnd, m_mTree.at( nRoot).m_vInters.back().nOut) ;
vOpen.push_back( i) ;
}
}
// riordino le intersezioni
std::sort( m_mTree.at(nRoot).m_vInters.begin(), m_mTree.at(nRoot).m_vInters.end()) ;
m_vnLeaves.push_back( -1) ;
// chiamo la GetPolygons
POLYLINEMATRIX mPL ;
GetPolygons( mPL) ;
//creo il nuovo vettore di polyline di trim
// tengo quelli che erano i trim chiusi
for ( int t = int(vOpen.size()) - 1 ; t > -1 ; ++t ) {
m_vPlApprox.erase( m_vPlApprox.begin() + vOpen[t]) ;
}
// aggiungo i nuovi trim creati
for ( int t = 0 ; t < int( mPL[0].size()) ; ++t) {
m_vPlApprox.push_back( pair<PolyLine, bool>(mPL[0][t], true)) ;
}
m_vnLeaves.clear() ;
m_mTree.at( nRoot).m_vInters.clear() ;
//// tra i loop del parametrico seleziono quelli aperti
//// creo il vettore inters, lo riordino e poi rendo chiusi i loop ( che possono restare indipendenti o unirsi ad altri loop aperti)
//vector<pair<int,Inters>> vInters ;
//INTVECTOR vClosed ;
//for ( int i = 0 ; i < int(m_vPlApprox.size()) ; ++i ) {
// if ( ! get<0>(m_vPlApprox[i]).IsClosed()) {
// vInters.emplace_back() ;
// vInters.back().first = i ;
// Point3d ptStart ; get<0>(m_vPlApprox[i]).GetFirstPoint( ptStart) ;
// OnWhichEdge( -1, ptStart, vInters.back().second.nIn) ;
// Point3d ptEnd ; get<0>(m_vPlApprox[i]).GetLastPoint( ptEnd) ;
// OnWhichEdge( -1, ptEnd, vInters.back().second.nOut) ;
// }
// else
// vClosed.push_back( i) ;
//}
//// A MANO
//// chiudo le curve aperte e se necessario le giunto tra loro
//if ( vInters.size() != 0) {
// ICurveComposite* pCCOpen ( CreateBasicCurveComposite()) ;
// pCCOpen->FromPolyLine( get<0>(m_vPlApprox[vInters[0].first])) ;
// //sort( vInters.begin(), vInters.end()) ;
// sort( vInters.begin(), vInters.end(), [](pair<int,Inters> &left, pair<int,Inters> &right) { return left.second < right.second;}) ;
// bool bNotCameBack = true ;
// int nEdge = vInters[0].second.nOut ;
// // se ero in un vertice passo all'edge successivo
// if ( nEdge > 3 && nEdge != 7)
// nEdge = nEdge - 4 ;
// else if ( nEdge == 7)
// nEdge = 0 ;
// int nInters = 0 ;
// while ( bNotCameBack) {
// bool bAtNextStart = false ;
// PolyLine plEdge ;
// int nCount = 0 ;
// plEdge.AddUPoint( nCount, vInters[nInters].ptEnd) ;
// ++ nCount ;
// ++ nInters ;
// if ( nInters == vInters.size())
// nInters = 0 ;
// // scorro tutti i lati finché non torno allo start del loop
// while( ! bAtNextStart) {
// Point3d ptToAdd ;
// if ( nEdge == 0)
// ptToAdd = m_mTree.at(-1).GetTopLeft() ;
// else if ( nEdge == 1)
// ptToAdd = m_mTree.at(-1).GetBottomLeft() ;
// else if ( nEdge == 2)
// ptToAdd = m_mTree.at(-1).GetBottomRight() ;
// else if ( nEdge == 3)
// ptToAdd = m_mTree.at(-1).GetTopRight() ;
// if ( plEdge.AddUPoint( nCount, ptToAdd))
// ++ nCount ;
// if ( nEdge > 3 && nEdge != 7)
// nEdge = nEdge - 4 ;
// else if ( nEdge < 3)
// ++ nEdge ;
// else
// nEdge = 0 ;
// if ( AreSameEdge(nEdge,vInters[nInters].second.nIn))
// bAtNextStart = true ;
// }
// ICurveComposite* pCC( CreateCurveComposite()) ;
// pCC->FromPolyLine( plEdge) ;
// // aggiungo il tratto di edge
// pCCOpen->AddCurve( pCC) ;
// // agggiungo il prossio taglio
// if ( nInters != 0)
// pCCOpen->AddCurve( Release( vInters[nInters].pCrv)) ;
// if ( AreSameEdge(nEdge, vInters[0].second.nIn)) {
// pCCOpen->Close() ;
// bNotCameBack = false ;
// }
// }
// if ( ! pCCOpen->IsClosed()) {
// LOG_ERROR( pGenLog, "Error creating the contour from open trims") ;
// return nullptr ;
// }
// if ( ! bPlanarSurf) {
// if ( ! SimplifyCurve( pCCOpen)) {
// LOG_ERROR( pGenLog, "Error simplifying the contour recreated from the open trims") ;
// return nullptr ;
// }
// }
// SfrCntr.AddCurve( pCCOpen) ;
//}
return true ;
}
+9 -4
View File
@@ -231,9 +231,9 @@ class Tree
public : public :
~Tree( void) ; ~Tree( void) ;
Tree( void) ; Tree( void) ;
Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ; //Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
Tree( const Point3d ptBl, const Point3d ptTr) ; // creatore da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno Tree( const Point3d ptBl, const Point3d ptTr) ; // creatore da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno
void SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ; bool SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini) bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini)
bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax il massimo per la dimensione maggiore di un triangolo della trimesh bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax il massimo per la dimensione maggiore di un triangolo della trimesh
// dSideMin lunghezza minima del lato di una cella nello spazio reale // dSideMin lunghezza minima del lato di una cella nello spazio reale
@@ -254,6 +254,7 @@ class Tree
std::vector<bool> GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli std::vector<bool> GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli
private : private :
bool LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ; // funzione che limita i loop di trim allo spazio parametrico
bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert
bool Split( int nId) ; // funzione di split di una cella dell'albero a met nella direzione data da bVert bool Split( int nId) ; // funzione di split di una cella dell'albero a met nella direzione data da bVert
void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondit di +- 1 void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondit di +- 1
@@ -284,15 +285,19 @@ class Tree
bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ; // indica a quale edge o vertice il punto è vicino entro EPS_SMALL bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ; // indica a quale edge o vertice il punto è vicino entro EPS_SMALL
bool AdjustCuts( void) ; bool AdjustCuts( void) ;
bool UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) ; bool UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) ;
bool CloseOpenCuts( void) ;
bool CloseOpenCuts( POLYLINEVECTOR& vPL, PolyLine& pl) const ;
bool VerifyLoopOrientation( ICURVEPLIST& vpCrv, BOOLVECTOR& vbOrientation) const ; // verifico l'orientazione ( CCW o CW) delle polyline in base a come sono contenute le une nelle altre
bool AdjustLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ;
private : private :
const SurfBezier* m_pSrfBz ; // superficie di bezier 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 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 bool m_bTrimmed ; // superficie trimmata
INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk //INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk
std::map<int,int> m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim 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 //ICURVEPOVECTOR m_vLoop ; // curve di loop
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW
bool m_bBilinear ; // superficie bilineare bool m_bBilinear ; // superficie bilineare
bool m_bMulti ; // superficie multi-patch bool m_bMulti ; // superficie multi-patch
+1 -1
View File
@@ -1225,7 +1225,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
dMinDist = dZ - ptP.z ; dMinDist = dZ - ptP.z ;
nI = ( vPt[i].z >= vPt[j].z) ? i : j ; nI = ( vPt[i].z >= vPt[j].z) ? i : j ;
double dY = vPt[i].y + ( vPt[j].y - vPt[i].y) * dCoeff ; double dY = vPt[i].y + ( vPt[j].y - vPt[i].y) * dCoeff ;
ptInt.Set( ptP.y, dY, dZ) ; ptInt.Set( ptP.x, dY, dZ) ;
} }
} }
break ; break ;
+4
View File
@@ -169,6 +169,10 @@ Vector3d::ToSpherical( double* pdLen, double* pdAngVertDeg, double* pdAngOrizzDe
bool bool
Vector3d::Normalize( double dEps) Vector3d::Normalize( double dEps)
{ {
// verifico validità
if ( ! IsValid())
return false ;
// se già normalizzato, ok // se già normalizzato, ok
double dSqLen = x * x + y * y + z * z ; double dSqLen = x * x + y * y + z * z ;
if ( abs( 1.0 - dSqLen) < ( 2 * 1000 * DBL_EPSILON)) if ( abs( 1.0 - dSqLen) < ( 2 * 1000 * DBL_EPSILON))
+19
View File
@@ -2172,6 +2172,25 @@ VolZmap::SetChiselTool( const string& sToolName, double dH, double dW, double dT
return m_vTool[m_nCurrTool].SetChiselTool( sToolName, dH, dW, dTh, nFlag) ; return m_vTool[m_nCurrTool].SetChiselTool( sToolName, dH, dW, dTh, nFlag) ;
} }
//----------------------------------------------------------------------------
bool
VolZmap::SetAdditiveTool( const std::string& sToolName,
double dH, double dR, double dRC, int nFlag, bool bFirst)
{
if ( bFirst) {
m_vTool.resize( 1) ;
m_vTool[0].Clear( true) ;
}
else
m_vTool.emplace_back( true) ;
m_nCurrTool = int( m_vTool.size()) - 1 ;
if ( m_nCurrTool < 0)
return false ;
m_vTool[m_nCurrTool].SetTolerances( m_dToolLinTol, m_dToolAngTolDeg) ;
return m_vTool[m_nCurrTool].SetAdditiveTool( sToolName, dH, dR, dRC, nFlag) ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
int int
VolZmap::GetToolCount( void) const VolZmap::GetToolCount( void) const
+11
View File
@@ -78,6 +78,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool CopyFrom( const IGeoObj* pGObjSrc) override ; bool CopyFrom( const IGeoObj* pGObjSrc) override ;
bool Clear( void) override ; bool Clear( void) override ;
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ; bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateEmptyMap( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex) override ;
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ; bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) override ; bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) override ;
int GetBlockCount( void) const override ; int GetBlockCount( void) const override ;
@@ -109,6 +110,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
double dH, double dW, double dTh, double dRc, int nFlag, bool bFirst) override ; double dH, double dW, double dTh, double dRc, int nFlag, bool bFirst) override ;
bool SetChiselTool( const std::string& sToolName, bool SetChiselTool( const std::string& sToolName,
double dH, double dW, double dTh, int nFlag, bool bFirst) override ; double dH, double dW, double dTh, int nFlag, bool bFirst) override ;
bool SetAdditiveTool( const std::string& sToolName,
double dH, double dR, double dRC, int nFlag, bool bFirst) override ;
int GetToolCount( void) const override ; int GetToolCount( void) const override ;
bool SetCurrTool( int nCurrTool) override ; bool SetCurrTool( int nCurrTool) override ;
bool ResetTools( void) override ; bool ResetTools( void) override ;
@@ -319,6 +322,14 @@ class VolZmap : public IVolZmap, public IGeoObjRW
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
// Generica traslazione sfera // Generica traslazione sfera
bool CompBall_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad, int nToolNum) ; bool CompBall_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad, int nToolNum) ;
// Additivi
bool AddingMotion( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx) ;
bool AddingCylinder( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dRad) ;
bool AddingTruncatedCone( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dMaxRad, double dMinRad, double dHei,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool AddingSphere( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad) ;
bool AddingGeneral( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx) ;
// BBox per utensili e solidi semplici con movimenti di traslazione // BBox per utensili e solidi semplici con movimenti di traslazione
inline bool TestToolBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV, inline bool TestToolBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ; int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
+85 -11
View File
@@ -1,4 +1,4 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// EgalTech 2015-2016 // EgalTech 2015-2016
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4 // File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4
@@ -29,11 +29,11 @@ using namespace std ;
bool bool
VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex) VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex)
{ {
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo // Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
if ( dStep < EPS_SMALL || dLengthX < EPS_SMALL || dLengthY < EPS_SMALL || dLengthZ < EPS_SMALL) if ( dStep < EPS_SMALL || dLengthX < EPS_SMALL || dLengthY < EPS_SMALL || dLengthZ < EPS_SMALL)
return false ; return false ;
// Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL
m_dStep = max( dStep, 100 * EPS_SMALL) ; m_dStep = max( dStep, 100 * EPS_SMALL) ;
// Aggiorno la dimensione della mappa 1 o 3 // Aggiorno la dimensione della mappa 1 o 3
@@ -133,6 +133,80 @@ VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dL
return true ; return true ;
} }
//----------------------------------------------------------------------------
bool
VolZmap::CreateEmptyMap( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex)
{
// Controlli sull'ammissibilit delle dimensioni lineari del grezzo e del passo
if ( dStep < EPS_SMALL || dLengthX < EPS_SMALL || dLengthY < EPS_SMALL || dLengthZ < EPS_SMALL)
return false ;
// Il passo di discretizzazione non pu essere inferiore a 100 * EPS_SMALL
m_dStep = max( dStep, 100 * EPS_SMALL) ;
// Aggiorno la dimensione della mappa 1 o 3
m_nMapNum = ( bTriDex ? 3 : 1) ;
// Disponendo i sistemi di riferimento in una successione, le coordinate x,y,z
// di uno si ottengono da una permutazione ciclica di quelle del precedente sistema.
// es: X(n) = Z(n-1), Y(n) = X(n-1), Z(n) = Y(n-1)
// Definisco il sistema di riferimento intrinseco
m_MapFrame.Set( ptO, X_AX, Y_AX, Z_AX) ;
// Definisco i vettori dei limiti su indici
m_nNx[0] = max( int( ( dLengthX + EPS_SMALL) / m_dStep + 0.5), 1) ;
m_nNy[0] = max( int( ( dLengthY + EPS_SMALL) / m_dStep + 0.5), 1) ;
// Numero di componenti connesse
m_nConnectedCompoCount = 1 ;
// Se tridexel
if ( bTriDex) {
m_nNx[1] = m_nNy[0] ;
m_nNy[1] = max( int( ( dLengthZ + EPS_SMALL) / m_dStep + 0.5), 1) ;
m_nNx[2] = m_nNy[1] ;
m_nNy[2] = m_nNx[0] ;
}
// altrimenti mono dexel
else {
m_nNx[1] = 0 ;
m_nNy[1] = 0 ;
m_nNx[2] = 0 ;
m_nNy[2] = 0 ;
}
// Definisco il numero di blocchi lungo x,y e z
if ( ! CalcBlockNum())
return false ;
// Creazione delle mappe
// Calcolo del numero di celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_nDim[i] = m_nNx[i] * m_nNy[i] ;
// Creazione delle celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_Values[i].resize( m_nDim[i]) ;
// Definizione delle limitazioni iniziali in Z per ogni mappa
m_dMinZ[0] = 0 ;
m_dMaxZ[0] = dLengthZ ;
m_dMinZ[1] = 0 ;
m_dMaxZ[1] = ( bTriDex ? dLengthX : 0) ;
m_dMinZ[2] = 0 ;
m_dMaxZ[2] = ( bTriDex ? dLengthY : 0) ;
// Tipologia
m_nShape = GENERIC ;
// Aggiornamento dello stato
m_nStatus = OK ;
return true ;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex)
@@ -140,7 +214,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
// Aggiorno la dimensione della mappa 1 o 3 // Aggiorno la dimensione della mappa 1 o 3
m_nMapNum = ( bTriDex ? 3 : 1) ; m_nMapNum = ( bTriDex ? 3 : 1) ;
// Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL
m_dStep = max( dStep, 100 * EPS_SMALL) ; m_dStep = max( dStep, 100 * EPS_SMALL) ;
// Determino il bounding box della flat region // Determino il bounding box della flat region
@@ -223,11 +297,11 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
CRVCVECTOR IntersectionResults ; CRVCVECTOR IntersectionResults ;
Surf.GetCurveClassification( GridLine, EPS_SMALL, IntersectionResults) ; Surf.GetCurveClassification( GridLine, EPS_SMALL, IntersectionResults) ;
// Analizzo le parti in cui la retta è stata divisa // Analizzo le parti in cui la retta è stata divisa
int nPart = int( IntersectionResults.size()) ; int nPart = int( IntersectionResults.size()) ;
for ( int k = 0 ; k < nPart ; ++ k) { for ( int k = 0 ; k < nPart ; ++ k) {
// Se la retta è interna alla regione o coincidente con parte della sua frontiera // Se la retta è interna alla regione o coincidente con parte della sua frontiera
int nType = IntersectionResults[k].nClass ; int nType = IntersectionResults[k].nClass ;
if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) { if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) {
@@ -334,7 +408,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
int nPart = int( IntersectionResults.size()) ; int nPart = int( IntersectionResults.size()) ;
for ( int k = 0 ; k < nPart ; ++ k) { for ( int k = 0 ; k < nPart ; ++ k) {
// Se la retta è interna alla regione o coincidente con parte della sua frontiera // Se la retta è interna alla regione o coincidente con parte della sua frontiera
int nType = IntersectionResults[k].nClass ; int nType = IntersectionResults[k].nClass ;
if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) { if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) {
@@ -471,7 +545,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
int nIntType = IntersectionResults[k].nILTT ; int nIntType = IntersectionResults[k].nILTT ;
// Se c'è intersezione // Se c'è intersezione
if ( nIntType != ILTT_NO) { if ( nIntType != ILTT_NO) {
double dCos = IntersectionResults[k].dCosDN ; double dCos = IntersectionResults[k].dCosDN ;
@@ -527,7 +601,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
bool bool
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex)
{ {
// Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare // Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
double dVol ; double dVol ;
if ( ! Surf.IsClosed() || ! Surf.GetVolume( dVol) || dVol < 0) if ( ! Surf.IsClosed() || ! Surf.GetVolume( dVol) || dVol < 0)
return false ; return false ;
@@ -543,14 +617,14 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
Point3d ptMapOrig, ptMapEnd ; Point3d ptMapOrig, ptMapEnd ;
SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ; SurfBBox.GetMinMax( ptMapOrig, ptMapEnd) ;
// Il dexel se parte da un triangolo della trimesh può non trovare l'intersezione, // Il dexel se parte da un triangolo della trimesh può non trovare l'intersezione,
// quindi espandiamo il bounding box per ovviare al problema. // quindi espandiamo il bounding box per ovviare al problema.
SurfBBox.Expand( 100 * EPS_SMALL, 100 * EPS_SMALL, 100 * EPS_SMALL) ; SurfBBox.Expand( 100 * EPS_SMALL, 100 * EPS_SMALL, 100 * EPS_SMALL) ;
// Sistema di riferimento intrinseco dello Zmap // Sistema di riferimento intrinseco dello Zmap
m_MapFrame.Set( ptMapOrig, Frame3d::TOP) ; m_MapFrame.Set( ptMapOrig, Frame3d::TOP) ;
// Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL // Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL
m_dStep = max( dStep, 100 * EPS_SMALL) ; m_dStep = max( dStep, 100 * EPS_SMALL) ;
// Determino le dimensioni lineari del BBox // Determino le dimensioni lineari del BBox
+970 -273
View File
File diff suppressed because it is too large Load Diff
+21 -3
View File
@@ -414,6 +414,11 @@ Voronoi::GetBisectorCurve( int i)
CurveLine* pLine = CreateBasicCurveLine() ; CurveLine* pLine = CreateBasicCurveLine() ;
if ( pLine == nullptr) if ( pLine == nullptr)
return nullptr ; return nullptr ;
// costruisco il bisettore orientato dal parametro minore al maggiore
if ( dParS > dParE) {
swap( ptS, ptE) ;
swap( dParS, dParE) ;
}
pLine->Set( ptS, ptE) ; pLine->Set( ptS, ptE) ;
pLine->SetTempParam( dParS, 0) ; pLine->SetTempParam( dParS, 0) ;
pLine->SetTempParam( dParE, 1) ; pLine->SetTempParam( dParE, 1) ;
@@ -433,7 +438,7 @@ Voronoi::GetBisectorCurve( int i)
return nullptr ; return nullptr ;
pArc->SetC2P( ptC, ptS, ptE) ; pArc->SetC2P( ptC, ptS, ptE) ;
pArc->SetTempParam( dParS, 0) ; pArc->SetTempParam( dParS, 0) ;
pArc->SetTempParam( dParS, 1) ; pArc->SetTempParam( dParS, 1) ; // dParE = dParS
pArc->ToGlob( m_Frame) ; pArc->ToGlob( m_Frame) ;
return pArc ; return pArc ;
} }
@@ -449,15 +454,23 @@ Voronoi::GetBisectorCurve( int i)
if ( pCompo == nullptr) if ( pCompo == nullptr)
return nullptr ; return nullptr ;
// verifico se devo leggere i punti del bisettore al contrario per averlo orientato dal parametro minore al maggiore
bool bInvert = false ;
double dPar1, dPar2 ;
m_vroni->GetApproxedBisectorParams( i, dPar1, dPar2) ;
if ( dPar1 > dPar2 + EPS_SMALL)
bInvert = true ;
// punto iniziale // punto iniziale
Point3d pt ; Point3d pt ;
double dParS ; double dParS ;
m_vroni->GetApproxedBisectorPoint( i, 0, pt.v, dParS) ; m_vroni->GetApproxedBisectorPoint( i, bInvert ? nPoints - 1 : 0, pt.v, dParS) ;
pCompo->AddPoint( pt) ; pCompo->AddPoint( pt) ;
int nCrvCount = 0 ; int nCrvCount = 0 ;
double dParPrev = dParS ; double dParPrev = dParS ;
for ( int j = 1 ; j < nPoints ; j ++) { int j = bInvert ? nPoints - 2 : 1 ;
while ( ( bInvert && j >= 0) || ( ! bInvert && j < nPoints)) {
double dPar ; double dPar ;
m_vroni->GetApproxedBisectorPoint( i, j, pt.v, dPar) ; m_vroni->GetApproxedBisectorPoint( i, j, pt.v, dPar) ;
if ( pCompo->AddLine( pt)) { if ( pCompo->AddLine( pt)) {
@@ -468,6 +481,11 @@ Voronoi::GetBisectorCurve( int i)
dParPrev = dPar ; dParPrev = dPar ;
nCrvCount ++ ; nCrvCount ++ ;
} }
// aggiorno per punto successivo
if ( bInvert)
j -- ;
else
j ++ ;
} }
// setto parametri sulla curva // setto parametri sulla curva