From 15ed754512a1afefed1febaa2a2e6e24e3a512d1 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 7 Dec 2023 13:13:28 +0100 Subject: [PATCH] =?UTF-8?q?EgtGeomKernel=20:=20-=20gestiti=20pi=C3=B9=20ch?= =?UTF-8?q?unk=20per=20la=20triangolaziome=20(=20MakeAdvanced)=20-=20picco?= =?UTF-8?q?le=20modifiche=20a=20Intersezione=20e=20creazione=20di=20Stm=20?= =?UTF-8?q?da=20curve.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- StmFromCurves.cpp | 58 ++++------------- SurfTriMesh.cpp | 2 +- SurfTriMeshBooleans.cpp | 28 ++++---- Triangulate.cpp | 137 ++++++++++++++++++++++++++++++++++++++++ Triangulate.h | 1 + 5 files changed, 167 insertions(+), 59 deletions(-) diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 1f47f22..e962eaf 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -790,56 +790,22 @@ bool CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol, POLYLINEVECTOR& vPL, Vector3d& vtN) { + // se non ho curve, non faccio nulla + if ( int( vpCurve.size()) == 0) + return true ; + // calcolo le polilinee che approssimano le curve - POLYLINEVECTOR vPLtmp ; - vPLtmp.resize( vpCurve.size()) ; + vPL.resize( vpCurve.size()) ; for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) { - if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPLtmp[i])) + if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i])) return false ; } - // ne calcolo l'area e genero un ordine in senso decrescente - typedef pair INDAREA ; // coppia indice, area - typedef vector INDAREAVECTOR ; // vettore di coppie indice, area - INDAREAVECTOR vArea ; - vArea.reserve( vPLtmp.size()) ; - Vector3d vtN0 ; - for ( int i = 0 ; i < int( vPLtmp.size()) ; ++ i) { - // verifico chiusura, calcolo piano medio e area - Plane3d plPlane ; - double dArea ; - if ( ! vPLtmp[i].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL)) + + // ricavo versore normale + Plane3d plPlane ; double dArea ; + if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL)) return false ; - // imposto la normale del primo contorno come riferimento - if ( i == 0) - vtN0 = plPlane.GetVersN() ; - // verifico che le normali siano molto vicine - if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN0)) - return false ; - // assegno il segno all'area secondo il verso della normale - if ( ( plPlane.GetVersN() * vtN0) > 0) - vArea.emplace_back( i, dArea) ; - else - vArea.emplace_back( i, - dArea) ; - } - sort( vArea.begin(), vArea.end(), - []( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ; - // sposto le polilinee nel vettore da restituire secondo l'ordine - vPL.clear() ; - vPL.resize( vPLtmp.size()) ; - bool bCCW = true ; - for ( int i = 0 ; i < int( vPLtmp.size()) ; ++ i) { - // scambio - swap( vPL[i], vPLtmp[vArea[i].first]) ; - // verifico senso di rotazione del contorno esterno - if ( i == 0) - bCCW = ( vArea[i].second > 0) ; - // aggiusto gli altri contorni - else { - if ( ( bCCW && vArea[i].second > 0) || ( ! bCCW && vArea[i].second < 0)) - vPL[i].Invert() ; - } - } - // restituisco la normale positiva alla regione - vtN = ( bCCW ? vtN0 : - vtN0) ; + vtN = plPlane.GetVersN() ; + return true ; } diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index d0b7568..96924bf 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -2044,7 +2044,7 @@ SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL) PNTVECTOR vPnt ; INTVECTOR vTria ; Triangulate Tri ; - if ( ! Tri.Make( vPL, vPnt, vTria)) + if ( ! Tri.MakeAdvanced( vPL, vPnt, vTria)) return false ; // inizializzo la superficie diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index c3dfa8e..a2a44d9 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -35,6 +35,7 @@ #include "/EgtDev/Include/EGkPolygon3d.h" #include "/EgtDev/Include/EgtPerfCounter.h" #include "/EgtDev/Include/EGnStringUtils.h" +#include "/EgtDev/Include/EGkGeoObjSave.h" #include using namespace std ; @@ -731,14 +732,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT } Polygon3d pgPol ; - pgPol.FromPolyLine(vPolygons[1]) ; + pgPol.FromPolyLine( vPolygons[1]) ; bool bCodirectedNormals = trTria.GetN() * pgPol.GetVersN() > 0. ; - if ( bCodirectedNormals) { - for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) { - vPolygons[nL].Invert() ; - } - } + //if ( bCodirectedNormals) { + // for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) { + // vPolygons[nL].Invert() ; + // } + //} pizza // Aggiungo al loop esterno i punti dei loop interni che si trovano su di esso PNTULIST& ExternLoopList = vPolygons[0].GetUPointList() ; @@ -788,12 +789,12 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT // Aggiungo i punti al loop esterno for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) ; ++ nPi) { itSt = ExternLoopList.emplace( itEn, vPointWithOrder[nPi]) ; - } + } } PNTVECTOR vPt ; INTVECTOR vTr ; - if ( Triangulate().Make( vPolygons, vPt, vTr)) { + if ( Triangulate().MakeAdvanced( vPolygons, vPt, vTr)) { // Inserisco i nuovi triangoli for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) { int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ; @@ -928,9 +929,11 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT } } } - for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) { - vPolygons[nL].Invert() ; - if ( Triangulate().Make( vPolygons[nL], vPt, vTr)) { + // pizza + //for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) { + // vPolygons[nL].Invert() ; + vPolygons.erase( vPolygons.begin()) ; + if ( Triangulate().MakeAdvanced( vPolygons, vPt, vTr)) { // Inserisco i nuovi triangoli for (int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) { int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ; @@ -950,7 +953,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT } } } - } + //} } vInnerLoop.resize( 0) ; } @@ -1359,6 +1362,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other) // Se avvenuta modifica, aggiorno tutto if ( bModif) bContinue = ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ; + SaveGeoObj( this, "C:\\Users\\riccardo.elitropi\\Desktop\\PocketingVolumi\\a.nge") ; // Triangoli sovrapposti if ( bContinue) { int nTriaNum2A = GetTriangleSize() ; diff --git a/Triangulate.cpp b/Triangulate.cpp index f9aba85..2eea13d 100644 --- a/Triangulate.cpp +++ b/Triangulate.cpp @@ -21,8 +21,11 @@ #include "/EgtDev/Include/EGkPlane3d.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EgtNumUtils.h" +#include "CurveComposite.h" +#include "IntersCrvCompoCrvCompo.h" #include + using namespace std ; //---------------------------------------------------------------------------- @@ -218,6 +221,140 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) return true ; } +//--------------------------------------------------------------------------- +bool +Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVECTOR& vTr) +{ + vPt.clear() ; + vTr.clear() ; + // se non ho PolyLine, allora non faccio nulla + if ( int( vPLORIG.size()) == 0) + return true ; + + // copio il vettore di PolyLine + POLYLINEVECTOR vPL ; + for ( int i = 0 ; i < int( vPLORIG.size()) ; ++ i) + vPL.push_back( vPLORIG[i]) ; + + typedef std::pair INDAREA ; + std::vector m_vArea ; + // calcolo piano medio e area delle curve + m_vArea.reserve( vPL.size()) ; + Vector3d vtN0 ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + // calcolo piano medio e area + Plane3d plPlane ; + double dArea ; + if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea)) + return false ; + // imposto la normale del primo contorno come riferimento + if ( i == 0) + vtN0 = plPlane.GetVersN() ; + // verifico che le normali siano molto vicine + if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN0)) + return false ; + // assegno il segno all'area secondo il verso della normale + if ( ( plPlane.GetVersN() * vtN0) > 0) + m_vArea.emplace_back( i, dArea) ; + else + m_vArea.emplace_back( i, - dArea) ; + } + // ordino in senso decrescente sull'area + sort( m_vArea.begin(), m_vArea.end(), + []( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ; + + // dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive) + Frame3d frRef ; frRef.Set( ORIG, vtN0) ; + if ( ! frRef.IsValid()) + return false ; + ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ; + for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + vCrvCompo[i].Set( CreateCurveComposite()) ; + vCrvCompo[i]->FromPolyLine( vPL[i]) ; + vCrvCompo[i]->ToLoc( frRef) ; + } + + // creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle + // successive i loop interni + INTMATRIX vnPLIndMat ; + + // aggiungo le diverse curve + bool bExtLoop = false ; + bool bFirstCrv ; + Plane3d plExtLoop ; + do { + bFirstCrv = true ; + for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) { + // recupero indice di percorso e verifico sia valido + int j = m_vArea[i].first ; + if ( j < 0) + continue ; + // lo inserisco come esterno... + if ( bFirstCrv) { + vnPLIndMat.push_back({ j}) ; + m_vArea[i].first = -1 ; + // inverto se necessario + if ( m_vArea[i].second < EPS_SMALL) { + vPL[j].Invert() ; + vCrvCompo[j]->Invert() ; + } + bFirstCrv = false ; + } + // ... altrimenti verifico se il loop è interno o no + else { + // il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo + // esterno a tutti i loop già inseriti nella riga attuale. + // verifica rispetto loop esterno + IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ; + CRVCVECTOR ccClass ; + if ( ccInt.GetCrossOrOverlapIntersCount() > 0 || + ! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) || + ccClass.empty() || ccClass[0].nClass != CRVC_IN) + continue ; + // verifica rispetto ai loop interni + bool bOk = true ; + for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) { + IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ; + CRVCVECTOR ccClass2 ; + if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 || + ! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) || + ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) { + bOk = false ; + break ; + } + } + if ( bOk) { + // inserisco nella matrice + vnPLIndMat.back().push_back( j) ; + m_vArea[i].first = -1 ; + // inverto se necessario + if ( m_vArea[i].second > - EPS_SMALL) { + vPL[j].Invert() ; + vCrvCompo[j]->Invert() ; + } + } + } + } + } while ( ! bFirstCrv) ; + + // chiamo la Triangolazione per ogni riga della matrice ( quindi su ogni "Chunk") + for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++ i) { + PNTVECTOR vPt_tmp ; INTVECTOR vTr_tmp ; + POLYLINEVECTOR vPL_tmp ; + for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++ j) + vPL_tmp.push_back( vPL[vnPLIndMat[i][j]]) ; + if ( ! Make( vPL_tmp, vPt_tmp, vTr_tmp)) + return false ; + int nSize = int( vPt.size()) ; + for ( int p = 0 ; p < int( vPt_tmp.size()) ; ++ p) + vPt.push_back( vPt_tmp[p]) ; + for ( int t = 0 ; t < int( vTr_tmp.size()) ; ++ t) + vTr.push_back( nSize + vTr_tmp[t]) ; + } + + return true ; +} + //---------------------------------------------------------------------------- // Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0]) // Ear Clipping algorithm from mapbox diff --git a/Triangulate.h b/Triangulate.h index d5470b7..5c6054a 100644 --- a/Triangulate.h +++ b/Triangulate.h @@ -22,6 +22,7 @@ class Triangulate public : bool Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr) ; bool Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ; + bool MakeAdvanced( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ; private : bool MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr) ;