Compare commits
144 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3e924113d3 | |||
| dcc3fc772a | |||
| a48f373e4d | |||
| 2ed2a34d55 | |||
| fcbdee1dba | |||
| 33d1ef4123 | |||
| fe2aba43e5 | |||
| c0b5f38301 | |||
| 1c157f323e | |||
| 3e6aa0d81b | |||
| 34089648b0 | |||
| 0bef1638d0 | |||
| 17759877d4 | |||
| d00064a671 | |||
| dc91f932f7 | |||
| d911862c84 | |||
| 1b025ec60e | |||
| 9d18e1a9ba | |||
| 3a8900983a | |||
| 971a76e473 | |||
| 35c019a03e | |||
| de97f249a2 | |||
| 81f0cc23bf | |||
| 8a0234093e | |||
| 88d355f2f7 | |||
| 20fd06d67c | |||
| 52f2785e67 | |||
| 2e2bd0ceec | |||
| e4c3c9a2a4 | |||
| e490c173e8 | |||
| 7e165a6dea | |||
| 49ff6e79a8 | |||
| 1160e3d067 | |||
| 91d667bcfc | |||
| b23df89cd3 | |||
| cf9737a48e | |||
| ae52115bda | |||
| 3dd9466938 | |||
| c0f7eb6727 | |||
| 76e2843ed3 | |||
| faa2004c29 | |||
| c9a59dc5ea | |||
| aaaf951990 | |||
| cc263089ca | |||
| d99b8f4c86 | |||
| f5e5441469 | |||
| 4206a4822f | |||
| 788a5bc4eb | |||
| a5a96c2bb5 | |||
| 881691e678 | |||
| 80f4d64ad4 | |||
| 7d9a641e39 | |||
| d82ccd8947 | |||
| 318b1e4b2f | |||
| 583e30170a | |||
| fe46b8ebd2 | |||
| 6a845e4f81 | |||
| 46e18b3977 | |||
| 20d146268b | |||
| 5013fc2b6c | |||
| 32a0e1d2b5 | |||
| 7ce9e7e26c | |||
| 9a6e972521 | |||
| 8c008f36c2 | |||
| eae29d4854 | |||
| 2bd53476ca | |||
| 015065f3c8 | |||
| 12862a6c76 | |||
| 9d869411e8 | |||
| 0c3c17e0f4 | |||
| 47f6eedd9c | |||
| b36adefd10 | |||
| 8cf8c0def5 | |||
| 1e6a70c60d | |||
| 9712e8c526 | |||
| 6b1f932dfc | |||
| 7882964b26 | |||
| 9653ba8d53 | |||
| ba66891539 | |||
| 4ab4a2fc81 | |||
| a6d9811595 | |||
| c94a62f5b2 | |||
| 535011072d | |||
| 718f5ce716 | |||
| 3f02119ef7 | |||
| 632b711b2a | |||
| 07faeaaa11 | |||
| 104726c5ee | |||
| e2445c0a15 | |||
| d253312139 | |||
| 9880fa0173 | |||
| 5952eee22c | |||
| 4483434711 | |||
| d276809906 | |||
| 93678ce56c | |||
| 8c4b0bde37 | |||
| 67c03daa42 | |||
| 469d1c3445 | |||
| 4268da4a1f | |||
| 7d3284fef3 | |||
| 3857cd4b5a | |||
| a04a748552 | |||
| 13ecae3829 | |||
| 1acd97d42a | |||
| 4f485d0e87 | |||
| d48348fa1c | |||
| 003dd0bdef | |||
| 6a92f6b80f | |||
| bf3760808e | |||
| ec109908fa | |||
| 3630b85632 | |||
| 45226d0b6f | |||
| fdce6e1853 | |||
| 8ffa9d7fb7 | |||
| 96ea6bc73e | |||
| 360484c9af | |||
| 47606bffcd | |||
| 7a2af0b5f2 | |||
| 8d2ae598e5 | |||
| aea99a635f | |||
| ce139c6925 | |||
| 4b19936136 | |||
| 6efb3a6e7f | |||
| 5dcf5f5616 | |||
| 451ef8356b | |||
| 3a623996d2 | |||
| 4bada73c83 | |||
| 156d0eea4b | |||
| 6e810f050e | |||
| 6bfb5c619f | |||
| c303b1273d | |||
| 8d0c04e092 | |||
| 5d62db3e73 | |||
| 8be2246249 | |||
| 1005aae0e9 | |||
| 0f8012ce61 | |||
| 2c159d7ce6 | |||
| b4058ad363 | |||
| 6b5de066b7 | |||
| 56cff98cf3 | |||
| 3168bee865 | |||
| 3d2f8c1495 | |||
| a3531c4841 | |||
| d7ec1fd304 |
@@ -16,9 +16,9 @@
|
||||
#include "CurveBezier.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkArcPntDirTgCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
+10
-3
@@ -14,8 +14,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "CAvToolTriangle.h"
|
||||
#include "CAvToolSurfTm.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DllMain.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include <thread>
|
||||
#include <future>
|
||||
@@ -104,6 +104,9 @@ CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir, const Ve
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
return false ;
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Imposto il riferimento di movimento
|
||||
if ( ! AreSameOrOppositeVectorApprox( vtDir, vtMove))
|
||||
m_frMove.Set( ORIG, vtMove, vtDir) ;
|
||||
@@ -122,6 +125,9 @@ CAvToolSurfTm::TestPath( PNTULIST& lPntM, const Vector3d& vtDir, const Vector3d&
|
||||
// Se utensile non definito, errore
|
||||
if ( m_Tool.GetType() == Tool::UNDEF)
|
||||
return false ;
|
||||
// Se direzioni non definite, errore
|
||||
if ( vtDir.IsSmall() || vtMove.IsSmall())
|
||||
return false ;
|
||||
// Se lista vuota, non devo fare alcunché
|
||||
if ( lPntM.empty())
|
||||
return true ;
|
||||
@@ -206,8 +212,9 @@ CAvToolSurfTm::TestSubPath( int nId, PNTULIST& lPntM, const Vector3d& vtDir, dou
|
||||
while ( itPntMCurr != lPntM.end()) {
|
||||
// verifico il punto
|
||||
ptCurr = itPntMCurr->first ;
|
||||
itPntMCurr->second = MyTestPositionHG( itPntMCurr->first, vtDir) ;
|
||||
if ( itPntMCurr->second < - EPS_SMALL)
|
||||
double dMove = MyTestPositionHG( itPntMCurr->first, vtDir) ;
|
||||
itPntMCurr->second = - dMove ;
|
||||
if ( dMove < - EPS_SMALL)
|
||||
return false ;
|
||||
// se esiste il punto precedente devo verificare il medio
|
||||
if ( itPntMPrev != lPntM.end()) {
|
||||
|
||||
+1
-1
@@ -17,8 +17,8 @@
|
||||
#include "CAvToolTriangle.h"
|
||||
#include "IntersLineSurfStd.h"
|
||||
#include "IntersLineTria.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "CDeUtility.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
|
||||
+39
-2
@@ -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
|
||||
// BoundingBox e Closed SurftriMesh.
|
||||
//
|
||||
//
|
||||
// Modifiche : 05.10.16 DS Creazione modulo.
|
||||
// 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
|
||||
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 ;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
// SurfTm e SurfTm.
|
||||
//
|
||||
// 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) ;
|
||||
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 ;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
// Cone e Closed SurftriMesh.
|
||||
//
|
||||
//
|
||||
// Modifiche : 09.11.20 LM Creazione modulo.
|
||||
// 24.03.24 DS Aggiunta TestConeFrustumSurfTm.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -69,4 +70,44 @@ CDeConeFrustumClosedSurfTm( const Frame3d& frCone, double dBaseRad, double dTopR
|
||||
DistPointSurfTm DistConeCenSurfCalc( ptConeCen, Stm) ;
|
||||
// Se il tronco di cono è interno c'è collisione
|
||||
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,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
// Cone e Triangle3d.
|
||||
//
|
||||
|
||||
@@ -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
|
||||
// toro convesso e SurfTriMesh.
|
||||
//
|
||||
// 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
|
||||
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
@@ -1,13 +1,13 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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
|
||||
// Cylinder e Closed SurftriMesh.
|
||||
//
|
||||
//
|
||||
// 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
|
||||
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 ;
|
||||
}
|
||||
|
||||
+1
-1
@@ -13,9 +13,9 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "CDeCylTria.h"
|
||||
#include "CDeConvexTorusTria.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkPolygon3d.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -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
|
||||
// Prismoide a basi rettangolari e Closed SurfTriMesh.
|
||||
//
|
||||
// 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
|
||||
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
@@ -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
|
||||
// Sphere e Closed SurftriMesh.
|
||||
//
|
||||
//
|
||||
// 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.
|
||||
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 ;
|
||||
}
|
||||
|
||||
+1
-2
@@ -12,11 +12,10 @@
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "CDeTriaTria.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "CDeUtility.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+3
-3
@@ -759,7 +759,7 @@ GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICU
|
||||
PtrOwner<ISurfFlatRegion> pSrfToolRegLinki( GetSurfFlatRegionFromFatCurve( Release( pCrvLink_i), s_dRad + 5 * EPS_SMALL, false, false)) ;
|
||||
if ( ! IsNull( pSrfToolRegLinki)) {
|
||||
if ( ! pSrfTool_Links->IsValid() || pSrfTool_Links->GetChunkCount() == 0)
|
||||
pSrfTool_Links.Set( GetBasicSurfFlatRegion( pSrfToolRegLinki)) ;
|
||||
pSrfTool_Links.Set( GetBasicSurfFlatRegion( Release( pSrfToolRegLinki))) ;
|
||||
else
|
||||
pSrfTool_Links->Add( *pSrfToolRegLinki) ;
|
||||
}
|
||||
@@ -2536,7 +2536,7 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, ICRVCOMPOPOVECTOR& vpCrvs, double
|
||||
vAddedLinks.emplace_back( pCrvLink->Clone()) ;
|
||||
|
||||
// pSeg2 ora diventa pSeg1 e il procedimento si itera per tutto il percorso
|
||||
pLastSeg.Set( Release( pSeg2)) ;
|
||||
pLastSeg.Set( pSeg2) ;
|
||||
}
|
||||
// cerco nella stessa fila o in quella successiva sezione successiva raccordabile tramite il contorno
|
||||
double dUstart = Sec.dOe ;
|
||||
@@ -3164,7 +3164,7 @@ AdjustLinkDifferentY( const ICurve* pCrvSegPrec, const ICurve* pCrvSegSucc, cons
|
||||
if ( IsNull( pSfrTrap_c))
|
||||
return false ;
|
||||
if ( ! pSfrTrap->Offset( - s_dRad / 5, ICurve::OFF_CHAMFER))
|
||||
pSfrTrap.Set( Release( pSfrTrap_c)) ;
|
||||
pSfrTrap.Set( pSfrTrap_c) ;
|
||||
|
||||
// se il Link interseca questa regione, allora va eliminato
|
||||
CRVCVECTOR ccClass ;
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
#include "CurveBezier.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkCircleCenTgCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
+55
-45
@@ -189,7 +189,7 @@ CurveArc::Set3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d&
|
||||
// calcolo del versore normale
|
||||
m_VtN = vtA ^ vtB ;
|
||||
double dNSqLen = m_VtN.SqLen() ;
|
||||
// se i punti sono praticamente allineati non si può calcolare la circonferenza
|
||||
// se i punti sono praticamente allineati non si può calcolare la circonferenza
|
||||
if ( ! m_VtN.Normalize( EPS_ZERO))
|
||||
return false ;
|
||||
// calcolo del centro
|
||||
@@ -216,17 +216,17 @@ CurveArc::Set3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d&
|
||||
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, dAng2Deg, bDet2) || ! bDet2)
|
||||
return false ;
|
||||
// deduzione dell'angolo al centro
|
||||
// se uno dei due angoli è nullo, errore
|
||||
// se uno dei due angoli è nullo, errore
|
||||
if ( abs( dAng1Deg) < EPS_ANG_SMALL || abs( dAng2Deg) < EPS_ANG_SMALL)
|
||||
return false ;
|
||||
// se i due angoli hanno lo stesso segno e Ang1 è minore di Ang2 in modulo
|
||||
// se i due angoli hanno lo stesso segno e Ang1 è minore di Ang2 in modulo
|
||||
else if ( dAng1Deg * dAng2Deg > 0 && abs( dAng1Deg) < abs( dAng2Deg))
|
||||
m_dAngCenDeg = dAng2Deg ;
|
||||
// altrimenti hanno segno opposto oppure Ang1 è maggiore di Ang2 in modulo
|
||||
// altrimenti hanno segno opposto oppure Ang1 è maggiore di Ang2 in modulo
|
||||
else
|
||||
m_dAngCenDeg = - _copysign( ANG_FULL, dAng2Deg) + dAng2Deg ;
|
||||
}
|
||||
// non c'è DeltaN
|
||||
// non c'è DeltaN
|
||||
m_dDeltaN = 0 ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
@@ -255,7 +255,7 @@ CurveArc::Set2PNB( const Point3d& ptIni, const Point3d& ptFin, const Vector3d& v
|
||||
Vector3d vtDiff = ptFin - ptIni ;
|
||||
if ( vtDiff.IsSmall())
|
||||
return false ;
|
||||
// deltaN eventuale ( è componente parallela a VtN)
|
||||
// deltaN eventuale ( è componente parallela a VtN)
|
||||
m_dDeltaN = vtDiff * m_VtN ;
|
||||
vtDiff -= m_dDeltaN * m_VtN ;
|
||||
if ( abs( m_dDeltaN) < EPS_SMALL)
|
||||
@@ -304,7 +304,7 @@ CurveArc::Set2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStart
|
||||
// calcolo del versore normale
|
||||
m_VtN = vtA ^ vtB ;
|
||||
double dNSqLen = m_VtN.SqLen() ;
|
||||
// se tangente e punti sono praticamente allineati non si può calcolare la circonferenza
|
||||
// se tangente e punti sono praticamente allineati non si può calcolare la circonferenza
|
||||
if ( ! m_VtN.Normalize( EPS_ZERO))
|
||||
return false ;
|
||||
// calcolo del centro
|
||||
@@ -321,7 +321,7 @@ CurveArc::Set2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStart
|
||||
double dAng1Deg ;
|
||||
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, dAng1Deg, bDet1) || ! bDet1)
|
||||
return false ;
|
||||
// poichè il senso di rotazione è sempre CCW, se l'angolo è negativo prendo il suo complemento al giro
|
||||
// poichè il senso di rotazione è sempre CCW, se l'angolo è negativo prendo il suo complemento al giro
|
||||
if ( dAng1Deg < 0)
|
||||
m_dAngCenDeg = ANG_FULL + dAng1Deg ;
|
||||
else
|
||||
@@ -414,7 +414,7 @@ CurveArc::Set2PRS( const Point3d& ptStart, const Point3d& ptEnd, double dRad, bo
|
||||
bool bDet ;
|
||||
if ( ! m_VtS.GetRotation( ( ptEnd - m_PtCen), m_VtN, m_dAngCenDeg, bDet) || ! bDet)
|
||||
return false ;
|
||||
// quando è 180deg il segno è determinato solo dal senso
|
||||
// quando è 180deg il segno è determinato solo dal senso
|
||||
if ( abs( m_dAngCenDeg - ANG_STRAIGHT) < 10 * EPS_ANG_SMALL &&
|
||||
( ( bCCW && m_dAngCenDeg < 0) ||
|
||||
( ! bCCW && m_dAngCenDeg > 0)))
|
||||
@@ -529,7 +529,7 @@ CurveArc::SetC2P( const Point3d& ptCen, const Point3d& ptStart, const Point3d& p
|
||||
if ( m_dRad < EPS_ZERO)
|
||||
return false ;
|
||||
m_VtS /= m_dRad ;
|
||||
// calcolo l'angolo al centro (la funzione trova sempre il più piccolo)
|
||||
// calcolo l'angolo al centro (la funzione trova sempre il più piccolo)
|
||||
bool bDet ;
|
||||
if ( ! m_VtS.GetRotation( ( ptNearEnd - m_PtCen), m_VtN, m_dAngCenDeg, bDet) || ! bDet)
|
||||
return false ;
|
||||
@@ -733,7 +733,7 @@ CurveArc::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
// assegno il box nel riferimento
|
||||
@@ -820,7 +820,7 @@ CurveArc::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
}
|
||||
}
|
||||
|
||||
// se c'è estrusione, devo tenerne conto
|
||||
// se c'è estrusione, devo tenerne conto
|
||||
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
|
||||
Vector3d vtFrExtr = m_VtExtr ;
|
||||
vtFrExtr.ToGlob( frRef) ;
|
||||
@@ -838,7 +838,7 @@ bool
|
||||
CurveArc::Validate( void)
|
||||
{
|
||||
if ( m_nStatus == TO_VERIFY) {
|
||||
// limito l'angolo al centro a un giro se è piatto ( non è elica)
|
||||
// limito l'angolo al centro a un giro se è piatto ( non è elica)
|
||||
if ( abs( m_dDeltaN) < EPS_SMALL) {
|
||||
if ( m_dAngCenDeg > ANG_FULL)
|
||||
m_dAngCenDeg = ANG_FULL ;
|
||||
@@ -1167,7 +1167,7 @@ CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLin
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se necessario, sistemo per convessità dalla parte ammessa
|
||||
// se necessario, sistemo per convessità dalla parte ammessa
|
||||
if ( nType == APL_RIGHT_CONVEX || nType == APL_LEFT_CONVEX) {
|
||||
if ( ! PL.MakeConvex( vtExtr, ( nType == APL_LEFT_CONVEX)))
|
||||
return false ;
|
||||
@@ -1241,7 +1241,7 @@ CurveArc::CopyParamRange( double dUStart, double dUEnd) const
|
||||
return nullptr ;
|
||||
// se il parametro start supera quello di end
|
||||
if ( dUStart > dUEnd - EPS_PARAM) {
|
||||
// se curva aperta, il trim la cancella completamente quindi non resta alcunchè
|
||||
// se curva aperta, il trim la cancella completamente quindi non resta alcunchè
|
||||
if ( ! IsClosed())
|
||||
return nullptr ;
|
||||
// se curva chiusa, il trim si avvolge attorno al punto di giunzione
|
||||
@@ -1331,7 +1331,7 @@ bool
|
||||
CurveArc::MyExtendedOffset( double dDist, bool bAll, int nType)
|
||||
{
|
||||
// bAll == true fa accettare raggi nulli ==> da usare solo internamente
|
||||
// quando si è sicuri di aumentare subito il raggio o di cancellare
|
||||
// quando si è sicuri di aumentare subito il raggio o di cancellare
|
||||
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
@@ -1409,7 +1409,7 @@ CurveArc::ModifyEnd( const Point3d& ptNewEnd)
|
||||
ptOldEndIntr.ToLoc( frIntr) ;
|
||||
Point3d ptEndIntr = ptNewEnd ;
|
||||
ptEndIntr.ToLoc( frIntr) ;
|
||||
// se coincidono nel piano XY, è cambiato solo il deltaN
|
||||
// se coincidono nel piano XY, è cambiato solo il deltaN
|
||||
if ( AreSamePointXYExact( ptOldEndIntr, ptEndIntr)) {
|
||||
m_dDeltaN += ptEndIntr.z - ptOldEndIntr.z ;
|
||||
}
|
||||
@@ -1615,8 +1615,10 @@ CurveArc::Translate( const Vector3d& vtMove)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// traslo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->Translate( vtMove) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -1634,12 +1636,14 @@ CurveArc::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, dou
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// verifico validità dell'asse di rotazione
|
||||
// verifico validità dell'asse di rotazione
|
||||
if ( vtAx.IsSmall())
|
||||
return false ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// ruoto Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -1787,7 +1791,7 @@ CurveArc::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// verifico validità del piano di specchiatura
|
||||
// verifico validità del piano di specchiatura
|
||||
if ( vtNorm.IsSmall())
|
||||
return false ;
|
||||
|
||||
@@ -1815,11 +1819,11 @@ CurveArc::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vt
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// verifico validità dei parametri
|
||||
// verifico validità dei parametri
|
||||
if ( vtNorm.IsSmall() || vtDir.IsSmall())
|
||||
return false ;
|
||||
|
||||
// possibile solo se l'arco è piatto e il piano di scorrimento coincide con quello dell'arco
|
||||
// possibile solo se l'arco è piatto e il piano di scorrimento coincide con quello dell'arco
|
||||
if ( ! ( abs( m_dDeltaN) < EPS_SMALL) ||
|
||||
! AreSameOrOppositeVectorExact( m_VtN, vtNorm))
|
||||
return false ;
|
||||
@@ -1849,16 +1853,18 @@ CurveArc::ToGlob( const Frame3d& frRef)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se frame identità, non devo fare alcunché
|
||||
// se frame identità, non devo fare alcunché
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->ToGlob( frRef) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -1876,16 +1882,18 @@ CurveArc::ToLoc( const Frame3d& frRef)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se frame identità, non devo fare alcunché
|
||||
// se frame identità, non devo fare alcunché
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->ToLoc( frRef) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -1903,16 +1911,18 @@ CurveArc::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dei frame
|
||||
// verifico validità dei frame
|
||||
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
if ( AreSameFrame( frOri, frDest))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -1989,12 +1999,12 @@ CurveArc::MyCalcPointParamPosiz( const Point3d& ptP, double& dU, int& nPos, doub
|
||||
// verifica posizione punto su arco
|
||||
nPos = PP_NULL ; // fuori
|
||||
if ( abs( DiffAngle( dAngDeg, 0) * DEGTORAD * m_dRad) < dLinTol) {
|
||||
nPos = ( IsACircle() ? PP_MID : PP_START) ; // se cerchio è interno, altrimenti vicino a inizio
|
||||
nPos = ( IsACircle() ? PP_MID : PP_START) ; // se cerchio è interno, altrimenti vicino a inizio
|
||||
dU = AngleNearAngle( dAngDeg, 0) / m_dAngCenDeg ;
|
||||
dU = max( dU, 0.) ;
|
||||
}
|
||||
else if ( abs( DiffAngle( dAngDeg, m_dAngCenDeg) * DEGTORAD * m_dRad) < dLinTol) {
|
||||
nPos = ( IsACircle() ? PP_MID : PP_END) ; // se cerchio è interno, altrimenti vicino a fine
|
||||
nPos = ( IsACircle() ? PP_MID : PP_END) ; // se cerchio è interno, altrimenti vicino a fine
|
||||
dU = AngleNearAngle( dAngDeg, m_dAngCenDeg) / m_dAngCenDeg ;
|
||||
dU = min( dU, 1.) ;
|
||||
}
|
||||
@@ -2011,7 +2021,7 @@ CurveArc::ChangeRadius( double dNewRadius)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// verifico validità del raggio
|
||||
// verifico validità del raggio
|
||||
if ( ! ( dNewRadius > EPS_SMALL && dNewRadius < MAX_ARC_RAD))
|
||||
return false ;
|
||||
|
||||
@@ -2057,7 +2067,7 @@ CurveArc::ChangeAngCenter( double dNewAngCenDeg)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// verifico accettabilità angolo
|
||||
// verifico accettabilità angolo
|
||||
if ( ! ( abs( m_dAngCenDeg) > EPS_ANG_ZERO))
|
||||
return false ;
|
||||
|
||||
@@ -2153,11 +2163,11 @@ CurveArc::Flip( void)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Oggetto locale per approssimazione di archi
|
||||
// Approx interna è quella cordale standard.
|
||||
// Approx esterna è quella tangente a inizio e fine con metà tratto e un punto in più.
|
||||
// Approx interna è quella cordale standard.
|
||||
// Approx esterna è quella tangente a inizio e fine con metà tratto e un punto in più.
|
||||
// I punti si calcolano a partire dal triangolo tra due punti consecutivi interni e il centro,
|
||||
// usando il versore medio dal centro e moltiplicandolo per il coefficiente ( 2 / ( 1 + cosA)).
|
||||
// Il versore dell'ultimo punto è già stato calcolato per il penultimo.
|
||||
// Il versore dell'ultimo punto è già stato calcolato per il penultimo.
|
||||
//----------------------------------------------------------------------------
|
||||
ArcApproxer::ArcApproxer( double dLinTol, double dAngTolDeg, bool bInside, const CurveArc& arArc)
|
||||
{
|
||||
@@ -2281,7 +2291,7 @@ CurveArc::GetVoronoiObject() const
|
||||
if ( m_nStatus != OK)
|
||||
return nullptr ;
|
||||
|
||||
// se non è stato calcolato, lo calcolo
|
||||
// se non è stato calcolato, lo calcolo
|
||||
if ( m_pVoronoiObj == nullptr)
|
||||
CalcVoronoiObject() ;
|
||||
|
||||
|
||||
+5
-2
@@ -186,7 +186,10 @@ class CurveArc : public ICurveArc, public IGeoObjRW
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
CurveArc( void) ;
|
||||
@@ -200,13 +203,13 @@ class CurveArc : public ICurveArc, public IGeoObjRW
|
||||
bool MyExtendedOffset( double dDist, bool bAll, int nType = OFF_FILLET) ;
|
||||
bool MyCalcPointParamPosiz( const Point3d& ptP, double& dU, int& nPos, double dLinTol) const ;
|
||||
Voronoi* GetVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
bool CopyFrom( const CurveArc& caSrc) ;
|
||||
bool Validate( void) ;
|
||||
bool GetDir( double dU, Vector3d& vtDir) const ;
|
||||
bool CalcVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
@@ -222,7 +225,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
|
||||
double m_dDeltaN ; // variazione di quota lungo VtN della fine rispetto all'inizio
|
||||
Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN)
|
||||
double m_dThick ; // spessore
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable Voronoi* m_pVoronoiObj ; // Voronoi
|
||||
} ;
|
||||
|
||||
+394
-32
@@ -2,7 +2,7 @@
|
||||
// EgalTech 2013-2013
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CurveAux.cpp Data : 22.11.13 Versione : 1.3a1
|
||||
// Contenuto : Implementazione di alcune funzioni di utilità per le curve.
|
||||
// Contenuto : Implementazione di alcune funzioni di utilità per le curve.
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -39,7 +39,7 @@ IsClosed( const ICurve& crvC)
|
||||
bool
|
||||
IsValidParam( const ICurve& crvC, double dPar, ICurve::Side nSide)
|
||||
{
|
||||
// recupero l'intervallo di validità del parametro
|
||||
// recupero l'intervallo di validità del parametro
|
||||
double dStart, dEnd ;
|
||||
if ( ! crvC.GetDomain( dStart, dEnd))
|
||||
return false ;
|
||||
@@ -60,11 +60,11 @@ IsValidParam( const ICurve& crvC, double dPar, ICurve::Side nSide)
|
||||
bool
|
||||
IsStartParam( const ICurve& crvC, double dPar)
|
||||
{
|
||||
// recupero l'intervallo di validità del parametro
|
||||
// recupero l'intervallo di validità del parametro
|
||||
double dStart, dEnd ;
|
||||
if ( ! crvC.GetDomain( dStart, dEnd))
|
||||
return false ;
|
||||
// se il parametro non è nell'intorno dell'inizio
|
||||
// se il parametro non è nell'intorno dell'inizio
|
||||
if ( abs( dPar - dStart) > EPS_PARAM)
|
||||
return false ;
|
||||
return true ;
|
||||
@@ -74,11 +74,11 @@ IsStartParam( const ICurve& crvC, double dPar)
|
||||
bool
|
||||
IsEndParam( const ICurve& crvC, double dPar)
|
||||
{
|
||||
// recupero l'intervallo di validità del parametro
|
||||
// recupero l'intervallo di validità del parametro
|
||||
double dStart, dEnd ;
|
||||
if ( ! crvC.GetDomain( dStart, dEnd))
|
||||
return false ;
|
||||
// se il parametro non è nell'intorno della fine
|
||||
// se il parametro non è nell'intorno della fine
|
||||
if ( abs( dPar - dEnd) > EPS_PARAM)
|
||||
return false ;
|
||||
return true ;
|
||||
@@ -98,7 +98,7 @@ GetNearestExtremityToPoint( const Point3d& ptP, const ICurve& Curve, bool& bStar
|
||||
return false ;
|
||||
// se curva aperta
|
||||
if ( ! AreSamePointApprox( ptStart, ptEnd)) {
|
||||
// è il più vicino tra inizio e fine
|
||||
// è il più vicino tra inizio e fine
|
||||
bStart = ( SqDist( ptP, ptStart) <= SqDist( ptP, ptEnd)) ;
|
||||
return true ;
|
||||
}
|
||||
@@ -186,7 +186,7 @@ GetPointTang( const ICurve& crvC, double dU, ICurve::Side nS, Point3d& ptPos, Ve
|
||||
return false ;
|
||||
double dUmod = dU + ( nS == ICurve::FROM_MINUS ? -1 : +1) * 100 * EPS_PARAM ;
|
||||
Point3d ptDummy ;
|
||||
// se anche la derivata seconda è nulla, provo a spostarmi di poco
|
||||
// se anche la derivata seconda è nulla, provo a spostarmi di poco
|
||||
if ( ! vtTang.Normalize( EPS_ZERO)) {
|
||||
if ( ! crvC.GetPointD1D2( dUmod, nS, ptDummy, &vtDummy, &vtTang))
|
||||
return false ;
|
||||
@@ -263,14 +263,14 @@ GetPointDiffGeom( const ICurve& crvC, double dU, ICurve::Side nS, CrvPointDiffGe
|
||||
bool
|
||||
ImproveCurveParamAtPoint( double& dU, const Point3d& ptP, const ICurve* pCrv)
|
||||
{
|
||||
// Da usare quando il parametro è già molto vicino a quello esatto
|
||||
// Da usare quando il parametro è già molto vicino a quello esatto
|
||||
|
||||
// calcolo il punto della curva in corrispondenza al parametro
|
||||
Point3d ptQ ;
|
||||
Vector3d vtD ;
|
||||
if ( ! pCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptQ, &vtD))
|
||||
return false ;
|
||||
// se sono uguali, è già tutto ok
|
||||
// se sono uguali, è già tutto ok
|
||||
if ( AreSamePointExact( ptP, ptQ))
|
||||
return true ;
|
||||
// se derivata nulla, non posso migliorare
|
||||
@@ -332,7 +332,7 @@ CurveGetArea( const ICurve& crvC, Plane3d& plPlane, double& dArea)
|
||||
bool
|
||||
CurveDump( const ICurve& crvC, string& sOut, bool bMM, const char* szNewLine)
|
||||
{
|
||||
// verifico validità curva
|
||||
// verifico validità curva
|
||||
if ( ! crvC.IsValid())
|
||||
return false ;
|
||||
|
||||
@@ -403,9 +403,20 @@ CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurveBezier*
|
||||
LineToBezierCurve( const ICurveLine* pCrvLine)
|
||||
{
|
||||
PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ;
|
||||
// rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali
|
||||
pCrvBezier->Init( 2, true) ;
|
||||
pCrvBezier->FromLine( *pCrvLine) ;
|
||||
return Release( pCrvBezier) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
ArcToBezierCurve( const ICurve* pCrv)
|
||||
ArcToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2)
|
||||
{
|
||||
// verifico sia un arco
|
||||
const CurveArc* pArc = GetBasicCurveArc( pCrv) ;
|
||||
@@ -413,7 +424,8 @@ ArcToBezierCurve( const ICurve* pCrv)
|
||||
return nullptr ;
|
||||
|
||||
// se angolo al centro sotto il limite, basta una curva
|
||||
if ( abs( pArc->GetAngCenter()) < BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL) {
|
||||
if ( ( abs( pArc->GetAngCenter()) < BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL && abs( pArc->GetDeltaN()) < EPS_ZERO && ! bDeg3OrDeg2) ||
|
||||
( abs( pArc->GetAngCenter()) < BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL && bDeg3OrDeg2)) {
|
||||
// creo la curva di Bezier equivalente all'arco
|
||||
PtrOwner<CurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
|
||||
if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( *pArc))
|
||||
@@ -429,6 +441,8 @@ ArcToBezierCurve( const ICurve* pCrv)
|
||||
return nullptr ;
|
||||
// inserisco nella CC le curve di Bezier equivalenti alle parti dell'arco
|
||||
int nParts = (int) ceil( abs( pArc->GetAngCenter()) / ( BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL)) ;
|
||||
if ( ! bDeg3OrDeg2 && abs( pArc->GetDeltaN()) > EPS_ZERO)
|
||||
nParts *= 2 ;
|
||||
nParts = max( nParts, 2) ;
|
||||
for ( int i = 0 ; i < nParts ; ++ i) {
|
||||
// copio l'arco originale
|
||||
@@ -451,11 +465,265 @@ ArcToBezierCurve( const ICurve* pCrv)
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
CompositeToBezierCurve( const ICurveComposite* pCC)
|
||||
{
|
||||
// converto tutte le curve in bezier razionali di grado 2
|
||||
PtrOwner<ICurveComposite> pCCBezier( CreateCurveComposite()) ;
|
||||
for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) {
|
||||
PtrOwner<ICurve> pCrvNew ;
|
||||
if ( pCC->GetCurve(i)->GetType() == CRV_ARC) {
|
||||
const CurveArc* crArc = GetBasicCurveArc( pCC->GetCurve(i)) ;
|
||||
ICurve* pCrvBezier = ArcToBezierCurve( crArc) ;
|
||||
if ( pCrvBezier == nullptr)
|
||||
return nullptr ;
|
||||
// se la curva è di grado superiore al secondo allora devo ricondurla al secondo grado
|
||||
pCrvNew.Set( pCrvBezier) ;
|
||||
}
|
||||
else if ( pCC->GetCurve(i)->GetType() == CRV_LINE) {
|
||||
const CurveLine* crLine = GetBasicCurveLine( pCC->GetCurve(i)) ;
|
||||
ICurve* pCrvBezier = LineToBezierCurve( crLine) ;
|
||||
if ( pCrvBezier == nullptr)
|
||||
return nullptr ;
|
||||
pCrvNew.Set( pCrvBezier) ;
|
||||
}
|
||||
else if ( pCC->GetCurve(i)->GetType() == CRV_BEZIER ) {
|
||||
const CurveBezier* crvBezier = GetBasicCurveBezier( pCC->GetCurve(i)) ;
|
||||
ICurve* pCrvBezier = BezierToBasicBezierCurve( crvBezier) ;
|
||||
if ( pCrvBezier == nullptr)
|
||||
return nullptr ;
|
||||
pCrvNew.Set( pCrvBezier) ;
|
||||
}
|
||||
|
||||
pCCBezier->AddCurve( Release( pCrvNew)) ;
|
||||
}
|
||||
return Release( pCCBezier) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
BezierToBasicBezierCurve( const ICurveBezier* pCrvBezier)
|
||||
{
|
||||
// resta da calcolare un errore sull'approssimazione oppure usare la tecnica di spezzare la curva originale in sottocurve e approssimarle con bezier cubiche
|
||||
// per ridurre molto l'errore
|
||||
|
||||
// dovrei restituire una bezier di grado 2, razionale per poter essere uniforme con le altre curve trasmorate in bezier
|
||||
PtrOwner<ICurveBezier> pCrvNew( pCrvBezier->Clone()) ;
|
||||
int nDeg = pCrvBezier->GetDegree() ;
|
||||
bool bRat = pCrvBezier->IsRational() ;
|
||||
// se la curva è già nella forma giusta la restituisco
|
||||
if ( nDeg == 2 && bRat)
|
||||
return Release( pCrvNew) ;
|
||||
// sennò la riduco di grado fino al 2
|
||||
PtrOwner<ICurveBezier> pBasicBezier ( CreateCurveBezier()) ;
|
||||
pBasicBezier->Init( 2, true) ;
|
||||
double dW = 1 ;
|
||||
if ( nDeg == 1) {
|
||||
Point3d ptStart = pCrvBezier->GetControlPoint( 0) ;
|
||||
Point3d ptEnd = pCrvBezier->GetControlPoint( 1) ;
|
||||
pBasicBezier->SetControlPoint( 0, ptStart, dW) ;
|
||||
pBasicBezier->SetControlPoint( 1, 0.5 * (ptStart + ptEnd), dW) ;
|
||||
pBasicBezier->SetControlPoint( 2, ptEnd, dW) ;
|
||||
return Release( pBasicBezier) ;
|
||||
}
|
||||
while ( nDeg > 2 ) {
|
||||
pCrvNew.Set( BezierDecreaseDegree( pCrvNew, 1)) ;
|
||||
if ( IsNull( pCrvNew) || ! pCrvNew->IsValid())
|
||||
return nullptr ;
|
||||
-- nDeg ;
|
||||
}
|
||||
for ( int i = 0 ; i < 3 ; ++i) {
|
||||
Point3d ptCopy = pCrvNew->GetControlPoint( i) ;
|
||||
if ( bRat)
|
||||
dW = pCrvNew->GetControlWeight( i) ;
|
||||
pBasicBezier->SetControlPoint( i, ptCopy, dW) ;
|
||||
}
|
||||
|
||||
return Release( pBasicBezier) ;
|
||||
}
|
||||
|
||||
ICurveBezier*
|
||||
BezierIncreaseDegree(const ICurveBezier* pCrvBezier)
|
||||
{
|
||||
if ( pCrvBezier == nullptr)
|
||||
return nullptr ;
|
||||
// creo la versione con grado aumentato
|
||||
PtrOwner<ICurveBezier> pNewBezier( CreateCurveBezier()) ;
|
||||
int nDeg = pCrvBezier->GetDegree() + 1;
|
||||
bool bRat = pCrvBezier->IsRational();
|
||||
pNewBezier->Init( nDeg , bRat) ;
|
||||
// prev e curr sono riferiti alla curva di partenza
|
||||
// salvo il primo punto
|
||||
Point3d ptCtrlPrev = pCrvBezier->GetControlPoint( 0) ;
|
||||
double dWprev = 1 ;
|
||||
if ( bRat ) {
|
||||
dWprev = pCrvBezier->GetControlWeight( 0) ;
|
||||
pNewBezier->SetControlPoint( 0, ptCtrlPrev, dWprev) ;
|
||||
}
|
||||
else
|
||||
pNewBezier->SetControlPoint( 0, ptCtrlPrev) ;
|
||||
// ciclo sui punti di controllo intermedi per calcolare quelli nuovi
|
||||
Point3d ptCtrlCurr ;
|
||||
double dWcurr ;
|
||||
for ( double i = 1 ; i < nDeg ; ++i) {
|
||||
ptCtrlCurr = pCrvBezier->GetControlPoint( int( i)) ;
|
||||
Point3d ptNew = ( i / nDeg) * ptCtrlPrev + ( 1 - i / ( nDeg)) * ptCtrlCurr ;
|
||||
if ( bRat) {
|
||||
dWcurr = pCrvBezier->GetControlWeight( int( i)) ;
|
||||
double dWnew = ( i / nDeg) * dWprev + ( 1 - i / ( nDeg)) * dWcurr ;
|
||||
pNewBezier->SetControlPoint( int( i), ptNew, dWnew) ;
|
||||
dWprev = dWnew ;
|
||||
}
|
||||
else
|
||||
pNewBezier->SetControlPoint( int( i), ptNew) ;
|
||||
ptCtrlPrev = ptCtrlCurr ;
|
||||
}
|
||||
// salvo l'ultimo punto
|
||||
ptCtrlCurr = pCrvBezier->GetControlPoint( nDeg - 1) ;
|
||||
if ( bRat ) {
|
||||
dWcurr = pCrvBezier->GetControlWeight( nDeg - 1) ;
|
||||
pNewBezier->SetControlPoint( nDeg, ptCtrlCurr, dWcurr) ;
|
||||
}
|
||||
else
|
||||
pNewBezier->SetControlPoint( nDeg, ptCtrlCurr) ;
|
||||
return Release( pNewBezier) ;
|
||||
}
|
||||
|
||||
ICurveBezier*
|
||||
BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol)
|
||||
{
|
||||
if ( pCrvBezier == nullptr)
|
||||
return nullptr ;
|
||||
PtrOwner<ICurveBezier> pNewBezier( CreateCurveBezier()) ;
|
||||
int nDeg = pCrvBezier->GetDegree() - 1 ;
|
||||
if ( nDeg == 0)
|
||||
return nullptr ;
|
||||
bool bRat = pCrvBezier->IsRational() ;
|
||||
pNewBezier->Init( nDeg, bRat) ;
|
||||
// prev e curr sono riferiti alla nuova curva
|
||||
//salvo il primo punto
|
||||
Point3d ptCtrlPrev = pCrvBezier->GetControlPoint( 0) ;
|
||||
double dWprev = 1 ;
|
||||
if ( bRat ) {
|
||||
dWprev = pCrvBezier->GetControlWeight( 0) ;
|
||||
pNewBezier->SetControlPoint( 0, ptCtrlPrev, dWprev) ;
|
||||
}
|
||||
else
|
||||
pNewBezier->SetControlPoint( 0, ptCtrlPrev) ;
|
||||
// ciclo sui punti intermedi per trovare i nuovi punti di controllo // equazioni da NURBS book
|
||||
Point3d ptCtrlCurr ;
|
||||
double dWcurr ;
|
||||
int r = int (nDeg / 2) ;
|
||||
// prima metà
|
||||
for ( double i = 1 ; i < r ; ++i) {
|
||||
double dAlpha = i / ( nDeg + 1) ;
|
||||
// old è riferito alla curva originale
|
||||
Point3d ptOld = pCrvBezier->GetControlPoint( int( i)) ;
|
||||
ptCtrlCurr = ( ptOld + (- dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ;
|
||||
if ( bRat) {
|
||||
double dWold = pCrvBezier->GetControlWeight( int( i)) ;
|
||||
dWcurr = ( dWold + (- dAlpha * dWprev)) / ( 1 - dAlpha) ;
|
||||
pNewBezier->SetControlPoint( int( i), ptCtrlCurr, dWcurr) ;
|
||||
dWprev = dWcurr ;
|
||||
}
|
||||
else
|
||||
pNewBezier->SetControlPoint( int( i), ptCtrlCurr) ;
|
||||
ptCtrlPrev = ptCtrlCurr ;
|
||||
}
|
||||
// risolvo il punto di mezzo per il caso nDeg pari
|
||||
if ( ( nDeg + 1) % 2 == 0) { // pari
|
||||
double dAlpha = r / ( nDeg + 1.) ;
|
||||
Point3d ptOld = pCrvBezier->GetControlPoint( r) ;
|
||||
ptCtrlCurr = ( ptOld + (- dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ;
|
||||
if ( bRat) {
|
||||
double dWold = pCrvBezier->GetControlWeight( r) ;
|
||||
dWcurr = ( dWold + (- dAlpha * dWprev)) / ( 1 - dAlpha) ;
|
||||
pNewBezier->SetControlPoint( r, ptCtrlCurr, dWcurr) ;
|
||||
dWprev = dWcurr ;
|
||||
}
|
||||
else
|
||||
pNewBezier->SetControlPoint( r, ptCtrlCurr) ;
|
||||
}
|
||||
// salvo l'ultimo punto
|
||||
ptCtrlCurr = pCrvBezier->GetControlPoint( nDeg + 1) ;
|
||||
if ( bRat ) {
|
||||
dWcurr = pCrvBezier->GetControlWeight( nDeg + 1) ;
|
||||
pNewBezier->SetControlPoint( nDeg, ptCtrlCurr, dWcurr) ;
|
||||
}
|
||||
else
|
||||
pNewBezier->SetControlPoint( nDeg, ptCtrlCurr) ;
|
||||
ptCtrlPrev = ptCtrlCurr ;
|
||||
if ( bRat)
|
||||
dWprev = dWcurr ;
|
||||
// seconda metà
|
||||
for ( double i = nDeg - 1 ; i > r ; --i) {
|
||||
double dAlpha = ( i + 1) / ( nDeg + 1) ;
|
||||
Point3d ptOld = pCrvBezier->GetControlPoint( int( i) + 1) ;
|
||||
ptCtrlCurr = ( ptOld + ( - ( 1 - dAlpha) * ptCtrlPrev)) / dAlpha ;
|
||||
if ( bRat) {
|
||||
double dWold = pCrvBezier->GetControlWeight( int( i) + 1) ;
|
||||
dWcurr = ( dWold - ( ( 1 - dAlpha) * dWprev)) / dAlpha ;
|
||||
pNewBezier->SetControlPoint( int( i), ptCtrlCurr, dWcurr) ;
|
||||
dWprev = dWcurr ;
|
||||
}
|
||||
else
|
||||
pNewBezier->SetControlPoint( int( i), ptCtrlCurr) ;
|
||||
ptCtrlPrev = ptCtrlCurr ;
|
||||
}
|
||||
// risolvo il punto di mezzo per il caso nDeg dispari
|
||||
// calcolo anche l'errore di approssimazione
|
||||
double dErr = 0 ;
|
||||
if ( (nDeg + 1) % 2 != 0) { // dispari
|
||||
// puntdo di sinistra
|
||||
double dAlpha = r / ( nDeg + 1.) ;
|
||||
ptCtrlPrev = pNewBezier->GetControlPoint( r - 1) ;
|
||||
Point3d ptOld = pCrvBezier->GetControlPoint( r) ;
|
||||
Point3d ptL = ( ptOld + ( - dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ;
|
||||
double dWL = 1 ;
|
||||
if ( bRat) {
|
||||
dWprev = pNewBezier->GetControlWeight( r - 1) ;
|
||||
double dWold =pCrvBezier->GetControlWeight( r) ;
|
||||
dWL = ( dWold - ( dAlpha * dWprev)) / ( 1 - dAlpha) ;
|
||||
}
|
||||
// punto di destra
|
||||
dAlpha = ( r + 1.) / ( nDeg + 1.) ;
|
||||
ptCtrlPrev = pNewBezier->GetControlPoint( r + 1) ;
|
||||
ptOld = pCrvBezier->GetControlPoint( r + 1) ;
|
||||
double dWR = 1 ;
|
||||
if ( bRat) {
|
||||
dWprev = pNewBezier->GetControlWeight( r + 1) ;
|
||||
double dWold =pCrvBezier->GetControlWeight( r + 1) ;
|
||||
dWR = ( dWold - ( ( 1 - dAlpha) * dWprev)) / dAlpha ;
|
||||
}
|
||||
Point3d ptR = ( ptOld + ( - ( 1 - dAlpha) * ptCtrlPrev)) / dAlpha ;
|
||||
// calcolo il punto di mezzo e lo aggiungo
|
||||
Point3d ptNew = ( ptL + ptR) / 2 ;
|
||||
double dWnew = ( dWL + dWR) / 2 ;
|
||||
if ( bRat)
|
||||
pNewBezier->SetControlPoint( r, ptNew, dWnew) ;
|
||||
else
|
||||
pNewBezier->SetControlPoint( r, ptNew) ;
|
||||
dErr = Dist( ptL, ptR) ;
|
||||
}
|
||||
else {
|
||||
ptCtrlCurr = pNewBezier->GetControlPoint( r + 1) ;
|
||||
ptCtrlPrev = pNewBezier->GetControlPoint( r) ;
|
||||
Point3d ptOld = pCrvBezier->GetControlPoint( r + 1) ;
|
||||
dErr = Dist( ptOld, 0.5 * ( ptCtrlPrev + ptCtrlCurr)) ;
|
||||
}
|
||||
//// se l'approssimazione dà un errore troppo alto allora annullo tutto // da controllare
|
||||
//if ( dErr > dTol)
|
||||
// return nullptr ;
|
||||
|
||||
return Release( pNewBezier) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
CurveToNoArcsCurve( const ICurve* pCrv)
|
||||
{
|
||||
// verifico validità curva
|
||||
// verifico validità curva
|
||||
if ( pCrv == nullptr)
|
||||
return nullptr ;
|
||||
// se arco, devo trasformarlo in curva di Bezier (semplice o composta)
|
||||
@@ -479,7 +747,7 @@ CurveToNoArcsCurve( const ICurve* pCrv)
|
||||
ICurve*
|
||||
CurveToArcsPerpExtrCurve( const ICurve* pCrv, double dLinTol, double dAngTolDeg)
|
||||
{
|
||||
// verifico validità curva
|
||||
// verifico validità curva
|
||||
if ( pCrv == nullptr)
|
||||
return nullptr ;
|
||||
// se arco in piano non perpendicolare ad estrusione, curva composita o curva di Bezier trasformo
|
||||
@@ -524,14 +792,89 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
|
||||
// se periodica
|
||||
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)
|
||||
// bisogna aumentare la molteplicità dei nodi u_p-1 e u_(m-p+1) fino ad arrivare al grado della nurbs
|
||||
// bisogna aumentare la molteplicità dei nodi u_p-1 e u_(m-p+1) fino ad arrivare al grado della nurbs
|
||||
// e poi scartare nodi e punti fuori dalla regione clamped ( al di fuori della regione u_p-1 -> u_(m-p+1))
|
||||
|
||||
// l'agoritmo per l'inserimento dei nodi l' A5.1 del libro delle Nurbs ( Piegl e Tiller), con qualche modifica
|
||||
// agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p
|
||||
// agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p
|
||||
|
||||
// comincio ad aumentare la molteplictià del nodo u_m-p+1
|
||||
// comincio ad aumentare la molteplictià del nodo u_m-p+1
|
||||
int nCP = int( cnData.vCP.size()) ;
|
||||
int nU = nCP + cnData.nDeg - 1 ;
|
||||
int nDeg = cnData.nDeg ;
|
||||
@@ -540,12 +883,12 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
DBLVECTOR vBW ;
|
||||
vBW.resize( nDeg + 1) ;
|
||||
|
||||
// trovo il nodo di cui aumentare la molteplicità e ne calcolo la molteplicità
|
||||
// trovo il nodo di cui aumentare la molteplicità e ne calcolo la molteplicità
|
||||
int b = nU - nDeg - 1 + 1 ;
|
||||
int i = b ;
|
||||
while ( b > 0 && abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO)
|
||||
-- b ;
|
||||
int mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg
|
||||
int mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg
|
||||
// recupero i punti da modificare
|
||||
if ( ! cnData.bRat) {
|
||||
for ( int i = 0 ; i <= nDeg - mult ; ++ i)
|
||||
@@ -559,7 +902,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
}
|
||||
|
||||
// salvo i punti inalterati
|
||||
int r = nDeg - mult ; // numero di volte che dovrò inserire il nodo
|
||||
int r = nDeg - mult ; // numero di volte che dovrò inserire il nodo
|
||||
cnData.vCP.resize( nCP + r) ;
|
||||
for ( int p = nCP - 1 ; p > b - mult ; --p) {
|
||||
cnData.vCP[r + p] = cnData.vCP[p] ;
|
||||
@@ -604,12 +947,12 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
|
||||
nU = nU + r ;
|
||||
nCP = nCP + r ;
|
||||
|
||||
// aumento la molteplicità del punto u_p-1
|
||||
// aumento la molteplicità del punto u_p-1
|
||||
b = nDeg - 1 ;
|
||||
i = b ;
|
||||
while ( b > 0 && abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO)
|
||||
-- b ;
|
||||
mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg
|
||||
mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg
|
||||
// recupero i punti da modificare
|
||||
if ( ! cnData.bRat) {
|
||||
for ( int i = 0 ; i <= nDeg - mult ; ++ i)
|
||||
@@ -719,7 +1062,7 @@ NurbsToBezierCurve( const CNurbsData& cnData)
|
||||
if ( ! bOk)
|
||||
return nullptr ;
|
||||
|
||||
// se 1 solo intervallo, la Nurbs è già una curva di Bezier
|
||||
// se 1 solo intervallo, la Nurbs è già una curva di Bezier
|
||||
if ( nInt == 1) {
|
||||
// creo la curva di Bezier
|
||||
PtrOwner<CurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
|
||||
@@ -738,14 +1081,14 @@ NurbsToBezierCurve( const CNurbsData& cnData)
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
// se non è una curva ma un punto, la invalido
|
||||
// se non è una curva ma un punto, la invalido
|
||||
if ( pCrvBez->IsAPoint())
|
||||
pCrvBez->Init( cnData.nDeg, cnData.bRat) ;
|
||||
// restituisco la curva
|
||||
return Release( pCrvBez) ;
|
||||
}
|
||||
|
||||
// altrimenti è equivalente ad una curva composita, la creo
|
||||
// altrimenti è equivalente ad una curva composita, la creo
|
||||
PtrOwner<CurveComposite> pCrvCompo( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo))
|
||||
return nullptr ;
|
||||
@@ -813,7 +1156,7 @@ NurbsToBezierCurve( const CNurbsData& cnData)
|
||||
return nullptr ;
|
||||
// se precedente saltata
|
||||
if ( bPrevRejected) {
|
||||
// prendo l'ultimo punto della curva composita per garantire la continuità
|
||||
// prendo l'ultimo punto della curva composita per garantire la continuità
|
||||
Point3d ptEnd ;
|
||||
if ( pCrvCompo->GetEndPoint( ptEnd))
|
||||
vBC[0] = ptEnd ;
|
||||
@@ -833,13 +1176,13 @@ NurbsToBezierCurve( const CNurbsData& cnData)
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
// se è una vera curva, la aggiungo alla curva composita
|
||||
// se è una vera curva, la aggiungo alla curva composita
|
||||
if ( ! pCrvBez->IsAPoint()) {
|
||||
if ( ! pCrvCompo->AddCurve( Release( pCrvBez)))
|
||||
return nullptr ;
|
||||
bPrevRejected = false ;
|
||||
}
|
||||
// altrimenti è un punto, la cancello
|
||||
// altrimenti è un punto, la cancello
|
||||
else {
|
||||
pCrvBez.Reset() ;
|
||||
bPrevRejected = true ;
|
||||
@@ -911,7 +1254,7 @@ FlattenCurve( const ICurve& crCrv, double dToler, double dAngToler, int nFlag)
|
||||
Point3d ptCen ;
|
||||
if ( ! crCrv.GetCentroid( ptCen))
|
||||
return nullptr ;
|
||||
// Verifico se curva già piatta
|
||||
// Verifico se curva già piatta
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL_INT, PL))
|
||||
return nullptr ;
|
||||
@@ -924,7 +1267,7 @@ FlattenCurve( const ICurve& crCrv, double dToler, double dAngToler, int nFlag)
|
||||
bFlat = false ;
|
||||
bPoint = PL.GetNextPoint( ptP) ;
|
||||
}
|
||||
// Se curva già piatta, la copio ed esco
|
||||
// Se curva già piatta, la copio ed esco
|
||||
if ( bFlat) {
|
||||
PtrOwner<ICurve> pCrv( crCrv.Clone()) ;
|
||||
if ( IsNull( pCrv))
|
||||
@@ -975,7 +1318,7 @@ ProjectCurveOnPlane( const ICurve& crCrv, const Plane3d& plPlane)
|
||||
// determino se curva piana e suo eventuale piano
|
||||
Plane3d plCrv ;
|
||||
if ( crCrv.IsFlat( plCrv, false, EPS_SMALL / 2)) {
|
||||
// se il piano della curva è parallelo a quello di proiezione
|
||||
// se il piano della curva è parallelo a quello di proiezione
|
||||
if ( AreSameOrOppositeVectorExact( plCrv.GetVersN(), plPlane.GetVersN())) {
|
||||
// copio la curva
|
||||
PtrOwner<ICurve> pCrv( crCrv.Clone()) ;
|
||||
@@ -1087,3 +1430,22 @@ CalcCurveFatCurve( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dRadius, bo
|
||||
return pVoronoiObj->CalcFatCurve( vCrvs, dRadius, bSquareEnds, bSquareMids) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
ResetCurveVoronoi( const ICurve& crvC)
|
||||
{
|
||||
switch ( crvC.GetType()) {
|
||||
case CRV_LINE :
|
||||
GetBasicCurveLine( &crvC)->ResetVoronoiObject() ;
|
||||
break ;
|
||||
case CRV_ARC :
|
||||
GetBasicCurveArc( &crvC)->ResetVoronoiObject() ;
|
||||
break ;
|
||||
case CRV_BEZIER :
|
||||
GetBasicCurveBezier( &crvC)->ResetVoronoiObject() ;
|
||||
break ;
|
||||
case CRV_COMPO :
|
||||
GetBasicCurveComposite( &crvC)->ResetVoronoiObject() ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
+77
-11
@@ -19,7 +19,6 @@
|
||||
#include "BiArcs.h"
|
||||
#include "GeoConst.h"
|
||||
#include "PolygonPlane.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoObjFactory.h"
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
@@ -27,12 +26,16 @@
|
||||
#include "Bernstein.h"
|
||||
#include "deCasteljau.h"
|
||||
#include "Voronoi.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "/EgtDev/Include/EGkCurveArc.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
#include "/EgtDev/Include/ENkPolynomial.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkCurveLine.h"
|
||||
#include <array>
|
||||
|
||||
using namespace std ;
|
||||
@@ -195,6 +198,35 @@ CurveBezier::FromArc( const ICurveArc& crArc)
|
||||
SetControlPoint( 1, ptNew1, dW) ;
|
||||
SetControlPoint( 2, ptNew2, dW) ;
|
||||
SetControlPoint( 3, ptEnd, 1) ;
|
||||
|
||||
//// anziché usare una bezier cubica approssimo le eliche con più bezier quadratiche razionali.
|
||||
//// più è grande l'angolo al centro dell'arco e maggiore sarà l'errore di approssimazione
|
||||
//
|
||||
// // quadratica razionale
|
||||
// // peso del punto di controllo intermedio
|
||||
// double dW = dCosAhalf ;
|
||||
// // calcolo dei punti di controllo
|
||||
// Point3d ptStart ;
|
||||
// crArc.GetStartPoint( ptStart) ;
|
||||
// Point3d ptEnd ;
|
||||
// crArc.GetEndPoint( ptEnd) ;
|
||||
// // Point3d ptMed = Media( ptStart, ptEnd, 0.5) ;
|
||||
// //Vector3d vtDir = ptMed - crArc.GetCenter() ;
|
||||
// // Point3d ptNew = crArc.GetCenter() + vtDir / ( dCosAhalf * dCosAhalf) ;
|
||||
// Vector3d vtStart ; crArc.GetStartDir( vtStart) ;
|
||||
// Vector3d vtEnd ; crArc.GetEndDir( vtEnd) ;
|
||||
// PtrOwner<CurveLine> pCrvLine1( CreateBasicCurveLine()) ;
|
||||
// pCrvLine1->SetPVL( ptStart, vtStart, 10) ;
|
||||
// PtrOwner<CurveLine> pCrvLine2( CreateBasicCurveLine()) ;
|
||||
// pCrvLine2->SetPVL( ptEnd, vtEnd, 10) ;
|
||||
// IntersLineLine ill( *pCrvLine1, *pCrvLine2, false) ;
|
||||
// IntCrvCrvInfo iccInfo ; ill.GetIntCrvCrvInfo( iccInfo) ;
|
||||
// Point3d ptNew = 0.5 * (iccInfo.IciA->ptI + iccInfo.IciB->ptI) ;
|
||||
// // inserimento nella curva dei punti di controllo con i pesi
|
||||
// Init( 2, true) ;
|
||||
// SetControlPoint( 0, ptStart, 1) ;
|
||||
// SetControlPoint( 1, ptNew, dW) ;
|
||||
// SetControlPoint( 2, ptEnd, 1) ;
|
||||
}
|
||||
|
||||
// copio estrusione e spessore
|
||||
@@ -204,6 +236,30 @@ CurveBezier::FromArc( const ICurveArc& crArc)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::FromLine( const ICurveLine& crLine)
|
||||
{
|
||||
if ( ! crLine.IsValid())
|
||||
return false ;
|
||||
double dWeight = 1 ;
|
||||
int nCount = 0 ;
|
||||
Point3d ptStart ; crLine.GetStartPoint( ptStart) ;
|
||||
SetControlPoint( nCount, ptStart, dWeight) ;
|
||||
++nCount ;
|
||||
double dPart = 1. / m_nDeg ;
|
||||
for ( int i = 1 ; i < m_nDeg ; ++i) {
|
||||
double dU = i * dPart ;
|
||||
Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ;
|
||||
SetControlPoint( nCount, ptMid, dWeight) ;
|
||||
++nCount ;
|
||||
}
|
||||
Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ;
|
||||
SetControlPoint( nCount, ptEnd, dWeight) ;
|
||||
++nCount ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveBezier::IsAPoint( void) const
|
||||
@@ -1873,8 +1929,10 @@ CurveBezier::Translate( const Vector3d& vtMove)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// traslo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->Translate( vtMove) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -1897,8 +1955,10 @@ CurveBezier::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng,
|
||||
if ( vtAx.IsSmall())
|
||||
return false ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// ruoto Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -2032,8 +2092,10 @@ CurveBezier::ToGlob( const Frame3d& frRef)
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->ToGlob( frRef) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -2061,8 +2123,10 @@ CurveBezier::ToLoc( const Frame3d& frRef)
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->ToLoc( frRef) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -2090,8 +2154,10 @@ CurveBezier::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
if ( AreSameFrame( frOri, frDest))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
|
||||
+9
-5
@@ -117,7 +117,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
ICurve* CopyParamRange( double dUStart, double dUEnd) const override ;
|
||||
bool Invert( void) override ;
|
||||
bool SimpleOffset( double dDist, int nType = OFF_FILLET) override
|
||||
{ return false ; } // l'offset di crvBezier non è crvBezier tranne in casi molto particolari
|
||||
{ return false ; } // l'offset di crvBezier non è crvBezier tranne in casi molto particolari
|
||||
bool ModifyStart( const Point3d& ptNewStart) override ;
|
||||
bool ModifyEnd( const Point3d& ptNewEnd) override ;
|
||||
bool SetExtrusion( const Vector3d& vtExtr) override
|
||||
@@ -138,6 +138,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
bool SetControlPoint( int nInd, const Point3d& ptCtrl) override ;
|
||||
bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ;
|
||||
bool FromArc( const ICurveArc& crArc) override ;
|
||||
bool FromLine( const ICurveLine& crLine) override ;
|
||||
int GetDegree( void) const override
|
||||
{ return m_nDeg ; }
|
||||
bool IsRational( void) const override
|
||||
@@ -151,7 +152,10 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
CurveBezier( void) ;
|
||||
@@ -165,6 +169,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
bool ApproxWithLines( int nStep, PolyLine& PL) const ;
|
||||
bool GetApproxLength( double& dLen) const ;
|
||||
Voronoi* GetVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
bool CopyFrom( const CurveBezier& cbSrc) ;
|
||||
@@ -183,23 +188,22 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
|
||||
bool ToPowerBase( PolynomialPoint3d& pol3P) const ;
|
||||
bool ToPowerBase( PolynomialPoint3d& pol3Num, Polynomial& polDen) const ;
|
||||
bool CalcVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
static const int MAXDEG = 11 ;
|
||||
static const int MAXDEG = 21 ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
Status m_nStatus ; // stato
|
||||
int m_nDeg ; // grado
|
||||
bool m_bRat ; // flag di razionale/polinomiale
|
||||
mutable double m_dParSing ; // eventuale parametro della singolarità (-1=no, -2=da calcolare)
|
||||
mutable double m_dParSing ; // eventuale parametro della singolarità (-1=no, -2=da calcolare)
|
||||
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
|
||||
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
|
||||
Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN)
|
||||
double m_dThick ; // spessore
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable Voronoi* m_pVoronoiObj ; // Voronoi
|
||||
} ;
|
||||
|
||||
+1
-1
@@ -16,8 +16,8 @@
|
||||
#include "CurveComposite.h"
|
||||
#include "CalcDerivate.h"
|
||||
#include "BiArcs.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "RemoveCurveDefects.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkCurveByApprox.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkPolyArc.h"
|
||||
|
||||
+201
-160
@@ -14,7 +14,6 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DistPointCrvComposite.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
@@ -27,6 +26,7 @@
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
#include "Voronoi.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkCurveByApprox.h"
|
||||
#include "/EgtDev/Include/EGkArcSpecial.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
@@ -186,7 +186,7 @@ CurveComposite::AddCurveByRelocate( CurveComposite& ccSrc, bool bEndOrStart, dou
|
||||
bool
|
||||
CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinTol)
|
||||
{
|
||||
// prendo la proprietà del puntatore
|
||||
// prendo la proprietà del puntatore
|
||||
PtrOwner<ICurve> pCrv( pSmplCrv) ;
|
||||
if ( IsNull( pCrv))
|
||||
return false ;
|
||||
@@ -211,15 +211,15 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
if ( ! pCrv->GetStartPoint( ptCrvStart) || ! pCrv->GetEndPoint( ptCrvEnd))
|
||||
return false ;
|
||||
|
||||
// se non è la prima
|
||||
// se non è la prima
|
||||
if ( ! m_CrvSmplS.empty()) {
|
||||
// se inserita alla fine
|
||||
if ( bEndOrStart) {
|
||||
// verifico sia in continuità con il finale attuale
|
||||
// verifico sia in continuità con il finale attuale
|
||||
Point3d ptEnd ;
|
||||
GetEndPoint( ptEnd) ;
|
||||
if ( ! AreSamePointEpsilon( ptCrvStart, ptEnd, EPS_CONNECT)) {
|
||||
// se in tolleranza, modifico l'inizio dell'entità
|
||||
// se in tolleranza, modifico l'inizio dell'entità
|
||||
if ( SqDist( ptCrvStart, ptEnd) < ( dLinTol * dLinTol)) {
|
||||
// lunghezza della curva originale
|
||||
double dOldLen ; pCrv->GetLength( dOldLen) ;
|
||||
@@ -237,11 +237,11 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT
|
||||
}
|
||||
// altrimenti inserita all'inizio
|
||||
else {
|
||||
// verifico sia in continuità con l'iniziale attuale
|
||||
// verifico sia in continuità con l'iniziale attuale
|
||||
Point3d ptStart ;
|
||||
GetStartPoint( ptStart) ;
|
||||
if ( ! AreSamePointEpsilon( ptCrvEnd, ptStart, EPS_CONNECT)) {
|
||||
// se in tolleranza, modifico la fine dell'entità
|
||||
// se in tolleranza, modifico la fine dell'entità
|
||||
if ( SqDist( ptCrvEnd, ptStart) < ( dLinTol * dLinTol)) {
|
||||
// lunghezza della curva originale
|
||||
double dOldLen ; pCrv->GetLength( dOldLen) ;
|
||||
@@ -286,7 +286,7 @@ CurveComposite::Close( void)
|
||||
if ( ! GetStartPoint( ptStart) ||
|
||||
! GetEndPoint( ptEnd))
|
||||
return false ;
|
||||
// se distanza inferiore al limite ridotto, non faccio alcunché
|
||||
// se distanza inferiore al limite ridotto, non faccio alcunché
|
||||
if ( AreSamePointEpsilon( ptStart, ptEnd, EPS_CONNECT))
|
||||
return true ;
|
||||
// se molto vicini li modifico
|
||||
@@ -324,7 +324,7 @@ CurveComposite::FromSplit( const ICurve& cCrv, int nParts)
|
||||
if ( ! cCrv.IsValid() || ! cCrv.IsSimple())
|
||||
return false ;
|
||||
|
||||
// se 1 parte o meno, non fa alcunchè
|
||||
// se 1 parte o meno, non fa alcunchè
|
||||
if ( nParts <= 1)
|
||||
return true ;
|
||||
|
||||
@@ -565,11 +565,11 @@ CurveComposite::Clone( void) const
|
||||
bool
|
||||
CurveComposite::CopyFrom( const IGeoObj* pGObjSrc)
|
||||
{
|
||||
// se sorgente è una curva composita
|
||||
// se sorgente è una curva composita
|
||||
const CurveComposite* pCC = GetBasicCurveComposite( pGObjSrc) ;
|
||||
if ( pCC != nullptr)
|
||||
return CopyFrom( *pCC) ;
|
||||
// se sorgente è un'altro tipo di curva
|
||||
// se sorgente è un'altro tipo di curva
|
||||
const ICurve* pCrv = ::GetCurve( pGObjSrc) ;
|
||||
if ( pCrv != nullptr) {
|
||||
Clear() ;
|
||||
@@ -745,7 +745,7 @@ CurveComposite::Load( NgeReader& ngeIn)
|
||||
ICurve* pCrv = ::GetCurve( pGeoO) ;
|
||||
bOk = bOk && ( pCrv != nullptr && pCrv->IsSimple()) ;
|
||||
// aggiungo questa curva (sicuramente semplice)
|
||||
bOk = bOk && AddSimpleCurve( pCrv) ;
|
||||
bOk = bOk && AddSimpleCurve( pCrv, true, 10 * EPS_SMALL) ;
|
||||
// se errore
|
||||
if ( ! bOk)
|
||||
return false ;
|
||||
@@ -782,7 +782,7 @@ CurveComposite::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
||||
// passo alla curva successiva
|
||||
pCrvSmpl = GetNextCurve() ;
|
||||
}
|
||||
// se c'è estrusione, devo tenerne conto (curve componenti sempre con vtExtr e dThick nulli)
|
||||
// se c'è estrusione, devo tenerne conto (curve componenti sempre con vtExtr e dThick nulli)
|
||||
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
|
||||
Point3d ptMinExtr = b3Loc.GetMin() + m_VtExtr * m_dThick ;
|
||||
Point3d ptMaxExtr = b3Loc.GetMax() + m_VtExtr * m_dThick ;
|
||||
@@ -799,7 +799,7 @@ CurveComposite::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
// inizializzo il box
|
||||
@@ -816,7 +816,7 @@ CurveComposite::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
// passo alla curva successiva
|
||||
pCrvSmpl = GetNextCurve() ;
|
||||
}
|
||||
// se c'è estrusione, devo tenerne conto (curve componenti sempre con vtExtr e dThick nulli)
|
||||
// se c'è estrusione, devo tenerne conto (curve componenti sempre con vtExtr e dThick nulli)
|
||||
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
|
||||
Vector3d vtFrExtr = m_VtExtr ;
|
||||
vtFrExtr.ToGlob( frRef) ;
|
||||
@@ -838,14 +838,14 @@ CurveComposite::Validate( void)
|
||||
// ciclo su tutte le curve
|
||||
int nCount = 0 ;
|
||||
for ( auto Iter = m_CrvSmplS.cbegin() ; Iter != m_CrvSmplS.cend() ; ++Iter) {
|
||||
// verifico validità della curva e sua semplicità
|
||||
// verifico validità della curva e sua semplicità
|
||||
if ( ! (*Iter)->IsValid() || (*Iter)->GetType() == CRV_COMPO) {
|
||||
m_nStatus = ERR ;
|
||||
return false ;
|
||||
}
|
||||
// incremento contatore
|
||||
++ nCount ;
|
||||
// verifico continuità con la precedente (se non è la prima)
|
||||
// verifico continuità con la precedente (se non è la prima)
|
||||
if ( nCount > 1) {
|
||||
(*Iter)->GetStartPoint( ptStart) ;
|
||||
if ( ! AreSamePointApprox( ptPrevEnd, ptStart)) {
|
||||
@@ -870,7 +870,7 @@ CurveComposite::Validate( void)
|
||||
bool
|
||||
CurveComposite::TestClosure( void)
|
||||
{
|
||||
// se non è chiusa, esco subito
|
||||
// se non è chiusa, esco subito
|
||||
if ( ! IsClosed())
|
||||
return true ;
|
||||
// verifico ed eventualmente aggiusto coincidenza punti estremi
|
||||
@@ -878,10 +878,13 @@ CurveComposite::TestClosure( void)
|
||||
Point3d ptEnd ; m_CrvSmplS.back()->GetEndPoint( ptEnd) ;
|
||||
// se distanza superiore al limite ridotto forzo i punti a coincidere
|
||||
if ( ! AreSamePointEpsilon( ptStart, ptEnd, EPS_CONNECT)) {
|
||||
// se un solo arco
|
||||
if ( m_CrvSmplS.size() == 1 && m_CrvSmplS.front()->GetType() == CRV_ARC)
|
||||
return GetBasicCurveArc( m_CrvSmplS.front())->ChangeAngCenter( ANG_FULL) ;
|
||||
// caso generale
|
||||
Point3d ptM = Media( ptStart, ptEnd) ;
|
||||
if ( ! m_CrvSmplS.front()->ModifyStart( ptM) ||
|
||||
! m_CrvSmplS.back()->ModifyEnd( ptM))
|
||||
return false ;
|
||||
return ( m_CrvSmplS.front()->ModifyStart( ptM) &&
|
||||
m_CrvSmplS.back()->ModifyEnd( ptM)) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
@@ -939,7 +942,7 @@ CurveComposite::IsFlat( Plane3d& plPlane, bool bUseExtrusion, double dToler) con
|
||||
} break ;
|
||||
}
|
||||
}
|
||||
// recupero dati sulla planarità della polilinea
|
||||
// recupero dati sulla planarità della polilinea
|
||||
int nRank ;
|
||||
Point3d ptCen ;
|
||||
Vector3d vtDir ;
|
||||
@@ -1022,7 +1025,7 @@ CurveComposite::GetMidPoint( Point3d& ptMid) const
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// determino il valore del parametro a metà lunghezza
|
||||
// determino il valore del parametro a metà lunghezza
|
||||
double dLen, dMid ;
|
||||
if ( ! GetLength( dLen) || ! GetParamAtLength( 0.5 * dLen, dMid))
|
||||
return false ;
|
||||
@@ -1083,7 +1086,7 @@ CurveComposite::GetMidDir( Vector3d& vtDir) const
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// determino il valore del parametro a metà lunghezza
|
||||
// determino il valore del parametro a metà lunghezza
|
||||
double dLen, dMid ;
|
||||
if ( ! GetLength( dLen) || ! GetParamAtLength( 0.5 * dLen, dMid))
|
||||
return false ;
|
||||
@@ -1363,7 +1366,7 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P
|
||||
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
|
||||
dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ;
|
||||
|
||||
// se speciale, approssimo ogni singola entità e conservo le estremità interne (joint)
|
||||
// se speciale, approssimo ogni singola entità e conservo le estremità interne (joint)
|
||||
if ( nType == APL_SPECIAL || nType == APL_SPECIAL_INT) {
|
||||
// eseguo approssimazione
|
||||
double dStartPar = 0 ;
|
||||
@@ -1409,7 +1412,7 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P
|
||||
Vector3d vtExtr = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ;
|
||||
if ( ! PL.ApproxOnSide( vtExtr, ( nType == APL_LEFT || nType == APL_LEFT_CONVEX), dLinTol))
|
||||
return false ;
|
||||
// se necessario, sistemo per convessità dalla parte ammessa
|
||||
// se necessario, sistemo per convessità dalla parte ammessa
|
||||
if ( nType == APL_RIGHT_CONVEX || nType == APL_LEFT_CONVEX) {
|
||||
if ( ! PL.MakeConvex( vtExtr, ( nType == APL_LEFT_CONVEX)))
|
||||
return false ;
|
||||
@@ -1418,7 +1421,7 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P
|
||||
}
|
||||
|
||||
// altrimenti standard
|
||||
// prima approssimazione lineare a 10 * Epsilon di ogni singola entità
|
||||
// prima approssimazione lineare a 10 * Epsilon di ogni singola entità
|
||||
if ( ! ApproxWithLines( 10 * EPS_SMALL, dAngTolDeg, APL_SPECIAL, PL))
|
||||
return false ;
|
||||
// eliminazione dei punti in tolleranza
|
||||
@@ -1436,7 +1439,7 @@ CurveComposite::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla
|
||||
// determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla
|
||||
Frame3d frNat ;
|
||||
if ( ! m_VtExtr.IsSmall()) {
|
||||
frNat.Set( ORIG, m_VtExtr) ;
|
||||
@@ -1500,7 +1503,7 @@ CurveComposite::ApproxWithArcsEx( double dLinTol, double dAngTolDeg, double dLin
|
||||
double dMlStartPar = 0 ;
|
||||
CurveByApprox crvByApprox ;
|
||||
|
||||
// determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla
|
||||
// determino riferimento naturale della curva in base all'estrusione o al piano medio se questa è nulla
|
||||
Frame3d frNat ;
|
||||
if ( ! m_VtExtr.IsSmall()) {
|
||||
frNat.Set( ORIG, m_VtExtr) ;
|
||||
@@ -1617,12 +1620,12 @@ CurveComposite::CopyParamRange( double dUStart, double dUEnd) const
|
||||
if ( dUStart < - EPS_PARAM || dUStart > dMaxU + EPS_PARAM ||
|
||||
dUEnd < - EPS_PARAM || dUEnd > dMaxU + EPS_PARAM)
|
||||
return nullptr ;
|
||||
// se i parametri coincidono, non resta alcunchè
|
||||
// se i parametri coincidono, non resta alcunchè
|
||||
if ( abs( dUEnd - dUStart) < EPS_PARAM)
|
||||
return nullptr ;
|
||||
// se il parametro start supera quello di end
|
||||
if ( dUStart > dUEnd - EPS_PARAM) {
|
||||
// se curva aperta, il trim la cancella completamente quindi non resta alcunchè
|
||||
// se curva aperta, il trim la cancella completamente quindi non resta alcunchè
|
||||
if ( ! IsClosed())
|
||||
return nullptr ;
|
||||
// se curva chiusa, il trim si avvolge attorno al punto di giunzione
|
||||
@@ -1681,7 +1684,7 @@ CurveComposite::Invert( void)
|
||||
bool
|
||||
CurveComposite::SimpleOffset( double dDist, int nType)
|
||||
{
|
||||
// se distanza di offset nulla, non devo fare alcunché
|
||||
// se distanza di offset nulla, non devo fare alcunché
|
||||
if ( abs( dDist) < EPS_SMALL)
|
||||
return true ;
|
||||
|
||||
@@ -1842,7 +1845,7 @@ CurveComposite::AddArcTg( const Point3d& ptNew, bool bEndOrStart)
|
||||
return false ;
|
||||
// recupero il versore normale al piano ( estrusione oppure se nulla asse Z locale)
|
||||
Vector3d vtN = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ;
|
||||
// costruisco l'arco (in casi articolari può essere una linea)
|
||||
// costruisco l'arco (in casi articolari può essere una linea)
|
||||
PtrOwner<ICurve> pCrv ;
|
||||
// se da aggiungere alla fine
|
||||
if ( bEndOrStart) {
|
||||
@@ -1875,7 +1878,7 @@ CurveComposite::AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEn
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK && m_nStatus != TO_VERIFY)
|
||||
return false ;
|
||||
// costruisco l'arco (in casi articolari può essere una linea)
|
||||
// costruisco l'arco (in casi articolari può essere una linea)
|
||||
PtrOwner<ICurve> pCrv ;
|
||||
// se da aggiungere alla fine
|
||||
if ( bEndOrStart) {
|
||||
@@ -1917,7 +1920,7 @@ CurveComposite::AddJoint( double dU)
|
||||
if ( IsNull( pCrv1) || IsNull( pCrv2))
|
||||
return false ;
|
||||
// della prima curva tengo la parte dall'inizio al parametro, della seconda la rimanente
|
||||
// ( se non riesco a trimmare, la nuova giunzione coincide con una già esistente, esco con successo)
|
||||
// ( se non riesco a trimmare, la nuova giunzione coincide con una già esistente, esco con successo)
|
||||
if ( ! pCrv1->TrimEndAtParam( dLocU) || ! pCrv2->TrimStartAtParam( dLocU))
|
||||
return true ;
|
||||
// elimino la curva originale
|
||||
@@ -1955,17 +1958,17 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
else if ( IsClosed())
|
||||
nNextCrv = 0 ;
|
||||
ICurve* pNextCrv = ( nNextCrv != -1 ? m_CrvSmplS[ nNextCrv] : nullptr) ;
|
||||
// recupero punto iniziale dell'entità precedente (se esiste)
|
||||
// recupero punto iniziale dell'entità precedente (se esiste)
|
||||
Point3d ptStart ;
|
||||
if ( pPrevCrv != nullptr && ! pPrevCrv->GetStartPoint( ptStart))
|
||||
return false ;
|
||||
// recupero punto finale dell'entità successiva (se esiste)
|
||||
// recupero punto finale dell'entità successiva (se esiste)
|
||||
Point3d ptEnd ;
|
||||
if ( pNextCrv != nullptr && ! pNextCrv->GetEndPoint( ptEnd))
|
||||
return false ;
|
||||
// modifico il punto finale dell'eventuale entità precedente
|
||||
// modifico il punto finale dell'eventuale entità precedente
|
||||
if ( pPrevCrv != nullptr && ! pPrevCrv->ModifyEnd( ptNewJoint)) {
|
||||
// se entità precedente si annulla, la elimino
|
||||
// se entità precedente si annulla, la elimino
|
||||
if ( AreSamePointApprox( ptStart, ptNewJoint)) {
|
||||
delete pPrevCrv ;
|
||||
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
|
||||
@@ -1982,9 +1985,9 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
delete( pPrevCrv) ;
|
||||
}
|
||||
}
|
||||
// modifico il punto iniziale dell'eventuale entità successiva
|
||||
// modifico il punto iniziale dell'eventuale entità successiva
|
||||
if ( pNextCrv != nullptr && ! pNextCrv->ModifyStart( ptNewJoint)) {
|
||||
// se entità successiva si annulla, la elimino
|
||||
// se entità successiva si annulla, la elimino
|
||||
if ( AreSamePointApprox( ptNewJoint, ptEnd)) {
|
||||
delete pNextCrv ;
|
||||
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
|
||||
@@ -2101,17 +2104,17 @@ CurveComposite::MoveCurve( int nCrv, const Vector3d& vtMove)
|
||||
else if ( IsClosed())
|
||||
nNextCrv = 0 ;
|
||||
ICurve* pNextCrv = ( nNextCrv != -1 ? m_CrvSmplS[ nNextCrv] : nullptr) ;
|
||||
// recupero punti iniziale e finale dell'entità precedente (se esiste)
|
||||
// recupero punti iniziale e finale dell'entità precedente (se esiste)
|
||||
Point3d ptPrevStart, ptPrevEnd ;
|
||||
if ( pPrevCrv != nullptr && ( ! pPrevCrv->GetStartPoint( ptPrevStart) || ! pPrevCrv->GetEndPoint( ptPrevEnd)))
|
||||
return false ;
|
||||
// recupero punti iniziale e finale dell'entità successiva (se esiste)
|
||||
// recupero punti iniziale e finale dell'entità successiva (se esiste)
|
||||
Point3d ptNextStart, ptNextEnd ;
|
||||
if ( pNextCrv != nullptr && ( ! pNextCrv->GetStartPoint( ptNextStart) || ! pNextCrv->GetEndPoint( ptNextEnd)))
|
||||
return false ;
|
||||
// modifico il punto finale dell'eventuale entità precedente
|
||||
// modifico il punto finale dell'eventuale entità precedente
|
||||
if ( pPrevCrv != nullptr && ! pPrevCrv->ModifyEnd( ptPrevEnd + vtMove)) {
|
||||
// se entità precedente si annulla, la elimino
|
||||
// se entità precedente si annulla, la elimino
|
||||
if ( AreSamePointApprox( ptPrevStart, ptPrevEnd + vtMove)) {
|
||||
delete pPrevCrv ;
|
||||
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
|
||||
@@ -2130,9 +2133,9 @@ CurveComposite::MoveCurve( int nCrv, const Vector3d& vtMove)
|
||||
delete( pPrevCrv) ;
|
||||
}
|
||||
}
|
||||
// modifico il punto iniziale dell'eventuale entità successiva
|
||||
// modifico il punto iniziale dell'eventuale entità successiva
|
||||
if ( pNextCrv != nullptr && ! pNextCrv->ModifyStart( ptNextStart + vtMove)) {
|
||||
// se entità successiva si annulla, la elimino
|
||||
// se entità successiva si annulla, la elimino
|
||||
if ( AreSamePointApprox( ptNextStart + vtMove, ptNextEnd)) {
|
||||
delete pNextCrv ;
|
||||
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
|
||||
@@ -2209,7 +2212,7 @@ CurveComposite::ModifyCurveToLine( int nCrv)
|
||||
return false ;
|
||||
// recupero la curva corrente
|
||||
ICurve* pCrv = m_CrvSmplS[nCrv] ;
|
||||
// se già linea non devo fare alcunchè
|
||||
// se già linea non devo fare alcunchè
|
||||
if ( pCrv->GetType() == CRV_LINE)
|
||||
return true ;
|
||||
// recupero gli estremi
|
||||
@@ -2237,7 +2240,7 @@ CurveComposite::ModifyCurveToLine( int nCrv)
|
||||
bool
|
||||
CurveComposite::TrimStartAtParam( double dUTrim)
|
||||
{
|
||||
// verifico validità parametro
|
||||
// verifico validità parametro
|
||||
double dMaxU = double( m_CrvSmplS.size()) ;
|
||||
if ( dUTrim < -EPS_PARAM || dUTrim > dMaxU - EPS_PARAM)
|
||||
return false ;
|
||||
@@ -2267,7 +2270,7 @@ CurveComposite::TrimStartAtParam( double dUTrim)
|
||||
Iter = m_CrvSmplS.erase( Iter) ;
|
||||
break ;
|
||||
}
|
||||
// altrimenti superata lunghezza ancora da tagliare (taglio già fatto al test sopra)
|
||||
// altrimenti superata lunghezza ancora da tagliare (taglio già fatto al test sopra)
|
||||
else {
|
||||
break ;
|
||||
}
|
||||
@@ -2280,7 +2283,7 @@ CurveComposite::TrimStartAtParam( double dUTrim)
|
||||
bool
|
||||
CurveComposite::TrimEndAtParam( double dUTrim)
|
||||
{
|
||||
// verifico validità parametro
|
||||
// verifico validità parametro
|
||||
double dMaxU = double( m_CrvSmplS.size()) ;
|
||||
if ( dUTrim < EPS_PARAM || dUTrim > dMaxU + EPS_PARAM)
|
||||
return false ;
|
||||
@@ -2301,7 +2304,7 @@ CurveComposite::TrimEndAtParam( double dUTrim)
|
||||
dUToTrim -= ( dParEnd - dParStart) ;
|
||||
// se da cancellare
|
||||
if ( bToErase) {
|
||||
// cancello l'entità, la tolgo dalla lista e passo alla successiva
|
||||
// cancello l'entità, la tolgo dalla lista e passo alla successiva
|
||||
delete (*Iter) ;
|
||||
Iter = m_CrvSmplS.erase( Iter) ;
|
||||
}
|
||||
@@ -2311,7 +2314,7 @@ CurveComposite::TrimEndAtParam( double dUTrim)
|
||||
}
|
||||
// se lunghezza parametrica ancora da tagliare nulla (entro la tolleranza)
|
||||
else if ( dUToTrim > - EPS_PARAM) {
|
||||
// passo alla entità successiva
|
||||
// passo alla entità successiva
|
||||
++ Iter ;
|
||||
// dichiaro ingresso in zona da cancellare
|
||||
bToErase = true ;
|
||||
@@ -2324,7 +2327,7 @@ CurveComposite::TrimEndAtParam( double dUTrim)
|
||||
bToErase = true ;
|
||||
continue ;
|
||||
}
|
||||
// passo alla entità successiva
|
||||
// passo alla entità successiva
|
||||
++ Iter ;
|
||||
// dichiaro ingresso in zona da cancellare
|
||||
bToErase = true ;
|
||||
@@ -2389,7 +2392,7 @@ CurveComposite::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
|
||||
bool
|
||||
CurveComposite::TrimStartAtLen( double dLenTrim)
|
||||
{
|
||||
// verifico validità lunghezza risultante
|
||||
// verifico validità lunghezza risultante
|
||||
if ( dLenTrim < EPS_ZERO)
|
||||
return true ;
|
||||
double dLen ;
|
||||
@@ -2443,7 +2446,7 @@ CurveComposite::TrimStartAtLen( double dLenTrim)
|
||||
bool
|
||||
CurveComposite::TrimEndAtLen( double dLenTrim)
|
||||
{
|
||||
// verifico validità lunghezza risultante
|
||||
// verifico validità lunghezza risultante
|
||||
if ( dLenTrim < EPS_SMALL)
|
||||
return false ;
|
||||
double dLen ;
|
||||
@@ -2456,7 +2459,7 @@ CurveComposite::TrimEndAtLen( double dLenTrim)
|
||||
double dLenToTrim = dLenTrim ;
|
||||
for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) {
|
||||
double dCrvLen = 0 ;
|
||||
// se non sono già nella zona da cancellare, aggiorno lunghezze
|
||||
// se non sono già nella zona da cancellare, aggiorno lunghezze
|
||||
if ( ! bToErase) {
|
||||
// lunghezza della curva
|
||||
if ( ! (*Iter)->GetLength( dCrvLen))
|
||||
@@ -2466,18 +2469,18 @@ CurveComposite::TrimEndAtLen( double dLenTrim)
|
||||
}
|
||||
// se da cancellare
|
||||
if ( bToErase) {
|
||||
// cancello l'entità, la tolgo dalla lista e passo alla successiva
|
||||
// cancello l'entità, la tolgo dalla lista e passo alla successiva
|
||||
delete (*Iter) ;
|
||||
Iter = m_CrvSmplS.erase( Iter) ;
|
||||
}
|
||||
// se lunghezza ancora da tagliare non nulla
|
||||
else if ( dLenToTrim > EPS_SMALL) {
|
||||
// passo alla entità successiva
|
||||
// passo alla entità successiva
|
||||
++ Iter ;
|
||||
}
|
||||
// se lunghezza ancora da tagliare nulla (entro la tolleranza)
|
||||
else if ( dLenToTrim > - EPS_SMALL) {
|
||||
// passo alla entità successiva
|
||||
// passo alla entità successiva
|
||||
++ Iter ;
|
||||
// dichiaro ingresso in zona da cancellare
|
||||
bToErase = true ;
|
||||
@@ -2489,7 +2492,7 @@ CurveComposite::TrimEndAtLen( double dLenTrim)
|
||||
m_nStatus = ERR ;
|
||||
return false ;
|
||||
}
|
||||
// passo alla entità successiva
|
||||
// passo alla entità successiva
|
||||
++ Iter ;
|
||||
// dichiaro ingresso in zona da cancellare
|
||||
bToErase = true ;
|
||||
@@ -2565,8 +2568,10 @@ CurveComposite::Translate( const Vector3d& vtMove)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// traslo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->Translate( vtMove) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -2584,12 +2589,14 @@ CurveComposite::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dell'asse di rotazione
|
||||
// verifico validità dell'asse di rotazione
|
||||
if ( vtAx.IsSmall())
|
||||
return false ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// ruoto Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -2649,9 +2656,9 @@ CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou
|
||||
// se tutto bene, passo alla prossima
|
||||
if ( bOk)
|
||||
++Iter ;
|
||||
// altrimenti, l'entità si è annullata => devo toglierla dalla lista e cancellarla
|
||||
// altrimenti, l'entità si è annullata => devo toglierla dalla lista e cancellarla
|
||||
else {
|
||||
// si è annullata l'entità, la elimino e la tolgo dalla lista
|
||||
// si è annullata l'entità, la elimino e la tolgo dalla lista
|
||||
delete (*Iter) ;
|
||||
Iter = m_CrvSmplS.erase( Iter) ;
|
||||
}
|
||||
@@ -2699,7 +2706,7 @@ CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del piano di specchiatura
|
||||
// verifico validità del piano di specchiatura
|
||||
if ( vtNorm.IsSmall())
|
||||
return false ;
|
||||
|
||||
@@ -2725,7 +2732,7 @@ CurveComposite::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dei parametri
|
||||
// verifico validità dei parametri
|
||||
if ( vtNorm.IsSmall() || vtDir.IsSmall())
|
||||
return false ;
|
||||
|
||||
@@ -2760,16 +2767,18 @@ CurveComposite::ToGlob( const Frame3d& frRef)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se frame identità, non devo fare alcunché
|
||||
// se frame identità, non devo fare alcunché
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->ToGlob( frRef) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -2790,16 +2799,18 @@ CurveComposite::ToLoc( const Frame3d& frRef)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se frame identità, non devo fare alcunché
|
||||
// se frame identità, non devo fare alcunché
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->ToLoc( frRef) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -2820,16 +2831,18 @@ CurveComposite::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dei frame
|
||||
// verifico validità dei frame
|
||||
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
if ( AreSameFrame( frOri, frDest))
|
||||
return true ;
|
||||
return true ;
|
||||
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
|
||||
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -2976,7 +2989,7 @@ CurveComposite::RemoveFirstOrLastCurve( bool bLast)
|
||||
bool
|
||||
CurveComposite::IsParamAtJoint( double dU) const
|
||||
{
|
||||
// se aperta e all'inizio o alla fine o lontano dagli interi non è giunzione
|
||||
// se aperta e all'inizio o alla fine o lontano dagli interi non è giunzione
|
||||
bool bClosed = IsClosed() ;
|
||||
if ( ( ! bClosed && abs( dU) < EPS_PARAM) ||
|
||||
( ! bClosed && abs( dU - double( m_CrvSmplS.size())) < EPS_PARAM) ||
|
||||
@@ -2994,7 +3007,7 @@ CurveComposite::ChangeStartPoint( double dU)
|
||||
if ( ! IsClosed())
|
||||
return false ;
|
||||
|
||||
// questa funzione gestisce già anche il cambio di inizio su curve chiuse
|
||||
// questa funzione gestisce già anche il cambio di inizio su curve chiuse
|
||||
return TrimStartEndAtParam( dU, dU) ;
|
||||
}
|
||||
|
||||
@@ -3004,19 +3017,19 @@ CurveComposite::ArcsToBezierCurves( void)
|
||||
{
|
||||
// verifico le singole curve
|
||||
for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
|
||||
// se arco, devo trasformare in una o più curve di Bezier
|
||||
// se arco, devo trasformare in una o più curve di Bezier
|
||||
if ( (*Iter)->GetType() == CRV_ARC) {
|
||||
// eseguo trasformazione
|
||||
PtrOwner<ICurve> pNewCrv( ArcToBezierCurve( (*Iter))) ;
|
||||
if ( IsNull( pNewCrv))
|
||||
return false ;
|
||||
// se risultato è singola curva
|
||||
// se risultato è singola curva
|
||||
if ( pNewCrv->IsSimple()) {
|
||||
// elimino l'arco e lo sostituisco con la curva di Bezier
|
||||
delete (*Iter) ;
|
||||
(*Iter) = Release( pNewCrv) ;
|
||||
}
|
||||
// altrimenti è una curva composita
|
||||
// altrimenti è una curva composita
|
||||
else {
|
||||
CurveComposite* pCC = GetBasicCurveComposite( pNewCrv) ;
|
||||
if ( pCC == nullptr)
|
||||
@@ -3058,13 +3071,13 @@ CurveComposite::ArcsBezierCurvesToArcsPerpExtr( double dLinTol, double dAngTolDe
|
||||
(*Iter)->SetExtrusion( V_NULL) ;
|
||||
if ( IsNull( pNewCrv))
|
||||
return false ;
|
||||
// se risultato è singola curva
|
||||
// se risultato è singola curva
|
||||
if ( pNewCrv->IsSimple()) {
|
||||
// elimino la curva originale e la sostituisco con l'arco
|
||||
delete (*Iter) ;
|
||||
(*Iter) = Release( pNewCrv) ;
|
||||
}
|
||||
// altrimenti è una curva composita
|
||||
// altrimenti è una curva composita
|
||||
else {
|
||||
CurveComposite* pCC = GetBasicCurveComposite( pNewCrv) ;
|
||||
if ( pCC == nullptr)
|
||||
@@ -3130,7 +3143,7 @@ CurveComposite::StraightArcsToLines( double dLinTol, double dAngTolDeg)
|
||||
static int
|
||||
MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAngTol, bool bNeedSameProp)
|
||||
{
|
||||
// verifico compatibilità delle proprietà
|
||||
// verifico compatibilità delle proprietà
|
||||
int nTpr0P = pCrvP->GetTempProp( 0) ;
|
||||
int nTpr0C = pCrvC->GetTempProp( 0) ;
|
||||
int nTpr1P = pCrvP->GetTempProp( 1) ;
|
||||
@@ -3177,7 +3190,7 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
if ( pLineC->ModifyStart( pLineP->GetStart())) {
|
||||
// diminuisco la tolleranza corrente dell'errore attuale
|
||||
dCurrLinTol -= COEFF_TOL * sqrt( dSqDist) ;
|
||||
// se curve originali con proprietà diversa, la cancello
|
||||
// se curve originali con proprietà diversa, la cancello
|
||||
if ( nTpr0P != nTpr0C)
|
||||
pLineC->SetTempProp( 0, 0) ;
|
||||
if ( nTpr1P != nTpr1C)
|
||||
@@ -3202,7 +3215,7 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
// verifico la coincidenza dei raggi
|
||||
if ( abs( pArcP->GetRadius() - pArcC->GetRadius()) > dCurrLinTol)
|
||||
return 0 ;
|
||||
// verifico la collinearità delle normali (tenendo conto del raggio)
|
||||
// verifico la collinearità delle normali (tenendo conto del raggio)
|
||||
if ( ! (( pArcP->GetNormVersor() - pArcC->GetNormVersor()) * pArcP->GetRadius()).IsSmall() &&
|
||||
! (( pArcP->GetNormVersor() + pArcC->GetNormVersor()) * pArcP->GetRadius()).IsSmall())
|
||||
return 0 ;
|
||||
@@ -3212,61 +3225,64 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
// verifico di non superare l'angolo giro al centro
|
||||
if ( abs( pArcP->GetAngCenter() + pArcC->GetAngCenter()) > ANG_FULL + EPS_ANG_SMALL)
|
||||
return 0 ;
|
||||
// se archi piatti
|
||||
if ( pArcP->IsPlane() && pArcC->IsPlane()) {
|
||||
// se calcolo nuovo arco ok, procedo con l'unione
|
||||
Point3d ptP1 ;
|
||||
pArcP->GetStartPoint( ptP1) ;
|
||||
Point3d ptP2 ;
|
||||
pArcP->GetEndPoint( ptP2) ;
|
||||
Point3d ptP3 ;
|
||||
pArcC->GetEndPoint( ptP3) ;
|
||||
// verifico se circonferenza completa
|
||||
bool bCirc = ( AreSamePointApprox( ptP1, ptP3)) ;
|
||||
if ( bCirc)
|
||||
pArcC->GetMidPoint( ptP3) ;
|
||||
CurveArc NewArc ;
|
||||
if ( NewArc.Set3P( ptP1, ptP2, ptP3, bCirc)) {
|
||||
// verifico normale al piano dell'arco
|
||||
if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0)
|
||||
NewArc.InvertN() ;
|
||||
// se curve originali con la stessa proprietà, la riporto
|
||||
if ( nTpr0P == nTpr0C)
|
||||
NewArc.SetTempProp( nTpr0C, 0) ;
|
||||
if ( nTpr1P == nTpr1C)
|
||||
NewArc.SetTempProp( nTpr1C, 1) ;
|
||||
// aggiorno l'arco corrente e torno flag modifica
|
||||
*pArcC = NewArc ;
|
||||
return -1 ;
|
||||
}
|
||||
else
|
||||
// verifico se archi piatti
|
||||
bool bPlaneArcs = pArcP->IsPlane() && pArcC->IsPlane() ;
|
||||
// se archi non piatti verifico coincidenza pendenza sulla normale
|
||||
if ( ! bPlaneArcs) {
|
||||
double dN = pArcP->GetNormVersor() * pArcC->GetNormVersor() ;
|
||||
if ( abs(( pArcC->GetDeltaN() * pArcP->GetAngCenter() - dN * pArcP->GetDeltaN() * pArcC->GetAngCenter()) /
|
||||
( pArcP->GetAngCenter() + pArcC->GetAngCenter())) > dCurrLinTol)
|
||||
return 0 ;
|
||||
}
|
||||
// verifico coincidenza pendenza sulla normale
|
||||
double dN = pArcP->GetNormVersor() * pArcC->GetNormVersor() ;
|
||||
if ( abs(( pArcC->GetDeltaN() * pArcP->GetAngCenter() - dN * pArcP->GetDeltaN() * pArcC->GetAngCenter()) /
|
||||
( pArcP->GetAngCenter() + pArcC->GetAngCenter())) < dCurrLinTol) {
|
||||
// se calcolo nuovo arco ok, procedo con l'unione
|
||||
Point3d ptP1 ;
|
||||
pArcP->GetStartPoint( ptP1) ;
|
||||
Vector3d vtDir1 ;
|
||||
pArcP->GetStartDir( vtDir1) ;
|
||||
Point3d ptP3 ;
|
||||
pArcC->GetEndPoint( ptP3) ;
|
||||
CurveArc NewArc ;
|
||||
if ( NewArc.Set2PVN( ptP1, ptP3, vtDir1, pArcC->GetNormVersor())) {
|
||||
// se curve originali con la stessa proprietà, la riporto
|
||||
if ( nTpr0P == nTpr0C)
|
||||
NewArc.SetTempProp( nTpr0C, 0) ;
|
||||
if ( nTpr1P == nTpr1C)
|
||||
NewArc.SetTempProp( nTpr1C, 1) ;
|
||||
// aggiorno l'arco corrente e torno flag modifica
|
||||
*pArcC = NewArc ;
|
||||
return -1 ;
|
||||
}
|
||||
else
|
||||
return 0 ;
|
||||
|
||||
// se calcolo nuovo arco ok, procedo con l'unione
|
||||
Point3d ptP1 ;
|
||||
pArcP->GetStartPoint( ptP1) ;
|
||||
Point3d ptP2 ;
|
||||
pArcP->GetEndPoint( ptP2) ;
|
||||
Point3d ptP3 ;
|
||||
pArcC->GetEndPoint( ptP3) ;
|
||||
|
||||
// se archi non piani costruisco arco sul piano definito dalla normale e dal punto di partenza del primo arco
|
||||
Frame3d frRef ;
|
||||
if ( ! frRef.Set( ptP1, pArcP->GetNormVersor()))
|
||||
return 0 ;
|
||||
if ( ! bPlaneArcs) {
|
||||
ptP1.Scale( frRef, 1, 1, 0) ;
|
||||
ptP2.Scale( frRef, 1, 1, 0) ;
|
||||
ptP3.Scale( frRef, 1, 1, 0) ;
|
||||
}
|
||||
|
||||
// verifico se circonferenza completa
|
||||
bool bCirc = ( AreSamePointApprox( ptP1, ptP3)) ;
|
||||
if ( bCirc) {
|
||||
pArcC->GetMidPoint( ptP3) ;
|
||||
if ( ! bPlaneArcs)
|
||||
ptP3.Scale( frRef, 1, 1, 0) ;
|
||||
}
|
||||
|
||||
CurveArc NewArc ;
|
||||
if ( NewArc.Set3P( ptP1, ptP2, ptP3, bCirc)) {
|
||||
// verifico normale al piano dell'arco
|
||||
if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0)
|
||||
NewArc.InvertN() ;
|
||||
// se archi non piani ripristino il deltaN
|
||||
if ( ! bPlaneArcs) {
|
||||
double dDeltaN1 = pArcP->GetDeltaN() ;
|
||||
double dDeltaN2 = pArcC->GetDeltaN() ;
|
||||
NewArc.ChangeDeltaN( dDeltaN1 + dDeltaN2) ;
|
||||
}
|
||||
// se curve originali con la stessa proprietà, la riporto
|
||||
if ( nTpr0P == nTpr0C)
|
||||
NewArc.SetTempProp( nTpr0C, 0) ;
|
||||
if ( nTpr1P == nTpr1C)
|
||||
NewArc.SetTempProp( nTpr1C, 1) ;
|
||||
// aggiorno l'arco corrente e torno flag modifica
|
||||
*pArcC = NewArc ;
|
||||
return -1 ;
|
||||
}
|
||||
else
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
// nessuna fusione
|
||||
@@ -3293,11 +3309,11 @@ CurveComposite::MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd,
|
||||
while ( iterC != m_CrvSmplS.end()) {
|
||||
// se curve unite
|
||||
switch ( MergeTwoCurves( *iterP, *iterC, dCurrLinTol, dCosAngTol, bNeedSameProp)) {
|
||||
case -1 : // cancello l'entità precedente e la tolgo dalla lista
|
||||
case -1 : // cancello l'entità precedente e la tolgo dalla lista
|
||||
delete (*iterP) ;
|
||||
iterC = m_CrvSmplS.erase( iterP) ;
|
||||
break ;
|
||||
case 1 : // cancello l'entità corrente e la tolgo dalla lista
|
||||
case 1 : // cancello l'entità corrente e la tolgo dalla lista
|
||||
delete (*iterC) ;
|
||||
iterC = m_CrvSmplS.erase( iterC) ;
|
||||
iterC = prev( iterC) ;
|
||||
@@ -3314,11 +3330,11 @@ CurveComposite::MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd,
|
||||
if ( bStartEnd && m_CrvSmplS.size() >= 2 && IsClosed()) {
|
||||
iterC = m_CrvSmplS.begin() ;
|
||||
switch ( MergeTwoCurves( *iterP, *iterC, dCurrLinTol, dCosAngTol, bNeedSameProp)) {
|
||||
case -1 : // cancello l'entità precedente e la tolgo dalla lista
|
||||
case -1 : // cancello l'entità precedente e la tolgo dalla lista
|
||||
delete (*iterP) ;
|
||||
m_CrvSmplS.erase( iterP) ;
|
||||
break ;
|
||||
case 1 : // cancello l'entità corrente e la tolgo dalla lista
|
||||
case 1 : // cancello l'entità corrente e la tolgo dalla lista
|
||||
delete (*iterC) ;
|
||||
m_CrvSmplS.erase( iterC) ;
|
||||
break ;
|
||||
@@ -3377,7 +3393,7 @@ SplitTopBottomArcs( CurveComposite& cCompo)
|
||||
// le ordino in senso crescente di ampiezza assoluta
|
||||
if ( abs( dAng1) > abs( dAng2))
|
||||
swap( dAng1, dAng2) ;
|
||||
// verifico se la prima di queste rotazioni è compresa nell'arco
|
||||
// verifico se la prima di queste rotazioni è compresa nell'arco
|
||||
if ( abs( dAng1) > EPS_ANG_SMALL && abs( dAng1) < abs( pArc->GetAngCenter()) - EPS_ANG_SMALL) {
|
||||
cCompo.AddJoint( i + dAng1 / pArc->GetAngCenter()) ;
|
||||
}
|
||||
@@ -3427,7 +3443,7 @@ CurveComposite::RemoveUndercutOnY( double dLinTol, double dAngTolDeg)
|
||||
Point3d ptStart, ptEnd ;
|
||||
pCompo->GetStartPoint( ptStart) ;
|
||||
pCompo->GetEndPoint( ptEnd) ;
|
||||
// se curva pressochè verticale non sottende alcunché, quindi la salto
|
||||
// se curva pressochè verticale non sottende alcunché, quindi la salto
|
||||
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL)
|
||||
continue ;
|
||||
// ordino gli estremi
|
||||
@@ -3533,7 +3549,7 @@ CurveComposite::IsALine( double dLinTol, Point3d& ptStart, Point3d& ptEnd) const
|
||||
// elimino i punti allineati entro la tolleranza
|
||||
if ( ! PL.RemoveAlignedPoints( dLinTol))
|
||||
return false ;
|
||||
// se sono rimasti due punti è una retta
|
||||
// se sono rimasti due punti è una retta
|
||||
return ( PL.GetPointNbr() == 2) ;
|
||||
}
|
||||
|
||||
@@ -3541,7 +3557,7 @@ CurveComposite::IsALine( double dLinTol, Point3d& ptStart, Point3d& ptEnd) const
|
||||
bool
|
||||
CurveComposite::IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const
|
||||
{
|
||||
// deve essere una sola entità
|
||||
// deve essere una sola entità
|
||||
if ( GetCurveCount() != 1)
|
||||
return false ;
|
||||
// deve essere un arco di circonferenza completo
|
||||
@@ -3564,7 +3580,7 @@ CurveComposite::IsACircle( double dLinTol, Point3d& ptCen, Vector3d& vtN, double
|
||||
if ( ! IsClosed())
|
||||
return false ;
|
||||
|
||||
// se è formata da una sola entità arco che è una circonferenza
|
||||
// se è formata da una sola entità arco che è una circonferenza
|
||||
if ( IsOneCircle( ptCen, vtN, dRad, bCCW))
|
||||
return true ;
|
||||
|
||||
@@ -3601,10 +3617,10 @@ CurveComposite::IsARectangle( double dLinTol, Point3d& ptP, Vector3d& vtL1, Vect
|
||||
Point3d ptV2 ; PL.GetNextPoint( ptV2) ;
|
||||
Point3d ptV3 ; PL.GetNextPoint( ptV3) ;
|
||||
Point3d ptV4 ; PL.GetNextPoint( ptV4) ;
|
||||
// verifico che le diagonali si incontrino nel loro punto medio (-> è un parallelogramma)
|
||||
// verifico che le diagonali si incontrino nel loro punto medio (-> è un parallelogramma)
|
||||
if ( ! AreSamePointEpsilon( Media( ptV1, ptV3), Media( ptV2, ptV4), dLinTol / 2))
|
||||
return false ;
|
||||
// verifico che le diagonali abbiano la stessa lunghezza (-> è un rettangolo)
|
||||
// verifico che le diagonali abbiano la stessa lunghezza (-> è un rettangolo)
|
||||
if ( abs( Dist( ptV1, ptV3) - Dist( ptV2, ptV4)) > dLinTol)
|
||||
return false ;
|
||||
// assegno i parametri del rettangolo
|
||||
@@ -3637,7 +3653,7 @@ CurveComposite::IsATrapezoid( double dLinTol, Point3d& ptP, Vector3d& vtB1, Vect
|
||||
Point3d ptV2 ; PL.GetNextPoint( ptV2) ;
|
||||
Point3d ptV3 ; PL.GetNextPoint( ptV3) ;
|
||||
Point3d ptV4 ; PL.GetNextPoint( ptV4) ;
|
||||
// verifico se V4->V3 è parallelo a V1->V2
|
||||
// verifico se V4->V3 è parallelo a V1->V2
|
||||
double dV3B12, dV4B12 ;
|
||||
if ( ! DistPointLine( ptV3, ptV1, ptV2, false).GetDist( dV3B12) ||
|
||||
! DistPointLine( ptV4, ptV1, ptV2, false).GetDist( dV4B12))
|
||||
@@ -3649,7 +3665,7 @@ CurveComposite::IsATrapezoid( double dLinTol, Point3d& ptP, Vector3d& vtB1, Vect
|
||||
vtB2 = ptV3 - ptV4 ;
|
||||
return true ;
|
||||
}
|
||||
// verifico se V1->V4 è parallelo a V2->V3
|
||||
// verifico se V1->V4 è parallelo a V2->V3
|
||||
double dV1B23, dV4B23 ;
|
||||
if ( ! DistPointLine( ptV1, ptV2, ptV3, false).GetDist( dV1B23) ||
|
||||
! DistPointLine( ptV4, ptV2, ptV3, false).GetDist( dV4B23))
|
||||
@@ -3661,7 +3677,7 @@ CurveComposite::IsATrapezoid( double dLinTol, Point3d& ptP, Vector3d& vtB1, Vect
|
||||
vtB2 = ptV4 - ptV1 ;
|
||||
return true ;
|
||||
}
|
||||
// non è un trapezio
|
||||
// non è un trapezio
|
||||
return false ;
|
||||
}
|
||||
|
||||
@@ -3747,7 +3763,7 @@ CurveComposite::GetVoronoiObject() const
|
||||
if ( m_nStatus != OK)
|
||||
return nullptr ;
|
||||
|
||||
// se non è stato calcolato, lo calcolo
|
||||
// se non è stato calcolato, lo calcolo
|
||||
if ( m_pVoronoiObj == nullptr)
|
||||
CalcVoronoiObject() ;
|
||||
|
||||
@@ -3763,3 +3779,28 @@ CurveComposite::ResetVoronoiObject() const
|
||||
delete m_pVoronoiObj ;
|
||||
m_pVoronoiObj = nullptr ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::FromPoint(Point3d& ptStart)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != TO_VERIFY)
|
||||
return false ;
|
||||
// assegno il punto e setto lo stato
|
||||
m_ptStart = ptStart ;
|
||||
m_nStatus = IS_A_POINT ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::GetOnlyPoint(Point3d& ptStart) const
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != IS_A_POINT)
|
||||
return false ;
|
||||
// restituisco il punto
|
||||
ptStart = m_ptStart ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
+9
-4
@@ -150,7 +150,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool IsParamAtJoint( double dU) const override ;
|
||||
ICurve* RemoveFirstOrLastCurve( bool bLast = true) override ;
|
||||
bool ChangeStartPoint( double dU) override ;
|
||||
bool AddPoint( const Point3d& ptStart) override ;
|
||||
bool AddPoint( const Point3d& ptStart) override ; // funzione per aggiungere il ptStart prima di usare la funzione AddLine
|
||||
bool AddLine( const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddLineTg( double dLen, bool bEndOrStart = true) override ;
|
||||
bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
@@ -177,11 +177,16 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool GetCurveTempProp( int nCrv, int& nProp, int nPropInd = 0) const override ;
|
||||
bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
|
||||
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
|
||||
bool FromPoint( Point3d& ptStart) override ; // funzione per settare la curva ad un unico punto
|
||||
bool GetOnlyPoint( Point3d& ptStart) const override ; // funzione per recuperare l'unico punto da cui è composta la curva ( degenere)
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
CurveComposite( void) ;
|
||||
@@ -195,6 +200,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool RelocateFrom( CurveComposite& ccSrc) ;
|
||||
bool GetApproxLength( double& dLen) const ;
|
||||
Voronoi* GetVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
bool CopyFrom( const CurveComposite& ccSrc) ;
|
||||
@@ -206,10 +212,9 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET) ;
|
||||
bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ;
|
||||
bool CalcVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ;
|
||||
|
||||
private :
|
||||
typedef std::deque<ICurve*> PCRVSMPL_DEQUE ;
|
||||
@@ -222,7 +227,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN)
|
||||
double m_dThick ; // spessore
|
||||
Point3d m_ptStart ; // punto iniziale per composita vuota per Add di linee o archi
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable Voronoi* m_pVoronoiObj ; // Voronoi
|
||||
mutable PCSD_CONST_ITER m_Iter ; // iteratore
|
||||
|
||||
+38
-28
@@ -14,11 +14,11 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveLine.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoObjFactory.h"
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
#include "Voronoi.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
@@ -162,7 +162,7 @@ CurveLine::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
||||
// dati generali di una curva
|
||||
if ( ! CurveDump( *this, sOut, bMM, szNewLine))
|
||||
return false ;
|
||||
// parametri : sono già compresi nei dati generali (PS e PE)
|
||||
// parametri : sono già compresi nei dati generali (PS e PE)
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -223,7 +223,7 @@ CurveLine::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
||||
return false ;
|
||||
// assegno il box in locale
|
||||
b3Loc.Set( m_PtStart, m_PtEnd) ;
|
||||
// se c'è estrusione, devo tenerne conto
|
||||
// se c'è estrusione, devo tenerne conto
|
||||
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
|
||||
Point3d ptMinExtr = b3Loc.GetMin() + m_VtExtr * m_dThick ;
|
||||
Point3d ptMaxExtr = b3Loc.GetMax() + m_VtExtr * m_dThick ;
|
||||
@@ -241,7 +241,7 @@ CurveLine::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
// porto gli estremi nel riferimento passato
|
||||
@@ -251,7 +251,7 @@ CurveLine::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
ptFrEnd.ToGlob( frRef) ;
|
||||
// assegno il box nel riferimento
|
||||
b3Ref.Set( ptFrStart, ptFrEnd) ;
|
||||
// se c'è estrusione, devo tenerne conto
|
||||
// se c'è estrusione, devo tenerne conto
|
||||
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
|
||||
Vector3d vtFrExtr = m_VtExtr ;
|
||||
vtFrExtr.ToGlob( frRef) ;
|
||||
@@ -390,7 +390,7 @@ CurveLine::GetLength( double& dLen) const
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// la lunghezza è la distanza tra gli estremi
|
||||
// la lunghezza è la distanza tra gli estremi
|
||||
dLen = Dist( m_PtStart, m_PtEnd) ;
|
||||
|
||||
return ( dLen > EPS_SMALL) ;
|
||||
@@ -416,7 +416,7 @@ CurveLine::GetLengthAtParam( double dU, double& dLen) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
// la lunghezza totale è la distanza tra gli estremi
|
||||
// la lunghezza totale è la distanza tra gli estremi
|
||||
double dTotLen = Dist( m_PtStart, m_PtEnd) ;
|
||||
|
||||
// fine
|
||||
@@ -448,7 +448,7 @@ CurveLine::GetParamAtLength( double dLen, double& dU) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
// la lunghezza totale è la distanza tra gli estremi
|
||||
// la lunghezza totale è la distanza tra gli estremi
|
||||
double dTotLen = Dist( m_PtStart, m_PtEnd) ;
|
||||
|
||||
// se dopo fine, errore
|
||||
@@ -811,8 +811,10 @@ CurveLine::Translate( const Vector3d& vtMove)
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// traslo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->Translate( vtMove) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -830,12 +832,14 @@ CurveLine::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, do
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dell'asse di rotazione
|
||||
// verifico validità dell'asse di rotazione
|
||||
if ( vtAx.IsSmall())
|
||||
return false ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// ruoto Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -894,7 +898,7 @@ CurveLine::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del piano di specchiatura
|
||||
// verifico validità del piano di specchiatura
|
||||
if ( vtNorm.IsSmall())
|
||||
return false ;
|
||||
|
||||
@@ -919,7 +923,7 @@ CurveLine::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& v
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dei parametri
|
||||
// verifico validità dei parametri
|
||||
if ( vtNorm.IsSmall() || vtDir.IsSmall())
|
||||
return false ;
|
||||
|
||||
@@ -949,16 +953,18 @@ CurveLine::ToGlob( const Frame3d& frRef)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se frame identità, non devo fare alcunché
|
||||
// se frame identità, non devo fare alcunché
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->ToGlob( frRef) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -973,16 +979,18 @@ CurveLine::ToLoc( const Frame3d& frRef)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se frame identità, non devo fare alcunché
|
||||
// se frame identità, non devo fare alcunché
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->ToLoc( frRef) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -997,16 +1005,18 @@ CurveLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
// la curva deve essere validata
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dei frame
|
||||
// verifico validità dei frame
|
||||
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
if ( AreSameFrame( frOri, frDest))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo di Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
@@ -1065,7 +1075,7 @@ CurveLine::GetVoronoiObject() const
|
||||
if ( m_nStatus != OK)
|
||||
return nullptr ;
|
||||
|
||||
// se non è stato calcolato, lo calcolo
|
||||
// se non è stato calcolato, lo calcolo
|
||||
if ( m_pVoronoiObj == nullptr)
|
||||
CalcVoronoiObject() ;
|
||||
|
||||
|
||||
+6
-3
@@ -146,7 +146,10 @@ class CurveLine : public ICurveLine, public IGeoObjRW
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
CurveLine( void) ;
|
||||
@@ -158,12 +161,12 @@ class CurveLine : public ICurveLine, public IGeoObjRW
|
||||
LOG_ERROR( GetEGkLogger(), "CurveLine : copy error")
|
||||
return *this ; }
|
||||
Voronoi* GetVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
bool CopyFrom( const CurveLine& clSrc) ;
|
||||
bool Validate( void) ;
|
||||
bool CalcVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
bool CalcVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
@@ -175,7 +178,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW
|
||||
Point3d m_PtEnd ; // punto finale
|
||||
Vector3d m_VtExtr ; // vettore estrusione
|
||||
double m_dThick ; // spessore
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable Voronoi* m_pVoronoiObj ; // Voronoi
|
||||
} ;
|
||||
|
||||
+3
-4
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2020-2022
|
||||
// EgalTech 2020-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistLineLine.h Data : 12.08.22 Versione : 2.4h1
|
||||
// File : DistLineLine.cpp Data : 10.05.24 Versione : 2.6e3
|
||||
// Contenuto : Implementazione della classe distanza fra elementi lineari.
|
||||
//
|
||||
//
|
||||
@@ -12,11 +12,10 @@
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
#include "/EgtDev/Include/EGkGeoConst.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2020-2020
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistLineLine.h Data : 06.11.20 Versione : 2.2k1
|
||||
// Contenuto : Dichiarazione della classe distanza fra elementi lineari.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 06.11.20 LM Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkVector3d.h"
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class DistLineLine
|
||||
{
|
||||
public :
|
||||
DistLineLine( const Point3d& ptSt1, const Point3d& ptEn1,
|
||||
const Point3d& ptSt2, const Point3d& ptEn2,
|
||||
bool bIsSegment1 = true, bool bIsSegment2 = true) ;
|
||||
DistLineLine( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1,
|
||||
const Point3d& ptSt2, const Vector3d& vtD2, double dLen2,
|
||||
bool bIsSegment1 = true, bool bIsSegment2 = true) ;
|
||||
|
||||
public :
|
||||
bool GetSqDist( double& dSqDist) const ;
|
||||
bool GetDist( double& dDist) const ;
|
||||
bool IsEpsilon( double dTol) const
|
||||
{ double dSqDist ; return ( GetSqDist( dSqDist) && ( dSqDist < SQ_EPS_ZERO || dSqDist < dTol * dTol)) ; }
|
||||
bool IsSmall( void) const
|
||||
{ return IsEpsilon( EPS_SMALL) ; }
|
||||
bool IsZero( void) const
|
||||
{ return IsEpsilon( EPS_ZERO) ; }
|
||||
bool GetMinDistPoints( Point3d& ptMinDist1, Point3d& ptMinDist2) const ;
|
||||
bool GetPositionsAtMinDistPoints( double& dPos1, double& dPos2) const ;
|
||||
|
||||
private :
|
||||
void Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1,
|
||||
const Point3d& ptSt2, const Vector3d& vtD2, double dLen2,
|
||||
bool bIsSegment1, bool bIsSegment2) ;
|
||||
private:
|
||||
double m_dSqDist ;
|
||||
mutable double m_dDist ;
|
||||
double m_dPos1 ;
|
||||
double m_dPos2 ;
|
||||
Point3d m_ptMinDist1 ;
|
||||
Point3d m_ptMinDist2 ;
|
||||
} ;
|
||||
+2
-2
@@ -14,9 +14,9 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DllMain.h"
|
||||
#include "DistPointCrvAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "DistPointCrvAux.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -13,10 +13,10 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DistPointArc.h"
|
||||
#include "DistPointCrvBezier.h"
|
||||
#include "DistPointCrvComposite.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
|
||||
|
||||
|
||||
+4
-4
@@ -1,19 +1,19 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2013
|
||||
// EgalTech 2013-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistPointLine.cpp Data : 17.12.13 Versione : 1.4l1
|
||||
// File : DistPointLine.cpp Data : 20.05.24 Versione : 2.6e5
|
||||
// Contenuto : Implementazione della classe distanza punto da linea/segmento.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 17.12.13 DS Creazione modulo.
|
||||
//
|
||||
// 20.05.24 DS Reso pubblico in Include.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2014
|
||||
//----------------------------------------------------------------------------
|
||||
// File : DistPointLine.h Data : 02.01.14 Versione : 1.5a1
|
||||
// Contenuto : Dichiarazione della classe distanza punto da linea/segmento.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 30.12.12 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkCurveLine.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class DistPointLine
|
||||
{
|
||||
friend class DistPointCurve ;
|
||||
|
||||
public :
|
||||
DistPointLine( const Point3d& ptP,
|
||||
const ICurveLine& crvLine, bool bIsSegment = true) ;
|
||||
DistPointLine( const Point3d& ptP,
|
||||
const Point3d& ptIni, const Point3d& ptFin, bool bIsSegment = true) ;
|
||||
DistPointLine( const Point3d& ptP,
|
||||
const Point3d& ptIni, const Vector3d& vtDir, double dLen, bool bIsSegment = true) ;
|
||||
|
||||
public :
|
||||
bool GetSqDist( double& dSqDist) const ;
|
||||
bool GetDist( double& dDist) const ;
|
||||
bool IsEpsilon( double dTol) const
|
||||
{ double dSqDist ; return ( GetSqDist( dSqDist) && ( dSqDist < SQ_EPS_ZERO || dSqDist < dTol * dTol)) ; }
|
||||
bool IsSmall( void) const
|
||||
{ return IsEpsilon( EPS_SMALL) ; }
|
||||
bool IsZero( void) const
|
||||
{ return IsEpsilon( EPS_ZERO) ; }
|
||||
int GetNbrMinDist( void) const
|
||||
{ return (( m_dSqDist < 0) ? 0 : 1) ; }
|
||||
bool GetMinDistPoint( Point3d& ptMinDist) const ;
|
||||
bool GetParamAtMinDistPoint( double& dParam) const ;
|
||||
|
||||
private :
|
||||
DistPointLine( void) ;
|
||||
void Calculate( const Point3d& ptP,
|
||||
const Point3d& ptIni, const Vector3d& vtDir, double dLen, bool bIsSegment) ;
|
||||
|
||||
private :
|
||||
double m_dSqDist ;
|
||||
mutable double m_dDist ;
|
||||
double m_dParam ;
|
||||
Point3d m_ptMinDist ;
|
||||
} ;
|
||||
|
||||
+82
-15
@@ -15,6 +15,7 @@
|
||||
#include "SurfTriMesh.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -93,6 +94,8 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
{
|
||||
// Inizializzo distanza non calcolata
|
||||
m_dDist = - 1. ;
|
||||
// Controllo se la superficie è chiusa
|
||||
m_bIsSurfClosed = tmSurf.IsClosed() ;
|
||||
|
||||
// Lavoro con l'oggetto superficie trimesh di base
|
||||
const SurfTriMesh* pStm = GetBasicSurfTriMesh( &tmSurf) ;
|
||||
@@ -121,6 +124,9 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
// Finché non si verifica la condizione di terminazione ingrandisco il box.
|
||||
pStm->ResetTempInts() ;
|
||||
bool bContinue = true ;
|
||||
|
||||
// creazione del vettore dei triangoli più vicini a ptP
|
||||
vector<pair<int, Triangle3d>> vTria ; // <indice triangolo, Triangolo>
|
||||
while ( bContinue) {
|
||||
// Calcolo il box differenza con il precedente per non esplorare parti già considerate
|
||||
BOXVECTOR vBox ;
|
||||
@@ -134,8 +140,8 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
continue ;
|
||||
// ricerca sui triangoli nel box
|
||||
bCollide = true ;
|
||||
INTVECTOR vnIds ;
|
||||
if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) {
|
||||
INTVECTOR vnIds ;
|
||||
if ( pStm->GetAllTriaOverlapBox( b3Int, vnIds)) {
|
||||
// Ciclo sui triangoli del sotto-box corrente
|
||||
for ( auto nT : vnIds) {
|
||||
int nTriaTemp ;
|
||||
@@ -144,18 +150,24 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
pStm->SetTempInt( nT, 1) ;
|
||||
DistPointTriangle distPT( ptP, trCurTria) ;
|
||||
double dCurSqDist ;
|
||||
// Se la distanza del triangolo č valida e minore di quella attuale aggiorno
|
||||
if ( distPT.GetSqDist( dCurSqDist) && dCurSqDist < dMinSqDist) {
|
||||
dMinSqDist = dCurSqDist ;
|
||||
nMinDistTriaIndex = nT ;
|
||||
distPT.GetMinDistPoint( ptMinDistPoint) ;
|
||||
// Se la distanza del triangolo è valida e minore di quella attuale aggiorno
|
||||
if ( distPT.GetSqDist( dCurSqDist)) {
|
||||
if ( abs( dCurSqDist - dMinSqDist) < EPS_SMALL) // se distanze uguali...
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ; // aggiungo il triangolo
|
||||
else if ( dCurSqDist < dMinSqDist) { // se minore...
|
||||
vTria.clear() ; // pulisco il vettore
|
||||
dMinSqDist = dCurSqDist ;
|
||||
nMinDistTriaIndex = nT ;
|
||||
distPT.GetMinDistPoint( ptMinDistPoint) ;
|
||||
vTria.emplace_back( make_pair( nT, trCurTria)) ; // aggiungo il triangolo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Se si verifica la condizione di terminazione arresto il ciclo altrimenti aggiorno i box
|
||||
if ( ! bCollide || dMinSqDist < EPS_SMALL * EPS_SMALL)
|
||||
if ( ! bCollide || dMinSqDist < SQ_EPS_SMALL)
|
||||
bContinue = false ;
|
||||
else {
|
||||
boxPPrev = boxP ;
|
||||
@@ -163,15 +175,70 @@ DistPointSurfTm::Calculate( const Point3d& ptP, const ISurfTriMesh& tmSurf)
|
||||
}
|
||||
}
|
||||
|
||||
if ( nMinDistTriaIndex != SVT_NULL) {
|
||||
m_dDist = sqrt( max( dMinSqDist, 0.)) ;
|
||||
// se non ho trovato nessun triangolo, esco
|
||||
if ( nMinDistTriaIndex == SVT_NULL)
|
||||
return ;
|
||||
|
||||
// salvo la distanza minima
|
||||
m_dDist = sqrt( max( dMinSqDist, 0.)) ;
|
||||
// salvo il punto a distanza minima
|
||||
m_ptMinDistPoint = ptMinDistPoint ;
|
||||
// se il punto è sulla TriMesh...
|
||||
if ( m_dDist < EPS_SMALL) {
|
||||
m_nMinDistTriaIndex = nMinDistTriaIndex ;
|
||||
m_ptMinDistPoint = ptMinDistPoint ;
|
||||
Triangle3d trMinDistTria ;
|
||||
pStm->GetTriangle( m_nMinDistTriaIndex, trMinDistTria) ;
|
||||
trMinDistTria.Validate() ;
|
||||
m_bIsInside = ( ( ptP - m_ptMinDistPoint) * trMinDistTria.GetN() < - EPS_SMALL) && pStm->IsClosed() ;
|
||||
m_bIsInside = false ;
|
||||
return ;
|
||||
}
|
||||
// se ho un solo triangolo, allora deduco le informazioni da lui
|
||||
else if ( int( vTria.size()) == 1) {
|
||||
m_nMinDistTriaIndex = vTria.back().first ;
|
||||
m_bIsInside = ( ( ptP - m_ptMinDistPoint) * vTria.back().second.GetN() < - EPS_SMALL) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
// controllo se tutti i triangoli a minima distanza forniscono la stessa informazione
|
||||
// ( il punto potrebbe essere esterno a tutti, interno a tutti o indefinito )
|
||||
bool bInside = false ;
|
||||
bool bOutside = false ;
|
||||
for ( int i = 0 ; i < int( vTria.size()) ; ++ i) { // scorro i triangoli a minima distanza
|
||||
if ( ( ptP - vTria[i].second.GetP( 0)) * vTria[i].second.GetN() < - EPS_SMALL)
|
||||
bInside = true ;
|
||||
else
|
||||
bOutside = true ;
|
||||
}
|
||||
|
||||
// inizializzo le variabili membro
|
||||
m_nMinDistTriaIndex = nMinDistTriaIndex ;
|
||||
m_bIsInside = false ;
|
||||
|
||||
// se le informazioni non sono coerenti, allora :
|
||||
// 1) calcolo i centroidi dei triangoli in questione
|
||||
// 2) ottengo il punto medio di questi centroidi
|
||||
// 3) controllo quale triangolo interseca il segmento che parte da ptP e arriva a tale punto
|
||||
// 4) userò questo triangolo per classificare ptP
|
||||
if ( bOutside == bInside) {
|
||||
// calcolo il baricentro complessivo
|
||||
Point3d ptBar_tot ;
|
||||
for ( auto& Tria : vTria)
|
||||
ptBar_tot += Tria.second.GetCentroid() ;
|
||||
ptBar_tot /= int( vTria.size()) ;
|
||||
// per ogni triangolo, cerco quello che interseca il segmento
|
||||
for ( auto& Tria : vTria) {
|
||||
Point3d ptInters1, ptInters2 ;
|
||||
int nType = IntersLineTria( ptP, ptBar_tot, Tria.second, ptInters1, ptInters2) ;
|
||||
if ( nType == ILTT_IN) { // se intersezione ho finito
|
||||
DistPointTriangle( ptP, Tria.second).GetMinDistPoint( m_ptMinDistPoint) ;
|
||||
m_bIsInside = ( ( ptP - m_ptMinDistPoint) * Tria.second.GetN() < - EPS_SMALL) ;
|
||||
m_nMinDistTriaIndex = Tria.first ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // se informazioni coerenti
|
||||
m_bIsInside = bInside ;
|
||||
|
||||
return ;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "ProjPlane.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
+21
-2
@@ -309,15 +309,36 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="CurveByApprox.cpp" />
|
||||
<ClCompile Include="CurveByInterp.cpp" />
|
||||
<ClCompile Include="CurveCompositeOffset.cpp" />
|
||||
<ClCompile Include="IntersCurveSurfTm.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersLineVolZmap.cpp" />
|
||||
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
||||
<ClCompile Include="IntersLineSurfBez.cpp" />
|
||||
<ClCompile Include="PolygonElevation.cpp" />
|
||||
<ClCompile Include="Quaternion.cpp" />
|
||||
<ClCompile Include="RotationMinimizingFrame.cpp" />
|
||||
<ClCompile Include="RotationXplaneFrame.cpp" />
|
||||
<ClCompile Include="SbzStandard.cpp" />
|
||||
<ClCompile Include="Voronoi.cpp" />
|
||||
<ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkCDeConeFrustumClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkCDeConvexTorusClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkCDeRectPrismoidClosedSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkDistLineLine.h" />
|
||||
<ClInclude Include="..\Include\EGkDistPointLine.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersCurveSurfTm.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersLineBox.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneBox.h" />
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h" />
|
||||
<ClInclude Include="..\Include\EGkPolygonElevation.h" />
|
||||
<ClInclude Include="..\Include\EGkQuaternion.h" />
|
||||
<ClInclude Include="..\Include\EGkRotationMinimizingFrame.h" />
|
||||
<ClInclude Include="..\Include\EGkRotationXplaneFrame.h" />
|
||||
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
|
||||
<ClInclude Include="CDeBoxTria.h" />
|
||||
<ClInclude Include="CDeCapsTria.h" />
|
||||
@@ -576,12 +597,10 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="CAvSimpleSurfFrMove.h" />
|
||||
<ClInclude Include="CAvToolSurfTm.h" />
|
||||
<ClInclude Include="CreateCurveAux.h" />
|
||||
<ClInclude Include="DistLineLine.h" />
|
||||
<ClInclude Include="DistPointArc.h" />
|
||||
<ClInclude Include="DistPointCrvAux.h" />
|
||||
<ClInclude Include="DistPointCrvBezier.h" />
|
||||
<ClInclude Include="DistPointCrvComposite.h" />
|
||||
<ClInclude Include="DistPointLine.h" />
|
||||
<ClInclude Include="DllMain.h" />
|
||||
<ClInclude Include="earcut.hpp" />
|
||||
<ClInclude Include="ExtDimension.h" />
|
||||
|
||||
@@ -43,15 +43,18 @@
|
||||
<Filter Include="File di origine\GeoOffset">
|
||||
<UniqueIdentifier>{f07670fd-9429-4b7e-ac6d-1c0022e756fb}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoCollision">
|
||||
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoProject">
|
||||
<UniqueIdentifier>{d96752da-1884-4a73-ba1b-5b20b606e469}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoElevation">
|
||||
<UniqueIdentifier>{4c6a9dc5-8fac-4ecd-bde6-3e37e056712e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoCollisionAvoid">
|
||||
<UniqueIdentifier>{ae52e402-3063-45e3-b9f7-1710035a1f56}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="File di origine\GeoCollisionDetection">
|
||||
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Vector3d.cpp">
|
||||
@@ -273,6 +276,9 @@
|
||||
<ClCompile Include="IntersLineSurfTm.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersLineSurfBez.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CircleCenTgCurve.cpp">
|
||||
<Filter>File di origine\GeoCreate</Filter>
|
||||
</ClCompile>
|
||||
@@ -372,17 +378,8 @@
|
||||
<ClCompile Include="IntersLineSurfStd.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvToolTriangle.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvToolSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeBoxTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvSimpleSurfFrMove.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersSurfTmSurfTm.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
@@ -400,19 +397,19 @@
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeCylTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeBoxClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeCylClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeSpheTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeSpheClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SurfBezier.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
@@ -430,34 +427,34 @@
|
||||
<Filter>File di origine\GeoDist</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeTriaTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeConeTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeUtility.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeClosedSurfTmClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeConeFrustumClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeConeFrustumTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeConvexTorusClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeConvexTorusTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeRectPrismoidClosedSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeRectPrismoidTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SurfTriMeshUtilities.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
@@ -469,7 +466,7 @@
|
||||
<Filter>File di origine\Base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CDeCapsTria.cpp">
|
||||
<Filter>File di origine\GeoCollision</Filter>
|
||||
<Filter>File di origine\GeoCollisionDetection</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Circle2P.cpp">
|
||||
<Filter>File di origine\GeoCreate</Filter>
|
||||
@@ -510,6 +507,36 @@
|
||||
<ClCompile Include="PolygonElevation.cpp">
|
||||
<Filter>File di origine\GeoElevation</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersCurveSurfTm.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvSimpleSurfFrMove.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvToolSurfTm.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvToolTriangle.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersLineVolZmap.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="IntersPlaneVolZmap.cpp">
|
||||
<Filter>File di origine\GeoInters</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SbzStandard.cpp">
|
||||
<Filter>File di origine\GeoCreate</Filter>
|
||||
</ClCompile>
|
||||
<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>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -566,9 +593,6 @@
|
||||
<ClInclude Include="DistPointArc.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DistPointLine.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DistPointCrvBezier.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
@@ -1091,9 +1115,6 @@
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneBox.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DistLineLine.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CDeUtility.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
@@ -1169,6 +1190,30 @@
|
||||
<ClInclude Include="Voronoi.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkIntersCurveSurfTm.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\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>
|
||||
<ClInclude Include="..\Include\EGkDistLineLine.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\Include\EGkDistPointLine.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
+140
-47
@@ -21,12 +21,14 @@
|
||||
#include "FontManager.h"
|
||||
#include "FontAux.h"
|
||||
#include "CurveArc.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkExtText.h"
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include <new>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -63,7 +65,7 @@ ExtDimension::~ExtDimension( void)
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ExtDimension::SetStyle( double dExtLineLen, double dArrowLen, double dTextDist, bool bLenIsMM,
|
||||
int nDecDigit, const string& sFont, double dTextHeight)
|
||||
int nDecDigit, const string& sFont, double dTextHeight)
|
||||
{
|
||||
m_dExtLineLen = max( dExtLineLen, MIN_EXTLINELEN) ;
|
||||
m_dArrowLen = max( dArrowLen, MIN_ARROWLEN) ;
|
||||
@@ -200,7 +202,7 @@ ExtDimension::SetDiametral( const Point3d& ptCen, const Point3d& ptPos,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ExtDimension::SetAngular( const Point3d& ptP1, const Point3d& ptV, const Point3d& ptP2, const Point3d& ptPos,
|
||||
ExtDimension::SetAngular( const Point3d& ptV, const Point3d& ptP1, const Point3d& ptP2, const Point3d& ptPos,
|
||||
const Vector3d& vtN, const string& sText)
|
||||
{
|
||||
// dichiaro quota non ancora determinata
|
||||
@@ -209,17 +211,16 @@ ExtDimension::SetAngular( const Point3d& ptP1, const Point3d& ptV, const Point3d
|
||||
m_vtN = vtN ;
|
||||
if ( ! m_vtN.Normalize())
|
||||
return false ;
|
||||
// porto i punti nel piano definito da P1 e N
|
||||
m_ptP1 = ptP1 ;
|
||||
m_ptP2 = ptP2 - ( ptP2 - m_ptP1) * m_vtN * m_vtN ;
|
||||
m_ptP6 = ptV - ( ptV - m_ptP1) * m_vtN * m_vtN ;
|
||||
m_ptPos = ptPos - ( ptPos - m_ptP1) * m_vtN * m_vtN ;
|
||||
// verifico che i punti di misura non siano coincidenti
|
||||
if ( AreSamePointApprox( m_ptP1, m_ptP2) || AreSamePointApprox( m_ptP1, m_ptP6) || AreSamePointApprox( m_ptP2, m_ptP5))
|
||||
return false ;
|
||||
// direzione di riferimento ( nel piano perpendicolare a vtN)
|
||||
// porto i punti e le direzioni nel piano definito da V e N
|
||||
m_ptP6 = ptV ;
|
||||
m_ptPos = ptPos - ( ptPos - m_ptP6) * m_vtN * m_vtN ;
|
||||
m_vtDir = m_ptPos - m_ptP6 ;
|
||||
double dLenDir = m_vtDir.Len() ;
|
||||
Vector3d vtLine1 = OrthoCompo( ptP1 - m_ptP6, m_vtN) ;
|
||||
Vector3d vtLine2 = OrthoCompo( ptP2 - m_ptP6, m_vtN) ;
|
||||
// verifico che i punti di misura non siano coincidenti
|
||||
if ( ! vtLine1.Normalize() || ! vtLine2.Normalize() || dLenDir < EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// controllo se è testo o se è la misura
|
||||
double dFactor ;
|
||||
@@ -243,20 +244,12 @@ ExtDimension::SetAngular( const Point3d& ptP1, const Point3d& ptV, const Point3d
|
||||
m_vtDir = m_ptPos - m_ptP6 ;
|
||||
dLenDir = m_vtDir.Len() ;
|
||||
}
|
||||
// calcolo le direzioni su cui giacciono i due lati dell'angolo
|
||||
Vector3d vtLine1 = m_ptP1 - m_ptP6 ;
|
||||
Vector3d vtLine2 = m_ptP2 - m_ptP6 ;
|
||||
double dLen1 = vtLine1.Len() ;
|
||||
double dLen2 = vtLine2.Len() ;
|
||||
if ( ! vtLine1.Normalize() || ! vtLine2.Normalize())
|
||||
return false ;
|
||||
// segnalo se i punti che definiscono i lati sono più lontani dal centro di ptPos
|
||||
bool bPt1Close = ( dLenDir < dLen1 ? true : false) ;
|
||||
bool bPt2Close = ( dLenDir < dLen2 ? true : false) ;
|
||||
m_ptP5 = m_ptP1 + ( dLenDir - dLen1) * vtLine1 ;
|
||||
Point3d ptP5_bis = m_ptP2 + ( dLenDir - dLen2) * vtLine2 ;
|
||||
m_ptP3 = m_ptP5 + ( bPt1Close ? - vtLine1 : vtLine1) * m_dExtLineLen ;
|
||||
m_ptP4 = ptP5_bis + ( bPt2Close ? - vtLine2 : vtLine2) * m_dExtLineLen ;
|
||||
// assegno gli altri punti notevoli della quotatura
|
||||
m_ptP1 = m_ptP6 ;
|
||||
m_ptP2 = m_ptP6 ;
|
||||
m_ptP5 = m_ptP6 + vtLine1 * dLenDir ;
|
||||
m_ptP3 = m_ptP6 + vtLine1 * ( dLenDir + m_dExtLineLen) ;
|
||||
m_ptP4 = m_ptP6 + vtLine2 * ( dLenDir + m_dExtLineLen) ;
|
||||
|
||||
// assegnazione del testo
|
||||
m_sText = sText ;
|
||||
@@ -266,7 +259,99 @@ ExtDimension::SetAngular( const Point3d& ptP1, const Point3d& ptV, const Point3d
|
||||
m_bToCalc = true ;
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
return true;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ExtDimension::SetAngularEx( const Point3d& ptV1, const Point3d& ptP1,
|
||||
const Point3d& ptV2, const Point3d& ptP2, const Point3d& ptPos,
|
||||
const Vector3d& vtN, const string& sText)
|
||||
{
|
||||
// dichiaro quota non ancora determinata
|
||||
m_nType = DT_NONE ;
|
||||
// verifico la definizione del versore normale
|
||||
m_vtN = vtN ;
|
||||
if ( ! m_vtN.Normalize())
|
||||
return false ;
|
||||
// calcolo l'intersezione tra le due linee
|
||||
CurveLine Line1 ;
|
||||
if ( ! Line1.Set( ptV1, ptP1) || ! Line1.SetExtrusion( m_vtN))
|
||||
return false ;
|
||||
CurveLine Line2 ;
|
||||
if ( ! Line2.Set( ptV2, ptP2) || ! Line2.SetExtrusion( m_vtN))
|
||||
return false ;
|
||||
IntersLineLine IntLL( Line1, Line2, false) ;
|
||||
IntCrvCrvInfo Info ;
|
||||
if ( ! IntLL.GetIntCrvCrvInfo( Info) || Info.bOverlap)
|
||||
return false ;
|
||||
Point3d ptV = Media( Info.IciA[0].ptI, Info.IciB[0].ptI) ;
|
||||
// porto i punti e le direzioni nel piano definito da V1 e N
|
||||
m_ptP6 = ptV ;
|
||||
m_ptPos = ptPos - ( ptPos - m_ptP6) * m_vtN * m_vtN ;
|
||||
m_vtDir = m_ptPos - m_ptP6 ;
|
||||
double dLenDir = m_vtDir.Len() ;
|
||||
Vector3d vtLine1 = OrthoCompo( ptP1 - m_ptP6, m_vtN) ;
|
||||
Vector3d vtLine2 = OrthoCompo( ptP2 - m_ptP6, m_vtN) ;
|
||||
// verifico che i punti di misura non siano coincidenti
|
||||
if ( ! vtLine1.Normalize() || ! vtLine2.Normalize() || dLenDir < EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// controllo se è testo o se è la misura
|
||||
double dFactor ;
|
||||
if ( m_sCalcText.find( IS_MEASURE) != string::npos) {
|
||||
m_sCalcText = "300.00" ;
|
||||
double dHalfDist = GetTextHalfDist( m_ptPos) ;
|
||||
dFactor = 2.5 * dHalfDist ;
|
||||
m_sCalcText = "" ;
|
||||
}
|
||||
else {
|
||||
double dHalfDist = GetTextHalfDist( m_ptPos) ;
|
||||
dFactor = 2.5 * dHalfDist ;
|
||||
}
|
||||
// allungo m_vtDir se è troppo vicino al centro
|
||||
if ( m_vtDir.Len() < dFactor) {
|
||||
Vector3d vtDir_n = m_vtDir ;
|
||||
if ( ! vtDir_n.Normalize())
|
||||
return false ;
|
||||
m_ptPos = m_ptP6 + dFactor * vtDir_n ;
|
||||
// ricalcolo m_vtDir
|
||||
m_vtDir = m_ptPos - m_ptP6 ;
|
||||
dLenDir = m_vtDir.Len() ;
|
||||
}
|
||||
// assegno gli altri punti notevoli della quotatura
|
||||
// se i ptV concidono con l'intersezione tra le linee le sposto leggermente verso l'altro punto di quel lato
|
||||
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 ;
|
||||
double dLen1 = Dist( m_ptP6, m_ptP1) ;
|
||||
m_ptP3 = m_ptP6 + vtLine1 * ( dLenDir + m_dExtLineLen * ( dLen1 < dLenDir ? 1 : -1)) ;
|
||||
double dLen2 = Dist( m_ptP6, m_ptP2) ;
|
||||
m_ptP4 = m_ptP6 + vtLine2 * ( dLenDir + m_dExtLineLen * ( dLen2 < dLenDir ? 1 : -1)) ;
|
||||
|
||||
// assegnazione del testo
|
||||
m_sText = sText ;
|
||||
// assegno il tipo
|
||||
m_nType = DT_ANGULAR ;
|
||||
// imposto da calcolare
|
||||
m_bToCalc = true ;
|
||||
m_OGrMgr.Reset() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1012,6 +1097,7 @@ ExtDimension::Update( void) const
|
||||
if ( ! GetTextMyBBox( b3Text) && ! b3Text.IsEmpty())
|
||||
return false ;
|
||||
double dHeight = b3Text.GetMax().y - b3Text.GetMin().y ;
|
||||
double dLength = b3Text.GetMax().x - b3Text.GetMin().x ;
|
||||
Vector3d vtPerpDir = m_ptPos - m_ptP6 ;
|
||||
if ( ! vtPerpDir.Normalize())
|
||||
return false ;
|
||||
@@ -1020,11 +1106,11 @@ ExtDimension::Update( void) const
|
||||
if ( ! frRef.Set( m_ptP6, m_vtN))
|
||||
return false ;
|
||||
double dAngDeg = 0 ;
|
||||
if ( ! m_vtDir.GetAngle( frRef.VersX(), dAngDeg) || ! vtPerpDir.Rotate( m_vtN, ( dAngDeg < 90 ? 90 : -90)))
|
||||
if ( ! m_vtDir.GetAngle( frRef.VersX(), dAngDeg) || ! vtPerpDir.Rotate( m_vtN, ( dAngDeg < 90 ? 90 : -90)))
|
||||
return false ;
|
||||
m_ptCalcPos = m_ptCalcPos + 0.6 * dHeight * vtPerpDir ;
|
||||
// semidistanza di interruzione
|
||||
double dHalfDist = GetTextHalfDist( m_ptCalcPos) ;
|
||||
double dHalfDist = GetTextHalfDist( m_ptCalcPos, false) ;
|
||||
// lunghezza della linea di misura
|
||||
double dLen = Dist( m_ptP1, m_ptP2) ;
|
||||
// determino come orientare le frecce e dove mettere il testo
|
||||
@@ -1049,7 +1135,16 @@ ExtDimension::Update( void) const
|
||||
Vector3d vtRad = m_ptPos - m_ptP5 ;
|
||||
if ( ! vtRad.Normalize())
|
||||
return false ;
|
||||
m_ptCalcPos = m_ptPos + vtRad * ( dHalfDist + 2 * m_dArrowLen) ;
|
||||
m_ptCalcPos = m_ptPos + vtRad * ( 2 * m_dArrowLen + m_dTextDist) ;
|
||||
const double COMP_LIM = 0.1 ; // circa 5.7deg
|
||||
if ( vtRad.x > COMP_LIM)
|
||||
m_ptCalcPos += dLength / 2 * X_AX ;
|
||||
else if ( vtRad.x < -COMP_LIM)
|
||||
m_ptCalcPos -= dLength / 2 * X_AX ;
|
||||
if ( vtRad.y > COMP_LIM)
|
||||
m_ptCalcPos += dHeight / 2 * Y_AX ;
|
||||
else if ( vtRad.y < -COMP_LIM)
|
||||
m_ptCalcPos -= dHeight / 2 * Y_AX ;
|
||||
}
|
||||
// dichiaro ricalcolo eseguito
|
||||
m_bToCalc = false ;
|
||||
@@ -1058,8 +1153,8 @@ ExtDimension::Update( void) const
|
||||
case DT_ANGULAR : {
|
||||
// angolo
|
||||
double dAngDeg, dAngDeg1, dAngDeg2 = 0 ;
|
||||
Vector3d vtLine1 = m_ptP1 - m_ptP6 ;
|
||||
Vector3d vtLine2 = m_ptP2 - m_ptP6 ;
|
||||
Vector3d vtLine1 = m_ptP3 - m_ptP6 ;
|
||||
Vector3d vtLine2 = m_ptP4 - m_ptP6 ;
|
||||
Vector3d vtLine3 = m_ptPos - m_ptP6 ;
|
||||
// calcolo gli angoli tra m_ptPos e i due punti che identificano i lati dell'angolo
|
||||
// per capire se sto calcolando l'angolo interno o esterno
|
||||
@@ -1074,10 +1169,9 @@ ExtDimension::Update( void) const
|
||||
ReplaceString( m_sCalcText, IS_MEASURE, sAngDeg + "°") ;
|
||||
}
|
||||
// calcolo ptP5_bis
|
||||
double dLen2 = vtLine2.Len() ;
|
||||
if ( ! vtLine2.Normalize())
|
||||
return false ;
|
||||
Point3d ptP5_bis = m_ptP2 + ( m_vtDir.Len() - dLen2) * vtLine2 ;
|
||||
Point3d ptP5_bis = m_ptP6 + m_vtDir.Len() * vtLine2 ;
|
||||
// calcolo l'arco su cui metterò la misura
|
||||
PtrOwner<CurveArc> pCrvPos( CreateBasicCurveArc()) ;
|
||||
if ( IsNull( pCrvPos) || ! pCrvPos->Set3P( ptP5_bis, m_ptPos, m_ptP5, false))
|
||||
@@ -1288,15 +1382,12 @@ ExtDimension::ApproxWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST&
|
||||
if ( IsNull( pCrvPos))
|
||||
return false ;
|
||||
// calcolo ptP5_bis
|
||||
Vector3d vtLine2 = m_ptP2 - m_ptP6 ;
|
||||
double dLen2 = vtLine2.Len() ;
|
||||
Vector3d vtLine2 = m_ptP4 - m_ptP6 ;
|
||||
if ( ! vtLine2.Normalize())
|
||||
return false ;
|
||||
Point3d ptP5_bis = m_ptP2 + ( m_vtDir.Len() - dLen2) * vtLine2 ;
|
||||
Point3d ptP5_bis = m_ptP6 + m_vtDir.Len() * vtLine2 ;
|
||||
// approssimerò l'arco con una polyline
|
||||
PolyLine plApprox ;
|
||||
double dLinTol = 0.01 ;
|
||||
double dAngTolDeg = 0.01 ;
|
||||
// se non ho testo
|
||||
if ( IsEmptyOrSpaces( m_sCalcText) || ! m_bCalcTextOn) {
|
||||
if ( ! pCrvPos->SetC2PN( m_ptP6, ptP5_bis, m_ptP5, m_vtN) || ! pCrvPos->ApproxWithLines( dLinTol, dAngTolDeg, ICurve::APL_STD, plApprox))
|
||||
@@ -1337,7 +1428,7 @@ ExtDimension::ApproxWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST&
|
||||
dFactor = 0 ;
|
||||
}
|
||||
lstPL.emplace_back() ;
|
||||
Vector3d vtLine1 = m_ptP1 - m_ptP6 ;
|
||||
Vector3d vtLine1 = m_ptP3 - m_ptP6 ;
|
||||
if ( ! vtLine1.Normalize())
|
||||
return false ;
|
||||
GetArrowHead( m_ptP5, ( m_bCalcArrowIn ? vtEndDir : - vtEndDir) + vtLine1 * dFactor, lstPL.back()) ;
|
||||
@@ -1356,23 +1447,25 @@ ExtDimension::ApproxWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST&
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
ExtDimension::GetTextHalfDist( const Point3d& ptText) const
|
||||
ExtDimension::GetTextHalfDist( const Point3d& ptText, bool bUseRot) const
|
||||
{
|
||||
// semi distanza di interruzione
|
||||
double dHalfDist = m_dTextHeight / 2 + m_dTextDist ;
|
||||
// recupero il box di ingombro del testo
|
||||
BBox3d b3Text ;
|
||||
Vector3d vtDir = m_vtDir ;
|
||||
if ( m_nType == DT_ANGULAR)
|
||||
vtDir.Normalize() ;
|
||||
if ( GetTextMyBBox( ptText, b3Text) && ! b3Text.IsEmpty()) {
|
||||
double dHalfL = ( b3Text.GetMax().x - b3Text.GetMin().x) / 2 ;
|
||||
double dHalfH = ( b3Text.GetMax().y - b3Text.GetMin().y) / 2 ;
|
||||
dHalfDist = sqrt( dHalfL * dHalfL + dHalfH * dHalfH) ;
|
||||
if ( abs( vtDir.x) > EPS_ZERO)
|
||||
dHalfDist = min( dHalfDist, dHalfL / abs( vtDir.x)) ;
|
||||
if ( abs( vtDir.y) > EPS_ZERO)
|
||||
dHalfDist = min( dHalfDist, dHalfH / abs( vtDir.y)) ;
|
||||
if ( bUseRot) {
|
||||
Vector3d vtDir = m_vtDir ;
|
||||
vtDir.Normalize() ;
|
||||
double dCoeff = ( dHalfH > 1 ? dHalfL / dHalfH : 0) ;
|
||||
if ( abs( vtDir.x) > dCoeff * abs( vtDir.y))
|
||||
dHalfDist = min( dHalfDist, dHalfL / abs( vtDir.x)) ;
|
||||
else
|
||||
dHalfDist = min( dHalfDist, dHalfH / abs( vtDir.y)) ;
|
||||
}
|
||||
dHalfDist += m_dTextDist ;
|
||||
}
|
||||
return dHalfDist ;
|
||||
|
||||
+10
-4
@@ -28,7 +28,7 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
|
||||
ExtDimension* Clone( void) const override ;
|
||||
GeoObjType GetType( void) const override ;
|
||||
bool IsValid( void) const override
|
||||
{ return ( m_nType != DT_NONE) ; }
|
||||
{ return ( m_nType != DT_NONE) ; }
|
||||
const std::string& GetTitle( void) const override ;
|
||||
bool Dump( std::string& sOut, bool bMM = true, const char* szNewLine = "\n") const override ;
|
||||
bool GetLocalBBox( BBox3d& b3Loc, int nFlag = BBF_STANDARD) const override ;
|
||||
@@ -71,8 +71,11 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
|
||||
const Vector3d& vtN, const std::string& sText) override ;
|
||||
bool SetDiametral( const Point3d& ptCen, const Point3d& ptPos,
|
||||
const Vector3d& vtN, const std::string& sText) override ;
|
||||
bool SetAngular( const Point3d& ptP1, const Point3d& ptV, const Point3d& ptP2, const Point3d& ptPos,
|
||||
bool SetAngular( const Point3d& ptV, const Point3d& ptP1, const Point3d& ptP2, const Point3d& ptPos,
|
||||
const Vector3d& vtN, const std::string& sText) override ;
|
||||
bool SetAngularEx( const Point3d& ptV1, const Point3d& ptP1,
|
||||
const Point3d& ptV2, const Point3d& ptP2, const Point3d& ptPos,
|
||||
const Vector3d& vtN, const std::string& sText) override ;
|
||||
const Vector3d& GetNormVersor( void) const override
|
||||
{ return m_vtN ; }
|
||||
const Vector3d& GetDirVersor( void) const override
|
||||
@@ -105,12 +108,16 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
|
||||
{ return m_dTextHeight ; }
|
||||
bool GetMidPoint( Point3d& ptMid) 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 ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
ExtDimension( void) ;
|
||||
@@ -124,9 +131,8 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
|
||||
|
||||
private :
|
||||
bool CopyFrom( const ExtDimension& gpSrc) ;
|
||||
const std::string& GetSubType( void) const ;
|
||||
bool Update( void) const ;
|
||||
double GetTextHalfDist( const Point3d& ptText) const ;
|
||||
double GetTextHalfDist( const Point3d& ptText, bool bUseRot = true) const ;
|
||||
bool GetArrowHead( const Point3d& ptTip, const Vector3d& vtDir, PolyLine& PL) const ;
|
||||
bool SetCurrFont( FontManager& fntMgr) const ;
|
||||
bool ApproxTextWithLines( double dLinTol, double dAngTolDeg, POLYLINELIST& lstPL) const ;
|
||||
|
||||
@@ -113,7 +113,10 @@ class ExtText : public IExtText, public IGeoObjRW
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
ExtText( void) ;
|
||||
|
||||
+49
-13
@@ -18,6 +18,7 @@
|
||||
#include "/EgtDev/Include/EGkFilletChamfer.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurves.h"
|
||||
#include "/EgtDev/Include/EgkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
@@ -40,13 +41,21 @@ CalcForFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
if ( ! dPC1.GetSideAtMinDistPoint( 0, vtNorm, nSide1))
|
||||
return false ;
|
||||
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()) ;
|
||||
if ( IsNull( pCopy1))
|
||||
return false ;
|
||||
pCopy1->ToLoc( frIntr) ;
|
||||
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 ;
|
||||
|
||||
// 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))
|
||||
return false ;
|
||||
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()) ;
|
||||
if ( IsNull( pCopy2))
|
||||
return false ;
|
||||
pCopy2->ToLoc( frIntr) ;
|
||||
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 ;
|
||||
|
||||
// calcolo l'intersezione tra le due curve
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
// calcolo le intersezioni tra tutte le curve di offset e seleziono quella più vicina ai punti passati
|
||||
Point3d ptInt1 = P_INVALID, ptInt2 = P_INVALID ;
|
||||
Point3d ptNearI = Media( ptNear1, ptNear2) ;
|
||||
ptNearI.ToLoc( frIntr) ;
|
||||
IntersCurveCurve intCC( *pCopy1, *pCopy2) ;
|
||||
if ( ! intCC.GetIntersPointNearTo( 0, ptNearI, ptInt1) ||
|
||||
! intCC.GetIntersPointNearTo( 1, ptNearI, ptInt2))
|
||||
return false ;
|
||||
double dMinDist = INFINITO ;
|
||||
for ( int i = 0 ; i < int( vOffs1.size()) ; i++) {
|
||||
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 ;
|
||||
|
||||
ptInt1.ToGlob( frIntr) ;
|
||||
ptInt2.ToGlob( frIntr) ;
|
||||
ptCen = Media( ptInt1, ptInt2) ;
|
||||
@@ -105,7 +141,7 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
const ICurve& cCrv2, const Point3d& ptNear2,
|
||||
const Vector3d& vtNorm, double dRadius, double& dPar1, double& dPar2)
|
||||
{
|
||||
// verifico validità parametri ricevuti
|
||||
// verifico validità parametri ricevuti
|
||||
if ( &cCrv1 == nullptr || &ptNear1 == nullptr ||
|
||||
&cCrv2 == nullptr || &ptNear2 == 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))
|
||||
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) ;
|
||||
if ( bParallel) {
|
||||
Point3d ptQQQ, ptQQ1, ptQQ2 ;
|
||||
@@ -165,7 +201,7 @@ CreateChamfer( const ICurve& cCrv1, const Point3d& ptNear1,
|
||||
const ICurve& cCrv2, const Point3d& ptNear2,
|
||||
const Vector3d& vtNorm, double dDist, double& dPar1, double& dPar2)
|
||||
{
|
||||
// verifico validità parametri ricevuti
|
||||
// verifico validità parametri ricevuti
|
||||
if ( &cCrv1 == nullptr || &ptNear1 == nullptr ||
|
||||
&cCrv2 == nullptr || &ptNear2 == nullptr ||
|
||||
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
|
||||
|
||||
+17
@@ -37,6 +37,23 @@ Frame3d::Set( const Point3d& ptOrig, const Vector3d& vtDirX,
|
||||
! m_vtVersZ.Normalize())
|
||||
return false ;
|
||||
|
||||
// se ci sono errori molto piccoli di ortogonalità, li correggo
|
||||
double dOrtXZ = m_vtVersX * m_vtVersZ ;
|
||||
if ( dOrtXZ > EPS_ZERO && dOrtXZ < 10 * EPS_ZERO) {
|
||||
m_vtVersX = OrthoCompo( m_vtVersX, m_vtVersZ) ;
|
||||
m_vtVersX.Normalize() ;
|
||||
}
|
||||
double dOrtYX = m_vtVersY * m_vtVersX ;
|
||||
if ( dOrtYX > EPS_ZERO && dOrtYX < 10 * EPS_ZERO) {
|
||||
m_vtVersY = OrthoCompo( m_vtVersY, m_vtVersX) ;
|
||||
m_vtVersY.Normalize() ;
|
||||
}
|
||||
double dOrtYZ = m_vtVersY * m_vtVersZ ;
|
||||
if ( dOrtYZ > EPS_ZERO && dOrtYZ < 10 * EPS_ZERO) {
|
||||
m_vtVersY = OrthoCompo( m_vtVersY, m_vtVersZ) ;
|
||||
m_vtVersY.Normalize() ;
|
||||
}
|
||||
|
||||
// verifica della ortogonalità dei versori e del senso destrorso
|
||||
if ( ! Verify())
|
||||
return false ;
|
||||
|
||||
+10
-2
@@ -101,6 +101,10 @@ GdbGeo::Save( int nBaseId, NgeWriter& ngeOut, INTUNORDSET* pSavedIds) const
|
||||
if ( pGObjRW == nullptr)
|
||||
return false ;
|
||||
|
||||
// eventuali modifiche prima del salvataggio
|
||||
if ( ! pGObjRW->PreSave( * const_cast<GdbGeo*>( this)))
|
||||
return false ;
|
||||
|
||||
// tipo entità e identificativi
|
||||
if ( ! ngeOut.WriteKey( pGObjRW->GetNgeId()))
|
||||
return false ;
|
||||
@@ -124,7 +128,11 @@ GdbGeo::Save( int nBaseId, NgeWriter& ngeOut, INTUNORDSET* pSavedIds) const
|
||||
// parametri geometrici
|
||||
if ( ! ngeOut.WriteKey( NGE_G))
|
||||
return false ;
|
||||
return pGObjRW->Save( ngeOut) ;
|
||||
if ( ! pGObjRW->Save( ngeOut))
|
||||
return false ;
|
||||
|
||||
// eventuali ripristini dopo il salvataggio
|
||||
return pGObjRW->PostSave( * const_cast<GdbGeo*>( this)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -181,7 +189,7 @@ GdbGeo::Load( int nNgeId, NgeReader& ngeIn, int nBaseGdbId, int& nParentId)
|
||||
|
||||
// parametri geometrici
|
||||
IGeoObjRW* pGObjRW = dynamic_cast<IGeoObjRW*>( m_pGeoObj) ;
|
||||
return ( pGObjRW != nullptr && pGObjRW->Load( ngeIn)) ;
|
||||
return ( pGObjRW != nullptr && pGObjRW->Load( ngeIn) && pGObjRW->PostLoad( *this)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -83,7 +83,10 @@ class GeoFrame3d : public IGeoFrame3d, public IGeoObjRW
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
GeoFrame3d( void) ;
|
||||
|
||||
+7
-3
@@ -1,13 +1,13 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2014-2014
|
||||
// EgalTech 2014-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : GeoObjRW.h Data : 14.03.14 Versione : 1.5d5
|
||||
// File : GeoObjRW.h Data : 08.03.24 Versione : 2.6c2
|
||||
// Contenuto : Dichiarazione della interfaccia IGeoObjRW.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 20.11.13 DS Creazione modulo.
|
||||
//
|
||||
// 08.03.24 DS Aggiunte PreSave, PostSave, PreLoad e PostLoad.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
class NgeWriter ;
|
||||
class NgeReader ;
|
||||
class GdbGeo ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class __declspec( novtable) IGeoObjRW
|
||||
@@ -22,5 +23,8 @@ class __declspec( novtable) IGeoObjRW
|
||||
public :
|
||||
virtual int GetNgeId( void) const = 0 ;
|
||||
virtual bool Save( NgeWriter& ngeOut) const = 0 ;
|
||||
virtual bool PreSave( GdbGeo& Wrapper) const = 0 ;
|
||||
virtual bool PostSave( GdbGeo& Wrapper) const = 0 ;
|
||||
virtual bool Load( NgeReader& ngeIn) = 0 ;
|
||||
virtual bool PostLoad( GdbGeo& Wrapper) = 0 ;
|
||||
} ;
|
||||
|
||||
@@ -77,7 +77,10 @@ class GeoPoint3d : public IGeoPoint3d, public IGeoObjRW
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
GeoPoint3d( void) ;
|
||||
|
||||
@@ -91,7 +91,10 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
GeoVector3d( void) ;
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersCurveSurfTm.cpp Data : 23.02.24 Versione : 2.6b4
|
||||
// Contenuto : Implementazione della intersezione curva/superficie trimesh.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 23.02.24 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurveSurfTm.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void
|
||||
UpdateInfoIntersCurveSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen, double dUs, double dUe,
|
||||
int nT, const Triangle3d& Tria, ICSIVECTOR& vInfo)
|
||||
{
|
||||
Point3d ptInt, ptInt2 ;
|
||||
int nRes = IntersLineTria( ptL, vtDir, dLen, Tria, ptInt, ptInt2, true) ;
|
||||
if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) {
|
||||
double dU = dUs + ( ptInt - ptL) * vtDir / dLen * ( dUe - dUs) ;
|
||||
double dCosDN = vtDir * Tria.GetN() ;
|
||||
vInfo.emplace_back( nRes, dU, nT, dCosDN, ptInt) ;
|
||||
}
|
||||
else if ( nRes == ILTT_SEGM || nRes == ILTT_SEGM_ON_EDGE) {
|
||||
double dU = dUs + ( ptInt - ptL) * vtDir / dLen * ( dUe - dUs) ;
|
||||
double dU2 = dUs + ( ptInt2 - ptL) * vtDir / dLen * ( dUe - dUs) ;
|
||||
double dCosDN = vtDir * Tria.GetN() ;
|
||||
vInfo.emplace_back( nRes, dU, dU2, nT, dCosDN, ptInt, ptInt2) ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void
|
||||
OrderInfoIntersCurveSurfTm( ICSIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
if ( vInfo.size() == 0)
|
||||
return ;
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
[]( const IntCrvStmInfo& a, const IntCrvStmInfo& b)
|
||||
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
return ( dUa < dUb) ; }) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una curva con una superficie TriMesh
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurveSurfTm( const ICurve& Curve, const ISurfTriMesh& Stm, double dLinTol, ICSIVECTOR& vInfo)
|
||||
{
|
||||
// verifico i parametri ricevuti
|
||||
if ( & Curve == nullptr || &Stm == nullptr || &vInfo == nullptr)
|
||||
return false ;
|
||||
dLinTol = max( dLinTol, EPS_SMALL) ;
|
||||
vInfo.clear() ;
|
||||
|
||||
// approssimo la curva con una spezzata
|
||||
PolyLine PL ;
|
||||
if ( ! Curve.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_SPECIAL, PL))
|
||||
return false ;
|
||||
|
||||
// per ogni segmento dell'approssimante cerco l'intersezione con la superficie
|
||||
double dParS, dParE ;
|
||||
Point3d ptStart, ptEnd ;
|
||||
bool bFound = PL.GetFirstULine( &dParS, &ptStart, &dParE, &ptEnd) ;
|
||||
while ( bFound) {
|
||||
Vector3d vtDir = ptEnd - ptStart ;
|
||||
double dLen = vtDir.Len() ;
|
||||
if ( dLen > EPS_SMALL) {
|
||||
vtDir /= dLen ;
|
||||
// cerco i triangoli intersecati dal segmento
|
||||
const double BOX_STEP = 10 ;
|
||||
int nStep = int( ceil( dLen / BOX_STEP)) ;
|
||||
Vector3d vtStep = dLen / nStep * vtDir ;
|
||||
INTVECTOR vPrevT ;
|
||||
for ( int i = 0 ; i < nStep ; ++ i) {
|
||||
BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ;
|
||||
INTVECTOR vT ;
|
||||
if ( Stm.GetAllTriaOverlapBox( b3Box, vT)) {
|
||||
for ( auto nT : vT) {
|
||||
// se triangolo non ancora intersecato
|
||||
if ( find( vPrevT.begin(), vPrevT.end(), nT) == vPrevT.end()) {
|
||||
vPrevT.emplace_back( nT) ;
|
||||
Triangle3d Tria ;
|
||||
Stm.GetTriangle( nT, Tria) ;
|
||||
// aggiorno info con intersezione
|
||||
UpdateInfoIntersCurveSurfTm( ptStart, vtDir, dLen, dParS, dParE, nT, Tria, vInfo) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// passo al segmento successivo
|
||||
bFound = PL.GetNextULine( &dParS, &ptStart, &dParE, &ptEnd) ;
|
||||
}
|
||||
|
||||
// ordino il vettore delle eventuali intersezioni secondo il senso crescente del parametro di linea
|
||||
OrderInfoIntersCurveSurfTm( vInfo) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurveSurfTmExt( const ICurve& Curve, const ISurfTriMesh& Stm, double dLinTol, INTDBLVECTOR& vInters)
|
||||
{
|
||||
ICSIVECTOR vInfo ;
|
||||
vInters.clear() ;
|
||||
return ( IntersCurveSurfTm( Curve, Stm, dLinTol, vInfo) && FilterCurveSurfTmInters( Curve, vInfo, vInters)) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FilterCurveSurfTmInters( const ICurve& Curve, const ICSIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
{
|
||||
// verifico i parametri ricevuti
|
||||
if ( & Curve == nullptr || &vInfo == nullptr || &vInters == nullptr)
|
||||
return false ;
|
||||
vInters.clear() ;
|
||||
// info sulla curva
|
||||
bool bClosedCrv = Curve.IsClosed() ;
|
||||
double dParSCrv, dParECrv ;
|
||||
Curve.GetDomain( dParSCrv, dParECrv) ;
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
||||
int nFlag = CSIT_NONE ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = CSIT_IN_OUT ;
|
||||
else if ( Info.dCosDN < -EPS_ZERO)
|
||||
nFlag = CSIT_OUT_IN ;
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
vInters.emplace_back( CSIT_IN_ON, Info.dU) ;
|
||||
vInters.emplace_back( CSIT_ON_IN, Info.dU2) ;
|
||||
}
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
int nStart = ( bClosedCrv ? 0 : 1) ;
|
||||
for ( int j = nStart ; j < int( vInters.size()) ; ) {
|
||||
// intersezione precedente
|
||||
int i = ( j > 0 ? j - 1 : int( vInters.size()) - 1) ;
|
||||
// se hanno lo stesso parametro
|
||||
if ( abs( vInters[i].second - vInters[j].second) < EPS_PARAM ||
|
||||
( bClosedCrv && abs( vInters[i].second - dParECrv) < EPS_PARAM && abs( vInters[j].second - dParSCrv) < EPS_PARAM)) {
|
||||
// flag per eseguita cancellazione
|
||||
bool bSomeErased = false ;
|
||||
// se sono entrambe entranti o uscenti, elimino la seconda
|
||||
if ( ( vInters[i].first == CSIT_OUT_IN && vInters[j].first == CSIT_OUT_IN) ||
|
||||
( vInters[i].first == CSIT_IN_OUT && vInters[j].first == CSIT_IN_OUT)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una entrante e l'altra uscente, cambio in touch da fuori ed elimino la seconda
|
||||
else if ( vInters[i].first == CSIT_OUT_IN && vInters[j].first == CSIT_IN_OUT) {
|
||||
vInters[i].first = CSIT_OUT_OUT ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una uscente e l'altra entrante, cambio in touch da dentro ed elimino la seconda
|
||||
else if ( vInters[i].first == CSIT_IN_OUT && vInters[j].first == CSIT_OUT_IN) {
|
||||
vInters[i].first = CSIT_IN_IN ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una touch da fuori o da dentro e l'altra entrante o uscente, elimino la prima
|
||||
else if ( ( vInters[i].first == CSIT_OUT_OUT || vInters[i].first == CSIT_IN_IN) &&
|
||||
( vInters[j].first == CSIT_OUT_IN || vInters[j].first == CSIT_IN_OUT)) {
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una entrante o uscente e l'altra touch da fuori o da dentro, elimino la seconda
|
||||
else if ( ( vInters[i].first == CSIT_OUT_IN || vInters[i].first == CSIT_IN_OUT) &&
|
||||
( vInters[j].first == CSIT_OUT_OUT || vInters[j].first == CSIT_IN_IN)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
|
||||
else if ( ( vInters[i].first == CSIT_OUT_IN || vInters[i].first == CSIT_IN_OUT || vInters[i].first == CSIT_NONE) &&
|
||||
( vInters[j].first == CSIT_IN_ON || vInters[j].first == CSIT_OUT_ON)) {
|
||||
vInters[j].first = ( vInters[i].first == CSIT_IN_OUT ? CSIT_IN_ON : CSIT_OUT_ON) ;
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
|
||||
else if ( ( vInters[i].first == CSIT_ON_IN || vInters[i].first == CSIT_ON_OUT) &&
|
||||
( vInters[j].first == CSIT_OUT_IN || vInters[j].first == CSIT_IN_OUT || vInters[j].first == CSIT_NONE)) {
|
||||
vInters[i].first = ( vInters[j].first == CSIT_IN_OUT ? CSIT_ON_OUT : CSIT_ON_IN) ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
|
||||
else if ( ( vInters[i].first == CSIT_ON_IN || vInters[i].first == CSIT_ON_OUT) &&
|
||||
( vInters[j].first == CSIT_IN_ON || vInters[j].first == CSIT_OUT_ON)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
vInters.erase( vInters.begin() + ( j > 0 ? i : i - 1)) ;
|
||||
bSomeErased = true ;
|
||||
}
|
||||
if ( bSomeErased) {
|
||||
if ( j > 0)
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
// passo alla successiva
|
||||
++ j ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
+1
-1
@@ -22,7 +22,7 @@ using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Linea e box allineato assi devono essere nel medesimo sistema di riferimento.
|
||||
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
// In caso di intersezione viene restituito true e i parametri lunghezza in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Linea e box allineato agli assi sono nel medesimo riferimento.
|
||||
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
// Con intersezione viene restituito true e i parametri lunghezza in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "IntersLineCaps.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSphere.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
+2
-2
@@ -57,7 +57,7 @@ IntersLineLine::IntersLineLine( const CurveLine& Line1, const CurveLine& Line2,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
IntersLineLine::IntersInfiniteLines( const ICurveLine& Line1, const ICurveLine& Line2)
|
||||
IntersLineLine::IntersInfiniteLines( const CurveLine& Line1, const CurveLine& Line2)
|
||||
{
|
||||
// linea 1 : Start, End, Direzione e Lunghezza
|
||||
Point3d ptS1 = Line1.GetStart() ;
|
||||
@@ -118,7 +118,7 @@ IntersLineLine::IntersInfiniteLines( const ICurveLine& Line1, const ICurveLine&
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
IntersLineLine::IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Line2)
|
||||
IntersLineLine::IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line2)
|
||||
{
|
||||
// verifico sovrapposizione box
|
||||
BBox3d boxL1 ;
|
||||
|
||||
+2
-2
@@ -38,8 +38,8 @@ class IntersLineLine
|
||||
|
||||
private :
|
||||
IntersLineLine( void) ;
|
||||
void IntersInfiniteLines( const ICurveLine& Line1, const ICurveLine& Line2) ;
|
||||
void IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Line2) ;
|
||||
void IntersInfiniteLines( const CurveLine& Line1, const CurveLine& Line2) ;
|
||||
void IntersFiniteLines( const CurveLine& Line1, const CurveLine& Line2) ;
|
||||
|
||||
private :
|
||||
bool m_bOverlaps ;
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersLineSurfBez.cpp Data : 06.02.24 Versione : 2.6b1
|
||||
// Contenuto : Implementazione della intersezione linea/superficie bezier.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 06.02.24 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfBez.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool bFinite,
|
||||
const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz)
|
||||
{
|
||||
// la funzione raffina la posisione del punto ptSP, minimizzando la distanza dalla retta e restituisce il punto di intersezione ptIBz
|
||||
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
|
||||
// usando un algoritmo di newton cerco di avvicinarmi il più possibile alla retta
|
||||
DistPointLine dpl( ptIBz, ptL, vtL, dLen, bFinite) ;
|
||||
double dDistNew = 0, dDistPre = 0 ;
|
||||
dpl.GetDist(dDistNew) ;
|
||||
|
||||
int nCount = 0 ;
|
||||
double dh = EPS_SMALL ;
|
||||
pSurfBz->GetPointD1D2( ptSP.x, ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
|
||||
// metodo di newton in più dimensioni
|
||||
// vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi.
|
||||
while ( dDistNew > EPS_SMALL && nCount < 100) {
|
||||
dDistPre = dDistNew ;
|
||||
Point3d ptIBzNew1 ;
|
||||
pSurfBz->GetPointD1D2( ( ptSP.x + dh) / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ;
|
||||
DistPointLine dplNewU( ptIBzNew1, ptL, vtL, dLen, bFinite) ;
|
||||
dplNewU.GetDist( dDistNew) ;
|
||||
double dfdU = ( dDistNew - dDistPre) / dh ;
|
||||
Point3d ptIBzNew2 ;
|
||||
pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ( ptSP.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ;
|
||||
DistPointLine dplNewV( ptIBzNew2, ptL, vtL, dLen, bFinite) ;
|
||||
dplNewV.GetDist( dDistNew) ;
|
||||
double dfdV = ( dDistNew - dDistPre) / dh ;
|
||||
// mi avvicino cercando di annullare la distanza in un colpo solo
|
||||
double dr = - dDistPre / ( dfdU + dfdV) ;
|
||||
pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptSP.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ;
|
||||
DistPointLine dplNew( ptIBz, ptL, vtL, dLen, bFinite) ;
|
||||
dplNew.GetDist( dDistNew) ;
|
||||
++ nCount ;
|
||||
}
|
||||
|
||||
return ( nCount != 99) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void
|
||||
UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos,
|
||||
const Point3d& ptSP2, const Point3d& ptIBz2, double dCos2, ILSBIVECTOR& vInfo)
|
||||
{
|
||||
if ( nILT == ILTT_IN || nILT == ILTT_EDGE || nILT == ILTT_VERT) {
|
||||
double dU = ( ptIBz - ptL) * vtDir ;
|
||||
vInfo.emplace_back( nILT, dU, nT, dCos, ptIBz, ptSP) ;
|
||||
}
|
||||
else if ( nILT == ILTT_SEGM || nILT == ILTT_SEGM_ON_EDGE) {
|
||||
double dU = ( ptIBz - ptL) * vtDir ;
|
||||
double dU2 = ( ptIBz2 - ptL) * vtDir ;
|
||||
vInfo.emplace_back( nILT, dU, dU2, nT, dCos2, ptIBz, ptIBz2, ptSP, ptSP2) ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static void
|
||||
OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
if ( vInfo.size() == 0)
|
||||
return ;
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
[]( const IntLinSbzInfo& a, const IntLinSbzInfo& b)
|
||||
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
return ( dUa < dUb) ; }) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una linea con una superficie di Bezier
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
|
||||
ILSBIVECTOR& vInfo, bool bFinite)
|
||||
{
|
||||
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ;
|
||||
if ( bFinite)
|
||||
pCL->SetPVL(ptL, vtL, dLen) ;
|
||||
else
|
||||
pCL->SetPVL(ptL, vtL, 1e6) ;
|
||||
// verifico linea
|
||||
Vector3d vtDir = vtL ;
|
||||
if ( ! vtDir.Normalize( EPS_ZERO))
|
||||
return false ;
|
||||
// verifico superficie
|
||||
if ( pSurfBz == nullptr)
|
||||
return false ;
|
||||
// verifico parametro di ritorno
|
||||
if ( &vInfo == nullptr)
|
||||
return false ;
|
||||
vInfo.clear() ;
|
||||
|
||||
// trovo le intersezioni con la trimesh ausiliaria
|
||||
const ISurfTriMesh* pSurfTm = pSurfBz->GetAuxSurf() ;
|
||||
ILSIVECTOR vInfoTm ;
|
||||
if ( ! IntersLineSurfTm( ptL, vtL, dLen, *pSurfTm, vInfoTm, bFinite))
|
||||
return false ;
|
||||
// ricavo le intersezioni con la superficie di Bezier
|
||||
for ( IntLinStmInfo InfoTm : vInfoTm ) {
|
||||
// devo raffinare i parametri lungo la curva, l'angolo e i punti di intersezione
|
||||
Point3d ptI, ptI2 ;
|
||||
// devo trovare le intersezioni
|
||||
Point3d ptSP, ptSP2 ; // coordinate parametriche delle soluzioni
|
||||
pSurfBz->UnprojectPointFromStm( InfoTm.nT, InfoTm.ptI, ptSP, InfoTm.nILTT) ;
|
||||
Point3d ptIBz, ptIBz2 ;
|
||||
if ( ! RefineIntersNewton( ptL, vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz)) {
|
||||
/////// posso provare anche a rilanciare newton con un punto di partenza diverso oppure con una direzione di avvicinamento diversa///////////////////////////////////
|
||||
// per restare nel triangolo mi sposto verso un vertice
|
||||
int nVert[3] ;
|
||||
pSurfTm->GetTriangle( InfoTm.nT, nVert) ;
|
||||
double dU0, dV0 ;
|
||||
pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ;
|
||||
ptSP = ptSP + Point3d(dU0, dV0, 0) ;
|
||||
if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz))
|
||||
return false ;
|
||||
}
|
||||
Vector3d vtN ;
|
||||
pSurfBz->GetPointNrmD1D2(ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ;
|
||||
double dCos = vtN * vtL ;
|
||||
double dCos2 = 0 ;
|
||||
// eventualmente ripeto tutto per ptI2 ( se ho un'intersezione con sovrapposizione)
|
||||
if ( InfoTm.nILTT == ILTT_SEGM || InfoTm.nILTT == ILTT_SEGM_ON_EDGE ) {
|
||||
pSurfBz->UnprojectPointFromStm( InfoTm.nT, InfoTm.ptI2, ptSP2, InfoTm.nILTT) ;
|
||||
if ( ! RefineIntersNewton(ptL, vtL, dLen, bFinite, pSurfBz, ptSP2, ptIBz2) ) {
|
||||
int nVert[3] ;
|
||||
pSurfTm->GetTriangle( InfoTm.nT, nVert) ;
|
||||
double dU0, dV0 ;
|
||||
pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ;
|
||||
ptSP = ptSP + Point3d(dU0, dV0, 0) ;
|
||||
if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz))
|
||||
return false ;
|
||||
}
|
||||
pSurfBz->GetPointNrmD1D2( ptSP2.x / SBZ_TREG_COEFF, ptSP2.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ;
|
||||
dCos2 = vtN * vtL ;
|
||||
}
|
||||
UpdateInfoIntersLineSurfBz( ptL, vtL, InfoTm.nILTT, InfoTm.nT, ptSP, ptIBz, dCos, ptSP2, ptIBz2, dCos2, vInfo) ;
|
||||
}
|
||||
|
||||
OrderInfoIntersLineSurfBz( vInfo) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
{
|
||||
// tengo per buone la classificazione delle intersezioni fatte sulla trimesh
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
||||
int nFlag = LSBT_TOUCH ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = LSBT_OUT ;
|
||||
else if ( Info.dCosDN < -EPS_ZERO)
|
||||
nFlag = LSBT_IN ;
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
vInters.emplace_back( LSBT_TG_INI, Info.dU) ;
|
||||
vInters.emplace_back( LSBT_TG_FIN, Info.dU2) ;
|
||||
}
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
// intersezione precedente
|
||||
size_t i = j - 1 ;
|
||||
// se hanno lo stesso parametro
|
||||
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
|
||||
// se sono entrambe entranti o uscenti, elimino la seconda
|
||||
if ( ( vInters[i].first == LSBT_IN && vInters[j].first == LSBT_IN) ||
|
||||
( vInters[i].first == LSBT_OUT && vInters[j].first == LSBT_OUT)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
|
||||
else if ( ( vInters[i].first == LSBT_IN && vInters[j].first == LSBT_OUT) ||
|
||||
( vInters[i].first == LSBT_OUT && vInters[j].first == LSBT_IN)) {
|
||||
vInters[i].first = LSBT_TOUCH ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
|
||||
else if ( ( vInters[i].first == LSBT_IN || vInters[i].first == LSBT_OUT || vInters[i].first == LSBT_TOUCH) && vInters[j].first == LSBT_TG_INI) {
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
|
||||
else if ( vInters[i].first == LSBT_TG_FIN && ( vInters[j].first == LSBT_IN || vInters[j].first == LSBT_OUT || vInters[j].first == LSBT_TOUCH)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
|
||||
else if ( i > 0 && vInters[i].first == LSBT_TG_FIN && vInters[j].first == LSBT_TG_INI) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
// passo alla successiva
|
||||
++ j ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
+72
-5
@@ -21,7 +21,7 @@
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
static void
|
||||
UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen,
|
||||
int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dL
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
static void
|
||||
OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
|
||||
{
|
||||
// se non trovati, esco
|
||||
@@ -52,6 +52,8 @@ OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
|
||||
[]( const IntLinStmInfo& a, const IntLinStmInfo& b)
|
||||
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
if ( abs( dUa - dUb) < EPS_SMALL)
|
||||
return ( a.dCosDN < b.dCosDN) ;
|
||||
return ( dUa < dUb) ; }) ;
|
||||
}
|
||||
|
||||
@@ -81,7 +83,7 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
// lo ingrandisco per non avere problemi con faccia piana su piani canonici
|
||||
b3Stm.Expand( 10 * EPS_SMALL) ;
|
||||
double dU1, dU2 ;
|
||||
if ( ! IntersLineBox( ptL, vtL, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2))
|
||||
if ( ! IntersLineBox( ptL, vtDir, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2))
|
||||
return true ;
|
||||
if ( bFinite) {
|
||||
dU1 = max( dU1, 0.) ;
|
||||
@@ -89,12 +91,12 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
|
||||
if ( dU2 - dU1 < EPS_SMALL)
|
||||
return true ;
|
||||
}
|
||||
Point3d ptStart = ptL + dU1 * vtL ;
|
||||
Point3d ptStart = ptL + dU1 * vtDir ;
|
||||
double dLenEff = dU2 - dU1 ;
|
||||
// cerco i triangoli intersecati dalla linea
|
||||
const double BOX_STEP = 10 ;
|
||||
int nStep = int( ceil( dLenEff / BOX_STEP)) ;
|
||||
Vector3d vtStep = dLenEff / nStep * vtL ;
|
||||
Vector3d vtStep = dLenEff / nStep * vtDir ;
|
||||
INTVECTOR vPrevT ;
|
||||
for ( int i = 0 ; i < nStep ; ++ i) {
|
||||
BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ;
|
||||
@@ -189,3 +191,68 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
{
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
||||
int nFlag = LST_TOUCH ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = LST_OUT ;
|
||||
else if ( Info.dCosDN < -EPS_ZERO)
|
||||
nFlag = LST_IN ;
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
vInters.emplace_back( LST_TG_INI, Info.dU) ;
|
||||
vInters.emplace_back( LST_TG_FIN, Info.dU2) ;
|
||||
}
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
// intersezione precedente
|
||||
size_t i = j - 1 ;
|
||||
// se hanno lo stesso parametro
|
||||
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
|
||||
// se sono entrambe entranti o uscenti, elimino la seconda
|
||||
if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_IN) ||
|
||||
( vInters[i].first == LST_OUT && vInters[j].first == LST_OUT)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
|
||||
else if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_OUT) ||
|
||||
( vInters[i].first == LST_OUT && vInters[j].first == LST_IN)) {
|
||||
vInters[i].first = LST_TOUCH ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
|
||||
else if ( ( vInters[i].first == LST_IN || vInters[i].first == LST_OUT || vInters[i].first == LST_TOUCH) && vInters[j].first == LST_TG_INI) {
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
|
||||
else if ( vInters[i].first == LST_TG_FIN && ( vInters[j].first == LST_IN || vInters[j].first == LST_OUT || vInters[j].first == LST_TOUCH)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
|
||||
else if ( i > 0 && vInters[i].first == LST_TG_FIN && vInters[j].first == LST_TG_INI) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
// passo alla successiva
|
||||
++ j ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@
|
||||
#include "CurveLine.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "IntersLineTria.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkFrame3d.h"
|
||||
#include <array>
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersLineVolZmap.cpp Data : 22.02.24 Versione : 2.6b4
|
||||
// Contenuto : Implementazione della intersezione linea/VolZmap.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 22.02.24 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "VolZmap.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una linea con la superficie di un solido VolZmap
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineVolZmap( const Point3d& ptL, const Vector3d& vtL, const IVolZmap& Vzm, ILZIVECTOR& vInfo)
|
||||
{
|
||||
// verifico linea
|
||||
Vector3d vtDir = vtL ;
|
||||
if ( ! vtDir.Normalize( EPS_ZERO))
|
||||
return false ;
|
||||
// verifico volume
|
||||
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
|
||||
if ( pVzm == nullptr)
|
||||
return false ;
|
||||
// verifico parametro di ritorno
|
||||
if ( &vInfo == nullptr)
|
||||
return false ;
|
||||
|
||||
// eseguo intersezione
|
||||
return pVzm->GetLineIntersection( ptL, vtL, vInfo) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
FilterLineVolZmapInters( const ILZIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
{
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
||||
int nFlag = LZT_TOUCH ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = LZT_OUT ;
|
||||
else if ( Info.dCosDN < -EPS_ZERO)
|
||||
nFlag = LZT_IN ;
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
||||
vInters.emplace_back( LZT_TG_INI, Info.dU) ;
|
||||
vInters.emplace_back( LZT_TG_FIN, Info.dU2) ;
|
||||
}
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
// intersezione precedente
|
||||
size_t i = j - 1 ;
|
||||
// se hanno lo stesso parametro
|
||||
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
|
||||
// se sono entrambe entranti o uscenti, elimino la seconda
|
||||
if ( ( vInters[i].first == LZT_IN && vInters[j].first == LZT_IN) ||
|
||||
( vInters[i].first == LZT_OUT && vInters[j].first == LZT_OUT)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
|
||||
else if ( ( vInters[i].first == LZT_IN && vInters[j].first == LZT_OUT) ||
|
||||
( vInters[i].first == LZT_OUT && vInters[j].first == LZT_IN)) {
|
||||
vInters[i].first = LZT_TOUCH ;
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
|
||||
else if ( ( vInters[i].first == LZT_IN || vInters[i].first == LZT_OUT || vInters[i].first == LZT_TOUCH) && vInters[j].first == LZT_TG_INI) {
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
|
||||
else if ( vInters[i].first == LZT_TG_FIN && ( vInters[j].first == LZT_IN || vInters[j].first == LZT_OUT || vInters[j].first == LZT_TOUCH)) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
continue ;
|
||||
}
|
||||
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
|
||||
else if ( i > 0 && vInters[i].first == LZT_TG_FIN && vInters[j].first == LZT_TG_INI) {
|
||||
vInters.erase( vInters.begin() + j) ;
|
||||
vInters.erase( vInters.begin() + i) ;
|
||||
-- j ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
// passo alla successiva
|
||||
++ j ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "ProjPlane.h"
|
||||
#include "CurveLine.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlaneSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : IntersPlaneVolZmap.cpp Data : 22.02.24 Versione : 2.6b4
|
||||
// Contenuto : Implementazione della intersezione piano/VolZmap.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 22.02.24 DS Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "VolZmap.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlaneVolZmap.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di unpiano con la superficie di un solido VolZmap
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR& vpLoop)
|
||||
{
|
||||
// verifico volume
|
||||
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
|
||||
if ( pVzm == nullptr)
|
||||
return false ;
|
||||
// verifico parametro di ritorno
|
||||
if ( &vpLoop == nullptr)
|
||||
return false ;
|
||||
|
||||
// eseguo intersezione
|
||||
return pVzm->GetPlaneIntersection( plPlane, vpLoop) ;
|
||||
}
|
||||
@@ -13,9 +13,9 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "IntersLineTria.h"
|
||||
#include "DllMain.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersSurfTmSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersTriaTria.h"
|
||||
#include "/EgtDev/Include/EGkPointGrid3d.h"
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkLineTgCurvePerpCurve.h"
|
||||
#include "/EgtDev/Include/EGkLinePntTgCurve.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CreateCurveAux.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkLineTgTwoCurves.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
|
||||
+1
-1
@@ -13,9 +13,9 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveArc.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkPolyArc.h"
|
||||
#include "/EgtDev/Include/EGkFrame3d.h"
|
||||
#include <algorithm>
|
||||
|
||||
+112
-98
@@ -1,4 +1,4 @@
|
||||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2013-2013
|
||||
//----------------------------------------------------------------------------
|
||||
// File : PolyLine.cpp Data : 22.12.13 Versione : 1.4l3
|
||||
@@ -14,13 +14,13 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveLine.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "IntersLineLine.h"
|
||||
#include "PolygonPlane.h"
|
||||
#include "PointsPCA.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
|
||||
@@ -53,7 +53,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
|
||||
{
|
||||
// se da aggiungere in coda
|
||||
if ( bEndOrStart) {
|
||||
// se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
|
||||
// se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
|
||||
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
|
||||
++ m_nRejected ;
|
||||
return true ;
|
||||
@@ -68,7 +68,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
|
||||
}
|
||||
// altrimenti si aggiunge in testa
|
||||
else {
|
||||
// se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok
|
||||
// se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok
|
||||
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.front().first)) {
|
||||
++ m_nRejected ;
|
||||
return true ;
|
||||
@@ -92,7 +92,7 @@ PolyLine::Close( void)
|
||||
// ci devono essere almeno 2 punti
|
||||
if ( m_lUPoints.size() < 2)
|
||||
return false ;
|
||||
// verifico non sia già chiuso
|
||||
// verifico non sia già chiuso
|
||||
if ( AreSamePointApprox( m_lUPoints.front().first, m_lUPoints.back().first))
|
||||
return false ;
|
||||
// aggiungo un punto uguale al primo in coda
|
||||
@@ -219,7 +219,7 @@ PolyLine::ToLoc( const Frame3d& frRef)
|
||||
bool
|
||||
PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
{
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
if ( AreSameFrame( frOri, frDest))
|
||||
return true ;
|
||||
// ciclo sui punti
|
||||
@@ -233,7 +233,7 @@ PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
bool
|
||||
PolyLine::Join( PolyLine& PL, double dOffsetPar)
|
||||
{
|
||||
// se l'altra polilinea non contiene alcunchè, esco con ok
|
||||
// se l'altra polilinea non contiene alcunchè, esco con ok
|
||||
if ( PL.m_lUPoints.size() == 0)
|
||||
return true ;
|
||||
// verifico che l'ultimo punto di questa polilinea coincida con il primo dell'altra
|
||||
@@ -385,7 +385,7 @@ PolyLine::GetPrevUPoint( double* pdPar, Point3d* pptP, bool bNotFirst) const
|
||||
bool
|
||||
PolyLine::GetCurrUPoint( double* pdPar, Point3d* pptP) const
|
||||
{
|
||||
// verifico validità punto corrente
|
||||
// verifico validità punto corrente
|
||||
if ( m_iter == m_lUPoints.end())
|
||||
return false ;
|
||||
|
||||
@@ -426,7 +426,7 @@ PolyLine::GetFirstULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d*
|
||||
bool
|
||||
PolyLine::GetNextULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* pptFin) const
|
||||
{
|
||||
// parametro e punto iniziali (è il precedente finale)
|
||||
// parametro e punto iniziali (è il precedente finale)
|
||||
if ( m_iter == m_lUPoints.end())
|
||||
return false ;
|
||||
if ( pdIni != nullptr)
|
||||
@@ -510,19 +510,19 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co
|
||||
ptsPCA.AddPoint( Media( ptP1, ptP2, 0.25), dLen / 2) ;
|
||||
ptsPCA.AddPoint( Media( ptP1, ptP2, 0.75), dLen / 2) ;
|
||||
}
|
||||
// recupero il rango, ovvero la dimensionalità dell'insieme di punti
|
||||
// recupero il rango, ovvero la dimensionalità dell'insieme di punti
|
||||
nRank = ptsPCA.GetRank() ;
|
||||
// se dimensione nulla, o non ci sono punti o sono tutti praticamente coincidenti
|
||||
if ( nRank == 0)
|
||||
return ptsPCA.GetCenter( ptCen) ;
|
||||
// se dimensione 1, allora i punti sono distribuiti su una linea
|
||||
if ( nRank == 1) {
|
||||
// assegno il centro e la direzione della linea (il verso è indifferente)
|
||||
// assegno il centro e la direzione della linea (il verso è indifferente)
|
||||
ptsPCA.GetCenter( ptCen) ;
|
||||
ptsPCA.GetPrincipalComponent( 0, vtDir) ;
|
||||
return true ;
|
||||
}
|
||||
// altrimenti dimensione 2 o 3, allora è determinato un piano principale, verifico se tutti i punti vi giacciono
|
||||
// altrimenti dimensione 2 o 3, allora è determinato un piano principale, verifico se tutti i punti vi giacciono
|
||||
// Center and normal vector
|
||||
ptsPCA.GetCenter( ptCen) ;
|
||||
Vector3d vtX, vtY ;
|
||||
@@ -530,9 +530,9 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co
|
||||
ptsPCA.GetPrincipalComponent( 1, vtY) ;
|
||||
vtDir = vtX ^ vtY ;
|
||||
if ( ! vtDir.Normalize()) {
|
||||
// riduco la dimensionalità a lineare
|
||||
// riduco la dimensionalità a lineare
|
||||
nRank = 1 ;
|
||||
// assegno il centro e la direzione della linea (il verso è indifferente)
|
||||
// assegno il centro e la direzione della linea (il verso è indifferente)
|
||||
ptsPCA.GetCenter( ptCen) ;
|
||||
vtDir = vtX ;
|
||||
return true ;
|
||||
@@ -561,12 +561,12 @@ PolyLine::IsFlat( Plane3d& plPlane, double dToler) const
|
||||
plPlane.Reset() ;
|
||||
return false ;
|
||||
}
|
||||
// recupero dati sulla planarità della polilinea
|
||||
// recupero dati sulla planarità della polilinea
|
||||
int nRank ;
|
||||
Point3d ptCen ;
|
||||
Vector3d vtDir ;
|
||||
bool bFlat = IsFlat( nRank, ptCen, vtDir, dToler) ;
|
||||
// imposto il piano a seconda della dimensionalità
|
||||
// imposto il piano a seconda della dimensionalità
|
||||
switch ( nRank) {
|
||||
case 0 : // punto
|
||||
plPlane.Set( ptCen, Z_AX) ;
|
||||
@@ -639,13 +639,13 @@ PolyLine::GetAreaXY( double& dArea) const
|
||||
// verifico sia chiusa
|
||||
if ( ! IsClosed())
|
||||
return false ;
|
||||
// calcolo l'area considerando solo XY (è la Z di Newell)
|
||||
// calcolo l'area considerando solo XY (è la Z di Newell)
|
||||
dArea = 0 ;
|
||||
Point3d ptIni, ptFin ;
|
||||
for ( bool bFound = GetFirstLine( ptIni, ptFin) ; bFound ; bFound = GetNextLine( ptIni, ptFin)) {
|
||||
dArea += ( ptIni.x - ptFin.x) * ( ptIni.y + ptFin.y) ; // projection on xy
|
||||
}
|
||||
// considero anche la linea tra l'ultimo e il primo punto perchè in alcuni casi potrebbero definire area
|
||||
// considero anche la linea tra l'ultimo e il primo punto perchè in alcuni casi potrebbero definire area
|
||||
// significativa anche se sono coincidenti per le nostre tolleranze
|
||||
ptIni = ptFin ;
|
||||
GetFirstPoint( ptFin) ;
|
||||
@@ -721,15 +721,42 @@ PolyLine::AdjustForMaxSegmentLen( double dMaxLen)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool
|
||||
PointsInTolerance( const PNTVECTOR& vRPT, const Point3d& ptP1, const Point3d& ptP2, double dSqTol)
|
||||
DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const int nIndStart,
|
||||
const int nIndEnd, INTVECTOR& vInd)
|
||||
{
|
||||
for ( const auto& ptQ : vRPT) {
|
||||
double dSqDist ;
|
||||
if ( ! DistPointLine( ptQ, ptP1, ptP2).GetSqDist( dSqDist) || dSqDist > dSqTol)
|
||||
// se indici uguali, ritorno
|
||||
if ( nIndStart == nIndEnd)
|
||||
return true ;
|
||||
|
||||
// distanza massima e indice del punto associato
|
||||
double dMaxSqDist = 0. ;
|
||||
int nMaxInd = 0 ;
|
||||
|
||||
// scorro i punti intermedi tra nIndStart e nIndEnd
|
||||
for ( int i = nIndStart + 1 ; i < nIndEnd ; ++ i) {
|
||||
double dCurrSqDist = 0. ;
|
||||
// distanza tra il punto attuale e la retta tra i punti di indici nIndStart ed nIndEnd
|
||||
DistPointLine DPL( vPtU[i].first, vPtU[nIndStart].first, vPtU[nIndEnd].first) ;
|
||||
if ( DPL.GetSqDist( dCurrSqDist) && dCurrSqDist > dMaxSqDist) {
|
||||
// aggiorno i parametri
|
||||
dMaxSqDist = dCurrSqDist ;
|
||||
nMaxInd = i ;
|
||||
}
|
||||
}
|
||||
|
||||
// se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra
|
||||
// (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd)
|
||||
if ( dMaxSqDist > dSqTol) {
|
||||
// inserisco il punto
|
||||
vInd.push_back( nMaxInd) ;
|
||||
// split
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nIndStart, nMaxInd, vInd) ||
|
||||
! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, nIndEnd, vInd))
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -743,59 +770,61 @@ PolyLine::RemoveAlignedPoints( double dToler)
|
||||
// controllo minimo valore di tolleranza
|
||||
dToler = max( dToler, LIN_TOL_MIN) ;
|
||||
double dSqTol = dToler * dToler ;
|
||||
// si analizza la distanza di un punto dal segmento che unisce precedente e successivo
|
||||
// punto precedente
|
||||
auto precP = m_lUPoints.begin() ;
|
||||
// punto corrente
|
||||
auto currP = next( precP) ;
|
||||
// punto successivo
|
||||
auto nextP = next( currP) ;
|
||||
// lista dei punti appena rimossi
|
||||
PNTVECTOR vRPT ; vRPT.reserve( 20) ;
|
||||
// mentre esiste un successivo
|
||||
while ( nextP != m_lUPoints.end()) {
|
||||
// distanza del punto corrente dal segmento che unisce gli adiacenti
|
||||
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
|
||||
double dSqDist ;
|
||||
// se da eliminare
|
||||
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vRPT, precP->first, nextP->first, dSqTol)) {
|
||||
// aggiungo il punto nella lista dei rimossi
|
||||
vRPT.emplace_back( currP->first) ;
|
||||
// elimino il punto
|
||||
m_lUPoints.erase( currP) ;
|
||||
// avanzo con corrente e successivo
|
||||
currP = nextP ;
|
||||
++ nextP ;
|
||||
|
||||
// vettore contenente i punti della polyline
|
||||
PNTUVECTOR vPtU ; vPtU.reserve( m_lUPoints.size()) ;
|
||||
for ( const auto& ptCurr : m_lUPoints)
|
||||
vPtU.emplace_back( ptCurr) ;
|
||||
|
||||
// vettore indici dei punti rimanenti
|
||||
INTVECTOR vInd ; vInd.reserve( vPtU.size()) ;
|
||||
|
||||
// se aperta
|
||||
if ( ! IsClosed()) {
|
||||
// considero tutti i punti della PolyLine
|
||||
vInd.push_back( 0) ;
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vInd))
|
||||
return false ;
|
||||
vInd.push_back( vPtU.size() - 1) ;
|
||||
}
|
||||
// altrimenti chiusa
|
||||
else {
|
||||
// cerco il punto più distante dal primo
|
||||
double dMaxDist = 0. ;
|
||||
int nMaxInd = 0 ;
|
||||
for ( int i = 1 ; i < int( vPtU.size()) ; ++ i) {
|
||||
double dCurrDist = Dist( vPtU[0].first, vPtU[i].first) ;
|
||||
if ( dCurrDist > dMaxDist) {
|
||||
dMaxDist = dCurrDist ;
|
||||
nMaxInd = i ;
|
||||
}
|
||||
}
|
||||
// altrimenti da tenere
|
||||
else {
|
||||
// cancello la lista dei rimossi
|
||||
vRPT.clear() ;
|
||||
// avanzo il terzetto di uno step
|
||||
precP = currP ;
|
||||
currP = nextP ;
|
||||
++ nextP ;
|
||||
// recupero due PolyLine di approssimazione
|
||||
vInd.push_back( 0) ;
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, nMaxInd, vInd))
|
||||
return false ;
|
||||
vInd.push_back( nMaxInd) ;
|
||||
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vInd))
|
||||
return false ;
|
||||
vInd.push_back( vPtU.size() - 1) ;
|
||||
}
|
||||
|
||||
// ordino in senso crescente
|
||||
sort( vInd.begin(), vInd.end()) ;
|
||||
|
||||
// se chiusa e almeno 4 punti rimasti, controllo allineamento dell'inizio con precedente e successivo rimasti
|
||||
if ( IsClosed() && vInd.size() >= 4) {
|
||||
if ( DistPointLine( vPtU[vInd[0]].first, vPtU[vInd[1]].first, vPtU[vInd[vInd.size()-2]].first).IsEpsilon( dToler)) {
|
||||
vInd.erase( vInd.begin()) ;
|
||||
vInd.back() = vInd.front() ;
|
||||
}
|
||||
}
|
||||
// se curva chiusa con almeno 4 punti, devo analizzare il terzetto attorno alla chiusura
|
||||
if ( IsClosed() && m_lUPoints.size() >= 4) {
|
||||
// precP e currP sono già corretti
|
||||
// il primo punto ripete l'ultimo (geometricamente coincide con currP)
|
||||
auto firstP = m_lUPoints.begin() ;
|
||||
// questo è il vero successivo
|
||||
nextP = next( firstP) ;
|
||||
// distanza del punto corrente dal segmento che unisce gli adiacenti
|
||||
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
|
||||
double dSqDist ;
|
||||
// se da eliminare
|
||||
if ( dPL.GetSqDist( dSqDist) && dSqDist < dSqTol && PointsInTolerance( vRPT, precP->first, nextP->first, dSqTol)) {
|
||||
// faccio coincidere il primo punto con il precedente
|
||||
firstP->first = precP->first ;
|
||||
// elimino il punto corrente
|
||||
m_lUPoints.erase( currP) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// rimetto in lista i soli punti rimasti
|
||||
m_lUPoints.clear() ;
|
||||
for ( auto Ind : vInd)
|
||||
m_lUPoints.push_back( vPtU[Ind]) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -937,7 +966,7 @@ PolyLine::MyApproxOnSide( const Vector3d& vtN, bool bLeftSide, double dToler)
|
||||
}
|
||||
}
|
||||
}
|
||||
// non è stato eliminato alcunché
|
||||
// non è stato eliminato alcunché
|
||||
// ripristino la tolleranza corrente
|
||||
dCurrToler = dToler ;
|
||||
// avanzo il terzetto di uno step
|
||||
@@ -978,7 +1007,7 @@ PolyLine::MakeConvex( const Vector3d& vtN, bool bLeftSide)
|
||||
bool
|
||||
PolyLine::MyMakeConvex( const Vector3d& vtN, bool bLeftSide)
|
||||
{
|
||||
// ciclo i controlli finchè non ci sono rimozioni
|
||||
// ciclo i controlli finchè non ci sono rimozioni
|
||||
bool bRemoved = true ;
|
||||
while ( bRemoved) {
|
||||
bRemoved = false ;
|
||||
@@ -1006,7 +1035,7 @@ PolyLine::MyMakeConvex( const Vector3d& vtN, bool bLeftSide)
|
||||
bRemoved = true ;
|
||||
continue ;
|
||||
}
|
||||
// non è stato eliminato alcunché : avanzo il terzetto di uno step
|
||||
// non è stato eliminato alcunché : avanzo il terzetto di uno step
|
||||
precP = currP ;
|
||||
currP = nextP ;
|
||||
++ nextP ;
|
||||
@@ -1033,7 +1062,7 @@ PolyLine::Invert( bool bInvertU)
|
||||
m_lUPoints.reverse() ;
|
||||
// se richiesto, inverto anche il parametro U
|
||||
if ( bInvertU) {
|
||||
// recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione
|
||||
// recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione
|
||||
double dUfin = m_lUPoints.front().second ;
|
||||
// ciclo su tutti gli elementi
|
||||
for ( auto& UPoint : m_lUPoints) {
|
||||
@@ -1248,7 +1277,7 @@ PolyLine::GetMinAreaRectangleXY( Point3d& ptCen, Vector3d& vtAx, double& dLen, d
|
||||
bool
|
||||
PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
|
||||
{
|
||||
// se vuota non faccio alcunché
|
||||
// se vuota non faccio alcunché
|
||||
if ( m_lUPoints.size() == 0)
|
||||
return false ;
|
||||
|
||||
@@ -1350,7 +1379,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler
|
||||
return false ;
|
||||
// Riferimento alla lista dei punti
|
||||
PNTULIST& List = const_cast<PolyLine&>( plPoly).GetUPointList() ;
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
Point3d ptMinDist ;
|
||||
auto itMinDistEnd = List.end() ;
|
||||
@@ -1439,7 +1468,7 @@ GetPointParamOnPolyLine( const Point3d& ptP, const PolyLine& plPoly, double dTol
|
||||
// assegno nuovo inizio
|
||||
ptStart = ptEnd ;
|
||||
}
|
||||
// Il punto è sulla linea se la sua distanza rispetta la tolleranza
|
||||
// Il punto è sulla linea se la sua distanza rispetta la tolleranza
|
||||
return ( dMinSqDist < dToler * dToler) ;
|
||||
}
|
||||
|
||||
@@ -1452,7 +1481,7 @@ ChangePolyLineStart( PolyLine& plPoly, const Point3d& ptNewStart, double dToler)
|
||||
return false ;
|
||||
// Riferimento alla lista dei punti
|
||||
PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
auto itMinDistEnd = LoopList.end() ;
|
||||
auto itStart = LoopList.begin() ;
|
||||
@@ -1496,7 +1525,7 @@ SplitPolyLineAtPoint( const PolyLine& plPoly, const Point3d& ptP, double dToler,
|
||||
return false ;
|
||||
// Riferimento alla lista dei punti
|
||||
const PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
|
||||
double dMinSqDist = SQ_INFINITO ;
|
||||
auto itMinDistEnd = LoopList.end() ;
|
||||
auto itStart = LoopList.begin() ;
|
||||
@@ -1560,10 +1589,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
int nLastJ = 0 ;
|
||||
vPnt1[0].second = 0 ;
|
||||
|
||||
double dFirstDist, dFirstParMinDist ;
|
||||
DistPointPolyLine( vPnt1[0].first, PL2, dFirstDist, dFirstParMinDist) ;
|
||||
int nFirstMinJ = ( int)( dFirstParMinDist + 0.5) ;
|
||||
|
||||
for ( int i = 1 ; i < nTotP1 ; ++ i) {
|
||||
|
||||
double dDist = INFINITO ;
|
||||
@@ -1580,14 +1605,10 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
}
|
||||
int nMinJ = ( int)( dMinDistPar + 0.5) ;
|
||||
|
||||
// eventuale correzione per i primi punti ( da forzare nel vertice 0)
|
||||
if ( nLastJ == 0 && nFirstMinJ > 0.5 * nTotP2 && nMinJ >= nFirstMinJ)
|
||||
nMinJ = 0 ;
|
||||
|
||||
if ( nMinJ < nLastJ)
|
||||
nMinJ = nLastJ ;
|
||||
|
||||
// verifica se è un punto interno in comune con l'altra polyline
|
||||
// verifica se è un punto interno in comune con l'altra polyline
|
||||
if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL)
|
||||
bCommonInternalPoints = true ;
|
||||
|
||||
@@ -1598,9 +1619,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
// calcoli per seconda curva
|
||||
int nLastI = 0 ;
|
||||
vPnt2[0].second = 0 ;
|
||||
|
||||
DistPointPolyLine( vPnt2[0].first, PL1, dFirstDist, dFirstParMinDist) ;
|
||||
int nFirstMinI = ( int)( dFirstParMinDist + 0.5) ;
|
||||
|
||||
for ( int j = 1 ; j < nTotP2 ; ++ j) {
|
||||
|
||||
@@ -1619,10 +1637,6 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV
|
||||
}
|
||||
int nMinI = ( int)( dMinDistPar + 0.5) ;
|
||||
|
||||
// eventuale correzione per primi punti
|
||||
if ( nLastI == 0 && nFirstMinI > 0.5 * nTotP1 && nMinI >= nFirstMinI)
|
||||
nMinI = 0 ;
|
||||
|
||||
if ( nMinI < nLastI)
|
||||
nMinI = nLastI ;
|
||||
|
||||
|
||||
+329
-57
@@ -13,13 +13,19 @@
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkProjectCurveSurfTm.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Angolo limite tra normale al triangolo e direzione di proiezione 89°
|
||||
const double COS_ANG_LIM = 0.0175 ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext, double dSqTol)
|
||||
@@ -33,63 +39,9 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen,
|
||||
PNT5AXVECTOR& vPt5ax)
|
||||
static bool
|
||||
RemovePointsInExcess( PNT5AXVECTOR& vMyPt5ax, double dLinTol, double dMaxSegmLen)
|
||||
{
|
||||
// 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
|
||||
double dSqMaxLen = dMaxSegmLen * dMaxSegmLen ;
|
||||
double dSqTol = dLinTol * dLinTol ;
|
||||
@@ -130,6 +82,326 @@ ProjectCurveOnSurfTm( const ICurve& crCrv, const ISurfTriMesh& tmSurf, const Vec
|
||||
++ 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 alla massima risoluzione
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( EPS_SMALL, 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) {
|
||||
// intersezione retta di proiezione con superficie
|
||||
Point3d ptL = GetToLoc( ptP, frRefLine) ;
|
||||
ILSIVECTOR vIntRes ;
|
||||
intPLSTM.GetInters( ptL, 1, vIntRes, false) ;
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
// calcolo il punto
|
||||
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)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
// calcolo il punto
|
||||
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 alla massima risoluzione
|
||||
PolyLine PL ;
|
||||
if ( ! crCrv.ApproxWithLines( EPS_SMALL, 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)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
// calcolo il punto
|
||||
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)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = int( vIntRes.size()) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
// calcolo il punto
|
||||
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
|
||||
vPt5ax.clear() ;
|
||||
|
||||
+158
@@ -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) ;
|
||||
}
|
||||
@@ -15,8 +15,8 @@
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "RemoveCurveDefects.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
@@ -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 ;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : SbzSphere.cpp Data : 14.02.2024 Versione : 2.6b2
|
||||
// Contenuto : Implementazione di funzioni per creazione di superfici Sbz
|
||||
// standard : Box, Pyramid, Cylinder, Sphere, Cone.
|
||||
//
|
||||
//
|
||||
// Modifiche : 14.02.2024 DB Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CurveArc.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkSbzStandard.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
CreateBezierSphere( const Point3d& ptCenter, double dR)
|
||||
{
|
||||
// creo una superficie di Bezier di grado 2 con 45 punti di controllo
|
||||
PtrOwner<ISurfBezier> pSrfBez( CreateSurfBezier()) ;
|
||||
int nDegU = 2 ;
|
||||
int nDegV = 2 ;
|
||||
int nSpanU = 4 ; // i poli della sfera sono a coordinate ( 0,0,-R) e ( 0,0,R)
|
||||
int nSpanV = 2 ;
|
||||
bool bRat = true ;
|
||||
double dW = SQRT2 ;
|
||||
pSrfBez->Init(nDegU, nDegV, nSpanU, nSpanV, bRat) ;
|
||||
// polo inferiore // dW = 1, dW = SQRT2 / 2
|
||||
for ( int i = 0 ; i < 9; ++i) {
|
||||
if ( i % 2 == 0)
|
||||
dW = 1 ;
|
||||
else
|
||||
dW = SQRT2 / 2 ;
|
||||
pSrfBez->SetControlPoint( i, 0, ptCenter + Point3d( 0, 0, -dR), dW) ;
|
||||
}
|
||||
// definisco la gabbia esterna // dW = SQRT2 / 2, dW = 1 / 2
|
||||
// parto dal punto ( 0,-dR, -dR) e completo riga per riga
|
||||
double dH = -dR ;
|
||||
for ( int j = 1 ; j < 4 ; ++j ) {
|
||||
Vector3d vtDir ( 0, -dR, 0) ;
|
||||
Point3d pt(-dR,-dR,dH) ;
|
||||
for ( int i = 0; i < 9 ; ++i ) {
|
||||
// ogni due punti ruoto di 90 gradi a sinistra
|
||||
if ( i%2 == 0) {
|
||||
vtDir.Rotate( Z_AX, 90) ;
|
||||
if ( j%2 == 1)
|
||||
dW = SQRT2 / 2 ;
|
||||
else
|
||||
dW = 1 ;
|
||||
}
|
||||
else {
|
||||
if ( j%2 == 1)
|
||||
dW = 1. / 2. ;
|
||||
else
|
||||
dW = SQRT2 / 2 ;
|
||||
}
|
||||
pt += vtDir ;
|
||||
pSrfBez->SetControlPoint( i, j, ptCenter + pt, dW) ;
|
||||
}
|
||||
dH += dR ;
|
||||
}
|
||||
// polo superiore // dW = 1, dW = SQRT2 / 2
|
||||
for ( int i = 0 ; i < 9; ++i) {
|
||||
if ( i % 2 == 0)
|
||||
dW = 1 ;
|
||||
else
|
||||
dW = SQRT2 / 2 ;
|
||||
pSrfBez->SetControlPoint( i, 4, ptCenter + Point3d( 0, 0, dR), dW) ;
|
||||
}
|
||||
|
||||
return Release( pSrfBez) ;
|
||||
}
|
||||
+774
-136
File diff suppressed because it is too large
Load Diff
+226
-47
@@ -20,12 +20,14 @@
|
||||
#include "CurveBezier.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfBezier.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EGkSurf.h"
|
||||
#include "/EgtDev/Include/EGkSurfAux.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
{
|
||||
@@ -60,11 +62,12 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
nuCurve.vCP = vPtCtrl ;
|
||||
nuCurve.vW = vWeCtrl ;
|
||||
// i punti dell' oggetto nuCurve devono essere in forma non omogenea
|
||||
NurbsCurveCanonicalize( nuCurve) ;
|
||||
for ( int i = 0 ; i < snData.nCPU ; ++i) {
|
||||
snData.mCP[i][j] = nuCurve.vCP[i] ;
|
||||
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) {
|
||||
snData.mCP[i][j] = nuCurve.vCP[i] ;
|
||||
}
|
||||
snData.vU = nuCurve.vU ;
|
||||
}
|
||||
snData.vU = nuCurve.vU ;
|
||||
}
|
||||
snData.bPeriodicU = false ;
|
||||
}
|
||||
@@ -97,37 +100,36 @@ NurbsSurfaceCanonicalize( SNurbsSurfData& snData)
|
||||
nuCurve.vCP = vPtCtrl ;
|
||||
nuCurve.vW = vWeCtrl ;
|
||||
// i punti dell' oggetto nuCurve devono essere in forma non omogenea
|
||||
NurbsCurveCanonicalize( nuCurve) ;
|
||||
for ( int j = 0 ; j < snData.nCPV ; ++j ) {
|
||||
snData.mCP[i][j] = nuCurve.vCP[j] ;
|
||||
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 ) {
|
||||
snData.mCP[i][j] = nuCurve.vCP[j] ;
|
||||
}
|
||||
snData.vV = nuCurve.vU ;
|
||||
}
|
||||
snData.vV = nuCurve.vU ;
|
||||
}
|
||||
snData.bPeriodicV = false ;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ISurf*
|
||||
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 )
|
||||
return nullptr ;
|
||||
// controllo sul numero dei nodi
|
||||
// controllo sul numero dei nodi
|
||||
int nU = snData.nCPU + snData.nDegU - 1 ;
|
||||
int nV = snData.nCPV + snData.nDegV - 1 ;
|
||||
// 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()))
|
||||
// controllo nodi e punti di controllo
|
||||
if ( nU != int(snData.vU.size()) || nV != int(snData.vV.size())) {
|
||||
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 ;
|
||||
// direzione U
|
||||
// direzione U
|
||||
for ( int i = 1 ; i < snData.nDegU ; ++ i) {
|
||||
if ( abs( snData.vU[i] - snData.vU[0]) >= EPS_ZERO)
|
||||
bOk = false ;
|
||||
@@ -136,7 +138,7 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
|
||||
if ( abs( snData.vU[nU - 1 - i] - snData.vU[nU - 1]) >= EPS_ZERO)
|
||||
bOk = false ;
|
||||
}
|
||||
// direzione V
|
||||
// direzione V
|
||||
for ( int i = 1 ; i < snData.nDegV ; ++ i) {
|
||||
if ( abs( snData.vV[i] - snData.vV[0]) >= EPS_ZERO)
|
||||
bOk = false ;
|
||||
@@ -148,8 +150,8 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
|
||||
if ( ! bOk)
|
||||
return nullptr ;
|
||||
|
||||
// algoritmo 5.7 del libro "The NURBS book"//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// creazione delle strips nella direzione U ( trasformo le curve iso con U costante in bezier)
|
||||
// algoritmo 5.7 del libro "The NURBS book"
|
||||
// creazione delle strips nella direzione U ( trasformo le curve iso con U costante in bezier)
|
||||
int a = snData.nDegU - 1 ;
|
||||
int b = snData.nDegU ;
|
||||
int nb = 0 ; // numero di strisce in U ( lunghezza con U costante)
|
||||
@@ -164,14 +166,14 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
|
||||
DBLVECTOR vAlpha ;
|
||||
vAlpha.resize( snData.nDegU - 1) ;
|
||||
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 ) {
|
||||
mBC[i][row] = snData.mCP[i][row] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
mW[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)
|
||||
++ b ;
|
||||
int mult = b - i + 1 ;
|
||||
if ( mult < snData.nDegU ) {
|
||||
if ( mult < snData.nDegU) {
|
||||
bRef = true ;
|
||||
// calcolo numeratore e alpha
|
||||
double numer = snData.vU[b] - snData.vU[a] ;
|
||||
for ( int j = snData.nDegU ; j > mult ; -- j)
|
||||
vAlpha[j-mult-1] = numer / ( snData.vU[a+j] - snData.vU[a]) ;
|
||||
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 s = mult + j ;
|
||||
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) {
|
||||
mBC[k][row] = vAlpha[k-s] * mBC[k][row] + ( 1 - vAlpha[k-s]) * mBC[k-1][row] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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] ;
|
||||
@@ -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) ;
|
||||
if ( ! snData.bRat)
|
||||
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] ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
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] ;
|
||||
mW_strip[i+ nb * snData.nDegU][row] = mW[i][row] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ho finito di definire la patch di Bezier attuale e passo alla successiva
|
||||
++ 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){
|
||||
for (int i = 0 ; i < snData.nDegU - 1 ; ++ i) {
|
||||
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
|
||||
if ( ! bRef ) {
|
||||
nCPU_ref = snData.nCPU ;
|
||||
@@ -308,8 +310,8 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
|
||||
else
|
||||
nCPU_ref = snData.nDegU * nb + 1 ; // numero dei punti di controllo in U dopo il raffinamento
|
||||
|
||||
// ora ho ottenuto le strisce nDegU x nCPV
|
||||
// devo ripetere la procedura, sulla dir V, per ottenere le patch nDegU x nDegV
|
||||
// ora ho ottenuto le strisce nDegU x nCPV
|
||||
// devo ripetere la procedura, sulla dir V, per ottenere le patch nDegU x nDegV
|
||||
a = snData.nDegV - 1 ;
|
||||
b = snData.nDegV ;
|
||||
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<DBLVECTOR> mW_tot( nCPU_ref, vV1_W) ;
|
||||
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 ) {
|
||||
m_BC1[i][row] = mPC_strip[i][row] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
mW1[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 ;
|
||||
if ( mult < snData.nDegV ) {
|
||||
bRef = true ;
|
||||
// calcolo numeratore e alpha
|
||||
// calcolo numeratore e alpha
|
||||
double numer = snData.vV[b] - snData.vV[a] ;
|
||||
for ( int j = snData.nDegV ; j > mult ; -- j)
|
||||
vAlpha1[j-mult-1] = numer / ( snData.vV[a+j] - snData.vV[a]) ;
|
||||
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 s = mult + j ;
|
||||
if ( ! snData.bRat) {
|
||||
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] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
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] ;
|
||||
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 ;
|
||||
for ( int k = 0 ; k < nCPU_ref; ++k){
|
||||
for ( int k = 0 ; k < nCPU_ref; ++k) {
|
||||
mPC_tot[k].resize( nRef) ;
|
||||
mW_tot[k].resize( nRef) ;
|
||||
}
|
||||
if ( ! snData.bRat)
|
||||
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] ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for ( int i = 0 ; i < nCPU_ref ; ++i) {
|
||||
for ( int row = 0 ; row <= snData.nDegV ; ++row ) {
|
||||
mPC_tot[i][row + nc * snData.nDegV] = m_BC1[i][row]/mW1[i][row] ;
|
||||
for ( int row = 0 ; row <= snData.nDegV ; ++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] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ho finito di definire la patch di Bezier attuale e passo alla successiva
|
||||
++ 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){
|
||||
for (int i = 0 ; i < nCPU_ref ; ++ i) {
|
||||
for ( int row = 0 ; row < snData.nDegV - 1 ; ++row) {
|
||||
@@ -450,7 +452,7 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
|
||||
++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
|
||||
if ( ! bRef) {
|
||||
nCPV_ref = snData.nCPV ;
|
||||
@@ -477,7 +479,7 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
|
||||
else
|
||||
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()) ;
|
||||
if ( IsNull( pSrfBz))
|
||||
return nullptr ;
|
||||
@@ -498,3 +500,180 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
|
||||
}
|
||||
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 ;
|
||||
}
|
||||
|
||||
+1728
-99
File diff suppressed because it is too large
Load Diff
+42
-2
@@ -22,6 +22,8 @@
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
#include "/EgtDev/Include/EGkGeoCollection.h"
|
||||
|
||||
using namespace std ;
|
||||
class Tree ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
@@ -87,7 +89,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
bool SetControlPoint( int nIndU, int nIndV, const Point3d& ptCtrl, double dW) override
|
||||
{ return SetControlPoint( GetInd( nIndU, nIndV), ptCtrl, dW) ; }
|
||||
bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ;
|
||||
bool SetTrimRegion( const ISurfFlatRegion& sfrTrimReg) override ;
|
||||
bool SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtract = true) override ;
|
||||
SurfFlatRegion* GetTrimRegion( void) const override ;
|
||||
bool GetInfo( int& nDegU, int& nDegV, int& nSpanU, int& nSpanV, bool& bIsRat, bool& bTrimmed) const override ;
|
||||
const Point3d& GetControlPoint( int nIndU, int nIndV, bool* pbOk) const override
|
||||
@@ -111,12 +113,38 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ;
|
||||
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
|
||||
const SurfTriMesh* GetAuxSurf( void) const override ;
|
||||
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.
|
||||
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
|
||||
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ;
|
||||
// funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier
|
||||
// a nIL si può passare 5 come valore di default
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ;
|
||||
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ;
|
||||
// restituisce il corrispettivo parametrico di un punto qualunque della trimesh associata alla superficie
|
||||
// ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie
|
||||
// pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato
|
||||
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ;
|
||||
// pPlCut è il piano di taglio su cui giace la curva
|
||||
bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC, const Plane3d* pPlCut) const override ;
|
||||
// funzione per tagliare una superficie di bezier con un piano ( cancello la parte dal lato positivo della normale del piano).
|
||||
// bSaveOnEq indica se tenere i triangoli (della trimesh associata) che sono sul piano
|
||||
bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ;
|
||||
// funzioni per incrementare le coordinate restando dentro lo spazio parametrico
|
||||
bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ;
|
||||
bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ;
|
||||
// funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier
|
||||
// se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate
|
||||
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ;
|
||||
bool IsPlanar( void) const override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
SurfBezier( void) ;
|
||||
@@ -131,7 +159,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
enum ParDir { ON_U = 1, ON_V = 2} ;
|
||||
static const int MAXDEG = 11 ;
|
||||
static const int MAXDEG = 21 ;
|
||||
|
||||
private :
|
||||
bool CopyFrom( const SurfBezier& sbSrc) ;
|
||||
@@ -159,6 +187,13 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
bool GetCurveOnV( double dU, int nStep, PolyLine& plCrvV) const ;
|
||||
double GetCurveOnUApproxLen( double dV) const ;
|
||||
double GetCurveOnVApproxLen( double dU) const ;
|
||||
// funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico)
|
||||
bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ;
|
||||
// restituisce il singolo edge della superficie non trimmata
|
||||
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
|
||||
bool UpdateEdgesFromTree( Tree& tr) const ;
|
||||
// funzione che calcola se gli edge sono collassati in poli
|
||||
bool CalcPoles( void) ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
@@ -170,11 +205,16 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
int m_nSpanV ; // numero di pezze in V
|
||||
bool m_bRat ; // flag di razionale/polinomiale
|
||||
bool m_bTrimmed ; // flag per presenza regione di trim
|
||||
mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U
|
||||
mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V
|
||||
mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli
|
||||
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
|
||||
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
|
||||
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable vector<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
|
||||
} ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
+49
-41
@@ -75,7 +75,7 @@ SurfFlatRegion::Clear( void)
|
||||
bool
|
||||
SurfFlatRegion::AddExtLoop( const ICurve& cCrv)
|
||||
{
|
||||
// verifico validità curva
|
||||
// verifico validità curva
|
||||
if ( &cCrv == nullptr)
|
||||
return false ;
|
||||
// creo una copia della curva
|
||||
@@ -146,7 +146,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
|
||||
else {
|
||||
// verifico che il piano della curva coincida con quello XY intrinseco
|
||||
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 ;
|
||||
// sistemo il senso di rotazione (deve essere CCW -> area > 0)
|
||||
if ( ( plPlane.GetVersN().z > 0 && dArea < 0) ||
|
||||
@@ -221,7 +221,7 @@ SurfFlatRegion::MyAddExtLoop( ICurve* pCrv)
|
||||
bool
|
||||
SurfFlatRegion::AddIntLoop( const ICurve& cCrv)
|
||||
{
|
||||
// verifico validità curva
|
||||
// verifico validità curva
|
||||
if ( &cCrv == nullptr)
|
||||
return false ;
|
||||
// creo una copia della curva
|
||||
@@ -288,7 +288,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
|
||||
Plane3d plPlane ;
|
||||
if ( ! pMyCrv->GetArea( plPlane, dArea))
|
||||
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 ;
|
||||
// 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))
|
||||
@@ -435,7 +435,7 @@ SurfFlatRegion::GetTitle( void) const
|
||||
bool
|
||||
SurfFlatRegion::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
||||
{
|
||||
// verifico validità regione
|
||||
// verifico validità regione
|
||||
if ( m_nStatus != OK)
|
||||
sOut += string( "Status=Invalid") + szNewLine ;
|
||||
// area
|
||||
@@ -583,7 +583,7 @@ SurfFlatRegion::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
||||
return false ;
|
||||
// reset del bbox
|
||||
b3Loc.Reset() ;
|
||||
// è il bounding box dei loop esterni
|
||||
// è il bounding box dei loop esterni
|
||||
for ( auto i : m_vExtInd) {
|
||||
BBox3d b3Tmp ;
|
||||
if ( m_vpLoop[i]->GetBBox( m_frF, b3Tmp, nFlag))
|
||||
@@ -603,7 +603,7 @@ SurfFlatRegion::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
||||
Frame3d frCompo = m_frF * frRef ;
|
||||
// reset del bbox
|
||||
b3Ref.Reset() ;
|
||||
// è il bounding box dei loop esterni
|
||||
// è il bounding box dei loop esterni
|
||||
for ( auto i : m_vExtInd) {
|
||||
BBox3d b3Tmp ;
|
||||
if ( m_vpLoop[i]->GetBBox( frCompo, b3Tmp, nFlag))
|
||||
@@ -622,8 +622,9 @@ SurfFlatRegion::Translate( const Vector3d& vtMove)
|
||||
// imposto ricalcolo della grafica
|
||||
ResetAuxSurf() ;
|
||||
m_OGrMgr.Reset() ;
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// traslo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->Translate( vtMove) ;
|
||||
// traslo il riferimento
|
||||
m_frF.Translate( vtMove) ;
|
||||
return true ;
|
||||
@@ -636,15 +637,16 @@ SurfFlatRegion::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dell'asse di rotazione
|
||||
// verifico validità dell'asse di rotazione
|
||||
if ( vtAx.IsSmall())
|
||||
return false ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
ResetAuxSurf() ;
|
||||
m_OGrMgr.Reset() ;
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
// ruoto Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
||||
|
||||
// ruoto il riferimento
|
||||
return m_frF.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
||||
@@ -673,7 +675,7 @@ SurfFlatRegion::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou
|
||||
return false ;
|
||||
}
|
||||
|
||||
// parziale scalatura del riferimento (non può essere completa)
|
||||
// parziale scalatura del riferimento (non può essere completa)
|
||||
Frame3d frTrasf = m_frF ;
|
||||
m_frF.PseudoScale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
|
||||
|
||||
@@ -712,7 +714,7 @@ SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
// verifico validità del piano di specchiatura
|
||||
// verifico validità del piano di specchiatura
|
||||
if ( vtNorm.IsSmall())
|
||||
return false ;
|
||||
|
||||
@@ -722,7 +724,7 @@ SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
|
||||
// parziale mirror del riferimento (non può essere completa)
|
||||
// parziale mirror del riferimento (non può essere completa)
|
||||
Frame3d frTrasf = m_frF ;
|
||||
m_frF.PseudoMirror( ptOn, vtNorm) ;
|
||||
|
||||
@@ -762,7 +764,7 @@ SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
// verifico validità dei parametri
|
||||
// verifico validità dei parametri
|
||||
if ( vtNorm.IsSmall() || vtDir.IsSmall())
|
||||
return false ;
|
||||
|
||||
@@ -778,7 +780,7 @@ SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector
|
||||
return false ;
|
||||
}
|
||||
|
||||
// parziale scorrimento del riferimento (non può essere completa)
|
||||
// parziale scorrimento del riferimento (non può essere completa)
|
||||
Frame3d frTrasf = m_frF ;
|
||||
m_frF.PseudoShear( ptOn, vtNorm, vtDir, dCoeff) ;
|
||||
|
||||
@@ -832,19 +834,21 @@ SurfFlatRegion::ToGlob( const Frame3d& frRef)
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se frame identità, non devo fare alcunché
|
||||
// se frame identità, non devo fare alcunché
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
ResetAuxSurf() ;
|
||||
m_OGrMgr.Reset() ;
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->ToGlob( frRef) ;
|
||||
|
||||
// trasformo il riferimento
|
||||
return m_frF.ToGlob( frRef) ; ;
|
||||
@@ -857,19 +861,21 @@ SurfFlatRegion::ToLoc( const Frame3d& frRef)
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità del frame
|
||||
// verifico validità del frame
|
||||
if ( frRef.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se frame identità, non devo fare alcunché
|
||||
// se frame identità, non devo fare alcunché
|
||||
if ( IsGlobFrame( frRef))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
ResetAuxSurf() ;
|
||||
m_OGrMgr.Reset() ;
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->ToLoc( frRef) ;
|
||||
|
||||
// trasformo il riferimento
|
||||
return m_frF.ToLoc( frRef) ; ;
|
||||
@@ -882,19 +888,21 @@ SurfFlatRegion::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
// verifico validità dei frame
|
||||
// verifico validità dei frame
|
||||
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
|
||||
return false ;
|
||||
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
// se i due riferimenti coincidono, non devo fare alcunché
|
||||
if ( AreSameFrame( frOri, frDest))
|
||||
return true ;
|
||||
|
||||
// imposto ricalcolo della grafica
|
||||
ResetAuxSurf() ;
|
||||
m_OGrMgr.Reset() ;
|
||||
// imposto ricalcolo Voronoi
|
||||
ResetVoronoiObject() ;
|
||||
|
||||
// trasformo Voronoi
|
||||
if ( m_pVoronoiObj != nullptr)
|
||||
m_pVoronoiObj->LocToLoc( frOri, frDest) ;
|
||||
|
||||
// trasformo il riferimento
|
||||
return m_frF.LocToLoc( frOri, frDest) ; ;
|
||||
@@ -978,7 +986,7 @@ SurfFlatRegion::GetCentroid( Point3d& ptCen) const
|
||||
return false ;
|
||||
// medio il centro
|
||||
ptCen /= dArea ;
|
||||
// lo porto dal riferimento intrinseco a quello in cui è immersa l'entità
|
||||
// lo porto dal riferimento intrinseco a quello in cui è immersa l'entità
|
||||
ptCen.ToGlob( m_frF) ;
|
||||
return true ;
|
||||
}
|
||||
@@ -997,7 +1005,7 @@ SurfFlatRegion::GetChunkCentroid( int nChunk, Point3d& ptCen) const
|
||||
const ICurve* pCrv = GetMyLoop( nChunk, 0) ;
|
||||
if ( pCrv == nullptr || ! pCrv->GetCentroid( ptCen))
|
||||
return false ;
|
||||
// lo porto dal riferimento intrinseco a quello in cui è immersa l'entità
|
||||
// lo porto dal riferimento intrinseco a quello in cui è immersa l'entità
|
||||
ptCen.ToGlob( m_frF) ;
|
||||
return true ;
|
||||
}
|
||||
@@ -1023,7 +1031,7 @@ SurfFlatRegion::GetLoopCount( int nChunk) const
|
||||
int nChunkMax = int( m_vExtInd.size()) - 1 ;
|
||||
if ( nChunk < 0 || nChunk > nChunkMax)
|
||||
return 0 ;
|
||||
// se non è l'ultimo Chunk
|
||||
// se non è l'ultimo Chunk
|
||||
if ( nChunk < nChunkMax)
|
||||
return ( m_vExtInd[nChunk+1] - m_vExtInd[nChunk]) ;
|
||||
// altrimenti
|
||||
@@ -1053,7 +1061,7 @@ SurfFlatRegion::GetChunkLoopFromInd( int nInd, int& nChunk, int& nLoop) const
|
||||
// valori non validi
|
||||
nChunk = - 1 ;
|
||||
nLoop = - 1 ;
|
||||
// verifico validità di nInd
|
||||
// verifico validità di nInd
|
||||
if ( nInd < 0 || nInd >= int( m_vpLoop.size()))
|
||||
return false ;
|
||||
// verifica esistenza array di chunks
|
||||
@@ -1105,7 +1113,7 @@ SurfFlatRegion::GetLoop( int nChunk, int nLoop) const
|
||||
return nullptr ;
|
||||
// assegno la normale alla regione come estrusione
|
||||
pCrv->SetExtrusion( Z_AX) ;
|
||||
// la porto nel riferimento in cui è inserito l'oggetto
|
||||
// la porto nel riferimento in cui è inserito l'oggetto
|
||||
pCrv->ToGlob( m_frF) ;
|
||||
return pCrv ;
|
||||
}
|
||||
@@ -1121,7 +1129,7 @@ SurfFlatRegion::ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, doub
|
||||
// ne creo una approssimazione
|
||||
if ( ! pMyCrv->ApproxWithLines( dLinTol, dAngTolDeg, nType, PL))
|
||||
return false ;
|
||||
// la porto nel riferimento in cui è inserito l'oggetto
|
||||
// la porto nel riferimento in cui è inserito l'oggetto
|
||||
PL.ToGlob( m_frF) ;
|
||||
return true ;
|
||||
}
|
||||
@@ -1174,7 +1182,7 @@ SurfFlatRegion::GetAuxSurf( void) const
|
||||
// la superficie deve essere validata
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return nullptr ;
|
||||
// se già calcolata, la restituisco
|
||||
// se già calcolata, la restituisco
|
||||
if ( m_pSTM != nullptr)
|
||||
return m_pSTM ;
|
||||
// la creo e la salvo
|
||||
@@ -1222,7 +1230,7 @@ SurfFlatRegion::CloneChunk( int nChunk) const
|
||||
bool
|
||||
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
|
||||
{
|
||||
// la curva deve già essere nel riferimento intrinseco della regione
|
||||
// la curva deve già essere nel riferimento intrinseco della regione
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK || m_vpLoop.empty())
|
||||
return false ;
|
||||
@@ -1254,7 +1262,7 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRV
|
||||
for ( auto& ccOne : ccPart) {
|
||||
switch ( ccOne.nClass) {
|
||||
case CRVC_IN :
|
||||
// IN è Remove degli altri
|
||||
// IN è Remove degli altri
|
||||
break ;
|
||||
case CRVC_OUT :
|
||||
// intervallo standard
|
||||
@@ -1383,7 +1391,7 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
|
||||
if ( ! AreSameVectorApprox( m_frF.VersZ(), Reg2.m_frF.VersZ()))
|
||||
return REGC_NULL ;
|
||||
|
||||
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
||||
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
||||
const ICurve* pCrv1Loc = GetMyLoop( nChunk, 0) ;
|
||||
|
||||
// curva esterna del chunk della seconda regione in locale nel riferimento intrinseco della prima
|
||||
@@ -1453,7 +1461,7 @@ SurfFlatRegion::ResetVoronoiObject() const
|
||||
bool
|
||||
SurfFlatRegion::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound) const
|
||||
{
|
||||
// verifico se è stato calcolato
|
||||
// verifico se è stato calcolato
|
||||
if ( m_pVoronoiObj == nullptr)
|
||||
if ( ! CalcVoronoiObject())
|
||||
return false ;
|
||||
@@ -1465,7 +1473,7 @@ SurfFlatRegion::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound) const
|
||||
bool
|
||||
SurfFlatRegion::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const
|
||||
{
|
||||
// verifico se è stato calcolato
|
||||
// verifico se è stato calcolato
|
||||
if ( m_pVoronoiObj == nullptr)
|
||||
if ( ! CalcVoronoiObject())
|
||||
return false ;
|
||||
|
||||
+8
-5
@@ -96,7 +96,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
{ return m_frF.VersZ() ; }
|
||||
int GetChunkCount( void) const override ;
|
||||
int GetLoopCount( int nChunk) const override ;
|
||||
ICurve* GetLoop( int nChunk, int nLoop) const override ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
|
||||
ICurve* GetLoop( int nChunk, int nLoop) const override ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
|
||||
bool ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ;
|
||||
const SurfTriMesh* GetAuxSurf( void) const override ;
|
||||
SurfFlatRegion* CloneChunk( int nChunk) const override ;
|
||||
@@ -104,12 +104,16 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ;
|
||||
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
|
||||
bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = 3) const override ;
|
||||
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;
|
||||
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;
|
||||
void ResetVoronoiObject( void) const override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool PostSave( GdbGeo& Wrapper) const override { return true ; }
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override { return true ; }
|
||||
|
||||
public :
|
||||
SurfFlatRegion( void) ;
|
||||
@@ -139,7 +143,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
int GetIndFromChunkLoop( int nChunk, int nLoop) const ;
|
||||
bool GetChunkLoopFromInd( int nInd, int& nChunk, int& nLoop) const ;
|
||||
ICurve* GetMyLoop( int nInd) const ; // indice nel vettore di tutti i loop
|
||||
ICurve* GetMyLoop( int nChunk, int nLoop) const ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
|
||||
ICurve* GetMyLoop( int nChunk, int nLoop) const ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
|
||||
void ResetAuxSurf( void) const ;
|
||||
bool ConvertArcsToBezierCurves( void) ;
|
||||
bool MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const ;
|
||||
@@ -149,7 +153,6 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
static SurfFlatRegion* MyNewSurfFromLoops( PCRV_DEQUE& vpLoop) ;
|
||||
static bool MyTestAndDelete( PCRV_DEQUE& vpCrv) ;
|
||||
bool CalcVoronoiObject( void) const ;
|
||||
void ResetVoronoiObject( void) const ;
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
@@ -158,7 +161,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
Frame3d m_frF ; // riferimento intrinseco
|
||||
PCRV_DEQUE m_vpLoop ; // deque delle curve che formano i loop
|
||||
INTVECTOR m_vExtInd ; // indice dei loop esterni nel precedente vettore
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
mutable Voronoi* m_pVoronoiObj ; // Voronoi
|
||||
|
||||
|
||||
+24
-46
@@ -16,6 +16,7 @@
|
||||
#include "GeoConst.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "AdjustLoops.h"
|
||||
#include "Voronoi.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
@@ -36,7 +37,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
if ( nChunk == 0)
|
||||
return nullptr ;
|
||||
|
||||
// se offset nullo, la nuova regione è la copia di quella attuale
|
||||
// se offset nullo, la nuova regione è la copia di quella attuale
|
||||
if ( abs( dDist) < 10 * EPS_SMALL)
|
||||
return this->Clone() ;
|
||||
|
||||
@@ -70,7 +71,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
while ( bOk && ! IsNull( pOffs)) {
|
||||
if ( pOffs->GetType() == CRV_COMPO) {
|
||||
CurveComposite* pOffsCompo = GetBasicCurveComposite( pOffs) ;
|
||||
// assegno proprietà
|
||||
// assegno proprietà
|
||||
pOffsCompo->SetTempProp( j, 1) ;
|
||||
for ( int k = 0 ; k < pOffsCompo->GetCurveCount() ; ++k)
|
||||
pOffsCompo->SetCurveTempProp( k, j, 1) ;
|
||||
@@ -80,7 +81,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
}
|
||||
else
|
||||
pOffs->SetTempProp( j, 1) ;
|
||||
// se prima curva esterna, è il primo contorno esterno della nuova regione
|
||||
// se prima curva esterna, è il primo contorno esterno della nuova regione
|
||||
if ( j == 0 && bFirstCurve) {
|
||||
if ( ! pSfrChk->AddExtLoop( Release( pOffs)))
|
||||
return nullptr ;
|
||||
@@ -137,7 +138,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
|
||||
// -------------------- OFFSET CON VORONOI -------------------------------------
|
||||
else {
|
||||
// verifico se oggetto Voronoi della superficie è definito
|
||||
// verifico se oggetto Voronoi della superficie è definito
|
||||
if ( m_pVoronoiObj == nullptr)
|
||||
CalcVoronoiObject() ;
|
||||
|
||||
@@ -146,51 +147,28 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
|
||||
if ( ! m_pVoronoiObj->CalcOffset( vOffs, dDist, nType))
|
||||
return nullptr ;
|
||||
|
||||
// costruisco la superficie
|
||||
if ( vOffs.size() > 0) {
|
||||
BOOLVECTOR vbAddOrSub( vOffs.size(), true) ;
|
||||
int nFirstId = -1 ;
|
||||
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) {
|
||||
// porto nel frame della flat region
|
||||
PCRV_DEQUE vLoops ;
|
||||
for ( int i = 0 ; i < int( vOffs.size()) ; i ++) {
|
||||
vOffs[i]->ToLoc( m_frF) ;
|
||||
// calcolo orientamento della curva
|
||||
double dAreaXY ;
|
||||
if ( ! vOffs[i]->GetAreaXY( dAreaXY))
|
||||
return nullptr ;
|
||||
vbAddOrSub[i] = ( dAreaXY > SQ_EPS_SMALL) ;
|
||||
// verifico se è il primo loop esterno
|
||||
if ( nFirstId == -1 && vbAddOrSub[i])
|
||||
nFirstId = i ;
|
||||
}
|
||||
|
||||
// inizializzo la superficie
|
||||
if ( nFirstId != -1 && ! pSfr->AddExtLoop( Release( vOffs[nFirstId])))
|
||||
return nullptr ;
|
||||
if ( pSfr->IsValid()) {
|
||||
|
||||
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) {
|
||||
// verifico non sia il primo loop esterno
|
||||
if ( i == nFirstId)
|
||||
continue ;
|
||||
// costruisco la superficie associata
|
||||
PtrOwner<SurfFlatRegion> pSrfCrv( CreateBasicSurfFlatRegion()) ;
|
||||
if ( IsNull( pSrfCrv) || ! pSrfCrv->AddExtLoop( Release( vOffs[i])))
|
||||
return nullptr ;
|
||||
if ( ! pSrfCrv->IsValid())
|
||||
continue ;
|
||||
|
||||
// aggiungo o sottraggo
|
||||
if ( vbAddOrSub[i]) {
|
||||
if ( ! pSfr->Add( *pSrfCrv))
|
||||
return nullptr ;
|
||||
}
|
||||
else {
|
||||
pSrfCrv->Invert() ;
|
||||
if ( ! pSfr->Subtract( *pSrfCrv))
|
||||
return nullptr ;
|
||||
}
|
||||
// rimuovo eventuali sovrapposizioni
|
||||
ICURVEPLIST CrvLst ;
|
||||
AdjustLoops( Release( vOffs[i]), CrvLst, true) ;
|
||||
for ( auto pCrv : CrvLst) {
|
||||
pCrv->SetExtrusion( Z_AX) ;
|
||||
vLoops.emplace_back( pCrv) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// verifico di avere ancora dei loops
|
||||
if ( vLoops.size() > 0) {
|
||||
pSfr.Set( MyNewSurfFromLoops( vLoops)) ;
|
||||
if ( IsNull( pSfr)) {
|
||||
MyTestAndDelete( vLoops) ;
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,7 +185,7 @@ SurfFlatRegion::Offset( double dDist, int nType)
|
||||
if ( nChunk == 0)
|
||||
return false ;
|
||||
|
||||
// se offset nullo, non devo fare alcunchè
|
||||
// se offset nullo, non devo fare alcunchè
|
||||
if ( abs( dDist) < 10 * EPS_SMALL)
|
||||
return true ;
|
||||
|
||||
|
||||
+390
-31
@@ -16,15 +16,18 @@
|
||||
#include "stdafx.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "GeoObjFactory.h"
|
||||
#include "GdbGeo.h"
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "Triangulate.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkPointGrid3d.h"
|
||||
#include "/EgtDev/Include/EGkPolygon3d.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
@@ -41,8 +44,9 @@ GEOOBJ_REGISTER( SRF_TRIMESH, NGE_S_TRM, SurfTriMesh) ;
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh::SurfTriMesh( void)
|
||||
: m_nStatus( TO_VERIFY), m_dLinTol( STM_STD_LIN_TOL), m_dBoundaryAng( STM_STD_BOUNDARY_ANG),
|
||||
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bOriented( false), m_bClosed( false), m_bFaceted( false), m_bFacEdged( false),
|
||||
m_nTimeStamp( 0), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_nMaxTFlag( 0), m_nParts( -1), m_pHGrd3d( nullptr)
|
||||
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bShowEdges( false), m_bOriented( false), m_bClosed( false),
|
||||
m_bFaceted( false), m_bFacEdged( false), m_nTimeStamp( 0), m_nTempProp{0,0}, m_dTempParam{0,0},
|
||||
m_nMaxTFlag( 0), m_nParts( -1), m_nShells( -1), m_pHGrd3d( nullptr)
|
||||
{
|
||||
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
|
||||
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
|
||||
@@ -59,7 +63,7 @@ bool
|
||||
SurfTriMesh::Init( int nNumVert, int nNumTria, int nNumFacet)
|
||||
{
|
||||
// imposto ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
m_OGrMgr.Clear() ;
|
||||
ResetHashGrids3d() ;
|
||||
// se superficie vuota
|
||||
if ( nNumVert == 0 && nNumTria == 0 && nNumFacet == 0)
|
||||
@@ -82,6 +86,7 @@ SurfTriMesh::Init( int nNumVert, int nNumTria, int nNumFacet)
|
||||
m_bClosed = false ;
|
||||
m_nMaxTFlag = 0 ;
|
||||
m_nParts = -1 ;
|
||||
m_nShells = -1 ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -91,6 +96,12 @@ bool
|
||||
SurfTriMesh::Clear( void)
|
||||
{
|
||||
m_nStatus = OK ;
|
||||
m_dLinTol = STM_STD_LIN_TOL ;
|
||||
m_dBoundaryAng = STM_STD_BOUNDARY_ANG ;
|
||||
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
|
||||
m_dSmoothAng = STM_STD_SMOOTH_ANG ;
|
||||
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
|
||||
m_bShowEdges = false ;
|
||||
m_bOriented = false ;
|
||||
m_bClosed = false ;
|
||||
m_bFaceted = false ;
|
||||
@@ -98,9 +109,16 @@ SurfTriMesh::Clear( void)
|
||||
m_vVert.clear() ;
|
||||
m_vTria.clear() ;
|
||||
m_vFacet.clear() ;
|
||||
m_OGrMgr.Clear() ;
|
||||
ResetHashGrids3d() ;
|
||||
m_nTimeStamp = 0 ;
|
||||
m_nTempProp[0] = 0 ;
|
||||
m_nTempProp[1] = 0 ;
|
||||
m_dTempParam[0] = 0 ;
|
||||
m_dTempParam[1] = 0 ;
|
||||
m_nMaxTFlag = 0 ;
|
||||
m_nParts = -1 ;
|
||||
m_nShells = -1 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -111,6 +129,7 @@ SurfTriMesh::AddVertex( const Point3d& ptVert, double dU, double dV)
|
||||
// imposto ricalcolo
|
||||
m_nStatus = TO_VERIFY ;
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = -1 ;
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
// inserisco il vertice
|
||||
@@ -142,6 +161,7 @@ SurfTriMesh::MoveVertex( int nInd, const Point3d& ptNewVert)
|
||||
// imposto ricalcolo
|
||||
m_nStatus = TO_VERIFY ;
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = - 1 ;
|
||||
m_bFaceted = false ;
|
||||
m_bFacEdged = false ;
|
||||
m_OGrMgr.Reset() ;
|
||||
@@ -211,6 +231,7 @@ SurfTriMesh::AddTriangle( const int nIdVert[3], int nTFlag)
|
||||
// imposto ricalcolo
|
||||
m_nStatus = TO_VERIFY ;
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = -1 ;
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
// inserisco il triangolo
|
||||
@@ -302,6 +323,7 @@ SurfTriMesh::RemoveTriangle( int nId)
|
||||
m_bFacEdged = false ;
|
||||
// invalido calcolo connettività
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = -1 ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -875,7 +897,7 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::CloneTriangle( int nT) const
|
||||
{
|
||||
// verifico validit� superficie ed esistenza del triangolo
|
||||
// verifico validità superficie ed esistenza del triangolo
|
||||
if ( ! IsValid() || nT < 0 || nT >= GetTriangleSize() || m_vTria[nT].nIdVert[0] == SVT_DEL)
|
||||
return nullptr ;
|
||||
|
||||
@@ -891,6 +913,7 @@ SurfTriMesh::CloneTriangle( int nT) const
|
||||
pSurfTM->m_dSmoothAng = m_dSmoothAng ;
|
||||
pSurfTM->m_dCosSmAng = m_dCosSmAng ;
|
||||
pSurfTM->m_nParts = 1 ;
|
||||
pSurfTM->m_nShells = 1 ;
|
||||
|
||||
// Copio il triangolo
|
||||
int nNewInd[3] = { pSurfTM->AddVertex( m_vVert[m_vTria[nT].nIdVert[0]].ptP),
|
||||
@@ -982,7 +1005,7 @@ SurfTriMesh::GetLoops( POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongLoop( nT, 1, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 0 � di contorno
|
||||
// se il lato 0 è di contorno
|
||||
else if ( nAdjT[0] == SVT_NULL) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
@@ -994,7 +1017,7 @@ SurfTriMesh::GetLoops( POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongLoop( nT, 1, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 1 � di contorno
|
||||
// se il lato 1 è di contorno
|
||||
else if ( nAdjT[1] == SVT_NULL) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
@@ -1006,7 +1029,7 @@ SurfTriMesh::GetLoops( POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongLoop( nT, 2, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// se il lato 2 � di contorno
|
||||
// se il lato 2 è di contorno
|
||||
else if ( nAdjT[2] == SVT_NULL) {
|
||||
// ho trovato l'inizio di un loop
|
||||
vPL.emplace_back() ;
|
||||
@@ -1018,7 +1041,7 @@ SurfTriMesh::GetLoops( POLYLINEVECTOR& vPL) const
|
||||
if ( ! MarchAlongLoop( nT, 0, m_nTimeStamp, vPL.back()))
|
||||
return false ;
|
||||
}
|
||||
// altrimenti non c'� contorno
|
||||
// altrimenti non c'è contorno
|
||||
else {
|
||||
// marco il triangolo come verificato
|
||||
m_vTria[nT].nTemp = m_nTimeStamp ;
|
||||
@@ -1034,10 +1057,16 @@ bool
|
||||
SurfTriMesh::MarchAlongLoop( int nT, int nV, int nTimeStamp, PolyLine& PL) const
|
||||
{
|
||||
// mi muovo lungo il loop, un triangolo alla volta
|
||||
int nCount = 0 ;
|
||||
bool bEnd = false ;
|
||||
while ( ! bEnd) {
|
||||
// altro triangolo
|
||||
if ( ! MarchOneTria( nT, nV, nTimeStamp, PL, bEnd))
|
||||
return false ;
|
||||
// per evitare loop infiniti
|
||||
++ nCount ;
|
||||
if ( nCount > 3 * int( m_vTria.size()) + 10)
|
||||
return true ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
@@ -1063,10 +1092,10 @@ SurfTriMesh::MarchOneTria( int& nT, int& nV, int nTimeStamp,
|
||||
return false ;
|
||||
// vertice di fine adiacenza e indice del successivo lato
|
||||
int nAdjV = Next( nAdjS) ;
|
||||
// verifico se il lato successivo � un bordo
|
||||
// verifico se il lato successivo è un bordo
|
||||
int nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ;
|
||||
if ( nNextT == SVT_NULL) {
|
||||
// se gi� recuperato
|
||||
// se già recuperato
|
||||
if ( m_vTria[nAdjT].nTemp == nTimeStamp) {
|
||||
bEnd = true ;
|
||||
return true ;
|
||||
@@ -1157,6 +1186,78 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR& vPL, bool bAllTria) const
|
||||
{
|
||||
// Verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// Verifico la direzione
|
||||
Vector3d vtVers = plPlane.GetVersN() ;
|
||||
if ( ! vtVers.Normalize())
|
||||
return false ;
|
||||
|
||||
// Controlli su tolleranza
|
||||
dTol = max( dTol, 100 * EPS_SMALL) ;
|
||||
|
||||
// Determino il riferimento di proiezione
|
||||
Frame3d frOCS ; frOCS.Set( plPlane.GetPoint(), vtVers) ;
|
||||
|
||||
// Ottengo la Silhouette come unione delle regioni dei triangoli proiettati (solo parti sopra il piano)
|
||||
// calcolo la regione dei triangoli proiettati
|
||||
PtrOwner<SurfFlatRegion> pSfr ;
|
||||
Triangle3d Tria ;
|
||||
int nT = GetFirstTriangle( Tria) ;
|
||||
while ( nT != SVT_NULL) {
|
||||
// verifico la normale
|
||||
if ( ( bAllTria && abs( Tria.GetN() * vtVers) > EPS_ZERO) ||
|
||||
( ! bAllTria && Tria.GetN() * vtVers > EPS_ZERO)) {
|
||||
// ricavo il poligono equivalente al triangolo
|
||||
Polygon3d pgTria ;
|
||||
pgTria.FromTriangle( Tria) ;
|
||||
// taglio il poligono con il piano
|
||||
pgTria.Trim( plPlane, false, true, bAllTria) ;
|
||||
// se rimasto qualcosa
|
||||
if ( pgTria.GetSideCount() > 0) {
|
||||
// lo proietto sul piano e creo la regione
|
||||
pgTria.Scale( frOCS, 1, 1, 0) ;
|
||||
PtrOwner<SurfFlatRegion> pSfrTria( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLine( pgTria.GetPolyLine()))) ;
|
||||
if ( ! IsNull( pSfrTria)) {
|
||||
if ( bAllTria && Tria.GetN() * vtVers < 0)
|
||||
pSfrTria->Invert() ;
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
pSfr->Add( *pSfrTria) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// passo al successivo
|
||||
nT = GetNextTriangle( nT, Tria) ;
|
||||
}
|
||||
|
||||
// Se non esiste la regione
|
||||
if ( IsNull( pSfr))
|
||||
return false ;
|
||||
|
||||
// Effettuo contro-offset
|
||||
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||
|
||||
// Recupero i contorni della regione
|
||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
|
||||
PolyLine PL ;
|
||||
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
vPL.emplace_back( PL) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::Clone( void) const
|
||||
@@ -1197,6 +1298,7 @@ SurfTriMesh::CopyFrom( const SurfTriMesh& stmSrc)
|
||||
m_dCosBndAng = stmSrc.m_dCosBndAng ;
|
||||
m_dSmoothAng = stmSrc.m_dSmoothAng ;
|
||||
m_dCosSmAng = stmSrc.m_dCosSmAng ;
|
||||
m_bShowEdges = stmSrc.m_bShowEdges ;
|
||||
m_bOriented = stmSrc.m_bOriented ;
|
||||
m_bClosed = stmSrc.m_bClosed ;
|
||||
m_bFaceted = stmSrc.m_bFaceted ;
|
||||
@@ -1210,6 +1312,7 @@ SurfTriMesh::CopyFrom( const SurfTriMesh& stmSrc)
|
||||
m_nTempProp[1] = stmSrc.m_nTempProp[1] ;
|
||||
m_nMaxTFlag = stmSrc.m_nMaxTFlag ;
|
||||
m_nParts = stmSrc.m_nParts ;
|
||||
m_nShells = stmSrc.m_nShells ;
|
||||
m_dTempParam[0] = stmSrc.m_dTempParam[0] ;
|
||||
m_dTempParam[1] = stmSrc.m_dTempParam[1] ;
|
||||
return true ;
|
||||
@@ -1247,10 +1350,12 @@ SurfTriMesh::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
||||
// segnalo eventuale incongruenza di orientamento
|
||||
if ( ! m_bOriented)
|
||||
sOut += string( "Inconsistent Orientation") + szNewLine ;
|
||||
// segnalo numero di parti se più di una
|
||||
// segnalo numero di parti
|
||||
int nParts = GetPartCount() ;
|
||||
if ( nParts > 1)
|
||||
sOut += string( "Parts =") + ToString( nParts) + szNewLine ;
|
||||
sOut += string( "Parts=") + ToString( nParts) + szNewLine ;
|
||||
// segnalo numero di gusci
|
||||
int nShells = GetShellCount() ;
|
||||
sOut += string( "Shells=") + ToString( nShells) + szNewLine ;
|
||||
// numero di vertici
|
||||
sOut += "Vert : Nbr=" + ToString( GetVertexCount()) +
|
||||
" Size=" + ToString( GetVertexSize()) + szNewLine ;
|
||||
@@ -1332,14 +1437,36 @@ SurfTriMesh::Save( NgeWriter& ngeOut) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::PreSave( GdbGeo& Wrapper) const
|
||||
{
|
||||
// salvo il flag di visualizzazione spigoli vivi anche in shading (default false)
|
||||
if ( m_bShowEdges)
|
||||
Wrapper.SetInfo( GDB_SI_SHOWEDGES, true) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::PostSave( GdbGeo& Wrapper) const
|
||||
{
|
||||
// elimino eventuali info aggiunte nella PreSave
|
||||
Wrapper.RemoveInfo( GDB_SI_SHOWEDGES) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::Load( NgeReader& ngeIn)
|
||||
{
|
||||
// imposto ricalcolo della grafica, della connessione e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
m_OGrMgr.Clear() ;
|
||||
m_nMaxTFlag = 0 ;
|
||||
m_nParts = -1 ;
|
||||
m_nShells = -1 ;
|
||||
ResetHashGrids3d() ;
|
||||
// leggo la prossima linea ( 2 parametri : dLinTol e dSmoothAng)
|
||||
// tolleranza lineare di costruzione
|
||||
@@ -1434,6 +1561,20 @@ SurfTriMesh::Load( NgeReader& ngeIn)
|
||||
return Validate() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::PostLoad( GdbGeo& Wrapper)
|
||||
{
|
||||
// recupero eventuale flag di visualizzazione spigoli vivi anche in shading
|
||||
bool bVal ;
|
||||
if ( Wrapper.GetInfo( GDB_SI_SHOWEDGES, bVal)) {
|
||||
m_bShowEdges = bVal ;
|
||||
Wrapper.RemoveInfo( GDB_SI_SHOWEDGES) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::Validate( bool bCorrect)
|
||||
@@ -1486,6 +1627,7 @@ SurfTriMesh::Validate( bool bCorrect)
|
||||
|
||||
// invalido calcolo connessione
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = -1 ;
|
||||
|
||||
return ( m_nStatus == OK) ;
|
||||
}
|
||||
@@ -1761,6 +1903,7 @@ SurfTriMesh::AdjustTopology( void)
|
||||
m_bFacEdged = false ;
|
||||
// invalido calcolo connessione
|
||||
m_nParts = - 1 ;
|
||||
m_nShells = - 1 ;
|
||||
// verifica indici
|
||||
if ( ! Validate( true))
|
||||
return false ;
|
||||
@@ -3194,7 +3337,6 @@ SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double
|
||||
bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ;
|
||||
|
||||
// aggiorno le facce
|
||||
bool bRecalc = ( abs( dCoeffX) < EPS_ZERO || abs( dCoeffY) < EPS_ZERO || abs( dCoeffZ) < EPS_ZERO) ;
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL) {
|
||||
// se c'è mirror, devo invertire la faccia
|
||||
@@ -3204,15 +3346,12 @@ SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double
|
||||
if ( ! CalcTriangleNormal( i)) {
|
||||
// elimino il triangolo
|
||||
RemoveTriangle( i) ;
|
||||
// richiedo ricalcolo vertici e topologia
|
||||
bRecalc = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( bRecalc)
|
||||
return DoCompacting() ;
|
||||
|
||||
return true ;
|
||||
return DoCompacting() ;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -3516,6 +3655,17 @@ SurfTriMesh::GetPartCount( void) const
|
||||
return m_nParts ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
int
|
||||
SurfTriMesh::GetShellCount( void) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return 0 ;
|
||||
if ( m_nShells == - 1 && ! VerifyConnection())
|
||||
return 0 ;
|
||||
return m_nShells ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::VerifyConnection( void) const
|
||||
@@ -3524,19 +3674,21 @@ SurfTriMesh::VerifyConnection( void) const
|
||||
return false ;
|
||||
|
||||
// reset connessione
|
||||
for ( auto Tria : m_vTria)
|
||||
for ( auto& Tria : m_vTria) {
|
||||
Tria.nPart = SVT_NULL ;
|
||||
Tria.nShell = SVT_NULL ;
|
||||
}
|
||||
|
||||
// ciclo sui triangoli
|
||||
m_nParts = 0 ;
|
||||
// ciclo sui triangoli per determinare le shells
|
||||
m_nShells = 0 ;
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// salto triangoli cancellati o gi� assegnati
|
||||
// salto triangoli cancellati o già assegnati
|
||||
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
|
||||
m_vTria[i].nPart != SVT_NULL)
|
||||
m_vTria[i].nShell != SVT_NULL)
|
||||
continue ;
|
||||
// assegno indice di parte connessa al triangolo
|
||||
m_vTria[i].nPart = m_nParts ;
|
||||
++ m_nParts ;
|
||||
m_vTria[i].nShell = m_nShells ;
|
||||
++ m_nShells ;
|
||||
// set di triangoli da aggiornare
|
||||
set<int> stTria ;
|
||||
stTria.insert( i) ;
|
||||
@@ -3548,13 +3700,137 @@ SurfTriMesh::VerifyConnection( void) const
|
||||
// aggiorno i triangoli adiacenti
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
|
||||
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nPart == SVT_NULL) {
|
||||
m_vTria[nAdjT].nPart = m_vTria[nT].nPart ;
|
||||
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nShell == SVT_NULL) {
|
||||
m_vTria[nAdjT].nShell = m_vTria[nT].nShell ;
|
||||
stTria.insert( nAdjT) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// identifico le parti
|
||||
m_nParts = 0 ;
|
||||
if ( m_nShells == 1) { // se ho solo una shell allora ho una sola parte
|
||||
m_nParts = 1 ;
|
||||
for ( auto& Tria : m_vTria)
|
||||
Tria.nPart = Tria.nShell ;
|
||||
}
|
||||
else { // se ho più shells devo controllare la loro posizione
|
||||
// salvo solo le Shells chiuse e per ognuna di esse il loro volume e l'indice della shell
|
||||
// < stmShell, ( nShellInd, dVol) >
|
||||
// NB. I Volumi sono sempre finiti, il segno del volume mi dice solo se sto considerando
|
||||
// la parte interna o esterna della superficie
|
||||
typedef pair<PtrOwner<ISurfTriMesh>, pair<int, double>> SHELLINFO ;
|
||||
vector<SHELLINFO> vClosedShells ;
|
||||
vClosedShells.reserve( m_nShells) ;
|
||||
INTVECTOR vOpenShells ; // vettore di indici di Shell aperte
|
||||
for ( int s = 0 ; s < GetShellCount() ; ++ s) {
|
||||
// recupero la Shell
|
||||
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( s)) ;
|
||||
if ( IsNull( pStmShell) || ! pStmShell->IsValid())
|
||||
return false ;
|
||||
double dVol = 0. ;
|
||||
// se chiusa calcolo il suo volume con segno
|
||||
if ( pStmShell->IsClosed()) {
|
||||
pStmShell->GetVolume( dVol) ;
|
||||
vClosedShells.emplace_back( make_pair( Release( pStmShell), make_pair( s, dVol))) ;
|
||||
}
|
||||
// se aperta, non rientra nella classficazione ( sarà coincidente ad una Part)
|
||||
else
|
||||
vOpenShells.push_back( s) ;
|
||||
}
|
||||
|
||||
// ordino il vettore in senso decrescente per volume, in valore assoluto
|
||||
// NB. tutte le shell con volume negativo sono state invertite !
|
||||
sort( vClosedShells.begin(), vClosedShells.end(),
|
||||
[]( const SHELLINFO& a, const SHELLINFO& b) {
|
||||
return abs( a.second.second) > abs( b.second.second) ;
|
||||
}) ;
|
||||
|
||||
// se la superficie in prima posizione è negativa, allora le inverto tutte; il numero di
|
||||
// Parts non cambia nel conto
|
||||
if ( ! vClosedShells.empty() && vClosedShells.front().second.second < - EPS_SMALL)
|
||||
for ( auto& Shell : vClosedShells)
|
||||
Shell.first->Invert() ;
|
||||
|
||||
// creo una matrice di interi ; ogni riga corrisponde ad una Parte, dove in posizione 0 c'è
|
||||
// la shell esterna e nelle successive le rispettiva shells interne
|
||||
INTMATRIX vnShellIndMat ;
|
||||
|
||||
bool bFirstShell ; // flag per indicare se la shell corrente è esterna
|
||||
int nIndExtShell = -1 ; // indice del vettore di shell chiuse della shell esterna
|
||||
INTVECTOR vIndIntShells ; // vettore di indici di shell chiuse interne alla shell esterna corrente
|
||||
do {
|
||||
bFirstShell = true ;
|
||||
for ( int i = 0 ; i < int( vClosedShells.size()) ; ++ i) {
|
||||
// recupero l'indice della shell e verifico che sia valido
|
||||
int j = vClosedShells[i].second.first ;
|
||||
if ( j < 0)
|
||||
continue ;
|
||||
// lo inserisco come esterno...
|
||||
if ( bFirstShell) {
|
||||
vnShellIndMat.push_back({ j}) ;
|
||||
vClosedShells[i].second.first = -1 ;
|
||||
bFirstShell = false ;
|
||||
nIndExtShell = i ;
|
||||
vIndIntShells.clear() ;
|
||||
}
|
||||
// altrimento verifico se la shell è interna o no
|
||||
else {
|
||||
// la shell è interna se è sia interna alla shell esterna corrente ( della riga di
|
||||
// vnShellIndMat ) e allo stesso tempo esterna a tutte le shell già inserite nella riga
|
||||
// attuale.
|
||||
Point3d ptCheck ;
|
||||
vClosedShells[i].first->GetFirstVertex( ptCheck) ;
|
||||
|
||||
// 1) verifica rispetto alla shell esterna
|
||||
DistPointSurfTm distCalculator( ptCheck, *vClosedShells[nIndExtShell].first) ;
|
||||
if ( ! distCalculator.IsPointInside())
|
||||
continue ;
|
||||
|
||||
// 2) verifica rispetto a tutte la shell già trovate interne
|
||||
bool bOk = true ;
|
||||
for ( int k = 1 ; k < int( vIndIntShells.size()) ; ++ k) {
|
||||
DistPointSurfTm distCalculator( ptCheck, *vClosedShells[vIndIntShells[k]].first) ;
|
||||
// NB. tutte le shell hanno volume negativo !
|
||||
if ( ! distCalculator.IsPointInside()) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bOk) {
|
||||
// inserisco nella matrice
|
||||
vnShellIndMat.back().push_back( j) ;
|
||||
vClosedShells[i].second.first = - 1 ;
|
||||
vIndIntShells.push_back( i) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( ! bFirstShell) ;
|
||||
|
||||
// scorro le righe della matrice e assegno la Part ( ovvero la riga )
|
||||
int nPart = 0 ;
|
||||
for ( nPart = 0 ; nPart < int( vnShellIndMat.size()) ; ++ nPart) {
|
||||
++ m_nParts ;
|
||||
for ( int j = 0 ; j < int( vnShellIndMat[nPart].size()) ; ++ j) {
|
||||
for ( auto& Tria : m_vTria) {
|
||||
if ( Tria.nShell == j)
|
||||
Tria.nPart = nPart ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// per tutte le superfici aperte, assegno loro una Parte
|
||||
for ( int i = 0 ; i < int( vOpenShells.size()) ; ++ i) {
|
||||
++ m_nParts ;
|
||||
for ( auto& Tria : m_vTria) {
|
||||
if ( Tria.nShell == i)
|
||||
Tria.nPart = i + ( nPart ++ ) ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -3590,6 +3866,38 @@ SurfTriMesh::RemovePart( int nPart)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemoveShell( int nShell)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// Il numero delle componenti deve essere maggiore di zero o calcolabile
|
||||
if ( m_nShells == -1 && ! VerifyConnection())
|
||||
return false ;
|
||||
|
||||
// Se la componente non esiste, errore
|
||||
if ( m_nShells <= 0 || nShell < 0 || nShell >= m_nShells)
|
||||
return false ;
|
||||
|
||||
int nShellsOld = m_nShells ;
|
||||
// Rimuovo i triangoli della componente nPart
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
if ( m_vTria[i].nShell == nShell)
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
|
||||
// Aggiorno il numero di componenti
|
||||
m_nShells = nShellsOld - 1 ;
|
||||
|
||||
// imposto ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::ClonePart( int nPart) const
|
||||
@@ -3617,6 +3925,7 @@ SurfTriMesh::ClonePart( int nPart) const
|
||||
pSurfTM->m_dSmoothAng = m_dSmoothAng ;
|
||||
pSurfTM->m_dCosSmAng = m_dCosSmAng ;
|
||||
pSurfTM->m_nParts = 1 ;
|
||||
pSurfTM->m_nShells = 1 ;
|
||||
|
||||
// Copio i triangoli
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
@@ -3636,6 +3945,53 @@ SurfTriMesh::ClonePart( int nPart) const
|
||||
return Release( pSurfTM) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
SurfTriMesh*
|
||||
SurfTriMesh::CloneShell( int nShell) const
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// Il numero delle componenti deve essere maggiore di zero o calcolabile
|
||||
if ( m_nShells == -1 && ! VerifyConnection())
|
||||
return nullptr ;
|
||||
|
||||
// Se la componente non esiste, errore
|
||||
if ( m_nShells <= 0 || nShell < 0 || nShell >= m_nShells)
|
||||
return nullptr ;
|
||||
|
||||
// Creo nuovo oggetto SurfTriMesh
|
||||
PtrOwner<SurfTriMesh> pSurfTM( new( nothrow) SurfTriMesh) ;
|
||||
if ( IsNull( pSurfTM))
|
||||
return nullptr ;
|
||||
|
||||
// Copio il valore dei membri
|
||||
pSurfTM->m_dLinTol = m_dLinTol ;
|
||||
pSurfTM->m_dBoundaryAng = m_dBoundaryAng ;
|
||||
pSurfTM->m_dCosBndAng = m_dCosBndAng ;
|
||||
pSurfTM->m_dSmoothAng = m_dSmoothAng ;
|
||||
pSurfTM->m_dCosSmAng = m_dCosSmAng ;
|
||||
pSurfTM->m_nParts = 1 ;
|
||||
pSurfTM->m_nShells = 1 ;
|
||||
|
||||
// Copio i triangoli
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
|
||||
int nNewInd[3] = { pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[0]].ptP),
|
||||
pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[1]].ptP),
|
||||
pSurfTM->AddVertex( m_vVert[m_vTria[i].nIdVert[2]].ptP)} ;
|
||||
if ( pSurfTM->AddTriangle( nNewInd, m_vTria[i].nTFlag) == SVT_NULL)
|
||||
return nullptr ;
|
||||
}
|
||||
}
|
||||
|
||||
// Aggiusto la superficie
|
||||
pSurfTM->DoCompacting() ;
|
||||
|
||||
// Restituisco la nuova superficie
|
||||
return Release( pSurfTM) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::ResetTFlags( void)
|
||||
@@ -3643,6 +3999,7 @@ SurfTriMesh::ResetTFlags( void)
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i)
|
||||
m_vTria[i].nTFlag = 0 ;
|
||||
m_nMaxTFlag = 0 ;
|
||||
m_OGrMgr.Clear() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -3663,6 +4020,8 @@ SurfTriMesh::SetTFlag( int nId, int nTFlag)
|
||||
if ( nId < 0 || nId >= GetTriangleSize() || m_vTria[nId].nIdVert[0] == SVT_DEL)
|
||||
return false ;
|
||||
m_vTria[nId].nTFlag = nTFlag ;
|
||||
m_nMaxTFlag = max( m_nMaxTFlag, abs( nTFlag)) ;
|
||||
m_OGrMgr.Clear() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
+26
-8
@@ -52,16 +52,16 @@ class StmTria
|
||||
public :
|
||||
StmTria( void)
|
||||
: nIdVert{ SVT_NULL, SVT_NULL, SVT_NULL}, nIdAdjac{ SVT_NULL, SVT_NULL, SVT_NULL}, nETempFlag{ 0, 0, 0},
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nPart( SVT_NULL), nTemp( 0), nTempPart{ 0} {}
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nShell( SVT_NULL), nPart( SVT_NULL), nTemp( 0), nTempShell{ 0}, nTempPart{ 0} {}
|
||||
StmTria( const int nIdV[3])
|
||||
: nIdVert{ nIdV[0], nIdV[1], nIdV[2]}, nIdAdjac{ SVT_NULL, SVT_NULL, SVT_NULL}, nETempFlag{ 0, 0, 0},
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nPart( SVT_NULL), nTemp( 0), nTempPart{ 0} {}
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( 0), nEFlag( 0), nShell( SVT_NULL), nPart( SVT_NULL), nTemp( 0), nTempShell{ 0}, nTempPart{ 0} {}
|
||||
StmTria( const int nIdV[3], int nTF)
|
||||
: nIdVert{ nIdV[0], nIdV[1], nIdV[2]}, nIdAdjac{ SVT_NULL, SVT_NULL, SVT_NULL}, nETempFlag{ 0, 0, 0},
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( 0), nPart( SVT_NULL), nTemp( 0), nTempPart{ 0} {}
|
||||
vtN(), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( 0), nShell( SVT_NULL), nPart( SVT_NULL), nTemp( 0), nTempShell{ 0}, nTempPart{ 0} {}
|
||||
StmTria( const int nIdV[3], const int nIdA[3], const Vector3d& vtV, int nTF, int nEF)
|
||||
: nIdVert{ nIdV[0], nIdV[1], nIdV[2]}, nIdAdjac{ nIdA[0], nIdA[1], nIdA[2]}, nETempFlag{ 0, 0, 0},
|
||||
vtN( vtV), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( nEF), nPart( SVT_NULL), nTemp( 0), nTempPart{ 0} {}
|
||||
vtN( vtV), nIdFacet( SVT_NULL), nTFlag( nTF), nEFlag( nEF), nShell( SVT_NULL), nPart( SVT_NULL), nTemp( 0), nTempShell{ 0}, nTempPart{ 0} {}
|
||||
public :
|
||||
int nIdVert[3] ;
|
||||
int nIdAdjac[3] ;
|
||||
@@ -70,9 +70,12 @@ class StmTria
|
||||
int nIdFacet ;
|
||||
int nTFlag ;
|
||||
int nEFlag ;
|
||||
mutable int nShell ;
|
||||
mutable int nPart ;
|
||||
mutable int nTemp ;
|
||||
mutable int nTempShell ;
|
||||
mutable int nTempPart ;
|
||||
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -226,6 +229,9 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
{ m_dSmoothAng = std::max( dSmoothAngDeg, EPS_ANG_SMALL) ;
|
||||
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
|
||||
m_OGrMgr.Reset() ; }
|
||||
void SetShowEdges( bool bShow) override
|
||||
{ m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica
|
||||
m_OGrMgr.Clear() ; }
|
||||
int AddVertex( const Point3d& ptVert, double dU = -1, double dV = -1) override ;
|
||||
bool MoveVertex( int nInd, const Point3d& ptNewVert) override ;
|
||||
int AddTriangle( const int nIdVert[3], int nTFlag = 0) override ;
|
||||
@@ -254,6 +260,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
{ return m_dLinTol ; }
|
||||
double GetSmoothAngle( void) const override
|
||||
{ return m_dSmoothAng ; }
|
||||
bool GetShowEdges( void) const override
|
||||
{ return m_bShowEdges ; }
|
||||
bool GetVertex( int nId, Point3d& ptP) const override ;
|
||||
bool GetVertexParam( int nId, double& dU, double& dV) const override ;
|
||||
int GetFirstVertex( Point3d& ptP) const override ;
|
||||
@@ -274,6 +282,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
SurfTriMesh* CloneTriangle( int nT) const override ;
|
||||
bool GetLoops( POLYLINEVECTOR& vPL) const override ;
|
||||
bool GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL, bool bAllTria = false) const override ;
|
||||
bool GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR& vPL, bool bAllTria = false) const override ;
|
||||
int GetFacetCount( void) const override ;
|
||||
int GetFacetSize( void) const override
|
||||
{ return int( m_vFacet.size()) ; }
|
||||
@@ -311,8 +320,13 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool GetAllTriaOverlapBox( const BBox3d& b3Box, INTVECTOR& vT) const override ;
|
||||
const BBox3d& GetAllTriaBox( void) const override ;
|
||||
int GetPartCount( void) const override ;
|
||||
int GetShellCount( void) const override ;
|
||||
bool RemovePart( int nPart) override ;
|
||||
bool RemoveShell( int nShell) override ;
|
||||
SurfTriMesh* ClonePart( int nPart) const override ;
|
||||
SurfTriMesh* CloneShell( int nShell) const override ;
|
||||
bool SetTFlag( int nId, int nTFlag) override ;
|
||||
bool GetTFlag( int nId, int& nFlag) const override ;
|
||||
int GetMaxTFlag( void) const override
|
||||
{ return m_nMaxTFlag ; }
|
||||
bool ResetTFlags( void) override ;
|
||||
@@ -320,7 +334,10 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override ;
|
||||
bool PostSave( GdbGeo& Wrapper) const override ;
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override ;
|
||||
|
||||
public :
|
||||
SurfTriMesh( void) ;
|
||||
@@ -335,10 +352,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool ExistsTriangle( int nT) const
|
||||
{ return ( nT >= 0 && nT < GetTriangleSize() && m_vTria[nT].nIdVert[0] != SVT_DEL) ; }
|
||||
bool GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const ;
|
||||
bool GetTFlag( int nId, int& nFlag) const ;
|
||||
bool GetTempInt( int nId, int& nTempInt) const ;
|
||||
bool ResetTempInts( void) const ;
|
||||
bool SetTFlag( int nId, int nTFlag) ;
|
||||
bool SetTempInt( int nId, int nTempInt) const ;
|
||||
|
||||
private :
|
||||
@@ -396,6 +411,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf) ;
|
||||
bool IntersectTriMeshTriangle( SurfTriMesh& Other) ;
|
||||
bool IdentifyParts( void) const ;
|
||||
bool IdentifyShells( void) const ;
|
||||
bool RemoveDoubleTriangles( bool& bModified) ;
|
||||
bool RemoveTJunctions( bool& bModified) ;
|
||||
bool FlipTriangles( int nTA, int nTB) ;
|
||||
@@ -413,6 +429,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
double m_dCosBndAng ; // coseno dell'angolo limite per considerare un lato un contorno
|
||||
double m_dSmoothAng ; // angolo limite per mediare le normali (in gradi)
|
||||
double m_dCosSmAng ; // coseno dell'angolo limite per mediare le normali
|
||||
bool m_bShowEdges ; // flag di visualizzazione spigoli vivi
|
||||
bool m_bOriented ; // la superficie è orientata consistentemente in tutte le sue parti
|
||||
bool m_bClosed ; // la superficie racchiude un volume
|
||||
bool m_bFaceted ; // flag di validità della sfaccettatura
|
||||
@@ -425,9 +442,10 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
int m_nMaxTFlag ; // massimo valore dei TFlag dei triangoli
|
||||
mutable int m_nParts ; // numero di parti connesse (-1 se da calcolare)
|
||||
mutable int m_nParts ; // numero di parti intese come volumi (-1 se da calcolare)
|
||||
mutable int m_nShells ; // numero di gusci connessi (-1 se da calcolare)
|
||||
mutable HashGrids3d* m_pHGrd3d ; // Hash Grid 3d nel suo riferimento
|
||||
mutable BBox3d m_b3HGrd3d ; // Box3d collegato a Hash Grid 3d
|
||||
mutable BBox3d m_b3HGrd3d ; // Box3d collegato a Hash Grid 3d
|
||||
} ;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
+250
-274
@@ -17,13 +17,14 @@
|
||||
#include "CurveLine.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "Triangulate.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EGkCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkDistPointTria.h"
|
||||
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineBox.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
|
||||
@@ -35,7 +36,6 @@
|
||||
#include "/EgtDev/Include/EGkPolygon3d.h"
|
||||
#include "/EgtDev/Include/EgtPerfCounter.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
@@ -77,10 +77,9 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
||||
( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2)))
|
||||
continue ; // la catena aperta non è interna al loop chiuso attuale
|
||||
|
||||
// il loop 1 segue sempre la direzione della catena, il loop 2 ha dentro la catena invertita
|
||||
// Ho sempre che il loop 1 è sempre interno ( la direzione della catena è determinata
|
||||
// dalla normale dei triangoli che la formano; avendo chimatao la chian senza ammettere inversioni, sono
|
||||
// curve tutte concordi ) e il loop 2 che è esterno
|
||||
// il loop 2 segue sempre la direzione della catena, il loop 1 ha dentro la catena invertita
|
||||
// ( la direzione della catena è determinata dalla normale dei triangoli che la formano;
|
||||
// avendo chiamato la chain senza ammettere inversioni, sono curve tutte concordi )
|
||||
bLoopSplitted = true ;
|
||||
// ricostrusico i due loop mediante concatenazione
|
||||
Chain cvCounterChain ;
|
||||
@@ -479,7 +478,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[2] = 0 ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nTempShell = nDist[nAloneVert] ;
|
||||
bModif = true ;
|
||||
}
|
||||
int nNewCoupleId1[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 1) % 3)), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)) } ;
|
||||
@@ -488,7 +487,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[2] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nTempShell = - nDist[nAloneVert] ;
|
||||
bModif = true ;
|
||||
}
|
||||
int nNewCoupleId2[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)), Surf.AddVertex( ptIntEn) } ;
|
||||
@@ -497,7 +496,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[2] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nTempShell = - nDist[nAloneVert] ;
|
||||
bModif = true ;
|
||||
}
|
||||
continue ;
|
||||
@@ -563,18 +562,18 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
vnDegVec.resize( 1) ;
|
||||
}
|
||||
else {
|
||||
Surf.m_vTria[it->first].nTempPart = 0 ;
|
||||
Surf.m_vTria[it->first].nTempShell = 0 ;
|
||||
continue ;
|
||||
}
|
||||
vbInOut.resize( 1) ;
|
||||
vbInOut[0] = true ;
|
||||
if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) {
|
||||
Surf.m_vTria[it->first].nTempPart = 0 ;
|
||||
Surf.m_vTria[it->first].nTempShell = 0 ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Surf.m_vTria[it->first].nTempPart = 0 ;
|
||||
Surf.m_vTria[it->first].nTempShell = 0 ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
@@ -585,6 +584,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
POLYLINEVECTOR vplPolyVec ;
|
||||
vplPolyVec.resize( cvBoundClosedLoopVec.size()) ;
|
||||
for ( int nLoop = 0 ; nLoop < int( vplPolyVec.size()) ; ++ nLoop) {
|
||||
|
||||
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine)
|
||||
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ;
|
||||
|
||||
@@ -592,7 +592,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
|
||||
// Assegno ai loop trovati i rispettivi interni
|
||||
// Assumo che i loop interni a uno dei loop creati fino ad'ora siano tutti sullo stesso livello.
|
||||
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
|
||||
// Il caso generale si risolve con una struttura ad albero in cui il nodo corrispondente a un
|
||||
// loop è figlio del nodo corrispondente al loop che lo contiene.
|
||||
INTVECTOR vInnerLoop ;
|
||||
for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) {
|
||||
@@ -731,9 +731,9 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
|
||||
if ( vbInOut[nLoop])
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = 1 ;
|
||||
else
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = - 1 ;
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = - 1 ;
|
||||
bModif = true ;
|
||||
}
|
||||
}
|
||||
@@ -743,6 +743,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
// se ho più loop, essi descrivono un poligono di n-lati
|
||||
POLYLINEVECTOR vPolygons ;
|
||||
vPolygons.emplace_back( vplPolyVec[nLoop]) ;
|
||||
|
||||
for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) {
|
||||
// per ognuno di essi, ricavo la PolyLine dai punti
|
||||
PolyLine CurLoop ;
|
||||
@@ -827,9 +828,9 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
|
||||
if ( bCodirectedNormals)
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = -1 ;
|
||||
else
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = 1 ;
|
||||
bModif = true ;
|
||||
}
|
||||
}
|
||||
@@ -862,7 +863,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
double dDist ;
|
||||
DistCalculator.GetDist( dDist) ;
|
||||
double dLongPos = ( ptP - ptSt) * vtSeg ;
|
||||
if ( dDist < EPS_SMALL && dLongPos > 0. && dLongPos < dSegLen) {
|
||||
if ( dDist < EPS_SMALL && dLongPos > EPS_SMALL && dLongPos < dSegLen - EPS_SMALL) {
|
||||
POINTU NewPointU ;
|
||||
NewPointU.first = ptP ;
|
||||
NewPointU.second = dLongPos ;
|
||||
@@ -932,27 +933,46 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
bool bReplaced = false ;
|
||||
for ( int nl = 0 ; nl < int( vAuxPolygons.size()) ; ++ nl) {
|
||||
if ( true) {
|
||||
if ( ! bReplaced) {
|
||||
vPolygons[nL].Clear() ;
|
||||
Point3d ptP ;
|
||||
bool bContinue = vAuxPolygons[nl].GetFirstPoint( ptP) ;
|
||||
while ( bContinue) {
|
||||
vPolygons[nL].AddUPoint( 0., ptP) ;
|
||||
bContinue = vAuxPolygons[nl].GetNextPoint( ptP) ;
|
||||
}
|
||||
bReplaced = true ;
|
||||
}
|
||||
else {
|
||||
vPolygons.emplace_back( vAuxPolygons[nl]) ;
|
||||
if ( ! bReplaced) {
|
||||
vPolygons[nL].Clear() ;
|
||||
Point3d ptP ;
|
||||
bool bContinue = vAuxPolygons[nl].GetFirstPoint( ptP) ;
|
||||
while ( bContinue) {
|
||||
vPolygons[nL].AddUPoint( 0., ptP) ;
|
||||
bContinue = vAuxPolygons[nl].GetNextPoint( ptP) ;
|
||||
}
|
||||
bReplaced = true ;
|
||||
}
|
||||
else {
|
||||
vPolygons.emplace_back( vAuxPolygons[nl]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tolgo il loop esterno per triangolare solo i loop interni
|
||||
vPolygons.erase( vPolygons.begin()) ;
|
||||
// tolgo le PolyLine non valide ( rejected )
|
||||
for ( int i = 0 ; i < int( vPolygons.size()) ; ) {
|
||||
if ( ! vPolygons[i].IsClosed())
|
||||
vPolygons.erase( vPolygons.begin() + i) ;
|
||||
else
|
||||
++ i ;
|
||||
|
||||
}
|
||||
|
||||
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)) {
|
||||
// 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 nNewId[3] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
|
||||
Surf.AddVertex( vPt[nNewTriaVertId[1]]),
|
||||
@@ -962,10 +982,10 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
|
||||
if ( bCodirectedNormals)
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
|
||||
if ( bCordirectedNormals_intLoop)
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = 1 ;
|
||||
else
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = -1 ;
|
||||
bModif = true ;
|
||||
}
|
||||
}
|
||||
@@ -1018,7 +1038,7 @@ SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Su
|
||||
for ( auto it = Ambiguos.begin() ; it != Ambiguos.end() ; ++ it) {
|
||||
// Se il triangolo ha l'indice diverso da zero vuol dire che oltre a un
|
||||
// contatto edge-edge ha avuto dei contatti che lo hanno già classificato.
|
||||
if ( Surf.m_vTria[it->first].nTempPart != 0)
|
||||
if ( Surf.m_vTria[it->first].nTempShell != 0)
|
||||
continue ;
|
||||
// Recupero il triangolo corrente
|
||||
Triangle3d trTria ;
|
||||
@@ -1082,11 +1102,11 @@ SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Su
|
||||
for ( int i = 0 ; i < 3 ; ++ i) {
|
||||
if ( nTriaClassificationByEdges[i] == 0)
|
||||
continue ;
|
||||
Surf.m_vTria[it->first].nTempPart = nTriaClassificationByEdges[i] ;
|
||||
Surf.m_vTria[it->first].nTempShell = nTriaClassificationByEdges[i] ;
|
||||
int j ;
|
||||
for ( j = i + 1 ; j < 3 ; ++ j) {
|
||||
if ( nTriaClassificationByEdges[j] != 0 && nTriaClassificationByEdges[i] != nTriaClassificationByEdges[j]) {
|
||||
Surf.m_vTria[it->first].nTempPart = 0 ;
|
||||
Surf.m_vTria[it->first].nTempShell = 0 ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
@@ -1126,13 +1146,13 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
|
||||
// Setto il triangolo come né fuori né dentro
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
|
||||
m_vTria[nTA].nTempPart = 0 ;
|
||||
m_vTria[nTA].nTempShell = 0 ;
|
||||
m_vTria[nTA].nETempFlag[0] = 0 ;
|
||||
m_vTria[nTA].nETempFlag[1] = 0 ;
|
||||
m_vTria[nTA].nETempFlag[2] = 0 ;
|
||||
}
|
||||
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
|
||||
SurfB.m_vTria[nTB].nTempPart = 0 ;
|
||||
SurfB.m_vTria[nTB].nTempShell = 0 ;
|
||||
SurfB.m_vTria[nTB].nETempFlag[0] = 0 ;
|
||||
SurfB.m_vTria[nTB].nETempFlag[1] = 0 ;
|
||||
SurfB.m_vTria[nTB].nETempFlag[2] = 0 ;
|
||||
@@ -1240,9 +1260,9 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
abs( ( trTriaA.GetP( ( nVA + 1) % 3) - trTriaB.GetP( 0)) * trTriaB.GetN()) < EPS_SMALL)
|
||||
break ;
|
||||
}
|
||||
m_vTria[nTA].nTempPart = ( ( trTriaA.GetP( nSegMaxDist) - trTriaB.GetP( 0)) * trTriaB.GetN() < - EPS_SMALL ? 1 : - 1) ;
|
||||
m_vTria[nTA].nTempShell = ( ( trTriaA.GetP( nSegMaxDist) - trTriaB.GetP( 0)) * trTriaB.GetN() < - EPS_SMALL ? 1 : - 1) ;
|
||||
if ( nVA >= 0 && nVA <= 2)
|
||||
m_vTria[nTA].nETempFlag[nVA] = m_vTria[nTA].nTempPart ;
|
||||
m_vTria[nTA].nETempFlag[nVA] = m_vTria[nTA].nTempShell ;
|
||||
}
|
||||
}
|
||||
// caso di Intersezione interno-edge ( per superficie A con B)
|
||||
@@ -1265,9 +1285,9 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
abs( ( trTriaB.GetP( ( nVB + 1) % 3) - trTriaA.GetP( 0)) * trTriaA.GetN()) < EPS_SMALL)
|
||||
break ;
|
||||
}
|
||||
SurfB.m_vTria[vNearTria[nTB]].nTempPart = ( ( trTriaB.GetP( nSegMaxDist) - trTriaA.GetP( 0)) * trTriaA.GetN() < - EPS_SMALL ? 1 : - 1) ;
|
||||
SurfB.m_vTria[vNearTria[nTB]].nTempShell = ( ( trTriaB.GetP( nSegMaxDist) - trTriaA.GetP( 0)) * trTriaA.GetN() < - EPS_SMALL ? 1 : - 1) ;
|
||||
if ( nVB >= 0 && nVB <= 2)
|
||||
SurfB.m_vTria[vNearTria[nTB]].nETempFlag[nVB] = SurfB.m_vTria[vNearTria[nTB]].nTempPart ;
|
||||
SurfB.m_vTria[vNearTria[nTB]].nETempFlag[nVB] = SurfB.m_vTria[vNearTria[nTB]].nTempShell ;
|
||||
}
|
||||
}
|
||||
// Intersezione edge-edge: salvo indice e vettore triangoli
|
||||
@@ -1307,171 +1327,28 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
bool bRetriangulated = true ;
|
||||
if ( ! bModif && ( int( AmbiguosA.size()) == 0 || int( AmbiguosB.size()) == 0)) {
|
||||
bRetriangulated = false ;
|
||||
int nVertNum = 0 ;
|
||||
Point3d ptFirstV ;
|
||||
int nCurVert = GetFirstVertex( ptFirstV) ;
|
||||
// devo assegnare a tutti i triangoli della superficie la medesima proprietà ( definita da nInOutNum)
|
||||
// ( -1 -> esterno | 0 -> indefinito | +1 -> interno )
|
||||
// devo farlo sia per la SurfA( *this) che per la SurfB
|
||||
int nInOutNum = 0 ;
|
||||
while ( nInOutNum == 0 && nCurVert != SVT_NULL) {
|
||||
INTVECTOR vnTriaNum ;
|
||||
double dMinDist = DBL_MAX ;
|
||||
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
|
||||
// Se il triangolo B non è valido, continuo
|
||||
Triangle3d trTriaB ;
|
||||
if ( ! SurfB.GetTriangle( nTB, trTriaB) || ! trTriaB.Validate( true))
|
||||
continue ;
|
||||
double dDist ;
|
||||
// potrei trovare più triangolo equidistanti, li salvo tutti
|
||||
if ( DistPointTriangle( ptFirstV, trTriaB).GetDist( dDist)) {
|
||||
if ( abs(dDist - dMinDist) < EPS_SMALL)
|
||||
vnTriaNum.push_back( nTB) ;
|
||||
else if ( dDist < dMinDist){
|
||||
vnTriaNum.clear() ;
|
||||
vnTriaNum.push_back( nTB) ;
|
||||
dMinDist = dDist ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! vnTriaNum.empty()) {
|
||||
Triangle3d trTriaB ;
|
||||
bool bSame = true ;
|
||||
// controllo se rispetto a questi triangoli il punto risulta sempre fuori o sempre dentro
|
||||
for ( int nTriaNum : vnTriaNum) {
|
||||
SurfB.GetTriangle( nTriaNum, trTriaB) ;
|
||||
if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL) {
|
||||
if ( nInOutNum == 0)
|
||||
nInOutNum = 1 ;
|
||||
else if ( nInOutNum == -1) {
|
||||
bSame = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL) {
|
||||
if ( nInOutNum == 0)
|
||||
nInOutNum = -1 ;
|
||||
else if ( nInOutNum == 1) {
|
||||
bSame = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino
|
||||
// e ricalcolo l'informazione che mi dà la sua normale
|
||||
if ( ! bSame) {
|
||||
Point3d ptBar_tot ;
|
||||
for (int nTriaNum : vnTriaNum) {
|
||||
SurfB.GetTriangle( nTriaNum, trTriaB) ;
|
||||
ptBar_tot += trTriaB.GetCentroid();
|
||||
}
|
||||
ptBar_tot /= int( vnTriaNum.size()) ;
|
||||
for ( int nTriaNum : vnTriaNum) {
|
||||
SurfB.GetTriangle( nTriaNum, trTriaB) ;
|
||||
Point3d ptInters1, ptInters2 ;
|
||||
int nInters = IntersLineTria( ptFirstV, ptBar_tot, trTriaB, ptInters1, ptInters2, true) ;
|
||||
if ( nInters == ILTT_NO)
|
||||
continue ;
|
||||
else if ( nInters == ILTT_IN) {
|
||||
if ( ( ptFirstV - trTriaB.GetP( 0)) * trTriaB.GetN() < - EPS_SMALL)
|
||||
nInOutNum = 1 ;
|
||||
else if ( ( ptFirstV - trTriaB.GetP( 0)) * trTriaB.GetN() > EPS_SMALL)
|
||||
nInOutNum = -1 ;
|
||||
break ;
|
||||
}
|
||||
else
|
||||
nInOutNum = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( nInOutNum == 0) {
|
||||
nCurVert = GetNextVertex( nVertNum, ptFirstV) ;
|
||||
++ nVertNum ;
|
||||
}
|
||||
for ( int v = 0 ; v < int( m_vVert.size()) && nInOutNum == 0 ; ++ v) {
|
||||
double dDist = 0. ;
|
||||
DistPointSurfTm distCalculator( m_vVert[v].ptP, SurfB) ;
|
||||
if ( distCalculator.GetDist( dDist) && dDist > EPS_SMALL)
|
||||
nInOutNum = ( distCalculator.IsPointOnLeftSide() ? 1 : -1) ;
|
||||
}
|
||||
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA)
|
||||
m_vTria[nTA].nTempPart = nInOutNum ;
|
||||
m_vTria[nTA].nTempShell = nInOutNum ;
|
||||
|
||||
nVertNum = 0 ;
|
||||
nCurVert = SurfB.GetFirstVertex( ptFirstV) ;
|
||||
nInOutNum = 0 ;
|
||||
while ( nInOutNum == 0 && nCurVert != SVT_NULL) {
|
||||
INTVECTOR vnTriaNum ;
|
||||
double dMinDist = DBL_MAX ;
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
|
||||
// Se il triangolo A non è valido, continuo
|
||||
Triangle3d trTriaA ;
|
||||
if ( ! ( GetTriangle( nTA, trTriaA) && trTriaA.Validate( true)))
|
||||
continue ;
|
||||
DistPointTriangle DistCalculator( ptFirstV, trTriaA) ;
|
||||
double dDist ;
|
||||
DistCalculator.GetDist( dDist) ;
|
||||
// potrei trovare più triangolo equidistanti, li salvo tutti
|
||||
if ( DistPointTriangle( ptFirstV, trTriaA).GetDist( dDist)) {
|
||||
if ( abs( dDist - dMinDist) < EPS_SMALL)
|
||||
vnTriaNum.push_back( nTA) ;
|
||||
else if ( dDist < dMinDist){
|
||||
vnTriaNum.clear() ;
|
||||
vnTriaNum.push_back( nTA) ;
|
||||
dMinDist = dDist ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! vnTriaNum.empty()) {
|
||||
Triangle3d trTriaA ;
|
||||
bool bSame = true ;
|
||||
// controllo se rispetto a questi triangoli il punto risulta sempre fuori o sempre dentro
|
||||
for ( int nTriaNum : vnTriaNum) {
|
||||
GetTriangle( nTriaNum, trTriaA) ;
|
||||
if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() < - EPS_SMALL) {
|
||||
if ( nInOutNum == 0)
|
||||
nInOutNum = 1 ;
|
||||
else if ( nInOutNum == -1) {
|
||||
bSame = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL) {
|
||||
if ( nInOutNum == 0)
|
||||
nInOutNum = -1 ;
|
||||
else if ( nInOutNum == 1) {
|
||||
bSame = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino
|
||||
// e ricalcolo l'informazione che mi dà la sua normale
|
||||
if ( ! bSame) {
|
||||
Point3d ptBar_tot ;
|
||||
for ( int nTriaNum : vnTriaNum) {
|
||||
GetTriangle( nTriaNum, trTriaA) ;
|
||||
ptBar_tot += trTriaA.GetCentroid();
|
||||
}
|
||||
ptBar_tot /= int( vnTriaNum.size()) ;
|
||||
for ( int nTriaNum : vnTriaNum) {
|
||||
GetTriangle( nTriaNum, trTriaA) ;
|
||||
Point3d ptInters1, ptInters2 ;
|
||||
int nInters = IntersLineTria( ptFirstV, ptBar_tot, trTriaA, ptInters1, ptInters2, true) ;
|
||||
if ( nInters == ILTT_NO)
|
||||
continue ;
|
||||
else if ( nInters == ILTT_IN) {
|
||||
if ( ( ptFirstV - trTriaA.GetP( 0)) * trTriaA.GetN() < - EPS_SMALL)
|
||||
nInOutNum = 1 ;
|
||||
else if ( ( ptFirstV - trTriaA.GetP( 0)) * trTriaA.GetN() > EPS_SMALL)
|
||||
nInOutNum = -1 ;
|
||||
break ;
|
||||
}
|
||||
else
|
||||
nInOutNum = 0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( nInOutNum == 0) {
|
||||
nCurVert = SurfB.GetNextVertex( nVertNum, ptFirstV) ;
|
||||
++ nVertNum ;
|
||||
}
|
||||
for ( int v = 0 ; v < int( SurfB.m_vVert.size()) && nInOutNum == 0 ; ++ v) {
|
||||
double dDist = 0. ;
|
||||
DistPointSurfTm distCalculator( SurfB.m_vVert[v].ptP, *this) ;
|
||||
if ( distCalculator.GetDist( dDist) && dDist > EPS_SMALL)
|
||||
nInOutNum = ( distCalculator.IsPointOnLeftSide() ? 1 : -1) ;
|
||||
}
|
||||
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB)
|
||||
SurfB.m_vTria[nTB].nTempPart = nInOutNum ;
|
||||
SurfB.m_vTria[nTB].nTempShell = nInOutNum ;
|
||||
}
|
||||
|
||||
// Se c'è stata una ritriangolazione di almeno un triangolo, NON siamo nel caso di tutto dentro o tutto fuori.
|
||||
@@ -1486,9 +1363,6 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
if ( bModif)
|
||||
bContinue = ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ;
|
||||
|
||||
SaveGeoObj( this, "C:\\Users\\riccardo.elitropi\\Desktop\\SurfA.nge") ;
|
||||
SaveGeoObj( SurfB.Clone(), "C:\\Users\\riccardo.elitropi\\Desktop\\SurfB.nge") ;
|
||||
|
||||
// Triangoli sovrapposti
|
||||
if ( bContinue) {
|
||||
int nTriaNum2A = GetTriangleSize() ;
|
||||
@@ -1515,12 +1389,12 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
Point3d ptTempA, ptTempB ;
|
||||
int nIntTypeAB = IntersTriaTria( trTriaA, trTriaB, ptTempA, ptTempB, vTriaAB) ;
|
||||
if ( nIntTypeAB == ITTT_OVERLAPS) {
|
||||
m_vTria[nTA].nTempPart = 2 ;
|
||||
SurfB.m_vTria[vNearTria[nTB]].nTempPart = 2 ;
|
||||
m_vTria[nTA].nTempShell = 2 ;
|
||||
SurfB.m_vTria[vNearTria[nTB]].nTempShell = 2 ;
|
||||
}
|
||||
else if ( nIntTypeAB == ITTT_COUNTER_OVERLAPS) {
|
||||
m_vTria[nTA].nTempPart = -2 ;
|
||||
SurfB.m_vTria[vNearTria[nTB]].nTempPart = -2 ;
|
||||
m_vTria[nTA].nTempShell = -2 ;
|
||||
SurfB.m_vTria[vNearTria[nTB]].nTempShell = -2 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1563,70 +1437,139 @@ SurfTriMesh::IdentifyParts( void) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::IdentifyShells( void) const
|
||||
{
|
||||
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
|
||||
// salto triangoli cancellati o già assegnati
|
||||
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
|
||||
abs( m_vTria[i].nTempShell) != 1)
|
||||
continue ;
|
||||
// set di triangoli da aggiornare
|
||||
set<int> stTria ;
|
||||
stTria.insert( i) ;
|
||||
while ( ! stTria.empty()) {
|
||||
// tolgo un triangolo dal set
|
||||
const auto iIt = stTria.begin() ;
|
||||
int nT = *iIt ;
|
||||
stTria.erase( iIt) ;
|
||||
// aggiorno i triangoli adiacenti
|
||||
for ( int j = 0 ; j < 3 ; ++ j) {
|
||||
if ( m_vTria[nT].nETempFlag[j] != 0)
|
||||
continue ;
|
||||
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
|
||||
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nTempShell == 0) {
|
||||
m_vTria[nAdjT].nTempShell = m_vTria[nT].nTempShell ;
|
||||
stTria.insert( nAdjT) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::Add( const ISurfTriMesh& Other)
|
||||
{
|
||||
// Le superfici devono essere valide
|
||||
|
||||
// le superfici devono essere valide
|
||||
if ( ! IsValid() || ! Other.IsValid())
|
||||
return false ;
|
||||
|
||||
// Se la seconda è vuota non devo fare alcunchè
|
||||
// se la seconda è vuota non devo fare alcunchè
|
||||
if ( Other.IsEmpty())
|
||||
return true ;
|
||||
|
||||
m_OGrMgr.Clear() ;
|
||||
|
||||
// Se la prima è vuota, copio la seconda nella prima
|
||||
// se la prima è vuota, copio la seconda nella prima
|
||||
if ( IsEmpty()) {
|
||||
CopyFrom( &Other) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// clono la superficie B
|
||||
SurfTriMesh SurfB ;
|
||||
SurfB.CopyFrom( &Other) ;
|
||||
|
||||
// creazione del frame per scalare A e B
|
||||
Frame3d frScalingRef ;
|
||||
frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ;
|
||||
// scalo A e B
|
||||
Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
|
||||
SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
|
||||
|
||||
IntersectTriMeshTriangle( SurfB) ;
|
||||
IdentifyParts() ;
|
||||
SurfB.IdentifyParts() ;
|
||||
// tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione )
|
||||
SurfTriMesh SurfB_cl ;
|
||||
SurfB_cl.CopyFrom( &SurfB) ;
|
||||
|
||||
// tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione )
|
||||
SurfTriMesh SurfA_cl ;
|
||||
SurfA_cl.CopyFrom( this) ;
|
||||
|
||||
// ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo
|
||||
IntersectTriMeshTriangle( SurfB) ;
|
||||
|
||||
// assegno un medesimo indice ai triangoli che non interferiscono con altri
|
||||
IdentifyShells() ;
|
||||
SurfB.IdentifyShells() ;
|
||||
|
||||
// rimozione dei triangoli di A con proprietà 1 e -2 ( e gestione dei triangoli ambigui, 0)
|
||||
int nTriaNumA = GetTriangleSize() ;
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
|
||||
if ( m_vTria[nTA].nTempPart == 1 || m_vTria[nTA].nTempPart == - 2)
|
||||
if ( m_vTria[nTA].nTempShell == 1 || m_vTria[nTA].nTempShell == - 2)
|
||||
RemoveTriangle( nTA) ;
|
||||
// se triangolo ambiguo
|
||||
if ( m_vTria[nTA].nTempShell == 0) {
|
||||
Triangle3d TriaA ;
|
||||
GetTriangle( nTA, TriaA) ;
|
||||
// rimuovo il triangolo se interno a surfB ( basta controllare un solo vertice(?) )
|
||||
DistPointSurfTm distCalculator( TriaA.GetP( 0), SurfB_cl) ;
|
||||
if ( distCalculator.IsPointOnLeftSide())
|
||||
RemoveTriangle( nTA) ;
|
||||
}
|
||||
}
|
||||
|
||||
// aggiunta di tutti i triangoli di B con proprietà -1 ( e gestione dei triangoli ambigui, 0)
|
||||
int nPrevMaxTFlag = m_nMaxTFlag ;
|
||||
int nTriaNumB = SurfB.GetTriangleSize() ;
|
||||
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
|
||||
if ( SurfB.m_vTria[nTB].nTempPart == - 1) {
|
||||
int nNewVert[3] ;
|
||||
for ( int nV = 0 ; nV < 3 ; ++ nV) {
|
||||
nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ;
|
||||
bool bAdd = ( SurfB.m_vTria[nTB].nTempShell == - 1) ;
|
||||
if ( ! bAdd) {
|
||||
// se ambiguo
|
||||
if ( SurfB.m_vTria[nTB].nTempShell == 0) {
|
||||
// aggiungo se il triangolo è a surfA ( basta controllare un solo vertice(?) )
|
||||
DistPointSurfTm distCalculator( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[0]].ptP, SurfA_cl) ;
|
||||
bAdd = ! distCalculator.IsPointOnLeftSide() ;
|
||||
}
|
||||
}
|
||||
if ( bAdd) {
|
||||
int nNewVert[3] ;
|
||||
for ( int nV = 0 ; nV < 3 ; ++ nV)
|
||||
nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ;
|
||||
if ( nPrevMaxTFlag == m_nMaxTFlag)
|
||||
++ m_nMaxTFlag ;
|
||||
AddTriangle( nNewVert, m_nMaxTFlag) ;
|
||||
}
|
||||
}
|
||||
|
||||
// sistemazioni varie
|
||||
bool bOk = ( AdjustVertices() && DoCompacting()) ;
|
||||
|
||||
bool bModified = false ;
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
|
||||
bOk = bOk && RemoveTJunctions( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
|
||||
// scalo alla dimensioni originali
|
||||
Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ;
|
||||
|
||||
// semplifico eventuale geometria delle facce
|
||||
if ( ! SimplifyFacets())
|
||||
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Add")
|
||||
|
||||
@@ -1637,6 +1580,7 @@ SurfTriMesh::Add( const ISurfTriMesh& Other)
|
||||
bool
|
||||
SurfTriMesh::Intersect( const ISurfTriMesh& Other)
|
||||
{
|
||||
|
||||
// Le superfici devono essere valide
|
||||
if ( ! IsValid() || ! Other.IsValid())
|
||||
return false ;
|
||||
@@ -1665,29 +1609,51 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
|
||||
Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
|
||||
SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
|
||||
|
||||
// tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione )
|
||||
SurfTriMesh SurfB_cl ;
|
||||
SurfB_cl.CopyFrom( &SurfB) ;
|
||||
|
||||
// tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione )
|
||||
SurfTriMesh SurfA_cl ;
|
||||
SurfA_cl.CopyFrom( this) ;
|
||||
|
||||
// ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo
|
||||
IntersectTriMeshTriangle( SurfB) ;
|
||||
|
||||
// assegno un medesimo indice ai triangoli che non interferiscono con altri
|
||||
IdentifyParts() ;
|
||||
SurfB.IdentifyParts() ;
|
||||
IdentifyShells() ;
|
||||
SurfB.IdentifyShells() ;
|
||||
|
||||
// rimozione dei triangoli di A con proprietà -1 e -2
|
||||
// rimozione dei triangoli di A con proprietà -1 e -2 (e gestione dei triangoli ambigui, 0)
|
||||
int nTriaNumA = GetTriangleSize() ;
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
|
||||
if ( m_vTria[nTA].nTempPart == - 1 || m_vTria[nTA].nTempPart == - 2)
|
||||
if ( m_vTria[nTA].nTempShell == - 1 || m_vTria[nTA].nTempShell == - 2)
|
||||
RemoveTriangle( nTA) ;
|
||||
// se triangolo ambiguo
|
||||
else if ( m_vTria[nTA].nTempShell == 0) {
|
||||
Triangle3d TriaA ;
|
||||
GetTriangle( nTA, TriaA) ;
|
||||
// rimuovo il triangolo se fuori a surfB ( basta controllare un solo vertice(?) )
|
||||
DistPointSurfTm distCalculator( TriaA.GetP( 0), SurfB_cl) ;
|
||||
if ( ! distCalculator.IsPointOnLeftSide())
|
||||
RemoveTriangle( nTA) ;
|
||||
}
|
||||
}
|
||||
|
||||
// aggiunta dei triangoli di B con proprietà +1
|
||||
// aggiunta dei triangoli di B con proprietà +1 ( e gestione dei triangoli ambigui, 0)
|
||||
int nPrevMaxTFlag = m_nMaxTFlag ;
|
||||
int nTriaNumB = SurfB.GetTriangleSize() ;
|
||||
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
|
||||
if ( SurfB.m_vTria[nTB].nTempPart == 1) {
|
||||
bool bAdd = ( SurfB.m_vTria[nTB].nTempShell == 1) ;
|
||||
if ( ! bAdd && SurfB.m_vTria[nTB].nTempShell == 0) {
|
||||
// aggiungo se il triangolo è interno a surfA ( basta controllare un solo vertice(?) )
|
||||
DistPointSurfTm distCalculator( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[0]].ptP, SurfA_cl) ;
|
||||
bAdd = distCalculator.IsPointOnLeftSide() ;
|
||||
}
|
||||
if ( bAdd) {
|
||||
int nNewVert[3] ;
|
||||
for ( int nV = 0 ; nV < 3 ; ++ nV)
|
||||
nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ;
|
||||
|
||||
if ( nPrevMaxTFlag == m_nMaxTFlag)
|
||||
++ m_nMaxTFlag ;
|
||||
AddTriangle( nNewVert, m_nMaxTFlag) ;
|
||||
@@ -1704,33 +1670,6 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
|
||||
// rimuovo tutte le parti esterne all'intersezione
|
||||
int nParts = GetPartCount() ;
|
||||
if ( nParts > 1) {
|
||||
for ( int i = 0 ; i < nParts ; ++ i) {
|
||||
// recupero i triangoli della stessa Part
|
||||
INTVECTOR vTriaPart ;
|
||||
for ( int j = 0 ; j < int( m_vTria.size()) ; ++ j)
|
||||
if ( m_vTria[j].nPart == i)
|
||||
vTriaPart.push_back( j) ;
|
||||
// controllo se il loro box interferisce con il box della superficie B
|
||||
bool bErasePart = true ;
|
||||
for ( int j = 0 ; j < int( vTriaPart.size()) && bErasePart ; ++ j) {
|
||||
// Se il triangolo A non è valido, continuo
|
||||
Triangle3d Tria ;
|
||||
if ( ! GetTriangle( j, Tria) || ! Tria.Validate( true))
|
||||
continue ;
|
||||
// Box del triangolo A
|
||||
BBox3d b3dTriaA ; Tria.GetLocalBBox( b3dTriaA) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
INTVECTOR vNearTria ; SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
|
||||
bErasePart = int( vNearTria.size() == 0) ;
|
||||
}
|
||||
if ( bErasePart)
|
||||
RemovePart( i) ;
|
||||
}
|
||||
}
|
||||
|
||||
// scalo alle dimensioni originali
|
||||
Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ;
|
||||
|
||||
@@ -1744,41 +1683,77 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
|
||||
bool
|
||||
SurfTriMesh::Subtract( const ISurfTriMesh& Other)
|
||||
{
|
||||
// Le superfici devono essere valide
|
||||
|
||||
// le superfici devono essere valide
|
||||
if ( ! IsValid() || ! Other.IsValid())
|
||||
return false ;
|
||||
|
||||
// Se una delle due è vuota non devo fare alcunchè
|
||||
// se una delle due è vuota non devo fare alcunchè
|
||||
if ( IsEmpty() || Other.IsEmpty())
|
||||
return true ;
|
||||
|
||||
// pulisco grafica
|
||||
m_OGrMgr.Clear() ;
|
||||
|
||||
// clono superficie B
|
||||
SurfTriMesh SurfB ;
|
||||
SurfB.CopyFrom( &Other) ;
|
||||
|
||||
Frame3d frScalingRef;
|
||||
// creazione del frame per scalare A e B
|
||||
Frame3d frScalingRef ;
|
||||
frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ;
|
||||
// scalo A e B
|
||||
Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
|
||||
SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
|
||||
|
||||
IntersectTriMeshTriangle( SurfB) ;
|
||||
IdentifyParts() ;
|
||||
SurfB.IdentifyParts() ;
|
||||
// tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione )
|
||||
SurfTriMesh SurfB_cl ;
|
||||
SurfB_cl.CopyFrom( &SurfB) ;
|
||||
|
||||
// tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione )
|
||||
SurfTriMesh SurfA_cl ;
|
||||
SurfA_cl.CopyFrom( this) ;
|
||||
|
||||
// ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo
|
||||
IntersectTriMeshTriangle( SurfB) ;
|
||||
|
||||
// assegno un medesimo indice ai triangoli che non interferiscono con altri
|
||||
IdentifyShells() ;
|
||||
SurfB.IdentifyShells() ;
|
||||
|
||||
// rimozione dei triangoli di A con proprietà 1 e 2 ( e gestione triangoli ambigui, 0)
|
||||
int nTriaNumA = GetTriangleSize() ;
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
|
||||
if ( m_vTria[nTA].nTempPart == 1 || m_vTria[nTA].nTempPart == 2)
|
||||
if ( m_vTria[nTA].nTempShell == 1 || m_vTria[nTA].nTempShell == 2)
|
||||
RemoveTriangle( nTA) ;
|
||||
// se triangolo ambiguo...
|
||||
if ( m_vTria[nTA].nTempShell == 0) {
|
||||
Triangle3d TriaA ;
|
||||
GetTriangle( nTA, TriaA) ;
|
||||
// rimuovo il triangolo se interno a SurfB ( basta controllare un solo vertice(?) )
|
||||
DistPointSurfTm distCalculator( TriaA.GetP( 0), SurfB_cl) ;
|
||||
if ( distCalculator.IsPointOnLeftSide())
|
||||
RemoveTriangle( nTA) ;
|
||||
}
|
||||
}
|
||||
|
||||
// aggiunta dei triangoli di B con proprietà +1 ( e gestione triangoli ambigui, 0)
|
||||
int nPrevMaxTFlag = m_nMaxTFlag ;
|
||||
int nTriaNumB = SurfB.GetTriangleSize() ;
|
||||
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
|
||||
if ( SurfB.m_vTria[nTB].nTempPart == 1) {
|
||||
int nNewVert[3] ;
|
||||
for ( int nV = 0 ; nV < 3 ; ++ nV) {
|
||||
nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ;
|
||||
bool bAdd = SurfB.m_vTria[nTB].nTempShell == 1 ;
|
||||
if ( ! bAdd) {
|
||||
// se ambiguo
|
||||
if ( SurfB.m_vTria[nTB].nTempShell == 0) {
|
||||
// aggiungo il triangolo se interno alla SurfA ( basta controllare un solo vertice(?) )
|
||||
DistPointSurfTm distCalculator( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[0]].ptP, SurfA_cl) ;
|
||||
bAdd = distCalculator.IsPointOnLeftSide() ;
|
||||
}
|
||||
}
|
||||
if ( bAdd) {
|
||||
int nNewVert[3] ;
|
||||
for ( int nV = 0 ; nV < 3 ; ++ nV)
|
||||
nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ;
|
||||
swap( nNewVert[1], nNewVert[2]) ;
|
||||
if ( nPrevMaxTFlag == m_nMaxTFlag)
|
||||
++ m_nMaxTFlag ;
|
||||
@@ -1786,22 +1761,23 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other)
|
||||
}
|
||||
}
|
||||
|
||||
// sistemazioni varie
|
||||
bool bOk = ( AdjustVertices() && DoCompacting()) ;
|
||||
|
||||
bool bModified = false ;
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
|
||||
bOk = bOk && RemoveTJunctions( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
|
||||
// scalo alle dimensioni originali
|
||||
Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ;
|
||||
|
||||
// semplifico le facce
|
||||
if ( ! SimplifyFacets())
|
||||
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Subtract")
|
||||
|
||||
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
@@ -1825,14 +1801,14 @@ SurfTriMesh::GetSurfClassification( const ISurfTriMesh& ClassifierSurf,
|
||||
SurfC.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
|
||||
|
||||
IntersectTriMeshTriangle( SurfC) ;
|
||||
IdentifyParts() ;
|
||||
IdentifyShells() ;
|
||||
Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ;
|
||||
|
||||
int nTriaNum = GetTriangleSize() ;
|
||||
for ( int nT = 0 ; nT < nTriaNum ; ++ nT) {
|
||||
if ( m_vTria[nT].nIdVert[0] == SVT_DEL)
|
||||
continue ;
|
||||
switch ( m_vTria[nT].nTempPart) {
|
||||
switch ( m_vTria[nT].nTempShell) {
|
||||
case -2 :
|
||||
vTriaOnM.push_back( nT) ;
|
||||
break ;
|
||||
@@ -1877,13 +1853,13 @@ SurfTriMesh::CutWithOtherSurf( const ISurfTriMesh& CutterSurf, bool bInVsOut, bo
|
||||
SurfC.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
|
||||
|
||||
IntersectTriMeshTriangle( SurfC) ;
|
||||
IdentifyParts() ;
|
||||
IdentifyShells() ;
|
||||
|
||||
int nPartToRemove = ( bInVsOut ? -1 : 1) ;
|
||||
int nCoplanarPartToRemove = ( bSaveOnEq ? ( nPartToRemove ? -2 : 2) : 5) ;
|
||||
int nTriaNum = GetTriangleSize() ;
|
||||
for ( int nT = 0 ; nT < nTriaNum ; ++ nT) {
|
||||
if ( m_vTria[nT].nTempPart == nPartToRemove || m_vTria[nT].nTempPart == nCoplanarPartToRemove)
|
||||
if ( m_vTria[nT].nTempShell == nPartToRemove || m_vTria[nT].nTempShell == nCoplanarPartToRemove)
|
||||
RemoveTriangle( nT) ;
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -15,10 +15,10 @@
|
||||
#include "CurveComposite.h"
|
||||
#include "SurfTriMesh.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "Triangulate.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
|
||||
@@ -79,7 +79,7 @@ SurfTriMesh::CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModi
|
||||
if ( m_vVert[i].nIdTria == SVT_DEL)
|
||||
continue ;
|
||||
double dDist = DistPointPlane( m_vVert[i].ptP, plPlane) ;
|
||||
if ( abs( dDist) < EPS_SMALL)
|
||||
if ( abs( dDist) < 1.1 * EPS_SMALL)
|
||||
m_vVert[i].nTemp = 0 ;
|
||||
else if ( dDist > 0)
|
||||
m_vVert[i].nTemp = +1 ;
|
||||
@@ -781,14 +781,14 @@ SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
|
||||
}
|
||||
}
|
||||
|
||||
// Ripristino scala originale
|
||||
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
|
||||
|
||||
// se superficie originale a facce, cerco di semplificarle in ogni caso
|
||||
if ( nFacetOriCnt < 200 || double( nTriaOriCnt) / nFacetOriCnt > 4) {
|
||||
if ( ! SimplifyFacets())
|
||||
if ( ! SimplifyFacets( CUT_SCALE * MAX_EDGE_LEN_STD))
|
||||
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::GeneralizedCut")
|
||||
}
|
||||
|
||||
// Ripristino scala originale
|
||||
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -901,7 +901,7 @@ SurfTriMesh::UpdateFacetEdging( void)
|
||||
int nTAdj = Tria.nIdAdjac[nE] ;
|
||||
if ( Tria.nETempFlag[nE] == 0) {
|
||||
if ( nTAdj == SVT_NULL) {
|
||||
m_vFacEdge.emplace_back( Tria.nIdVert[nE], Tria.nIdVert[nE2], Tria.nIdFacet, SVT_NULL, 0.) ;
|
||||
m_vFacEdge.emplace_back( Tria.nIdVert[nE], Tria.nIdVert[nE2], Tria.nIdFacet, SVT_NULL, 180.) ;
|
||||
}
|
||||
else if ( Tria.nIdFacet != m_vTria[nTAdj].nIdFacet) {
|
||||
// calcolo l'angolo tra le facce ( 0 = allineate, > 0 convesse, < 0 concave)
|
||||
|
||||
+52
-31
@@ -2,7 +2,7 @@
|
||||
// EgalTech 2021-2021
|
||||
//----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
//
|
||||
@@ -15,8 +15,8 @@
|
||||
#include "SurfTriMesh.h"
|
||||
#include "CurveLine.h"
|
||||
#include "Triangulate.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "DistLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std ;
|
||||
@@ -123,7 +123,7 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
|
||||
// Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro
|
||||
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
|
||||
// Se il triangolo non è valido, passo al successivo
|
||||
// Se il triangolo non è valido, passo al successivo
|
||||
Triangle3d trTria ;
|
||||
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
|
||||
continue ;
|
||||
@@ -138,7 +138,7 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
for ( int nSeg = 0 ; nSeg < 3 ; ++ nSeg) {
|
||||
// aggiungo al vettore il vertice iniziale del lato
|
||||
vVertOtl.emplace_back( m_vTria[nT].nIdVert[nSeg]) ;
|
||||
// Se in questo lato il triangolo è adiacente a un altro, lo salto.
|
||||
// Se in questo lato il triangolo è adiacente a un altro, lo salto.
|
||||
if ( m_vTria[nT].nIdAdjac[nSeg] != SVT_DEL && m_vTria[nT].nIdAdjac[nSeg] != SVT_NULL)
|
||||
continue ;
|
||||
int nPrevSize = int( vVertOtl.size()) ;
|
||||
@@ -152,7 +152,7 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
vtSeg /= dSegLen ;
|
||||
// Ciclo sui triangoli vicini
|
||||
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)
|
||||
continue ;
|
||||
// Cerco i vertici che stanno sul lato del triangolo
|
||||
@@ -175,11 +175,11 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
} ;
|
||||
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) {
|
||||
// Elimino i vertici ripetuti
|
||||
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)
|
||||
TriaMap.emplace( nT, vVertOtl) ;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
int nT = itT->first ;
|
||||
// Vettore degli altri vertici sul perimetro
|
||||
const INTVECTOR& vVertOtl = itT->second ;
|
||||
// Se il triangolo non è valido, passo al successivo
|
||||
// Se il triangolo non è valido, passo al successivo
|
||||
Triangle3d trTria ;
|
||||
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
|
||||
continue ;
|
||||
@@ -207,7 +207,7 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
int nLastNewTria = SVT_NULL ;
|
||||
// Se ci sono 4 vertici, inserisco due triangoli
|
||||
if ( vVertOtl.size() == 4) {
|
||||
// se 1-2-3 è triangolo (e quindi 0-1-3)
|
||||
// se 1-2-3 è triangolo (e quindi 0-1-3)
|
||||
int nNew1Id[3] = { vVertOtl[1], vVertOtl[2], vVertOtl[3]} ;
|
||||
int nNew1Tria = AddTriangle( nNew1Id, nTFlag) ;
|
||||
if ( nNew1Tria != SVT_NULL && nNew1Tria != SVT_DEL) {
|
||||
@@ -285,13 +285,13 @@ IsVertex( PNTULIST& PointList, PNTULIST::const_iterator itCurr)
|
||||
static bool
|
||||
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()))
|
||||
return true ;
|
||||
// altrimenti cerco il vertice più vicino
|
||||
// altrimenti cerco il vertice più vicino
|
||||
for ( auto it = next( PointList.begin()) ; it != PointList.end() ; ++it) {
|
||||
if ( IsVertex( PointList, it)) {
|
||||
// se ultimo punto non devo fare alcunché
|
||||
// se ultimo punto non devo fare alcunché
|
||||
if ( next( it) == PointList.end())
|
||||
return false ;
|
||||
// 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
|
||||
if ( itLast->second != it->second) {
|
||||
// Elimino i punti interni
|
||||
auto itNextToLast = next( itLast) ;
|
||||
for ( auto itInn = itNextToLast ; itInn != it ; ) {
|
||||
itInn = PointList.erase( itInn) ;
|
||||
bModif = true ;
|
||||
// Raccolgo i punti in una polyline
|
||||
PolyLine PL ;
|
||||
int nPar = -1 ;
|
||||
for ( auto itInn = itLast ; itInn != it ; ) {
|
||||
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
|
||||
double dSegLen = Dist( it->first, itLast->first) ;
|
||||
@@ -354,7 +375,7 @@ AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
|
||||
}
|
||||
// Se i punti sono allineati
|
||||
if ( bAreAligned) {
|
||||
// Verifico se il successivo punto non è più allineato
|
||||
// Verifico se il successivo punto non è più allineato
|
||||
auto itNextToCurr = next( it) ;
|
||||
if ( itNextToCurr != PointList.end()) {
|
||||
for ( auto itInn = itNextToLast ; itInn != itNextToCurr && bAreAligned ; ++ itInn) {
|
||||
@@ -402,7 +423,7 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// La trimesh deve essere valida
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
// Se la lunghezza massima del lato del triangolo sul bordo della faccia è nulla e non forzata, non devo fare alcunché
|
||||
// Se la lunghezza massima del lato del triangolo sul bordo della faccia è nulla e non forzata, non devo fare alcunché
|
||||
if ( dMaxEdgeLen < EPS_SMALL && ! bForced)
|
||||
return true ;
|
||||
|
||||
@@ -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() ;
|
||||
ResetHashGrids3d() ;
|
||||
|
||||
@@ -517,13 +538,13 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
bool
|
||||
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)
|
||||
return true ;
|
||||
// Se la catena originale è vuota, non è possibile aggiungere nulla
|
||||
// Se la catena originale è vuota, non è possibile aggiungere nulla
|
||||
if ( OrigChain.size() == 0)
|
||||
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) ;
|
||||
if ( AreSamePointApprox( OrigChain[0], OrigChain[nLastOrig]))
|
||||
return false ;
|
||||
@@ -562,11 +583,11 @@ SurfTriMesh::DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec,
|
||||
return false ;
|
||||
double dDistPtPl = DistPointPlane( ptP, plPlane) ;
|
||||
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 ;
|
||||
if ( ! IsPointInsidePolyLine( ptProjP, vPolyVec[0], EPS_SMALL))
|
||||
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) {
|
||||
Plane3d plPlane ;
|
||||
double dArea ;
|
||||
@@ -580,7 +601,7 @@ SurfTriMesh::DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec,
|
||||
dPointFacetDist = abs( dDistPtPl) ;
|
||||
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 ;
|
||||
if ( DistPointPolyLine( ptP, vPolyVec[nPtOut], dDist)) {
|
||||
dPointFacetDist = dDist ;
|
||||
@@ -593,7 +614,7 @@ SurfTriMesh::DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec,
|
||||
bool
|
||||
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 ;
|
||||
double dMinSqDinst = DBL_MAX ;
|
||||
for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) {
|
||||
@@ -657,7 +678,7 @@ SurfTriMesh::ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop)
|
||||
bool
|
||||
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 ;
|
||||
double dMinSqDinst = DBL_MAX ;
|
||||
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
|
||||
bool bFirst = AreSamePointApprox( Loop[nMinSeg], ptStop) ;
|
||||
bool bLast = AreSamePointApprox( Loop[( nMinSeg + 1) % int( Loop.size())], ptStop) ;
|
||||
// Se il punto è sul vertice finale del segmento, aggiungo il vertice alla lista da inglobare al primo loop
|
||||
// Se il punto è sul vertice finale del segmento, aggiungo il vertice alla lista da inglobare al primo loop
|
||||
if ( bLast)
|
||||
++ nMinSeg ;
|
||||
// Inglobo fino a nSeg nel primo loop
|
||||
for ( int nPt = 0 ; nPt <= nMinSeg && nPt < int( Loop.size()) ; ++ nPt)
|
||||
Loop1.emplace_back( Loop[nPt]) ;
|
||||
// Se il punto è interno al segmento, lo inglobo in entrambi i loop
|
||||
// Se il punto è interno al segmento, lo inglobo in entrambi i loop
|
||||
if ( ! ( bFirst || bLast)) {
|
||||
Loop1.emplace_back( ptStop) ;
|
||||
Loop2.emplace_back( ptStop) ;
|
||||
|
||||
@@ -580,3 +580,99 @@ Tool::SetChiselTool( const string& sToolName, double dH, double dW, double dTh,
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Tool::SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum)
|
||||
{
|
||||
// Impostazioni generali
|
||||
m_sName = sToolName ;
|
||||
m_nCurrentNum = nToolNum ;
|
||||
m_nType = UNDEF ;
|
||||
m_Outline.Clear() ;
|
||||
m_ArcLineApprox.Clear() ;
|
||||
|
||||
// Verifica sulle dimensioni
|
||||
if ( dH < 10 * EPS_SMALL || dR < 10 * EPS_SMALL || dRc < - EPS_SMALL || dR < dRc - EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// Assegnazione dati geometrici principali
|
||||
m_dHeight = dH ;
|
||||
m_dRadius = dR ;
|
||||
m_dRCorner = min( dRc, dR) ;
|
||||
if ( m_dRCorner < 10 * EPS_SMALL)
|
||||
m_dRCorner = 0 ;
|
||||
m_dTipHeight = 0 ;
|
||||
m_dTipRadius = 0 ;
|
||||
m_dRefRadius = 0 ;
|
||||
m_dCutterHeight = dH ;
|
||||
|
||||
// Utensile cilindrico con eventuale raggio corner (al limite sferico)
|
||||
if ( m_dRCorner <= m_dHeight / 2) {
|
||||
// Se Cilindrico
|
||||
if ( m_dRCorner < EPS_SMALL) {
|
||||
// inizio
|
||||
m_Outline.AddPoint( Point3d( 0, 0, 0)) ;
|
||||
// segmento orizzontale in alto
|
||||
m_Outline.AddLine( Point3d( m_dRadius, 0, 0)) ;
|
||||
m_Outline.SetCurveTempProp( 0, 1, 1) ;
|
||||
// segmento verticale
|
||||
m_Outline.AddLine( Point3d( m_dRadius, -m_dHeight, 0)) ;
|
||||
m_Outline.SetCurveTempProp( 1, 1, 1) ;
|
||||
// segmento orizzontale in basso
|
||||
m_Outline.AddLine( Point3d( 0, -m_dHeight, 0)) ;
|
||||
m_Outline.SetCurveTempProp( 2, 1, 1) ;
|
||||
}
|
||||
// Generico
|
||||
else {
|
||||
// inizio
|
||||
m_Outline.AddPoint( Point3d( 0, 0, 0)) ;
|
||||
int nInd = -1 ;
|
||||
// eventuale segmento orizzontale in alto
|
||||
if ( m_Outline.AddLine( Point3d( m_dRadius - m_dRCorner, 0, 0)))
|
||||
m_Outline.SetCurveTempProp( ++ nInd, 1, 1) ;
|
||||
// raggio corner in alto
|
||||
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, true, 2 * EPS_SMALL) ;
|
||||
m_Outline.SetCurveTempProp( ++ nInd, 1, 1) ;
|
||||
// eventuale segmento verticale
|
||||
if ( m_Outline.AddLine( Point3d( m_dRadius, -m_dHeight + m_dRCorner, 0)))
|
||||
m_Outline.SetCurveTempProp( ++ nInd, 1, 1) ;
|
||||
// raggio corner in basso
|
||||
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, true, 2 * EPS_SMALL) ;
|
||||
m_Outline.SetCurveTempProp( ++ nInd, 1, 1) ;
|
||||
// eventuale segmento orizzontale in basso
|
||||
if ( m_Outline.AddLine( Point3d( 0, -m_dHeight, 0)))
|
||||
m_Outline.SetCurveTempProp( ++ nInd, 1, 1) ;
|
||||
}
|
||||
m_Outline.SetTempProp( 1, 1) ;
|
||||
if ( ! SetGenTool( sToolName, &m_Outline, nToolNum))
|
||||
return false ;
|
||||
}
|
||||
// Utensile sfiancato
|
||||
else {
|
||||
double dCenX = m_dRadius - m_dRCorner ;
|
||||
double dCylRad = dCenX + sqrt( m_dRCorner * m_dRCorner - m_dHeight * m_dHeight / 4) ;
|
||||
// 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) ;
|
||||
if ( ! SetGenTool( sToolName, &m_Outline, nToolNum))
|
||||
return false ;
|
||||
}
|
||||
|
||||
m_nType = ADDITIVE ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ class Tool
|
||||
bool SetGenTool( const std::string& sToolName, const ICurveComposite* pToolOutline, int nToolNum) ;
|
||||
bool SetMortiserTool( const std::string& sToolName, double dH, double dW, double dTh, double dRc, int nToolNum) ;
|
||||
bool SetChiselTool( const std::string& sToolName, double dH, double dW, double dTh, int nToolNum) ;
|
||||
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) ;
|
||||
bool SetToolNum( int nToolNum)
|
||||
{ m_nCurrentNum = nToolNum ; return true ; }
|
||||
int GetType() const
|
||||
@@ -70,7 +71,8 @@ class Tool
|
||||
BULLNOSEMILL = 4, // Naso di toro
|
||||
CONEMILL = 5, // Con parte terminale conica
|
||||
MORTISER = 6, // Mortasatrice
|
||||
CHISEL = 7} ; // Scalpello
|
||||
CHISEL = 7, // Scalpello
|
||||
ADDITIVE = 8} ; // Additivo
|
||||
|
||||
private :
|
||||
bool ModifyForCutterHeight( void) ;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "GeoConst.h"
|
||||
#include "CurveLine.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include <map>
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -27,11 +28,12 @@ struct Inters {
|
||||
int nOut ;
|
||||
bool bCCW ;
|
||||
int nChunk ;
|
||||
bool bSortedbyStart ;
|
||||
// riordino le intersezioni per lato in senso antiorario dal top
|
||||
// se ho pi� intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
|
||||
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
|
||||
bool operator < ( Inters& b)
|
||||
{
|
||||
// trovo in che ordine stanno i due strat, tenendo conto anche della possibilit� che siano vertici
|
||||
// trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
|
||||
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
|
||||
const auto iter1 = find( vEdges.begin(), vEdges.end(), nIn) ;
|
||||
int nPos1 = std::distance( vEdges.begin(), iter1) ;
|
||||
@@ -52,7 +54,7 @@ struct Inters {
|
||||
pl.Close() ;
|
||||
pl.GetAreaXY( dAreaB) ;
|
||||
}
|
||||
// se nIn � un vertice sistemo il valore
|
||||
// se nIn è un vertice sistemo il valore
|
||||
int nEdgeIn = nIn ;
|
||||
if ( nIn > 3)
|
||||
nEdgeIn = nIn - 4 ;
|
||||
@@ -63,6 +65,67 @@ struct Inters {
|
||||
( bEqIn && nEdgeIn == 2 && vpt[0].x < b.vpt[0].x) ||
|
||||
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ;
|
||||
}
|
||||
|
||||
static bool FirstEncounter ( Inters& a, Inters& b)
|
||||
{
|
||||
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
|
||||
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
|
||||
// nell'intersezione salvo se il taglio è stato ordinato guardando l'ingresso o l'uscita
|
||||
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
|
||||
// trovo i lati di ingresso e uscita
|
||||
const auto iter1 = find( vEdges.begin(), vEdges.end(), a.nIn) ;
|
||||
int nPos1 = std::distance( vEdges.begin(), iter1) ;
|
||||
const auto iter2 = find( vEdges.begin(), vEdges.end(), a.nOut) ;
|
||||
int nPos2 = std::distance( vEdges.begin(), iter2) ;
|
||||
const auto iter3 = find( vEdges.begin(), vEdges.end(), b.nIn) ;
|
||||
int nPos3 = std::distance( vEdges.begin(), iter3) ;
|
||||
const auto iter4 = find( vEdges.begin(), vEdges.end(), b.nOut) ;
|
||||
int nPos4 = std::distance( vEdges.begin(), iter4) ;
|
||||
int nFirstA = 0 ;
|
||||
int nFirstB = 0 ;
|
||||
// salvo l'indice del primo punto dell'intersezione che ho incontrato scorrendo il bordo da ptTR
|
||||
// salvo il lato che viene prima confrontando ingresso e uscita
|
||||
if ( nPos2 < nPos1) {
|
||||
nPos1 = nPos2 ;
|
||||
nFirstA = int( a.vpt.size()) - 1 ;
|
||||
}
|
||||
// se ingresso e uscita sono sullo stesso lato allora confronto le coordinate per capire se viene prima l'ingresso o l'uscita
|
||||
else if ( nPos2 == nPos1 ) {
|
||||
if ( nPos1 == 0 )
|
||||
nFirstA = a.vpt[0].x > a.vpt.back().x ? 0 : ( int( a.vpt.size()) - 1) ;
|
||||
else if ( nPos1 == 1 )
|
||||
nFirstA = a.vpt[0].y > a.vpt.back().y ? 0 : ( int( a.vpt.size()) - 1) ;
|
||||
else if ( nPos1 == 2 )
|
||||
nFirstA = a.vpt[0].x < a.vpt.back().x ? 0 : ( int( a.vpt.size()) - 1) ;
|
||||
else if ( nPos1 == 3 )
|
||||
nFirstA = a.vpt[0].y < a.vpt.back().y ? 0 : ( int( a.vpt.size()) - 1) ;
|
||||
}
|
||||
if ( nPos4 < nPos3) {
|
||||
nPos3 = nPos4 ;
|
||||
nFirstB = int( b.vpt.size()) - 1 ;
|
||||
}
|
||||
else if ( nPos4 == nPos3 ) {
|
||||
if ( nPos3 == 0 )
|
||||
nFirstB = b.vpt[0].x > b.vpt.back().x ? 0 : ( int( b.vpt.size()) - 1) ;
|
||||
else if ( nPos3 == 1 )
|
||||
nFirstB = b.vpt[0].y > b.vpt.back().y ? 0 : ( int( b.vpt.size()) - 1) ;
|
||||
else if ( nPos3 == 2 )
|
||||
nFirstB = b.vpt[0].x < b.vpt.back().x ? 0 : ( int( b.vpt.size()) - 1) ;
|
||||
else if ( nPos3 == 3 )
|
||||
nFirstB = b.vpt[0].y < b.vpt.back().y ? 0 : ( int( b.vpt.size()) - 1) ;
|
||||
}
|
||||
a.bSortedbyStart = nFirstA == 0 ;
|
||||
b.bSortedbyStart = nFirstB == 0 ;
|
||||
// se sono diversi ritorno il confronto
|
||||
if ( nPos1 != nPos3)
|
||||
return nPos1 < nPos3 ;
|
||||
// se sono uguali devo valutare il punto di intersezione
|
||||
return ( nPos1 == 0 && a.vpt[nFirstA].x > b.vpt[nFirstB].x) ||
|
||||
( nPos1 == 1 && a.vpt[nFirstA].y > b.vpt[nFirstB].y) ||
|
||||
( nPos1 == 2 && a.vpt[nFirstA].x < b.vpt[nFirstB].x) ||
|
||||
( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ;
|
||||
}
|
||||
|
||||
bool operator == ( Inters& b)
|
||||
{
|
||||
return AreSamePointExact( vpt[0], b.vpt[0]) ;
|
||||
@@ -73,8 +136,8 @@ struct Inters {
|
||||
}
|
||||
} ;
|
||||
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
|
||||
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da l� in senso antiorario
|
||||
// -1 se la curva � sempre dentro la cella
|
||||
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
|
||||
// -1 se la curva è sempre dentro la cella
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class Cell
|
||||
@@ -116,6 +179,10 @@ class Cell
|
||||
{ return m_ptPbl ; }
|
||||
Point3d GetTopRight( void) const
|
||||
{ return m_ptPtr ; }
|
||||
Point3d GetTopLeft( void) const
|
||||
{ return Point3d( m_ptPbl.x, m_ptPtr.y) ; }
|
||||
Point3d GetBottomRight( void) const
|
||||
{ return Point3d( m_ptPtr.x, m_ptPbl.y); }
|
||||
double GetSplitValue( void) const
|
||||
{ return m_dSplit ; }
|
||||
bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, senn� orizzontalmente
|
||||
@@ -138,24 +205,24 @@ class Cell
|
||||
int m_nLeft ; // cella adiacente al lato left
|
||||
int m_nRight ; // cella adiacente al lato right
|
||||
int m_nParent ; // cella genitore
|
||||
int m_nDepth ; // profondit� della cella rispetto a root
|
||||
double m_dSplit ; // parametro a cui � stata splittata la cella
|
||||
int m_nDepth ; // profondità della cella rispetto a root
|
||||
double m_dSplit ; // parametro a cui è stata splittata la cella
|
||||
int m_nChild1 ; // prima cella figlio
|
||||
int m_nChild2 ; // seconda cella figlio
|
||||
int m_nFlag ; // falg che indica la caratterizzazione della cella rispetto ai loop di trim
|
||||
// 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop
|
||||
int m_nFlag2 ; // falg che indica se la cella � stata attraversata durante l'ultima fase del labelling
|
||||
int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 met� e met�
|
||||
bool m_bOnLeftEdge ; // flag che indica se la cella � sul lato sinistro ( per superfici chiuse sul parametro U)
|
||||
bool m_bOnTopEdge ; // flag che indica se la cella � sul lato top ( per superfici chiuse sul parametro V)
|
||||
int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling
|
||||
int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà
|
||||
bool m_bOnLeftEdge ; // flag che indica se la cella è sul lato sinistro ( per superfici chiuse sul parametro U)
|
||||
bool m_bOnTopEdge ; // flag che indica se la cella è sul lato top ( per superfici chiuse sul parametro V)
|
||||
std::vector<Inters> m_vInters ; // vettore delle intersezioni della cella con i loop di trim
|
||||
// ogni elemento del vettore � l'insieme dei punti che caratterizza un atrtaversamento della cella
|
||||
// ogni elemento del vettore è l'insieme dei punti che caratterizza un attraversamento della cella
|
||||
|
||||
private :
|
||||
Point3d m_ptPbl ; // punto bottom left
|
||||
Point3d m_ptPtr ; // punto top right
|
||||
bool m_bProcessed ; // flag che indica se la cella � stata processata
|
||||
bool m_bSplitVert ; // flag che indica in quale direzione � stata divisa la cella
|
||||
bool m_bProcessed ; // flag che indica se la cella è stata processata
|
||||
bool m_bSplitVert ; // flag che indica in quale direzione è stata divisa la cella
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -164,19 +231,30 @@ class Tree
|
||||
public :
|
||||
~Tree( void) ;
|
||||
Tree( void) ;
|
||||
Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
|
||||
void SetSurf( 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
|
||||
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 BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax � il massimo per la dimensione maggiore di un triangolo della trimesh
|
||||
// dSideMin � lunghezza minima del lato di una cella nello spazio reale
|
||||
bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ;
|
||||
bool GetPolygons( POLYLINEMATRIX& vPolygons) ;
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
|
||||
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
|
||||
// ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
|
||||
bool GetLeaves ( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero
|
||||
bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline
|
||||
bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle
|
||||
{ for ( int i = 0 ; i < int( m_vPlLoop2D.size()); ++i) vPl.emplace_back( m_vPlLoop2D[i]) ; return true ; };
|
||||
void SetTestMode( void) { m_bTestMode = true ;} ; // attivando la test mode, per la costruzione dell'albero viene usata la funzione BuiltTree_test e viene corretta di conseguenza la FindCell
|
||||
// funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico
|
||||
bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree
|
||||
bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli
|
||||
bool IsClosedU( void) const { return m_bClosedU ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro U
|
||||
bool IsClosedV( void) const { return m_bClosedV ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro V
|
||||
std::vector<bool> GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli
|
||||
|
||||
private :
|
||||
bool 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) ; // 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
|
||||
@@ -205,19 +283,27 @@ class Tree
|
||||
bool CategorizeCell( int nId) ; // categorizza la cella in base al flag m_nFlag (dentro, fuori, intersecata)
|
||||
bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW)
|
||||
bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ; // indica a quale edge o vertice il punto è vicino entro EPS_SMALL
|
||||
bool AdjustCuts( void) ;
|
||||
bool UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) ;
|
||||
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 :
|
||||
const SurfBezier* m_pSrfBz ; // superficie di bezier
|
||||
DBLVECTOR m_vDim ; // distanze tra i vertici della superficie di bezier in 3d in ordine antiorario a partire da ptP00
|
||||
bool m_bTrimmed ; // superficie trimmata
|
||||
INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk
|
||||
//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
|
||||
ICURVEPOVECTOR m_vLoop ; // curve di loop
|
||||
std::vector<std::tuple<PolyLine,bool>> m_vPlApprox ; // vettore contenente le approssimazioni dei 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
|
||||
bool m_bBilinear ; // superficie bilineare
|
||||
bool m_bMulti ; // superficie multi-patch
|
||||
bool m_bClosedU ; // superficie chiusa lungo il parametro U
|
||||
bool m_bClosedV ; // superficie chiusa lungo il parametro V
|
||||
BOOLVECTOR m_vbPole ; // vettore che indica se i vari lati sono collassati in poli ( indici riferiti all'ordine degli edge)
|
||||
bool m_bSplitPatches ; // flag che indica se le patches sono state divise prima della creazione dell'albero
|
||||
int m_nDegU ; // grado della superficie nel parametro U
|
||||
int m_nDegV ; // grado della superficie nel parametro V
|
||||
@@ -229,4 +315,6 @@ class Tree
|
||||
INTVECTOR m_vnLeaves ; // vettore delle foglie
|
||||
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
|
||||
bool m_bTestMode ; // bool che indica se la test mode è attiva
|
||||
POLYLINEVECTOR m_vPlLoop2D ; // vettore che contiene le polyline che rappresentano i loop di trim tenendo conto della divisione in celle
|
||||
std::vector<std::pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
|
||||
} ;
|
||||
+1
-1
@@ -1225,7 +1225,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
|
||||
dMinDist = dZ - ptP.z ;
|
||||
nI = ( vPt[i].z >= vPt[j].z) ? i : j ;
|
||||
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 ;
|
||||
|
||||
@@ -169,6 +169,10 @@ Vector3d::ToSpherical( double* pdLen, double* pdAngVertDeg, double* pdAngOrizzDe
|
||||
bool
|
||||
Vector3d::Normalize( double dEps)
|
||||
{
|
||||
// verifico validità
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// se già normalizzato, ok
|
||||
double dSqLen = x * x + y * y + z * z ;
|
||||
if ( abs( 1.0 - dSqLen) < ( 2 * 1000 * DBL_EPSILON))
|
||||
|
||||
+253
-14
@@ -14,16 +14,18 @@
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "VolZmap.h"
|
||||
#include "DistPointLine.h"
|
||||
#include "GeoObjFactory.h"
|
||||
#include "GdbGeo.h"
|
||||
#include "NgeWriter.h"
|
||||
#include "NgeReader.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include <thread>
|
||||
#include <future>
|
||||
|
||||
@@ -34,7 +36,8 @@ GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
VolZmap::VolZmap(void)
|
||||
: m_nStatus( TO_VERIFY), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_dStep( 10.0), m_nMapNum( 0), m_nShape( GENERIC), m_nVoxNumPerBlock( N_VOXBLOCK),
|
||||
: m_nStatus( TO_VERIFY), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_bShowEdges( false),
|
||||
m_dStep( 10.0), m_nMapNum( 0), m_nShape( GENERIC), m_nVoxNumPerBlock( N_VOXBLOCK),
|
||||
m_nDexVoxRatio( 1), m_nNumBlock( 0), m_nConnectedCompoCount( 0), m_nCurrTool( -1),
|
||||
m_dToolLinTol( LIN_TOL_STD), m_dToolAngTolDeg( ANG_TOL_APPROX_DEG)
|
||||
{
|
||||
@@ -47,7 +50,6 @@ VolZmap::VolZmap(void)
|
||||
m_nFracLin[i] = 0 ;
|
||||
}
|
||||
m_vTool.resize( 1) ;
|
||||
m_nCurrTool = 0 ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -60,8 +62,16 @@ bool
|
||||
VolZmap::Clear( void)
|
||||
{
|
||||
m_nStatus = TO_VERIFY ;
|
||||
m_nTempProp[0] = 0 ;
|
||||
m_nTempProp[1] = 0 ;
|
||||
m_dTempParam[0] = 0.0 ;
|
||||
m_dTempParam[1] = 0.0 ;
|
||||
m_bShowEdges = false ;
|
||||
m_dStep = 10.0 ;
|
||||
m_nMapNum = 0 ;
|
||||
m_nShape = GENERIC ;
|
||||
m_nVoxNumPerBlock = N_VOXBLOCK ;
|
||||
m_nDexVoxRatio = 1 ;
|
||||
m_nNumBlock = 0 ;
|
||||
m_nConnectedCompoCount = 0 ;
|
||||
m_MapFrame.Reset() ;
|
||||
@@ -73,17 +83,12 @@ VolZmap::Clear( void)
|
||||
m_dMaxZ[i] = 0 ;
|
||||
m_Values[i].clear() ;
|
||||
}
|
||||
m_dStep = EPS_SMALL ;
|
||||
m_nTempProp[0] = 0 ;
|
||||
m_nTempProp[1] = 0 ;
|
||||
m_dTempParam[0] = 0.0 ;
|
||||
m_dTempParam[1] = 0.0 ;
|
||||
m_vTool.resize( 1) ;
|
||||
m_nCurrTool = 0 ;
|
||||
m_dToolLinTol = LIN_TOL_STD ;
|
||||
m_dToolAngTolDeg = ANG_TOL_APPROX_DEG ;
|
||||
// imposto ricalcolo della grafica
|
||||
m_OGrMgr.Reset() ;
|
||||
// imposto ri-creazione della grafica
|
||||
m_OGrMgr.Clear() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -150,6 +155,7 @@ VolZmap::CopyFrom( const VolZmap& vzmSrc)
|
||||
m_nTempProp[1] = vzmSrc.m_nTempProp[1] ;
|
||||
m_dTempParam[0] = vzmSrc.m_dTempParam[0] ;
|
||||
m_dTempParam[1] = vzmSrc.m_dTempParam[1] ;
|
||||
m_bShowEdges = vzmSrc.m_bShowEdges ;
|
||||
|
||||
// dimensiono membri legati ai blocchi
|
||||
m_BlockToUpdate = vzmSrc.m_BlockToUpdate ;
|
||||
@@ -175,7 +181,7 @@ VolZmap::CopyFrom( const VolZmap& vzmSrc)
|
||||
bool
|
||||
VolZmap::ResetGraphics( void)
|
||||
{
|
||||
m_OGrMgr.Reset() ;
|
||||
m_OGrMgr.Clear() ;
|
||||
for ( int nCount = 0 ; nCount < m_nNumBlock ; ++ nCount)
|
||||
m_BlockToUpdate[nCount] = true ;
|
||||
return true ;
|
||||
@@ -318,6 +324,27 @@ VolZmap::Save( NgeWriter& ngeOut) const
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::PreSave( GdbGeo& Wrapper) const
|
||||
{
|
||||
// salvo il flag di visualizzazione spigoli vivi anche in shading (default false)
|
||||
if ( m_bShowEdges)
|
||||
Wrapper.SetInfo( GDB_SI_SHOWEDGES, true) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::PostSave( GdbGeo& Wrapper) const
|
||||
{
|
||||
// elimino eventuali info aggiunte nella PreSave
|
||||
Wrapper.RemoveInfo( GDB_SI_SHOWEDGES) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::Load( NgeReader& ngeIn)
|
||||
@@ -430,6 +457,20 @@ VolZmap::Load( NgeReader& ngeIn)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::PostLoad( GdbGeo& Wrapper)
|
||||
{
|
||||
// recupero eventuale flag di visualizzazione spigoli vivi anche in shading
|
||||
bool bVal ;
|
||||
if ( Wrapper.GetInfo( GDB_SI_SHOWEDGES, bVal)) {
|
||||
m_bShowEdges = bVal ;
|
||||
Wrapper.RemoveInfo( GDB_SI_SHOWEDGES) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
||||
@@ -1460,7 +1501,187 @@ VolZmap::GetPartMinDistFromPoint( const Point3d& ptP) const
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
|
||||
VolZmap::AddSurfTm( const ISurfTriMesh* pStm)
|
||||
{
|
||||
// controllo sulla superficie
|
||||
double dVol ;
|
||||
if ( pStm == nullptr || ! pStm->IsValid() || ! pStm->IsClosed() ||
|
||||
! pStm->GetVolume( dVol) || dVol < 0)
|
||||
return false ;
|
||||
|
||||
// controllo se il Box3d della superficie si interseca con il Box3d dello Zmap corrente
|
||||
BBox3d BBox_stm, BBox_curr ;
|
||||
if ( ! pStm->GetLocalBBox( BBox_stm) || ! GetLocalBBox( BBox_curr))
|
||||
return false ;
|
||||
BBox3d BBox_inters ;
|
||||
if ( BBox_stm.FindIntersection( BBox_curr, BBox_inters) && BBox_inters.IsEmpty())
|
||||
return true ; // se non ci sono intersezioni, la superficie non influenza lo Zmap
|
||||
Vector3d vtLen = BBox_curr.GetMax() - BBox_curr.GetMin() ; // dimensione massima dello spillone
|
||||
|
||||
// ciclo sulle griglie
|
||||
bool bCompleted = true ;
|
||||
for ( int g = 0 ; g < m_nMapNum ; ++ g) {
|
||||
// definisco dei sistemi di riferimento ausiliari
|
||||
Frame3d frMapFrame ;
|
||||
if ( g == 0)
|
||||
frMapFrame = m_MapFrame ;
|
||||
else if ( g == 1)
|
||||
frMapFrame.Set( m_MapFrame.Orig(), Y_AX, Z_AX, X_AX) ;
|
||||
else if ( g == 2)
|
||||
frMapFrame.Set( m_MapFrame.Orig(), Z_AX, X_AX, Y_AX) ;
|
||||
|
||||
// oggetto per calcolo massivo intersezioni
|
||||
IntersParLinesSurfTm intPLSTM( frMapFrame, *pStm) ;
|
||||
|
||||
// numero massimo di thread
|
||||
int nThreadMax = max( 1, int( thread::hardware_concurrency()) - 1) ;
|
||||
vector<future<bool>> vRes ;
|
||||
vRes.resize( nThreadMax) ;
|
||||
// se dimensione griglia in X maggiore di dimensione Y
|
||||
if ( m_nNx[g] > m_nNy[g]) {
|
||||
int nDexNum = m_nNx[g] / nThreadMax ;
|
||||
int nRemainder = m_nNx[g] % nThreadMax ;
|
||||
int nInfI = 0 ;
|
||||
int nSupI = 0 ;
|
||||
// aggiungo le parti interessate alla mappa
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfI = nSupI ;
|
||||
nSupI = nInfI + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, g,
|
||||
nInfI, nSupI, 0, m_nNy[g], ref( vtLen), ref( m_MapFrame.Orig()),
|
||||
ref( *pStm), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
// se dimensione griglia in Y maggiore di dimensione X
|
||||
else {
|
||||
int nDexNum = m_nNy[g] / nThreadMax ;
|
||||
int nRemainder = m_nNy[g] % nThreadMax ;
|
||||
int nInfJ = 0 ;
|
||||
int nSupJ = 0 ;
|
||||
// aggiungo le parti interessate alla mappa
|
||||
for ( int nThread = 0 ; nThread < nThreadMax ; ++ nThread) {
|
||||
nInfJ = nSupJ ;
|
||||
nSupJ = nInfJ + ( nThread < nRemainder ? nDexNum + 1 : nDexNum) ;
|
||||
vRes[nThread] = async( launch::async, &VolZmap::AddMapPart, this, g,
|
||||
0, m_nNx[g], nInfJ, nSupJ, ref( vtLen), ref( m_MapFrame.Orig()),
|
||||
ref( *pStm), ref( intPLSTM)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// ciclo per attendere che tutti gli async abbiano terminato.
|
||||
int nTerminated = 0 ;
|
||||
while ( nTerminated < nThreadMax) {
|
||||
for ( int nL = 0 ; nL < nThreadMax ; ++ nL) {
|
||||
// async terminato
|
||||
if ( vRes[nL].valid() && vRes[nL].wait_for( chrono::microseconds{ 1}) == future_status::ready) {
|
||||
++ nTerminated ;
|
||||
bCompleted = bCompleted && vRes[nL].get() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! bCompleted)
|
||||
return false ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::MakeUniform( double dToler)
|
||||
{
|
||||
// controllo validità dello Zmap
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
// la tolleranza deve essere minore dello step
|
||||
dToler = min( dToler, 0.95 * m_dStep) ;
|
||||
|
||||
// creo lo Zmpa che andrà a sostituire il corrente
|
||||
PtrOwner<VolZmap> pOldVolZmap( CloneBasicVolZmap( this)) ;
|
||||
if ( IsNull( pOldVolZmap))
|
||||
return false ;
|
||||
|
||||
// ciclo sulle griglie
|
||||
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
|
||||
// salvo lo Zmap prima di modificare gli spilloni
|
||||
PtrOwner<VolZmap> pVolZMapCurrGrid( CloneBasicVolZmap( this)) ;
|
||||
if ( IsNull( pVolZMapCurrGrid))
|
||||
return false ;
|
||||
// ciclo sul numero di dexel presenti
|
||||
for ( int nDex = 0 ; nDex < int( m_Values[nGrid].size()) ; ++ nDex) {
|
||||
// se il dexel corrente non ha sotto-intervalli passo al successivo
|
||||
if ( int( m_Values[nGrid][nDex].size()) == 0)
|
||||
continue ;
|
||||
// indici del dexel
|
||||
int nI = nDex % m_nNx[nGrid] ;
|
||||
int nJ = nDex / m_nNx[nGrid] ;
|
||||
// salvo le informazioni dei sotto-intervalli del dexel corrente
|
||||
vector<Data> vInfo ;
|
||||
for ( int nExtr = 0 ; nExtr < int( m_Values[nGrid][nDex].size()) ; ++ nExtr)
|
||||
vInfo.push_back( m_Values[nGrid][nDex][nExtr]) ;
|
||||
// per ogni sotto-intervallo, estendo a destra e a sinistra della tolleranza
|
||||
int nSub_intervals = int( vInfo.size()) ;
|
||||
// scorro gli intervalli
|
||||
for ( int nInfo = 0 ; nInfo < int( pVolZMapCurrGrid->m_Values[nGrid][nDex].size()) ; ++ nInfo) {
|
||||
// estremo inferiore
|
||||
if ( vInfo[nInfo].dMin - dToler > m_dMinZ[nGrid]) {
|
||||
AddIntervals( nGrid, nI, nJ,
|
||||
vInfo[nInfo].dMin - dToler,
|
||||
vInfo[nInfo].dMin + dToler,
|
||||
vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN, vInfo[nInfo].nToolMin,
|
||||
true) ;
|
||||
// se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due
|
||||
// direzioni nel voxel corrispondente
|
||||
if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL &&
|
||||
nSub_intervals != int( m_Values[nGrid][nDex].size())) {
|
||||
nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti
|
||||
// l'intervallo corrente si è unito con il precedente...
|
||||
AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMin, dToler,
|
||||
vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN,
|
||||
vInfo[nInfo].nToolMin) ;
|
||||
}
|
||||
}
|
||||
// estremo superiore
|
||||
if ( vInfo[nInfo].dMax + dToler < m_dMaxZ[nGrid]) {
|
||||
AddIntervals( nGrid, nI, nJ,
|
||||
vInfo[nInfo].dMax - dToler,
|
||||
vInfo[nInfo].dMax + dToler,
|
||||
vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN, vInfo[nInfo].nToolMax,
|
||||
true) ;
|
||||
if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL &&
|
||||
nSub_intervals != int( m_Values[nGrid][nDex].size())) {
|
||||
nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti
|
||||
AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMax, dToler,
|
||||
vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN,
|
||||
vInfo[nInfo].nToolMax) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// per ogni sotto-intervallo ricavato fino ad ora, restringo della tolleranza
|
||||
// ( NB. avendo aggiunto intervalli, il dexel può modificare la sua struttura interna )
|
||||
for ( int nInfo = 0 ; nInfo < int( m_Values[nGrid][nDex].size()) ; ++ nInfo) {
|
||||
// ( NB. la rimozione di un intervallo ora va definita per intervalli a destra e a sinistra,
|
||||
// altrimenti rimuovo parti in eccesso )
|
||||
if ( ! pVolZMapCurrGrid->m_Values[nGrid][nDex].empty()) {
|
||||
if ( nInfo != 0 ||
|
||||
pVolZMapCurrGrid->m_Values[nGrid][nDex][0].dMin - dToler > m_dMinZ[nGrid])
|
||||
m_Values[nGrid][nDex][nInfo].dMin += dToler ;
|
||||
if ( nInfo != int( m_Values[nGrid][nDex].size()) - 1 ||
|
||||
pVolZMapCurrGrid->m_Values[nGrid][nDex].back().dMax + dToler < m_dMaxZ[nGrid])
|
||||
m_Values[nGrid][nDex][nInfo].dMax -= dToler ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
|
||||
{
|
||||
// Controllo sulla validità della griglia
|
||||
if ( nGrid < 0 || nGrid > 2)
|
||||
@@ -1620,12 +1841,12 @@ VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
|
||||
bool
|
||||
VolZmap::IsMapPartABox( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, double& dMinZ, double& dMaxZ)
|
||||
{
|
||||
if ( ! m_bIsBox)
|
||||
return true ;
|
||||
dMinZ = m_dMaxZ[nMap] ;
|
||||
dMaxZ = m_dMinZ[nMap] ;
|
||||
for ( int i = nInfI ; i < nSupI ; ++ i) {
|
||||
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
|
||||
if ( ! m_bIsBox)
|
||||
return true ;
|
||||
int n = j * m_nNx[nMap] + i ;
|
||||
int nSize = int( m_Values[nMap][n].size()) ;
|
||||
if ( nSize > 1)
|
||||
@@ -2131,6 +2352,24 @@ VolZmap::SetChiselTool( const string& sToolName, double dH, double dW, double dT
|
||||
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
|
||||
VolZmap::GetToolCount( void) const
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2023
|
||||
// EgalTech 2015-2024
|
||||
//----------------------------------------------------------------------------
|
||||
// File : VolZmap.h Data : 12.09.23 Versione : 2.5i1
|
||||
// File : VolZmap.h Data : 22.04.24 Versione : 2.6d4
|
||||
// Contenuto : Dichiarazione della classe Volume Zmap.
|
||||
//
|
||||
//
|
||||
@@ -17,12 +17,15 @@
|
||||
#include "GeoObjRW.h"
|
||||
#include "Tool.h"
|
||||
#include "/EgtDev/Include/EGkVolZmap.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
|
||||
#include <unordered_map>
|
||||
#include <stack>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
|
||||
// ------------------------- FORWARD -------------------------------------------------------------
|
||||
class IntersParLinesSurfTm ;
|
||||
|
||||
// ------------------------- STRUTTURE -----------------------------------------------------------
|
||||
struct AppliedVector {
|
||||
Point3d ptPApp ;
|
||||
@@ -75,6 +78,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
|
||||
bool Clear( void) override ;
|
||||
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) override ;
|
||||
int GetBlockCount( void) const override ;
|
||||
@@ -88,6 +92,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
int GetResolution( void) const override
|
||||
{ return m_nDexVoxRatio ; }
|
||||
bool ChangeResolution( int nDexVoxRatio) override ;
|
||||
void SetShowEdges( bool bShow) override
|
||||
{ m_bShowEdges = bShow ; // qui è necessario far ricreare la grafica
|
||||
m_OGrMgr.Clear() ; }
|
||||
bool GetShowEdges( void) const override
|
||||
{ return m_bShowEdges ; }
|
||||
bool SetToolTolerances( double dLinTol, double dAngTolDeg = 90) override ;
|
||||
bool SetStdTool( const std::string& sToolName,
|
||||
double dH, double dR, double dCornR, double dCutterH, int nFlag, bool bFirst) override ;
|
||||
@@ -101,6 +110,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
double dH, double dW, double dTh, double dRc, int nFlag, bool bFirst) override ;
|
||||
bool SetChiselTool( const std::string& sToolName,
|
||||
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 ;
|
||||
bool SetCurrTool( int nCurrTool) override ;
|
||||
bool ResetTools( void) override ;
|
||||
@@ -112,8 +123,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
|
||||
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) override ;
|
||||
bool GetDepth( const Point3d& ptP, const Vector3d& vtD, double& dInLength, double& dOutLength, bool bExact) const override ;
|
||||
bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const override ;
|
||||
bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const override ;
|
||||
bool CDeBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool CDeSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bool bPrecise = false) const override ;
|
||||
bool CDeCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise = false) const override ;
|
||||
@@ -134,11 +143,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
VolZmap* ClonePart( int nPart) const override ;
|
||||
bool RemovePart( int nPart) override ;
|
||||
int GetPartMinDistFromPoint( const Point3d& ptP) const override ;
|
||||
bool AddSurfTm( const ISurfTriMesh* pStm) override ;
|
||||
bool MakeUniform( double dToler) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
bool Save( NgeWriter& ngeOut) const override ;
|
||||
bool PreSave( GdbGeo& Wrapper) const override ;
|
||||
bool PostSave( GdbGeo& Wrapper) const override ;
|
||||
bool Load( NgeReader& ngeIn) override ;
|
||||
bool PostLoad( GdbGeo& Wrapper) override ;
|
||||
|
||||
public :
|
||||
VolZmap( void) ;
|
||||
@@ -149,6 +163,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
{ if ( ! CopyFrom( stSrc))
|
||||
LOG_ERROR( GetEGkLogger(), "VolZmap : copy error")
|
||||
return *this ; }
|
||||
bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const ;
|
||||
bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const ;
|
||||
|
||||
private :
|
||||
enum CubeType { VOX_EXTERN = 1,
|
||||
@@ -189,22 +205,18 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
std::vector<BOOLVECTOR> vbFlipped ;
|
||||
} ;
|
||||
// Triangoli smooth
|
||||
struct SmoothTriaStruct {
|
||||
struct SmoothTriaStruct {
|
||||
int i, j, k ;
|
||||
TRIA3DEXVECTOR vTria ;
|
||||
};
|
||||
// Vettore di SharpTriaStruct con sharp feature
|
||||
typedef std::vector<SharpTriaStruct> SharpTriHolder ;
|
||||
// Vettore di SmoothTriaStruct con triangoli smooth
|
||||
typedef std::vector<SmoothTriaStruct> SmoothTriHolder ;
|
||||
// Vettore di SharpTriHolder con sharp feature: il primo indice individua il blocco, il secondo il voxel
|
||||
typedef std::vector<SharpTriHolder> SharpTriaMatrix ;
|
||||
// Vettore di SmoothTriHolder smooth: il primo indice individua il blocco, il secondo il voxel
|
||||
typedef std::vector<SmoothTriHolder> SmoothTriaMatrix ;
|
||||
} ;
|
||||
// Matrice di SharpTriaStruct con sharp feature: il primo indice individua il blocco, il secondo il voxel
|
||||
typedef std::vector<std::vector<SharpTriaStruct>> SharpTriaMatrix ;
|
||||
// Matrice di SmoothTriaStruct con triangoli smooth: il primo indice individua il blocco, il secondo il voxel
|
||||
typedef std::vector<std::vector<SmoothTriaStruct>> SmoothTriaMatrix ;
|
||||
// Tavola hash di Voxel
|
||||
typedef std::unordered_map <int, Voxel> VoxelContainer ;
|
||||
typedef std::unordered_map<int, Voxel> VoxelContainer ;
|
||||
// Unordered map per la coerenza topologica
|
||||
typedef std::unordered_map <int, bool> InterVoxMatter ;
|
||||
typedef std::unordered_map<int, bool> InterVoxMatter ;
|
||||
|
||||
private :
|
||||
bool CopyFrom( const VolZmap& clSrc) ;
|
||||
@@ -233,9 +245,15 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
INTVECTOR& vAdjBlockVoxComp, INTVECTOR& vAdjBordBlockVoxComp) const ;
|
||||
// OPERAZIONI SU INTERVALLI
|
||||
bool SubtractIntervals( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, int nToolNum) ;
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap = false) ;
|
||||
bool AddIntervals( int nGrid, int nI, int nJ,
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, int nToolNum) ;
|
||||
double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax,
|
||||
int nToolNum, bool bSkipSwap = false) ;
|
||||
bool AddMissingIntervalsInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, double dZ, double dToler,
|
||||
Vector3d vtToolMin, Vector3d vtToolMax, int nToolNum) ;
|
||||
bool AddSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax,
|
||||
Vector3d& vtMin, Vector3d& vtMax) ;
|
||||
// Spostamenti utensile
|
||||
bool MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA) ;
|
||||
bool MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
|
||||
@@ -312,6 +330,14 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
const Vector3d& vtToolDir, const Vector3d& vtAux, int nToolNum) ; // E' in realtà MillingPerp
|
||||
// Generica traslazione sfera
|
||||
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
|
||||
inline bool TestToolBBox( int nGrid, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV,
|
||||
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
|
||||
@@ -404,6 +430,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
// Funzione per crezione solido in parallelo
|
||||
bool CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||
bool AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
@@ -416,9 +444,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
Status m_nStatus ; // stato
|
||||
int m_nTempProp[2] ; // vettore proprietà temporanee
|
||||
double m_dTempParam[2] ; // vettore parametri temporanei
|
||||
bool m_bShowEdges ; // flag di visualizzazione spigoli vivi
|
||||
Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap
|
||||
double m_dStep ; // passo delle griglie
|
||||
int m_nMapNum ; // numero di griglie ( 1 o 3)
|
||||
Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap
|
||||
int m_nNx[N_MAPS] ; // dimensione di ciascuna griglia in X
|
||||
int m_nNy[N_MAPS] ; // dimensione di ciascuna griglia in Y
|
||||
int m_nDim[N_MAPS] ; // dimensione di ciascuna griglia ( X * Y)
|
||||
@@ -436,7 +465,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
} ;
|
||||
std::vector<std::vector<Data>> m_Values[N_MAPS] ; // dexel delle 3 griglie
|
||||
|
||||
int m_nShape ; // Forma : 0 generica, 1 box, 2 estrusione
|
||||
|
||||
int m_nShape ; // Forma : 0 generica, 1 box, 2 estrusione
|
||||
|
||||
int m_nVoxNumPerBlock ; // Numero di voxel per blocco
|
||||
int m_nDexVoxRatio ; // Rapporto dexel voxel
|
||||
@@ -462,7 +492,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
mutable std::vector<InterVoxMatter> m_SliceYZ ;
|
||||
mutable std::mutex m_SliceMutex ;
|
||||
|
||||
mutable std::atomic<bool> m_bBreak ;
|
||||
std::atomic<bool> m_bIsBox ;
|
||||
|
||||
int m_nCurrTool ;
|
||||
|
||||
+16
-8
@@ -2912,8 +2912,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
|
||||
int nNumVox ;
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
|
||||
nNumVox, nB, ptLineTria1, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
|
||||
}
|
||||
// altrimenti ci sono due intersezioni
|
||||
else {
|
||||
@@ -2921,8 +2922,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
|
||||
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
|
||||
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2948,8 +2950,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
|
||||
int nNumVox ;
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
|
||||
nNumVox, nB, ptLineTria1, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
|
||||
}
|
||||
// altrimenti ci sono due intersezioni
|
||||
else {
|
||||
@@ -2957,8 +2960,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
|
||||
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
|
||||
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2974,15 +2978,17 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
continue ;
|
||||
// se altrimenti c'è una sola intersezione
|
||||
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
|
||||
-1, nB, ptLineTria1, trTria) ;
|
||||
-1, nB, trTria, dCosDN, ptLineTria1) ;
|
||||
}
|
||||
// altrimenti ci sono due intersezioni
|
||||
else {
|
||||
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
|
||||
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
|
||||
-1, nB, ptLineTria1, ptLineTria2, trTria) ;
|
||||
-1, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3007,8 +3013,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
|
||||
int nNumVox ;
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
|
||||
nNumVox, nB, ptLineTria1, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
|
||||
}
|
||||
// altrimenti ci sono due intersezioni
|
||||
else {
|
||||
@@ -3016,8 +3023,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
|
||||
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
|
||||
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
|
||||
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
|
||||
double dCosDN = vtDir * trTria.GetN() ;
|
||||
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
|
||||
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
|
||||
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+188
-21
@@ -17,6 +17,7 @@
|
||||
#include "CurveLine.h"
|
||||
#include "VolZmap.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <future>
|
||||
|
||||
@@ -26,13 +27,13 @@ using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex)
|
||||
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, 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)
|
||||
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
|
||||
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
|
||||
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) ;
|
||||
|
||||
// Aggiorno la dimensione della mappa 1 o 3
|
||||
@@ -46,8 +47,8 @@ VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dL
|
||||
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) ;
|
||||
m_nNx[0] = max( int( ( dDimX + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
m_nNy[0] = max( int( ( dDimY + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
|
||||
// Numero di componenti connesse
|
||||
m_nConnectedCompoCount = 1 ;
|
||||
@@ -55,7 +56,7 @@ VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dL
|
||||
// Se tridexel
|
||||
if ( bTriDex) {
|
||||
m_nNx[1] = m_nNy[0] ;
|
||||
m_nNy[1] = max( int( ( dLengthZ + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
m_nNy[1] = max( int( ( dDimZ + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
m_nNx[2] = m_nNy[1] ;
|
||||
m_nNy[2] = m_nNx[0] ;
|
||||
}
|
||||
@@ -96,19 +97,19 @@ VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dL
|
||||
switch ( i) {
|
||||
case 0 :
|
||||
m_Values[i][j][0].vtMinN = - Z_AX ;
|
||||
m_Values[i][j][0].dMax = dLengthZ ;
|
||||
m_Values[i][j][0].dMax = dDimZ ;
|
||||
m_Values[i][j][0].vtMaxN = Z_AX ;
|
||||
m_Values[i][j][0].nToolMax = 0 ;
|
||||
break ;
|
||||
case 1 :
|
||||
m_Values[i][j][0].vtMinN = - X_AX ;
|
||||
m_Values[i][j][0].dMax = dLengthX ;
|
||||
m_Values[i][j][0].dMax = dDimX ;
|
||||
m_Values[i][j][0].vtMaxN = X_AX ;
|
||||
m_Values[i][j][0].nToolMax = 0 ;
|
||||
break ;
|
||||
case 2 :
|
||||
m_Values[i][j][0].vtMinN = - Y_AX ;
|
||||
m_Values[i][j][0].dMax = dLengthY ;
|
||||
m_Values[i][j][0].dMax = dDimY ;
|
||||
m_Values[i][j][0].vtMaxN = Y_AX ;
|
||||
m_Values[i][j][0].nToolMax = 0 ;
|
||||
break ;
|
||||
@@ -117,11 +118,11 @@ VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dL
|
||||
|
||||
// Definizione delle limitazioni iniziali in Z per ogni mappa
|
||||
m_dMinZ[0] = 0 ;
|
||||
m_dMaxZ[0] = dLengthZ ;
|
||||
m_dMaxZ[0] = dDimZ ;
|
||||
m_dMinZ[1] = 0 ;
|
||||
m_dMaxZ[1] = ( bTriDex ? dLengthX : 0) ;
|
||||
m_dMaxZ[1] = ( bTriDex ? dDimX : 0) ;
|
||||
m_dMinZ[2] = 0 ;
|
||||
m_dMaxZ[2] = ( bTriDex ? dLengthY : 0) ;
|
||||
m_dMaxZ[2] = ( bTriDex ? dDimY : 0) ;
|
||||
|
||||
// Tipologia
|
||||
m_nShape = BOX ;
|
||||
@@ -132,6 +133,80 @@ VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dL
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
|
||||
{
|
||||
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
|
||||
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < 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( ( dDimX + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
m_nNy[0] = max( int( ( dDimY + 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( ( dDimZ + 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] = dDimZ ;
|
||||
m_dMinZ[1] = 0 ;
|
||||
m_dMaxZ[1] = ( bTriDex ? dDimX : 0) ;
|
||||
m_dMinZ[2] = 0 ;
|
||||
m_dMaxZ[2] = ( bTriDex ? dDimY : 0) ;
|
||||
|
||||
// Tipologia
|
||||
m_nShape = GENERIC ;
|
||||
|
||||
// Aggiornamento dello stato
|
||||
m_nStatus = OK ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex)
|
||||
@@ -139,7 +214,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
|
||||
// Aggiorno la dimensione della mappa 1 o 3
|
||||
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) ;
|
||||
|
||||
// Determino il bounding box della flat region
|
||||
@@ -222,11 +297,11 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
|
||||
CRVCVECTOR 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()) ;
|
||||
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 ;
|
||||
if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) {
|
||||
|
||||
@@ -333,7 +408,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
|
||||
int nPart = int( IntersectionResults.size()) ;
|
||||
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 ;
|
||||
if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) {
|
||||
|
||||
@@ -470,7 +545,7 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
||||
|
||||
int nIntType = IntersectionResults[k].nILTT ;
|
||||
|
||||
// Se c'è intersezione
|
||||
// Se c'è intersezione
|
||||
if ( nIntType != ILTT_NO) {
|
||||
|
||||
double dCos = IntersectionResults[k].dCosDN ;
|
||||
@@ -522,11 +597,103 @@ VolZmap::CreateMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, co
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool
|
||||
VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig,
|
||||
const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM)
|
||||
{
|
||||
// controllo sui parametri
|
||||
if ( nMap < 0 || nMap > 2 ||
|
||||
nInfI < 0 || nInfI > m_nNx[nMap] ||
|
||||
nSupI < 0 || nSupI > m_nNx[nMap] ||
|
||||
nInfJ < 0 || nInfJ > m_nNy[nMap] ||
|
||||
nSupJ < 0 || nSupJ > m_nNy[nMap])
|
||||
return false ;
|
||||
|
||||
// determinazione e ridimensionamento dei dexel interni alla trimesh
|
||||
for ( int i = nInfI ; i < nSupI ; ++ i) {
|
||||
for ( int j = nInfJ ; j < nSupJ ; ++ j) {
|
||||
|
||||
// definisco la retta da intersecare con la trimesh
|
||||
double dX = ( i + 0.5) * m_dStep ;
|
||||
double dY = ( j + 0.5) * m_dStep ;
|
||||
Point3d ptP0( dX, dY, 0) ;
|
||||
|
||||
// intersezioni della retta con la TriMesh
|
||||
ILSIVECTOR IntersectionResults ;
|
||||
intPLSTM.GetInters( ptP0, vtLen.v[(nMap+2)%3], IntersectionResults) ;
|
||||
|
||||
// rimuovo le intersezioni in eccesso
|
||||
for ( int nI = 0 ; nI < int( IntersectionResults.size()) - 3 ; ++ nI) {
|
||||
int nJ = nI + 1 ; // prima successiva
|
||||
int nK = nJ + 1 ; // seconda successiva
|
||||
int nT = nK + 1 ; // terza successiva
|
||||
// determino i segni delle 4 intersezioni tra la linea e il trangolo della TriMesh
|
||||
int nSgnI = IntersectionResults[nI].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nI].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
int nSgnJ = IntersectionResults[nJ].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nJ].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
int nSgnK = IntersectionResults[nK].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nK].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
int nSgnT = IntersectionResults[nT].dCosDN > EPS_SMALL ? 1 : IntersectionResults[nT].dCosDN > -EPS_SMALL ? 0 : - 1 ;
|
||||
// parametri dell'intersezione sulla linea
|
||||
double dUJ = IntersectionResults[nJ].dU ;
|
||||
double dUK = IntersectionResults[nK].dU ;
|
||||
// controllo coerenza con segni...
|
||||
if ( nSgnI != 0 && nSgnI == nSgnJ &&
|
||||
nSgnK != 0 && nSgnK == nSgnT &&
|
||||
nSgnI == - nSgnT &&
|
||||
abs( dUJ - dUK) < EPS_SMALL) {
|
||||
// ... ed elimino le intersezioni in eccesso...
|
||||
IntersectionResults.erase( IntersectionResults.begin() + nK) ;
|
||||
IntersectionResults.erase( IntersectionResults.begin() + nJ) ;
|
||||
}
|
||||
}
|
||||
|
||||
int nInt = int( IntersectionResults.size()) ; // numero di intersezioni valide
|
||||
bool bInside = false ; // Flag entrata/uscita per tratto di retta
|
||||
Point3d ptIn ; Vector3d vtInN ;
|
||||
|
||||
// per ogni intersezione valida trovata...
|
||||
for ( int k = 0 ; k < nInt ; ++ k) {
|
||||
// ricavo il tipo di intersezione
|
||||
int nIntType = IntersectionResults[k].nILTT ;
|
||||
// se c'è intersezione
|
||||
if ( nIntType != ILTT_NO) {
|
||||
// ricavo il cos tra i vettori ( normale del triangolo e tangente alla retta)
|
||||
double dCos = IntersectionResults[k].dCosDN ;
|
||||
|
||||
// se entro nella superficie trimesh...
|
||||
if ( dCos < - EPS_SMALL) {
|
||||
ptIn = IntersectionResults[k].ptI ; // punto di intersezione
|
||||
int nT = IntersectionResults[k].nT ; // triangolo di interesse
|
||||
int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse
|
||||
Surf.GetFacetNormal( nF, vtInN) ;
|
||||
bInside = true ; // entrata
|
||||
}
|
||||
// ...se esco dalla superficie trimesh ( prima sono per forza entrato)
|
||||
else if ( dCos > EPS_SMALL && bInside) {
|
||||
Point3d ptOut = IntersectionResults[k].ptI ; // punto di intersezione
|
||||
int nT = IntersectionResults[k].nT ; // triangolo di interesse
|
||||
int nF = Surf.GetFacetFromTria( nT) ; // faccia di interesse
|
||||
Vector3d vtOutN ; Surf.GetFacetNormal( nF, vtOutN) ; // vettore d'uscita
|
||||
|
||||
// Aggiungo un tratto al dexel
|
||||
AddIntervals( nMap, i, j,
|
||||
ptIn.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3],
|
||||
ptOut.v[(nMap+2)%3] - ptMapOrig.v[(nMap+2)%3],
|
||||
vtInN, vtOutN, 0, true) ;
|
||||
bInside = false ; // uscita
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
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 ;
|
||||
if ( ! Surf.IsClosed() || ! Surf.GetVolume( dVol) || dVol < 0)
|
||||
return false ;
|
||||
@@ -542,14 +709,14 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
Point3d 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.
|
||||
SurfBBox.Expand( 100 * EPS_SMALL, 100 * EPS_SMALL, 100 * EPS_SMALL) ;
|
||||
|
||||
// Sistema di riferimento intrinseco dello Zmap
|
||||
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) ;
|
||||
|
||||
// Determino le dimensioni lineari del BBox
|
||||
|
||||
+31
-25
@@ -3327,12 +3327,12 @@ VolZmap::IsThereMat( int nI, int nJ, int nK) const
|
||||
nK *= m_nDexVoxRatio ;
|
||||
|
||||
// Se l'indice è alla frontiera del reticolo non vi è materiale
|
||||
if ( nI <= - 1 || nI >= int( m_nNx[0]) ||
|
||||
if ( nI <= - 1 || nI >= int( m_nNx[0]) ||
|
||||
nJ <= - 1 || nJ >= int( m_nNy[0]) ||
|
||||
nK <= - 1 || nK >= int( m_nNy[1]))
|
||||
nK <= - 1 || nK >= int( m_nNy[1]))
|
||||
return false ;
|
||||
|
||||
// ciclo sulle griglie
|
||||
// ciclo sulle griglie
|
||||
int nCount = 0 ;
|
||||
int nMinPos[3] = { -1, -1, -1} ;
|
||||
int nMinIndex[3] ;
|
||||
@@ -3361,18 +3361,22 @@ VolZmap::IsThereMat( int nI, int nJ, int nK) const
|
||||
}
|
||||
// verifica spillone su vertice
|
||||
double dMinDist = INFINITO ;
|
||||
int nIndex = 0 ;
|
||||
int nIndex = 0 ;
|
||||
int nPos = nGrJ * m_nNx[nGrid] + nGrI ;
|
||||
nDexSize[nGrid] = int( m_Values[nGrid][nPos].size()) ;
|
||||
// scorro i sotto-interalli dello spillone
|
||||
while ( nIndex < nDexSize[nGrid]) {
|
||||
// distanza tra la "Z" attuale e il parametro minimo e massimo dell'intervallo nIndex-esimo
|
||||
double dDistInf = dZ[nGrid] - m_Values[nGrid][nPos][nIndex].dMin + 2 * EPS_SMALL ;
|
||||
double dDistSup = dZ[nGrid] - m_Values[nGrid][nPos][nIndex].dMax - 2 * EPS_SMALL ;
|
||||
// se "Z" attuale a cavallo tra queste due distanze...
|
||||
if ( dDistInf > 0. && dDistSup < 0.) {
|
||||
nMinIndex[nGrid] = nIndex ;
|
||||
nMinIndex[nGrid] = nIndex ; // aggiorno l'indice
|
||||
++ nCount ;
|
||||
bInterOnNode[nGrid] = true ;
|
||||
bInterOnNode[nGrid] = true ; // flag T per griglia zero
|
||||
break ;
|
||||
}
|
||||
// se "Z" attuale tutta sopra o tutta sotto
|
||||
else {
|
||||
double dDist = min( abs( dDistInf), abs( dDistSup)) ;
|
||||
if ( dDist < dMinDist) {
|
||||
@@ -3380,16 +3384,22 @@ VolZmap::IsThereMat( int nI, int nJ, int nK) const
|
||||
nMinIndex[nGrid] = nIndex ;
|
||||
dMinDist = dDist ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// sotto-intervallo successivo
|
||||
nIndex += 1 ;
|
||||
}
|
||||
}
|
||||
if ( nCount == 3)
|
||||
} // fine ciclo sulle griglie
|
||||
|
||||
if ( nCount == 3) // ... se interno a tutte e 3 le griglie, allora c'è materiale ...
|
||||
return true ;
|
||||
else if ( nCount == 2) {
|
||||
else if ( nCount == 2) { // ... se interno solo a 2 griglie ...
|
||||
// recupero la griglia sulla quale è esterno
|
||||
int nGrid = ( bInterOnNode[0] ? ( bInterOnNode[1] ? 2 : 1) : 0) ;
|
||||
// se tale griglia non ha sotto-intervalli allora non c'è materiale
|
||||
if ( nDexSize[nGrid] == 0)
|
||||
return false ;
|
||||
// se il valore in "Z" dello spillone è vicino al punto ( 1/10 dello step), aggiorno il
|
||||
// parametro minimo e massimo e considero la presenza di materiale
|
||||
if ( dZ[nGrid] > m_Values[nGrid][nMinPos[nGrid]][nMinIndex[nGrid]].dMin - 0.1 * m_dStep &&
|
||||
dZ[nGrid] < m_Values[nGrid][nMinPos[nGrid]][nMinIndex[nGrid]].dMax + 0.1 * m_dStep) {
|
||||
double dDistInf = abs( dZ[nGrid] - m_Values[nGrid][nMinPos[nGrid]][nMinIndex[nGrid]].dMin) ;
|
||||
@@ -3401,9 +3411,9 @@ VolZmap::IsThereMat( int nI, int nJ, int nK) const
|
||||
return true ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
else // ... se invece interno a 1 o a nessuna delle griglie, allora non c'è materiale
|
||||
return false ;
|
||||
}
|
||||
|
||||
@@ -4673,23 +4683,19 @@ VolZmap::GetEdges( ICURVEPOVECTOR& vpCurve) const
|
||||
PtrOwner<CurveComposite> pCrvCompo( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo))
|
||||
return false ;
|
||||
// recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita
|
||||
// recupero gli estremi dei segmenti e li inserisco nella composita
|
||||
for ( int i = 0 ; i < int( vId.size()) ; ++ i) {
|
||||
// creo un segmento di retta
|
||||
// recupero indice e flag di inversione
|
||||
int nInd = abs( vId[i]) - 1 ;
|
||||
bool bInvert = ( vId[i] < 0) ;
|
||||
PtrOwner<CurveLine> pLine( CreateBasicCurveLine()) ;
|
||||
if ( IsNull( pLine) || ! pLine->Set( vBpt[nInd].first, vBpt[nInd].second))
|
||||
continue ;
|
||||
if ( bInvert)
|
||||
pLine->Invert() ;
|
||||
// lo accodo alla composita
|
||||
if ( ! pCrvCompo->AddCurve( Release( pLine), true, 1.1 * dToler) &&
|
||||
! AreSamePointApprox( ptNear, ( bInvert ? vBpt[nInd].first : vBpt[nInd].second)))
|
||||
return false ;
|
||||
// aggiorno il prossimo near
|
||||
ptNear = ( bInvert ? vBpt[nInd].first : vBpt[nInd].second) ;
|
||||
// se primo segmento, inserisco il punto iniziale
|
||||
if ( i == 0)
|
||||
pCrvCompo->AddPoint( ! bInvert ? vBpt[nInd].first : vBpt[nInd].second) ;
|
||||
// aggiungo il punto finale
|
||||
pCrvCompo->AddLine( ! bInvert ? vBpt[nInd].second : vBpt[nInd].first) ;
|
||||
}
|
||||
// aggiorno il prossimo near
|
||||
pCrvCompo->GetEndPoint( ptNear) ;
|
||||
// se lunghezza curva inferiore a 5 volte la tolleranza, la salto
|
||||
double dCrvLen ;
|
||||
if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5 * dToler)
|
||||
|
||||
+1176
-281
File diff suppressed because it is too large
Load Diff
+120
-27
@@ -79,7 +79,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
|
||||
// verifico se è una linea
|
||||
// verifico se è una linea
|
||||
int nType = pCrv->GetType() ;
|
||||
bool bIsLine = ( nType == CRV_LINE) ;
|
||||
if ( nType == CRV_COMPO) {
|
||||
@@ -92,7 +92,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
||||
// verifico sia piana e trovo piano su cui giace
|
||||
Plane3d plPlane ;
|
||||
if ( bIsLine) {
|
||||
// linea è sicuramente piana. Scelgo piano definito dall'estrusione ( se definita)
|
||||
// linea è sicuramente piana. Scelgo piano definito dall'estrusione ( se definita)
|
||||
Point3d ptS ; pCrv->GetStartPoint( ptS) ;
|
||||
Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ;
|
||||
if ( ! vtExtr.IsSmall())
|
||||
@@ -110,7 +110,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
||||
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
|
||||
}
|
||||
else {
|
||||
// altrimenti verifico sia complanare ad eventuali curve già presenti
|
||||
// altrimenti verifico sia complanare ad eventuali curve già presenti
|
||||
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), plPlane.GetVersN()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
|
||||
return false ;
|
||||
}
|
||||
@@ -122,7 +122,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
|
||||
pCrvLoc->ToLoc( m_Frame) ;
|
||||
|
||||
try {
|
||||
// verifico se oggetto vroni è stato inizializzato
|
||||
// verifico se oggetto vroni è stato inizializzato
|
||||
if ( m_vroni == nullptr) {
|
||||
m_vroni = new( nothrow) vroniObject() ;
|
||||
if ( m_vroni == nullptr)
|
||||
@@ -165,7 +165,7 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
|
||||
m_Frame.Set( ptCen, vtN) ;
|
||||
}
|
||||
else {
|
||||
// verifico sia complanare ad eventuali curve già presenti
|
||||
// verifico sia complanare ad eventuali curve già presenti
|
||||
Plane3d plPlane ;
|
||||
plPlane.Set( ptCen, pSfr->GetNormVersor()) ;
|
||||
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), pSfr->GetNormVersor()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
|
||||
@@ -173,7 +173,7 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
|
||||
}
|
||||
|
||||
try {
|
||||
// verifico se oggetto vroni è stato inizializzato
|
||||
// verifico se oggetto vroni è stato inizializzato
|
||||
if ( m_vroni == nullptr) {
|
||||
m_vroni = new( nothrow) vroniObject() ;
|
||||
if ( m_vroni == nullptr)
|
||||
@@ -315,7 +315,7 @@ Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLo
|
||||
for ( int i = 0 ; i < pCopy->GetCurveCount() ; i++) {
|
||||
Point3d ptForcedEnd = P_INVALID ;
|
||||
|
||||
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
|
||||
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
|
||||
if ( i == pCopy->GetCurveCount() - 1 && bClosed)
|
||||
pCompo->GetStartPoint( ptForcedEnd) ;
|
||||
|
||||
@@ -359,7 +359,7 @@ Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoo
|
||||
ICurve*
|
||||
Voronoi::GetCurve( int nId) const
|
||||
{
|
||||
// verifico validità indice
|
||||
// verifico validità indice
|
||||
if ( nId < 0 || nId > ( int)m_vpCrvs.size() - 1)
|
||||
return nullptr ;
|
||||
// ne faccio una copia
|
||||
@@ -375,11 +375,11 @@ Voronoi::GetCurve( int nId) const
|
||||
bool
|
||||
Voronoi::CalcVoronoi( int nBound)
|
||||
{
|
||||
// se già stato calcolato con lo stesso bound non devo fare nulla
|
||||
// se già stato calcolato con lo stesso bound non devo fare nulla
|
||||
if ( m_bVDComputed && nBound == m_nBound)
|
||||
return true ;
|
||||
|
||||
// se già stato calcolato reset dei dati
|
||||
// se già stato calcolato reset dei dati
|
||||
if ( m_bVDComputed)
|
||||
m_vroni->ResetVoronoiDiagram() ;
|
||||
|
||||
@@ -389,8 +389,8 @@ Voronoi::CalcVoronoi( int nBound)
|
||||
// calcolo
|
||||
m_bVDComputed = true ;
|
||||
string sTmp = "" ;
|
||||
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
|
||||
|
||||
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -414,6 +414,11 @@ Voronoi::GetBisectorCurve( int i)
|
||||
CurveLine* pLine = CreateBasicCurveLine() ;
|
||||
if ( pLine == 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->SetTempParam( dParS, 0) ;
|
||||
pLine->SetTempParam( dParE, 1) ;
|
||||
@@ -433,7 +438,7 @@ Voronoi::GetBisectorCurve( int i)
|
||||
return nullptr ;
|
||||
pArc->SetC2P( ptC, ptS, ptE) ;
|
||||
pArc->SetTempParam( dParS, 0) ;
|
||||
pArc->SetTempParam( dParS, 1) ;
|
||||
pArc->SetTempParam( dParS, 1) ; // dParE = dParS
|
||||
pArc->ToGlob( m_Frame) ;
|
||||
return pArc ;
|
||||
}
|
||||
@@ -449,15 +454,23 @@ Voronoi::GetBisectorCurve( int i)
|
||||
if ( pCompo == 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
|
||||
Point3d pt ;
|
||||
double dParS ;
|
||||
m_vroni->GetApproxedBisectorPoint( i, 0, pt.v, dParS) ;
|
||||
m_vroni->GetApproxedBisectorPoint( i, bInvert ? nPoints - 1 : 0, pt.v, dParS) ;
|
||||
pCompo->AddPoint( pt) ;
|
||||
int nCrvCount = 0 ;
|
||||
|
||||
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 ;
|
||||
m_vroni->GetApproxedBisectorPoint( i, j, pt.v, dPar) ;
|
||||
if ( pCompo->AddLine( pt)) {
|
||||
@@ -467,7 +480,12 @@ Voronoi::GetBisectorCurve( int i)
|
||||
// aggiorno parametro precedente
|
||||
dParPrev = dPar ;
|
||||
nCrvCount ++ ;
|
||||
}
|
||||
}
|
||||
// aggiorno per punto successivo
|
||||
if ( bInvert)
|
||||
j -- ;
|
||||
else
|
||||
j ++ ;
|
||||
}
|
||||
|
||||
// setto parametri sulla curva
|
||||
@@ -501,6 +519,9 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
|
||||
if ( ! IsNull( pCrv) && pCrv->IsValid())
|
||||
vCrvs.emplace_back( Release( pCrv)) ;
|
||||
}
|
||||
|
||||
// libero la memoria di vroni utilizzata per calcolare bisettore
|
||||
m_vroni->apiFreeBisectorBuffer() ;
|
||||
}
|
||||
catch (...) {
|
||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
||||
@@ -542,6 +563,9 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
|
||||
vCrvs.emplace_back( Release( pCrv)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// libero la memoria di vroni utilizzata per calcolare bisettore
|
||||
m_vroni->apiFreeBisectorBuffer() ;
|
||||
}
|
||||
catch (...) {
|
||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
||||
@@ -651,12 +675,12 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo
|
||||
|
||||
// sistemo i raccordi
|
||||
if ( bClosed && bSquareMids) {
|
||||
// se curva è chiusa tutti i raccordi rispondono a bSquareMids
|
||||
// se curva è chiusa tutti i raccordi rispondono a bSquareMids
|
||||
IdentifyFillets( pCrvOffs, dOffs) ;
|
||||
AdjustCurveFillets( pCrvOffs, dOffs, ICurve::OFF_EXTEND) ;
|
||||
}
|
||||
else if ( ! bClosed && ( bSquareMids || bSquareEnds)) {
|
||||
// se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e
|
||||
// se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e
|
||||
// modificare solo quelli richiesti
|
||||
for ( int j = 0 ; j < pCrvOffs->GetCurveCount() ; j ++) {
|
||||
int nOrigCrv ; pCrvOffs->GetCurveTempProp( j, nOrigCrv) ;
|
||||
@@ -738,13 +762,13 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs, bool bRightOff
|
||||
bOk = pCrvOffs->AddCurve( Release( pArc)) ;
|
||||
}
|
||||
|
||||
// se la curva è stata aggiunta
|
||||
// se la curva è stata aggiunta
|
||||
if ( bOk) {
|
||||
// setto come info la sottocurva da cui si è generata
|
||||
// setto come info la sottocurva da cui si è generata
|
||||
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
|
||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
|
||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
|
||||
// verifico se è raccordo relativo agli estremi della curva
|
||||
// verifico se è raccordo relativo agli estremi della curva
|
||||
if ( nOrigCrv == -1 && ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt))
|
||||
pCrvOffs->SetCurveTempParam( nCurrCrvId, 1.0, 0) ;
|
||||
}
|
||||
@@ -757,6 +781,9 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs, bool bRightOff
|
||||
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid())
|
||||
OffsList.push_back( Release( pCrvOffs)) ;
|
||||
}
|
||||
|
||||
// libero la memoria di vroni dedicata agli offset
|
||||
m_vroni->apiFreeOffsetData() ;
|
||||
}
|
||||
catch (...) {
|
||||
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
|
||||
@@ -789,7 +816,7 @@ Voronoi::VerifyCurvesValidityForOffset()
|
||||
if ( m_vpCrvs.size() == 1)
|
||||
return true ;
|
||||
|
||||
// se ho più curve, devono essere tutte chiuse
|
||||
// se ho più curve, devono essere tutte chiuse
|
||||
for ( auto pCrv : m_vpCrvs) {
|
||||
if ( ! pCrv->IsClosed())
|
||||
return false ;
|
||||
@@ -809,12 +836,29 @@ Voronoi::VerifyCurvesValidityForOffset()
|
||||
|
||||
// se curva con orientamento principale verifico sia esterna a tutte le altre curve con orientamento principale
|
||||
if ( vArea[i] * dRefArea > EPS_SMALL) {
|
||||
for ( int j = i + 1 ; j < ( int)vArea.size() ; j++) {
|
||||
if ( vArea[i] * vArea[j] > EPS_SMALL) {
|
||||
for ( int j = 0 ; j < ( int)vArea.size() ; j++) {
|
||||
if ( j != i && vArea[i] * vArea[j] > EPS_SMALL) {
|
||||
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ;
|
||||
int nRes = ccInt.GetRegionCurveClassification() ;
|
||||
if ( ( bRefCCW && nRes != CCREGC_OUT) || ( ! bRefCCW && nRes != CCREGC_IN1))
|
||||
if ( nRes == CCREGC_NULL || nRes == CCREGC_SAME || nRes == CCREGC_INTERS)
|
||||
return false ;
|
||||
if ( ( bRefCCW && nRes == CCREGC_IN1) || ( ! bRefCCW && nRes == CCREGC_IN2)) {
|
||||
// se è interna ad una curva con orientamento principale, verifico sia esterna ad almeno una curva con orientamento
|
||||
// diverso dal principale
|
||||
bool bFound = false ;
|
||||
for ( int k = 0 ; k < ( int)vArea.size() ; k++) {
|
||||
if ( k != i && vArea[i] * vArea[k] < EPS_SMALL) {
|
||||
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[k]) ;
|
||||
int nRes = ccInt.GetRegionCurveClassification() ;
|
||||
if ( ( bRefCCW && nRes == CCREGC_OUT) || ( ! bRefCCW && nRes == CCREGC_IN1)) {
|
||||
bFound = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! bFound)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -884,7 +928,7 @@ Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs)
|
||||
// mi posiziono dopo la junction
|
||||
pCompo.ChangeStartPoint( vJunctions[0] + 1) ;
|
||||
delete( pCompo.RemoveFirstOrLastCurve()) ;
|
||||
// verifico validità della curva
|
||||
// verifico validità della curva
|
||||
int nSide = GetOffsetCurveSide( pCompo, 0) ;
|
||||
if ( nSide == nSideRef) {
|
||||
// scorro fino alla prima curva non valida ed elimino la curva da quel punto fino alla fine
|
||||
@@ -895,7 +939,7 @@ Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// elimino finchè non trovo una curva valida
|
||||
// elimino finchè non trovo una curva valida
|
||||
while( nSide != nSideRef && pCompo.IsValid()) {
|
||||
delete( pCompo.RemoveFirstOrLastCurve( false)) ;
|
||||
if ( pCompo.IsValid())
|
||||
@@ -948,3 +992,52 @@ Voronoi::AdjustOffsetStart( ICurveComposite& pCrv)
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::Translate( const Vector3d & vtMove)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
return m_Frame.Translate( vtMove) ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
return m_Frame.Rotate( ptAx, vtAx, dAngDeg) ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool Voronoi::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
return m_Frame.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool Voronoi::ToGlob( const Frame3d& frRef)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
return m_Frame.ToGlob( frRef) ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool Voronoi::ToLoc( const Frame3d& frRef)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
return m_Frame.ToLoc( frRef) ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool Voronoi::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
||||
{
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
return m_Frame.LocToLoc( frOri, frDest) ;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,13 @@ class Voronoi
|
||||
bool CalcFatCurve( ICURVEPOVECTOR& vOffs, double dOffs, bool bSquareEnds, bool bSquareMids) ;
|
||||
bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) ;
|
||||
|
||||
bool Translate( const Vector3d& vtMove) ;
|
||||
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg) ;
|
||||
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) ;
|
||||
bool ToGlob( const Frame3d& frRef) ;
|
||||
bool ToLoc( const Frame3d& frRef) ;
|
||||
bool LocToLoc( const Frame3d& frOri, const Frame3d& frDest) ;
|
||||
|
||||
private :
|
||||
bool Clear( void) ;
|
||||
bool IsValid( void) const
|
||||
@@ -76,10 +83,10 @@ class Voronoi
|
||||
|
||||
private :
|
||||
vroniObject* m_vroni ; // oggetto base della libreria vroni
|
||||
Frame3d m_Frame ; // frame in cui è espresso l'oggetto vroni
|
||||
Frame3d m_Frame ; // frame in cui è espresso l'oggetto vroni
|
||||
int m_nBound ; // bound associato al diagramma di Voronoi corrente
|
||||
CICURVEPVECTOR m_vpCrvs ; // curve associate al Voronoi ( espresse rispetto a m_Frame)
|
||||
BBox3d m_bBox ; // box degli oggetti associati al Voronoi
|
||||
bool m_bVDComputed ; // indica se il diagramma di Voronoi è stato calcolato
|
||||
bool m_bVDComputed ; // indica se il diagramma di Voronoi è stato calcolato
|
||||
bool m_bAllowAdd ; // indica se possibile aggiungere altre curve/superifici dopo aver creato l'oggetto Voronoi
|
||||
} ;
|
||||
|
||||
Reference in New Issue
Block a user