diff --git a/SurfTriMeshOffset.cpp b/SurfTriMeshOffset.cpp index 666e863..56213cf 100644 --- a/SurfTriMeshOffset.cpp +++ b/SurfTriMeshOffset.cpp @@ -1,12 +1,14 @@ //---------------------------------------------------------------------------- -// EgalTech 2014-2022 +// EgalTech 2025 //---------------------------------------------------------------------------- // File : SurfTriMeshOffset.cpp Data : 10.06.25 Versione : 2.7e4 // Contenuto : Implementazione funzione per Offset di Superfici TriMesh. // // // -// Modifiche : 10.06.25 RE Creazione modulo. +// Modifiche : 10.06.25 RE - Creazione modulo. +// 10.06.25 RE - Offset di superfici chiuse. ( ver. 2.7e4) +// 04.07.25 RE - Thickening Offset di superfici generiche. ( ver. 2.7g1) // //---------------------------------------------------------------------------- @@ -44,17 +46,25 @@ SumStm( const CISURFTMPVECTOR& vStm) } //---------------------------------------------------------------------------- -/* Funzione che crea l'Offset di una superficie TriMesh chiusa */ +/* Funzione che crea l'Offset di una superficie TriMesh */ ISurfTriMesh* -CreateSurfTriMeshOffset( const ISurfTriMesh* pStm, double dOffs, double dLinTol) +CreateSurfTriMeshOffset( const ISurfTriMesh* pStm, double dOffs, double dLinTol, int nType) { - return CreateSurfTriMeshesOffset( { pStm}, dOffs, dLinTol) ; + return ( CreateSurfTriMeshesOffset( { pStm}, dOffs, dLinTol, nType)) ; +} + +//---------------------------------------------------------------------------- +/* Funzione che crea il Fat Offset di una superficie TriMesh */ +ISurfTriMesh* +CreateSurfTriMeshThickeningOffset( const ISurfTriMesh* pStm, double dOffs, double dLinTol, int nType) +{ + return ( CreateSurfTriMeshesThickeningOffset( { pStm}, dOffs, dLinTol, nType)) ; } //---------------------------------------------------------------------------- /* Funzione che crea l'Offset di un insieme di superfici */ ISurfTriMesh* -CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dLinTol) +CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dLinTol, int nType) { // se vettore delle superfici vuoto, non faccio nulla if ( vStm.empty()) @@ -66,10 +76,37 @@ CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dLi // ( questo valore serve per rimanere coerente con l'Offset delle curve) if ( abs( dOffs) < 10 * EPS_SMALL) return SumStm( vStm) ; - // --- NB. Per la creazione dello Zmap è necessario che le superfici siano chiuse + + // creo lo Zmap associato alle superfici TriMesh PtrOwner pVolZmap( CreateVolZmap()) ; - if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshOffset( vStm, dOffs, dMyLinTol)) + if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshOffset( vStm, dOffs, dMyLinTol, nType)) return nullptr ; + + // restituisco la superficie TriMesh + return ( pVolZmap->GetSurfTriMesh()) ; +} + +//---------------------------------------------------------------------------- +/* Funzione che crea il Fat Offset di un insieme di superfici */ +ISurfTriMesh* +CreateSurfTriMeshesThickeningOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dLinTol, int nType) +{ + // se vettore delle superfici vuoto, non faccio nulla + if ( vStm.empty()) + return nullptr ; + // controllo sul valore di tolleranza lineare + double dMyLinTol = max( dLinTol, 10 * EPS_SMALL) ; + // --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto) + // Nel caso sia minore, restituisco semplicemente la somma delle superfici + // ( questo valore serve per rimanere coerente con l'Offset delle curve) + if ( abs( dOffs) < 10 * EPS_SMALL) + return SumStm( vStm) ; + + // creo lo Zmap associato alle superfici TriMesh + PtrOwner pVolZmap( CreateVolZmap()) ; + if ( IsNull( pVolZmap) || ! pVolZmap->CreateFromTriMeshThickeningOffset( vStm, dOffs, dMyLinTol, nType)) + return nullptr ; + // restituisco la superficie TriMesh return ( pVolZmap->GetSurfTriMesh()) ; } \ No newline at end of file diff --git a/VolZmap.h b/VolZmap.h index 559dc14..d8ecd70 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -82,7 +82,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW 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, double dExtraBox = 0.) override ; - bool CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) override ; + bool CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = ISurfTriMesh::OFF_FILLET) override ; + bool CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType = ISurfTriMesh::OFF_FILLET) override ; int GetBlockCount( void) const override ; int GetBlockUpdatingCounter( int nBlock) const override ; bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ; @@ -439,8 +440,13 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const Vector3d& vtLen, const Point3d& ptMapOrig, const ISurfTriMesh& Surf, IntersParLinesSurfTm& intPLSTM) ; // Funzioni per Offset di superfici - bool CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid) ; - bool CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid) ; + bool InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ; + bool InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) ; + bool UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ; + bool UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ; + bool UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) ; + bool CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nVertexType = 0) ; + bool CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, int nVertexType = 0) ; bool SubtractIntervalsForOffset( int nGrid, int nI, int nJ, double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, int nToolNum, bool bSkipSwap = false) ; diff --git a/VolZmapOffset.cpp b/VolZmapOffset.cpp index f595812..61223bb 100644 --- a/VolZmapOffset.cpp +++ b/VolZmapOffset.cpp @@ -23,9 +23,8 @@ using namespace std ; - //---------------------------------------------------------------------------- -/* Funzione per aggiungere intervalli lungo un Dexel per l'offset di una superficie TriMesh */ +/* Funzione per sottrarre intervalli lungo un Dexel per l'offset di una superficie TriMesh */ bool VolZmap::SubtractIntervalsForOffset( int nGrid, int nI, int nJ, double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, @@ -50,7 +49,7 @@ VolZmap::AddIntervalsForOffset( int nGrid, int nI, int nJ, /* Funzione per la creazione di una sfera di Offset centrata sul vertice di una TriMesh con cui aggiungere o sottrarre intervalli lungo i Dexel coinvolti */ bool -VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid) +VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid, int nTool) { // determino il Box della sfera posizionata su tale vertice BBox3d BBoxSphere( ptV - dOffs * Vector3d( 1., 1., 1.), @@ -76,9 +75,9 @@ VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid) Vector3d vtNmax = Point3d( dX, dY, dMax) - ptV ; vtNmax.Normalize() ; if ( dOffs > 0.) - AddIntervalsForOffset( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, 0) ; + AddIntervalsForOffset( nGrid, i, j, dMin, dMax, vtNmin, vtNmax, nTool) ; else - SubtractIntervalsForOffset( nGrid, i, j, dMin, dMax, -vtNmin, -vtNmax, 0) ; + SubtractIntervalsForOffset( nGrid, i, j, dMin, dMax, -vtNmin, -vtNmax, nTool) ; } } } @@ -90,7 +89,8 @@ VolZmap::CreateOffsSphereOnVertex( const Point3d& ptV, double dOffs, int nGrid) /* Funzione per la creazione di un cilindro di Offset sul vertice di una TriMesh con cui aggiungere o sottrarre intervalli lungo i Dexel coinvolti */ bool -VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid) +VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, double dOffs, int nGrid, + int nTool) { // determino la lunghezza dello spigolo corrente double dH = Dist( ptP1, ptP2) ; @@ -129,9 +129,9 @@ VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, dou if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true, ptInt1, vtN1, ptInt2, vtN2)) { if ( dOffs > 0.) - AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, 0) ; + AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ; else - SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, 0) ; + SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ; } } } @@ -140,44 +140,53 @@ VolZmap::CreateOffsCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, dou } //---------------------------------------------------------------------------- -/* Funzione per la creazine di uno Zmap di Offset (positivo o negativo) a partire da una - superficie TriMesh */ +/* Funzione per inizializzare lo ZMap a partire da un vettore di superfici TriMesh */ +/* L'idea è quella di creare uno ZMap a partire dal Box complessivo delle superfici TriMesh : +* - le superfici chiuse possono già inserire i rispettivi spilloni +* - le superfici aperte non danno contributo */ bool -VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) +VolZmap::InitVolZMapOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) { + // se non ho superfici, non faccio nulla + if ( vSurf.empty()) + return true ; // controllo delle superfici for ( const ISurfTriMesh* Surf : vSurf) { if ( Surf == nullptr) return false ; } - // verifica sul parametro di Offset ( coerente con Curve e FlatRegion) - if ( abs( dOffs) < 10 * EPS_SMALL) - return true ; - // se non ho superfici, non faccio nulla - if ( vSurf.empty()) - return true ; - // definisco lo Zmap di partenza a partire dalle superfici - // se una sola superficie + // definisco la tolleranza di espansione del Box per la creazione dellop ZMap double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ; + + // --- se una sola superficie if ( int( vSurf.size()) == 1) { // controllo la validità della superficie if ( ! vSurf[0]->IsValid() || vSurf[0]->GetTriangleCount() == 0) return true ; - // definisco lo Zamp a partire dall'espansione del Box della superficie - if ( ! CreateFromTriMesh( *vSurf[0], dTol, true, dBoxExpansion)) + // --- se superficie chiusa posso direttamente creare lo Zmap iniziale + if ( vSurf[0]->IsClosed()) { + // definisco lo Zamp a partire dall'espansione del Box della superficie + if ( ! CreateFromTriMesh( *vSurf[0], dTol, true, dBoxExpansion)) + return false ; + } + // --- se superficie aperta, lo creo inizialmente vuoto a partire dal suo Box + BBox3d BBoxSurf ; + vSurf[0]->GetLocalBBox( BBoxSurf) ; + BBoxSurf.Expand( dBoxExpansion) ; + if ( ! CreateEmpty( BBoxSurf.GetMin(), BBoxSurf.GetDimX(), BBoxSurf.GetDimY(), BBoxSurf.GetDimZ(), dTol, true)) return false ; } - // se più superfici + // --- se più superfici else { - // calcolo il Box complessivo delle superfici TriMesh + // calcolo il Box complessivo BBox3d BBoxGlob ; - for ( int i = 0 ; i < int( vSurf.size()) ; ++ i) { + for ( const ISurfTriMesh* Surf : vSurf) { // controllo la validità della superficie - if ( ! vSurf[i]->IsValid() || vSurf[i]->GetTriangleCount() == 0) + if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0) continue ; // calcolo il Box della superficie - BBox3d BBoxSurf ; vSurf[i]->GetLocalBBox( BBoxSurf) ; + BBox3d BBoxSurf ; Surf->GetLocalBBox( BBoxSurf) ; // aggiungo il Box a quello complessivo BBoxGlob.Add( BBoxSurf) ; } @@ -185,20 +194,80 @@ VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, do BBoxGlob.Expand( dBoxExpansion) ; if ( ! CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true)) return false ; + // aggiungo tutte le superfici chiuse for ( const ISurfTriMesh* Surf : vSurf) { + if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0 || ! Surf->IsClosed()) + continue ; if ( ! AddSurfTm( Surf)) return false ; } } + return true ; +} + +//---------------------------------------------------------------------------- +/* Funzione per inizializzare lo ZMap a partire da un vettore di superfici TriMesh */ +/* L'idea è quella di creare uno ZMap vuoto a partire dal Box complessivo delle superfici TriMesh */ +bool +VolZmap::InitVolZMapThickeningOffs( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol) +{ + // se non ho superfici, non faccio nulla + if ( vSurf.empty()) + return true ; + // controllo delle superfici + for ( const ISurfTriMesh* Surf : vSurf) { + if ( Surf == nullptr) + return false ; + } + + // definisco la tolleranza di espansione del Box per la creazione dellop ZMap + double dBoxExpansion = ( abs( dOffs) + 1.5 * dTol) + 10 * EPS_SMALL ; + + // calcolo il Box complessivo + BBox3d BBoxGlob ; + for ( const ISurfTriMesh* Surf : vSurf) { + // controllo la validità della superficie + if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0) + continue ; + // calcolo il Box della superficie + BBox3d BBoxSurf ; Surf->GetLocalBBox( BBoxSurf) ; + // aggiungo il Box a quello complessivo + BBoxGlob.Add( BBoxSurf) ; + } + // definisco uno Zmap vuoto a partire dal Box + BBoxGlob.Expand( dBoxExpansion) ; + return ( CreateEmpty( BBoxGlob.GetMin(), BBoxGlob.GetDimX(), BBoxGlob.GetDimY(), BBoxGlob.GetDimZ(), dTol, true)) ; +} + +/* [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente + mediante una superficie chiusa */ +bool +VolZmap::UpdateVolZMapByOpenSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) +{ + // da studiare... + return false ; +} + +/* [Fillet] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente + mediante una superficie chiusa */ +bool +VolZmap::UpdateVolZMapByClosedSurfFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) +{ + // controlli sulla superficie + if ( Surf == nullptr || ! Surf->IsClosed()) + return false ; + if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0) + return true ; + /* Assunzioni : - Idea Generale di Offset - Su ogni vertice viene definita una sfera ( con raggio pari al valore di Offset e centro il vertice corrente) - - Su ogni lato viene definito un cilindro ( con raggio di pase pari al valore di Offset - e asse definito dall'edge stesso) - - Su ogni faccia viene definita una superficie di estrusione ( dove le due basi sono - definite dalla traslazione sia in positivo che in negativo della faccia lungo la sua normale) + - Su ogni lato viene definito un cilindro ( con raggio di base pari al valore di Offset + e asse definito dall'edge stesso) + - Su ogni faccia viene definita una superficie di estrusione ( dove le due basi sono + definite dalla traslazione sia in positivo che in negativo della faccia lungo la sua normale) - Segno dell'Offset : - Positivo ( si sommano gli intervalli corrisipondenti alle entità create) @@ -218,74 +287,57 @@ VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, do vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ; vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ; - // scorro le superfici - for ( const ISurfTriMesh* Surf : vSurf) { - // se superficie non valida, passo alla successiva - if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0) + // definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere + BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ; + // ----------------------- Cilindri e Sfere ----------------------- + // scorro gli Edge della superficie + for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) { + // recupero lo spigolo + int nV1, nV2, nF1, nF2 ; double dAng ; + Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ; + // controllo se il cilindro serve + // NB. la mancata creazione del cilindro comporta la mancata creazione delle sfere sui suoi vertici + // durante questa iterazione; non significa che questa sfera non verrà mai creata... + // Non esiste la sfera sul vertive V <=> non esiste alcun cilindro su tutti gli edge concorrenti + if ( dAng * dOffs < 0) continue ; - // definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere - BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ; - // ----------------------- Cilindri e Sfere ----------------------- - // scorro gli Edge della superficie - for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) { - // recupero lo spigolo - int nV1, nV2, nF1, nF2 ; double dAng ; - Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ; - // controllo se il cilindro serve - // NB. la mancata creazione del cilindro comporta la mancata creazione delle sfere sui suoi vertici - // durante questa iterazione; non significa che questa sfera non verrà mai creata... - // Non esiste la sfera sul vertive V <=> non esiste alcun cilindro su tutti gli edge concorrenti - if ( dAng * dOffs < 0) - continue ; - // recupero le coordinate dei vertici - Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ; - Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ; - // ciclo sulle griglie - for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) { - // esprimo gli estremi nel riferimento della griglia - ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; - ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; - // aggiungo/sottraggo gli intervalli definiti dal cilindro - if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, dOffs, nGrid)) + // recupero le coordinate dei vertici + Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ; + Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ; + // ciclo sulle griglie + for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) { + // esprimo gli estremi nel riferimento della griglia + ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; + ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; + // aggiungo/sottraggo gli intervalli definiti dal cilindro + if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, dOffs, nGrid)) + return false ; + // aggiungo/sottraggo gli intervalli definiti dalla sfera + if ( ! vbVert[nV1]) { + if ( ! CreateOffsSphereOnVertex( ptP1, dOffs, nGrid)) + return false ; + } + if ( ! vbVert[nV2]) { + if ( ! CreateOffsSphereOnVertex( ptP2, dOffs, nGrid)) return false ; - // aggiungo/sottraggo gli intervalli definiti dalla sfera - if ( ! vbVert[nV1]) { - vbVert[nV1] = ( nGrid == 2) ; - if ( ! CreateOffsSphereOnVertex( ptP1, dOffs, nGrid)) - return false ; - } - if ( ! vbVert[nV2]) { - vbVert[nV2] = ( nGrid == 2) ; - if ( ! CreateOffsSphereOnVertex( ptP2, dOffs, nGrid)) - return false ; - } } } - // ----------------------- Facce ----------------------- - // scorro tutte le facce definendo una superficie di estrusione - for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) { - // recupero lo faccia - POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ; - // recupero la normale della faccia - Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ; - // definisco la superficie di estrusione - CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ; - for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { - vPL[i].Translate( - abs( dOffs) * vtN) ; - PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) { - // dealloco le curve - for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { - delete ( vpCrvs[i]) ; - vpCrvs[i] = nullptr ; - } - return false ; - } - vpCrvs.emplace_back( Release( pCrvCompo)) ; - } - // recupero la TriMesh di estrusione - PtrOwner pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ; - if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) { + vbVert[nV1] = true ; + vbVert[nV2] = true ; + } + // ----------------------- Facce ----------------------- + // scorro tutte le facce definendo una superficie di estrusione + for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) { + // recupero lo faccia + POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ; + // recupero la normale della faccia + Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ; + // definisco la superficie di estrusione + CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + vPL[i].Translate( - abs( dOffs) * vtN) ; + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) { // dealloco le curve for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { delete ( vpCrvs[i]) ; @@ -293,22 +345,216 @@ VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, do } return false ; } - // aggiorno gli spilloni - if ( dOffs > 0.) - AddSurfTm( pStmExtr) ; - else - SubtractSurfTm( pStmExtr) ; + vpCrvs.emplace_back( Release( pCrvCompo)) ; + } + // recupero la TriMesh di estrusione + PtrOwner pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ; + if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) { // dealloco le curve for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { delete ( vpCrvs[i]) ; vpCrvs[i] = nullptr ; } + return false ; + } + // aggiorno gli spilloni + if ( dOffs > 0.) + AddSurfTm( pStmExtr) ; + else + SubtractSurfTm( pStmExtr) ; + // dealloco le curve + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + delete ( vpCrvs[i]) ; + vpCrvs[i] = nullptr ; } } - m_nShape = OFFSET ; return true ; } +/* [Fillet Thickening] Funzione per aggiornare mediante Sfere, Cilindri e Facce di estrusione lo ZMap corrente + mediante una superficie generica (aperta o chiusa) */ +//---------------------------------------------------------------------------- +bool +VolZmap::UpdateVolZMapBySurfThickeningFilletOffset( const ISurfTriMesh* Surf, double dOffs, double dTol) +{ + // controlli sulla superficie + if ( Surf == nullptr) + return false ; + if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0) + return true ; + + // non inizializzo lo Zmap, semplicemente lavoro con facce, spigoli e vertici + + // definisco vettore di frame Locali alle 3 griglie + FRAME3DVECTOR vFrGrid( 4) ; + vFrGrid[0].Set( ORIG, X_AX, Y_AX, Z_AX) ; + vFrGrid[1].Set( m_MapFrame.Orig(), m_MapFrame.VersX(), m_MapFrame.VersY(), m_MapFrame.VersZ()) ; + vFrGrid[2].Set( m_MapFrame.Orig(), m_MapFrame.VersY(), m_MapFrame.VersZ(), m_MapFrame.VersX()) ; + vFrGrid[3].Set( m_MapFrame.Orig(), m_MapFrame.VersZ(), m_MapFrame.VersX(), m_MapFrame.VersY()) ; + + // definisco una mappa dei vertici, in modo da sapere su quali sono state già create le sfere + BOOLVECTOR vbVert( Surf->GetVertexCount(), false) ; + // ----------------------- Cilindri e Sfere ----------------------- + // scorro gli Edge della superficie + for ( int nE = 0 ; nE < Surf->GetEdgeCount() ; ++ nE) { + // recupero lo spigolo + int nV1, nV2, nF1, nF2 ; double dAng ; + Surf->GetEdge( nE, nV1, nV2, nF1, nF2, dAng) ; + // recupero le coordinate dei vertici + Point3d ptP1 ; Surf->GetVertex( nV1, ptP1) ; + Point3d ptP2 ; Surf->GetVertex( nV2, ptP2) ; + // ciclo sulle griglie + for ( int nGrid = 0 ; nGrid < 3 ; ++ nGrid) { + // esprimo gli estremi nel riferimento della griglia + ptP1.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; + ptP2.LocToLoc( vFrGrid[nGrid], vFrGrid[nGrid + 1]) ; + // aggiungo/sottraggo gli intervalli definiti dal cilindro + if ( ! CreateOffsCylinderOnEdge( ptP1, ptP2, abs( dOffs), nGrid)) + return false ; + // aggiungo/sottraggo gli intervalli definiti dalla sfera + if ( ! vbVert[nV1]) { + if ( ! CreateOffsSphereOnVertex( ptP1, abs( dOffs), nGrid)) + return false ; + } + if ( ! vbVert[nV2]) { + if ( ! CreateOffsSphereOnVertex( ptP2, abs( dOffs), nGrid)) + return false ; + } + } + vbVert[nV1] = true ; + vbVert[nV2] = true ; + } + // ----------------------- Facce ----------------------- + // scorro tutte le facce definendo una superficie di estrusione + for ( int nF = 0 ; nF < Surf->GetFacetCount() ; ++ nF) { + // recupero lo faccia + POLYLINEVECTOR vPL ; Surf->GetFacetLoops( nF, vPL) ; + // recupero la normale della faccia + Vector3d vtN ; Surf->GetFacetNormal( nF, vtN) ; + // definisco la superficie di estrusione + CICURVEPVECTOR vpCrvs ; vpCrvs.reserve( vPL.size()) ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + vPL[i].Translate( - abs( dOffs) * vtN) ; + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( vPL[i])) { + // dealloco le curve + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + delete ( vpCrvs[i]) ; + vpCrvs[i] = nullptr ; + } + return false ; + } + vpCrvs.emplace_back( Release( pCrvCompo)) ; + } + // recupero la TriMesh di estrusione + PtrOwner pStmExtr( GetSurfTriMeshByRegionExtrusion( vpCrvs, 2 * abs( dOffs) * vtN)) ; + if ( IsNull( pStmExtr) || ! pStmExtr->IsValid() || pStmExtr->GetTriangleCount() == 0) { + // dealloco le curve + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + delete ( vpCrvs[i]) ; + vpCrvs[i] = nullptr ; + } + return false ; + } + // aggiorno gli spilloni + AddSurfTm( pStmExtr) ; + // dealloco le curve + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + delete ( vpCrvs[i]) ; + vpCrvs[i] = nullptr ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +/* Funzione per la creazine di uno Zmap di Offset (positivo o negativo) a partire da un + vettore di superfici TriMesh (aperte o chiuse) */ +/* + Definizione : + - Lo Zmap di Offset ( positivo o negativo) di una superficie chiusa è automaticamente l'Offset stesso + - Lo Zmap di Offset ( positivo o negativo) di una superficie aperta è ????? ( da capire...) +*/ +bool +VolZmap::CreateFromTriMeshOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType) +{ + // controllo delle superfici + for ( const ISurfTriMesh* Surf : vSurf) { + if ( Surf == nullptr) + return false ; + } + // verifica sul parametro di Offset ( coerente con Curve e FlatRegion) + if ( abs( dOffs) < 10 * EPS_SMALL) + return true ; + // se non ho superfici, non faccio nulla + if ( vSurf.empty()) + return true ; + + // inizializzo lo Zmap di Offset a partire dalle superfici + if ( ! InitVolZMapOffs( vSurf, dOffs, dTol)) + return false ; + + // scorro le superfici + for ( const ISurfTriMesh* Surf : vSurf) { + // se superficie non valida, passo alla successiva + if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0) + continue ; + // aggiorno lo ZMap + if ( Surf->IsClosed()) { + if ( nType == ISurfTriMesh::OFF_FILLET) { + if ( ! UpdateVolZMapByClosedSurfFilletOffset( Surf, dOffs, dTol)) + return false ; + } + } + else { + // --- LE SUPERFICI APERTE SONO PER ORA DISABILITATE --- + } + } + + m_nShape = OFFSET ; + return true ; +} + +//---------------------------------------------------------------------------- +/* Funzione per la creazine di uno Zmap di Fat Offset a partire da un + vettore di superfici TriMesh (aperte o chiuse) */ +bool +VolZmap::CreateFromTriMeshThickeningOffset( const CISURFTMPVECTOR& vSurf, double dOffs, double dTol, int nType) +{ + // controllo delle superfici + for ( const ISurfTriMesh* Surf : vSurf) { + if ( Surf == nullptr) + return false ; + } + // verifica sul parametro di Offset ( coerente con Curve e FlatRegion) + if ( abs( dOffs) < 10 * EPS_SMALL) + return true ; + // se non ho superfici, non faccio nulla + if ( vSurf.empty()) + return true ; + + // inizializzo lo Zmap di Offset a partire dalle superfici + if ( ! InitVolZMapThickeningOffs( vSurf, dOffs, dTol)) + return false ; + + // scorro le superfici + for ( const ISurfTriMesh* Surf : vSurf) { + // se superficie non valida, passo alla successiva + if ( ! Surf->IsValid() || Surf->GetTriangleCount() == 0) + continue ; + + // aggiorno lo Zmap + if ( nType == ISurfTriMesh::OFF_FILLET) { + if ( ! UpdateVolZMapBySurfThickeningFilletOffset( Surf, dOffs, dTol)) + return false ; + } + } + + m_nShape = OFFSET ; + return true ; +} +