From 87f6a29db3a3a0aadd18c2513d29269c36b38c2f Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 19 Jul 2024 13:13:45 +0200 Subject: [PATCH 01/16] EgtGeomKernel : - aggiunte le skinned con le Bezier. --- SbzFromCurves.cpp | 99 +++++++++++++++++++++++-------------- SurfBezier.cpp | 123 ++++++++++++++++++++++++++++++++++++++++++++++ SurfBezier.h | 1 + 3 files changed, 187 insertions(+), 36 deletions(-) diff --git a/SbzFromCurves.cpp b/SbzFromCurves.cpp index f792a62..95e22bc 100644 --- a/SbzFromCurves.cpp +++ b/SbzFromCurves.cpp @@ -118,9 +118,9 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, if ( IsNull( pSbz) || ! pSbz->CreateByExtrusion( pBezierForm, vtExtr)) return nullptr ; - //// se da fare, metto i tappi sulle estremità + //// se da fare, metto i tappi sulle estremità //if ( bDoCapEnds) { - // // creo la prima superficie di estremità + // // creo la prima superficie di estremità // SurfTriMesh STM1 ; // if ( ! STM1.CreateByFlatContour( PL)) // return nullptr ; @@ -166,7 +166,7 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, // for ( int i = 0 ; i < int( vPL.size()) ; ++ i) // vPL[i].Invert() ; // } -// // creo la prima superficie di estremità +// // creo la prima superficie di estremità // PtrOwner pSbz1( CreateBasicSurfBezier()) ; // if ( IsNull( pSbz1) || ! pSbz1->CreateByRegion( vPL)) // return nullptr ; @@ -184,7 +184,7 @@ GetSurfBezierByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, // //// salvo tolleranza lineare usata // //pSTM->SetLinearTolerance( dLinTol) ; // // restituisco la superficie -// return Release( pSrfCompo) ; // in realtà dovrei restituire tre superfici!!! due basi e una sup laterale( e quindi fare una SurfCompo) oppure dovrei spezzare le basi in tot pezzi e creare una superficie unica +// return Release( pSrfCompo) ; // in realtà dovrei restituire tre superfici!!! due basi e una sup laterale( e quindi fare una SurfCompo) oppure dovrei spezzare le basi in tot pezzi e creare una superficie unica //} //------------------------------------------------------------------------------- @@ -289,7 +289,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector return nullptr ; //// se richiesti caps /// richiede la SurfCompo //if ( bCapEnds) { - // // determino se la sezione è chiusa e piatta + // // determino se la sezione è chiusa e piatta // Plane3d plPlane ; double dArea ; // bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ; // // determino non sia una semplice rivoluzione @@ -333,7 +333,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) // return nullptr ; // Vector3d vtNorm = plGuide.GetVersN() ; -// // determino se la guida è chiusa +// // determino se la guida è chiusa // bool bGuideClosed = pGuide->IsClosed() ; // // curve di offset // OffsetCurve OffsCrvR ; @@ -374,7 +374,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // pSTM->SetSmoothAngle( 20) ; // // se guida aperta e tappi piatti // if ( ! bGuideClosed && nCapType == RSCAP_FLAT) { -// // verifico che le due estremità siano chiuse e piatte +// // verifico che le due estremità siano chiuse e piatte // POLYLINEVECTOR vPL ; // if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) // return nullptr ; @@ -453,7 +453,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // Point3d ptCen ; // pGuide->GetStartPoint( ptCen) ; // ptCen -= dDimV / 2 * vtNorm ; -// // determino se la guida è chiusa +// // determino se la guida è chiusa // bool bGuideClosed = pGuide->IsClosed() ; // // curve di offset // const int NUM_OFFS = 4 ; @@ -476,7 +476,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // } // } // else { -// // se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo +// // se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo // for ( int i = 0 ; i < NUM_OFFS && bOk ; ++ i) // bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ; // } @@ -553,7 +553,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // StmFromTriangleSoup stmCapSoup ; // if ( ! stmCapSoup.Start( nBuckets)) // return nullptr ; -// // verifico che le due estremità siano chiuse e piatte +// // verifico che le due estremità siano chiuse e piatte // POLYLINEVECTOR vPL ; // if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) // return nullptr ; @@ -654,9 +654,9 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector //static ISurfBezier* //GetSurfBezierSweptInPlane( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtNorm, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// //{ -// // determino se la sezione è chiusa +// // determino se la sezione è chiusa // bool bSectClosed = pSect->IsClosed() ; -// // determino se la guida è chiusa +// // determino se la guida è chiusa // bool bGuideClosed = pGuide->IsClosed() ; // // // riferimento all'inizio della linea guida @@ -719,7 +719,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // // // se richiesti caps e sezione chiusa e guida aperta // if ( bCapEnds && bSectClosed && ! bGuideClosed) { -// // verifico che le due estremità siano chiuse e piatte +// // verifico che le due estremità siano chiuse e piatte // POLYLINEVECTOR vPL ; // if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2) // return nullptr ; @@ -763,9 +763,9 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector //static ISurfBezier* //GetSurfBezierSwept3d( const ICurve* pSect, const ICurve* pGuide, const Vector3d& vtAx, bool bCapEnds, double dLinTol) // DA SISTEMARE - ancora copia della versione stm, cambia solo il nome della funzione////////////////////// //{ -// // determino se la sezione è chiusa +// // determino se la sezione è chiusa // bool bSectClosed = pSect->IsClosed() ; -// // determino se la guida è chiusa +// // determino se la guida è chiusa // bool bGuideClosed = pGuide->IsClosed() ; // // determino algoritmo da usare per calcolare i riferimenti lungo la curva // bool bRMF = vtAx.IsSmall() ; @@ -915,7 +915,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd)) // bIsLine = true ; // } -// // se la guida è piana +// // se la guida è piana // Plane3d plGuide ; // if ( pGuide->IsFlat( plGuide, bIsLine, 10 * EPS_SMALL)) // return GetSurfBezierSweptInPlane( pSect, pGuide, plGuide.GetVersN(), bCapEnds, dLinTol) ; @@ -961,7 +961,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // return nullptr ; // // // se rischiesta chiusura... -// // Controllo solo che la guida non sia chiusa, la sezione derivando da una Flatregion è sempre chiusa +// // Controllo solo che la guida non sia chiusa, la sezione derivando da una Flatregion è sempre chiusa // if ( bCapEnds && ! pGuide->IsClosed()) { // // recupero i loop all'inizio (dalla regione e apportunamente approssimati) // POLYLINEVECTOR vPLi ; @@ -972,7 +972,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // return nullptr ; // } // } -// // creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta) +// // creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta) // PtrOwner pSci( CreateSurfTriMesh()) ; // if ( ! pSci->CreateByRegion( vPLi)) // return nullptr ; @@ -1004,7 +1004,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // // verifica parametri // if ( pSect == nullptr || pGuide == nullptr) // return nullptr ; -// // determino se la sezione è chiusa +// // determino se la sezione è chiusa // bool bSectClosed = pSect->IsClosed() ; // // punto iniziale della sezione e vettore a inizio guida // Point3d ptStart ; @@ -1018,7 +1018,7 @@ GetSurfBezierByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector // PolyLine PLG ; // if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLG)) // return nullptr ; -// // determino se la guida è chiusa +// // determino se la guida è chiusa // bool bGuideClosed = PLG.IsClosed() ; // // calcolo la superficie // PtrOwner pSTM( CreateBasicSurfTriMesh()) ; @@ -1111,21 +1111,8 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou if ( pCurve1 == nullptr || pCurve2 == nullptr) return nullptr ; - // qui anziché fare le polyline converto le curve in bezier! - // SE NON HO LO STESSO NUMERO DI CURVE COME LO GESTISCO?? - - //// calcolo la polilinea che approssima la prima curva - //PolyLine PL1 ; - //if ( ! pCurve1->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL1)) - // return nullptr ; - //// calcolo la polilinea che approssima la seconda curva - //PolyLine PL2 ; - //if ( ! pCurve2->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL2)) - // return nullptr ; - - - // dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier - // se la curva è già una bezier singola la tengo, sennò la converto // e la compo di bezier??? + // dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier + // se la curva è già una bezier singola la tengo, sennò la converto PtrOwner pCC1( CreateCurveComposite()) ; if ( pCurve1->GetType() != CRV_BEZIER) pCC1->AddCurve( CurveToBezierCurve( pCurve1)) ; @@ -1134,7 +1121,7 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou if ( IsNull( pCC1) || ! pCC1->IsValid()) return nullptr ; - // se la curva è già una bezier singola la tengo, sennò la converto + // se la curva è già una bezier singola la tengo, sennò la converto PtrOwner pCC2( CreateCurveComposite()) ; if ( pCurve2->GetType() != CRV_BEZIER) pCC2->AddCurve( CurveToBezierCurve( pCurve2)) ; @@ -1151,4 +1138,44 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou //pSbz->SetLinearTolerance( dLinTol) ; // restituisco la superficie return Release( pSbz) ; +} + +//------------------------------------------------------------------------------- +ISurfBezier* +GetSurfBezierSkinned( const CICURVEPVECTOR& vCrv, double dLinTol) +{ + // verifico che le curve siano valide + for ( int i = 0 ; i < int( vCrv.size()) ; ++i) { + if( vCrv[i] == nullptr || ! vCrv[i]->IsValid()) + return nullptr ; + } + + // se ho solo due curve allora faccio la rigata + if( vCrv.size() == 2) + return GetSurfBezierRuled( vCrv[0], vCrv[1], ISurfBezier::RLT_B_MINDIST_PLUS, dLinTol) ; + + //trasformo le curve in curve di bezier, pareggio il numero di sottocurve e il grado + + // dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier + // se la curva è già una bezier singola la tengo, sennò la converto + ICURVEPOVECTOR vCrvBez ; + for( int c = 0 ; c < int( vCrv.size()) ; ++c){ + PtrOwner pCC( CreateCurveComposite()) ; + if ( vCrv[c]->GetType() != CRV_BEZIER ) + pCC->AddCurve( CurveToBezierCurve( vCrv[c])) ; + else + pCC->AddCurve( vCrv[c]->Clone()) ; + if ( IsNull( pCC) || ! pCC->IsValid()) + return nullptr ; + vCrvBez.emplace_back( Release( pCC)) ; + } + + // creo e setto la superficie trimesh + PtrOwner pSbz( CreateBasicSurfBezier()) ; + if ( IsNull( pSbz) || ! pSbz->CreateBySetOfCurves( vCrvBez)) + return nullptr ; + //// salvo tolleranza lineare usata + //pSbz->SetLinearTolerance( dLinTol) ; + // restituisco la superficie + return Release( pSbz) ; } \ No newline at end of file diff --git a/SurfBezier.cpp b/SurfBezier.cpp index d46de25..8ff0d4a 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -4630,3 +4630,126 @@ static bool ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposit } return true ; } + + +//---------------------------------------------------------------------------- +bool +SurfBezier::CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez) +{ + //uniformo le curve e determino il grado e il numero di span condiviso + //... + //... + int nDegU = 3 ; + int nSpanU = 2 ; + + // calcolo i punti di controllo in V + int nDegV = 3 ; + int nSpanV = int( vCrvBez.size()) - 1 ; + + //nSpanU = 1 ; + //nSpanV = 2 ; + + + Init( nDegU, nDegV, nSpanU, nSpanV, false) ; + // scorro le span + for ( int s = 0 ; s < int( nSpanU) ; ++s) { + // prendo le curve a gruppi di 3 per costruire la parabola per trovare la pendenza "intuitiva" della superficie in V + for ( int g = 0 ; g < nSpanV - 1 ; ++g) { + const ICurveComposite* pCC0 = GetCurveComposite( vCrvBez[g]) ; + const ICurveComposite* pCC1 = GetCurveComposite( vCrvBez[g + 1]) ; + const ICurveComposite* pCC2 = GetCurveComposite( vCrvBez[g + 2]) ; + // su ognuna di queste 3 curve prendo un punto per ogni punto di controllo ( semplicemente dividendo uniformemente il parametrico) + for ( int n = s == 0 ? 0 : 1 ; n < nDegU + 1 ; ++n) { + const ICurveBezier* pCrv0 = GetCurveBezier( pCC0->GetCurve( s)) ; + const ICurveBezier* pCrv1 = GetCurveBezier( pCC1->GetCurve( s)) ; + const ICurveBezier* pCrv2 = GetCurveBezier( pCC2->GetCurve( s)) ; + // setto come punti di controllo i punti delle curve + Point3d ptCtrl0 = pCrv0->GetControlPoint( n) ; + Point3d ptCtrl1 = pCrv1->GetControlPoint( n) ; + Point3d ptCtrl2 = pCrv2->GetControlPoint( n) ; + if ( g == 0) { + SetControlPoint( n + (s * nDegU) + (nDegU * nSpanU + 1) * g * 3, ptCtrl0) ; + SetControlPoint( n + (s * nDegU) + (nDegU * nSpanU + 1) * (g * 3 + 3), ptCtrl1) ; + } + SetControlPoint( n + (s * nDegU) + (nDegU * nSpanU + 1) * (g * 3 + 6), ptCtrl2) ; + //// trovo i punti di controllo intermedi tra le curve usando la parabola che unisce queste tre curve//// + double dPar = double(n) / nDegU ; + //Point3d ptP0 ; pCrv0->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP0, nullptr, nullptr) ; + //Point3d ptP1 ; pCrv1->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP1, nullptr, nullptr) ; + //Point3d ptP2 ; pCrv2->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP2, nullptr, nullptr) ; + + Point3d ptP0 = pCrv0->GetControlPoint( n) ; + Point3d ptP1 = pCrv1->GetControlPoint( n) ; + Point3d ptP2 = pCrv2->GetControlPoint( n) ; + DistPointLine dpl( ptP1, ptP0, ptP2, false) ; + double dDist = INFINITO ; dpl.GetDist( dDist) ; + Point3d ptP3, ptP4, ptP5, ptP6 ; + if ( dDist < EPS_SMALL) { + // i punti sono allineati quindi mi basta prendere dei punti intermedi su questa retta + ptP3 = ptP0 * 2/3 + ptP1 * 1/3 ; + ptP4 = ptP0 * 1/3 + ptP1 * 2/3 ; + ptP5 = ptP1 * 2/3 + ptP2 * 1/3 ; + ptP6 = ptP1 * 1/3 + ptP2 * 2/3 ; + } + else { + // calcolo il piano della parabola e porto i + Plane3d plParab ; plParab.Set( ptP0, ptP1, ptP2) ; + Point3d ptStartV, ptEndV ; + Vector3d vDirX = ptP2 - ptP0 ; + DistPointLine dpl( ptP1, ptP0, ptP2, true) ; + Point3d ptPerp ; dpl.GetMinDistPoint( ptPerp) ; + Vector3d vDirY = ptPerp - ptP1 ; + Frame3d frParab ; + //Vector3d vDirZ = plParab.GetVersN() ; + Vector3d vDirZ = X_AX ; + if ( ! frParab.Set( ptP0, vDirX, vDirY, vDirZ)) { + vDirY = vDirZ ^ vDirX ; + if ( ! frParab.Set( ptP0, vDirX, vDirY, vDirZ)) + return false ; + } + // porto i punti nel piano di riferimento della parabola + Point3d pt0 = ptP0 ; pt0.ToLoc( frParab) ; + Point3d pt1 = ptP1 ; pt1.ToLoc( frParab) ; + Point3d pt2 = ptP2 ; pt2.ToLoc( frParab) ; + + Eigen::Matrix3d mA ; + mA.col(0) << pow(pt0.x,2), pow(pt1.x,2) , pow(pt2.x,2) ; + mA.col(1) << pt0.x, pt1.x , pt2.x ; + mA.col(2) << 1, 1, 1 ; + if( abs( mA.determinant()) < EPS_SMALL) + return false ; + Eigen::Vector3d b ( pt0.y, pt1.y, pt2.y) ; + Eigen::Vector3d coeff = mA.fullPivLu().solve(b) ; + + // pendenze e termini noti nei punti di contatto + double dm0 = 2 * coeff.x() * pt0.x + coeff.y() ; + double dm1 = 2 * coeff.x() * pt1.x + coeff.y() ; + double dm2 = 2 * coeff.x() * pt2.x + coeff.y() ; + double dq0 = pt0.y - dm0 * pt0.x ; + double dq1 = pt1.y - dm1 * pt1.x ; + double dq2 = pt2.y - dm2 * pt2.x ; + // trovo le intersezioni a coppie tra le tre rette di tangenza + Point3d ptI1 , ptI2; + ptI1.x = (dq1 -dq0) / (dm0 - dm1) ; + ptI1.y = ptI1.x * dm0 + dq0 ; + ptI2.x = ( dq2 - dq1) / ( dm1 - dm2) ; + ptI2.y = ptI2.x * dm1 + dq1 ; + // porto i punti in globale e trovo i punti medi + ptI1.ToGlob( frParab) ; + ptI2.ToGlob( frParab) ; + + ptP3 = ( ptP0 + ptI1) / 2 ; + ptP4 = ( ptP1 + ptI1) / 2 ; + ptP5 = ( ptP1 + ptI2) / 2 ; + ptP6 = ( ptP2 + ptI2) / 2 ; + } + if ( g == 0) + SetControlPoint( n + (s * nDegU) + (nDegU * nSpanU + 1) * (g * 3 + 1), ptP3) ; + SetControlPoint( n + (s * nDegU) + (nDegU * nSpanU + 1) * (g * 3 + 2), ptP4) ; + SetControlPoint( n + (s * nDegU) + (nDegU * nSpanU + 1) * (g * 3 + 4), ptP5) ; + SetControlPoint( n + (s * nDegU) + (nDegU * nSpanU + 1) * (g * 3 + 5), ptP6) ; + } + } + } + return true ; +} diff --git a/SurfBezier.h b/SurfBezier.h index 6d8d63b..37c716b 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -143,6 +143,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ; bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ; bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ; + bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez) ; public : // IGeoObjRW int GetNgeId( void) const override ; From 19c7f63303e9d57ccf6b509b2f1d8c0ef334d45e Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 19 Jul 2024 16:59:47 +0200 Subject: [PATCH 02/16] EgtGeomKernel : - generalizzazione della skinned con bezier. --- SurfBezier.cpp | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 8ff0d4a..43e7cdf 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -4646,13 +4646,31 @@ SurfBezier::CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez) int nDegV = 3 ; int nSpanV = int( vCrvBez.size()) - 1 ; - //nSpanU = 1 ; - //nSpanV = 2 ; - + PNTMATRIX vPntCrvs ; + for ( int j = 0 ; j < nSpanU ; ++j ) { + PNTVECTOR vPntCtrl0 ; + PNTVECTOR vPntCtrl1 ; + for ( int i = 0 ; i < int( vCrvBez.size()) ; ++i) { + const ICurveComposite* pCC = GetCurveComposite(vCrvBez[i]) ; + const ICurveBezier* pCrvBez = GetCurveBezier(pCC->GetCurve( j)) ; + if ( j == 0) + vPntCtrl0.push_back( pCrvBez->GetControlPoint(0)) ; + vPntCtrl1.push_back( pCrvBez->GetControlPoint(nDegU)) ; + } + if( j==0 ) + vPntCrvs.push_back( vPntCtrl0) ; + vPntCrvs.push_back( vPntCtrl1) ; + } Init( nDegU, nDegV, nSpanU, nSpanV, false) ; // scorro le span for ( int s = 0 ; s < int( nSpanU) ; ++s) { + // trovo la direzione media del parametro V + Point3d ptMean = ORIG ; + for ( int i = 1 ; i < int( vPntCrvs[0].size()) ; ++i ) + ptMean += vPntCrvs[s][i] ; + ptMean /= int( vPntCrvs[0].size() - 1) ; + Vector3d vtDirXGeneral = ptMean - vPntCrvs[s][0] ; // prendo le curve a gruppi di 3 per costruire la parabola per trovare la pendenza "intuitiva" della superficie in V for ( int g = 0 ; g < nSpanV - 1 ; ++g) { const ICurveComposite* pCC0 = GetCurveComposite( vCrvBez[g]) ; @@ -4674,10 +4692,6 @@ SurfBezier::CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez) SetControlPoint( n + (s * nDegU) + (nDegU * nSpanU + 1) * (g * 3 + 6), ptCtrl2) ; //// trovo i punti di controllo intermedi tra le curve usando la parabola che unisce queste tre curve//// double dPar = double(n) / nDegU ; - //Point3d ptP0 ; pCrv0->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP0, nullptr, nullptr) ; - //Point3d ptP1 ; pCrv1->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP1, nullptr, nullptr) ; - //Point3d ptP2 ; pCrv2->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptP2, nullptr, nullptr) ; - Point3d ptP0 = pCrv0->GetControlPoint( n) ; Point3d ptP1 = pCrv1->GetControlPoint( n) ; Point3d ptP2 = pCrv2->GetControlPoint( n) ; @@ -4692,19 +4706,24 @@ SurfBezier::CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez) ptP6 = ptP1 * 1/3 + ptP2 * 2/3 ; } else { - // calcolo il piano della parabola e porto i + // calcolo il piano della parabola e porto i punti in quel riferimento Plane3d plParab ; plParab.Set( ptP0, ptP1, ptP2) ; Point3d ptStartV, ptEndV ; - Vector3d vDirX = ptP2 - ptP0 ; + //Vector3d vDirX = ptP2 - ptP0 ; DistPointLine dpl( ptP1, ptP0, ptP2, true) ; Point3d ptPerp ; dpl.GetMinDistPoint( ptPerp) ; - Vector3d vDirY = ptPerp - ptP1 ; + Vector3d vtDirY = ptPerp - ptP1 ; Frame3d frParab ; - //Vector3d vDirZ = plParab.GetVersN() ; - Vector3d vDirZ = X_AX ; - if ( ! frParab.Set( ptP0, vDirX, vDirY, vDirZ)) { - vDirY = vDirZ ^ vDirX ; - if ( ! frParab.Set( ptP0, vDirX, vDirY, vDirZ)) + Point3d ptStart, ptEnd ; + pCrv1->GetStartPoint( ptStart) ; + pCrv1->GetEndPoint( ptEnd) ; + Vector3d vtDirCrv1 = ptEnd - ptStart ; + Vector3d vtParabNorm = plParab.GetVersN() ; + Vector3d vtDirZ = vtDirCrv1 * vtParabNorm > 0 ? vtParabNorm : - vtParabNorm ; + Vector3d vtDirX = vtDirXGeneral - (vtDirXGeneral * vtDirZ * vtDirZ) ; + if ( ! frParab.Set( ptP0, vtDirX, vtDirY, vtDirZ)) { + vtDirY = vtDirZ ^ vtDirX ; + if ( ! frParab.Set( ptP0, vtDirX, vtDirY, vtDirZ)) return false ; } // porto i punti nel piano di riferimento della parabola From d0e0c46e2c4b6feb4f0804efebd4a4e699ebbb4b Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 22 Jul 2024 10:22:36 +0200 Subject: [PATCH 03/16] EgtGeomKernel : - correzione bug nella triangolazione bezier. --- Tree.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Tree.cpp b/Tree.cpp index 57ef219..3f9ee28 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -2642,6 +2642,13 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, plSimplePolygon.RemoveAlignedPoints() ; pCC->FromPolyLine( plSimplePolygon) ; IntersCurveCurve icc( clTrim, *pCC) ; + if ( icc.GetCrossOrOverlapIntersCount() < 1) { + CurveLine clTrimExtended = clTrim ; + clTrimExtended.ExtendEndByLen( 5 * EPS_SMALL) ; + clTrimExtended.ExtendStartByLen( 5 * EPS_SMALL) ; + IntersCurveCurve iccRetry( clTrimExtended, *pCC) ; + icc = iccRetry ; + } IntCrvCrvInfo iccInfo ; if ( icc.GetOverlaps()) { for ( int i = 0 ; i < icc.GetIntersCount() ; ++i) { @@ -2654,12 +2661,15 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, } else { int nLastInters = icc.GetIntersCount() -1 ; + if( nLastInters < 0) + return false ; icc.GetIntCrvCrvInfo( nLastInters, iccInfo) ; ptInters = iccInfo.IciA[0].ptI ; } // determino il lato/vertice di uscita - OnWhichEdge( nId, ptInters, nEdge) ; + if( ! OnWhichEdge( nId, ptInters, nEdge)) + return false ; m_mTree[nId].m_vInters.back().nOut = nEdge ; // se è risultato che sono abbastanza vicino( di EPS_SMALL) ad un vertice allora il punto aggiunto sarà il vertice vero e proprio // se è abbastanza vicino ad un lato allora modifico le sue coordinate in modo che sia esattamente sul lato From 746fa61e08e7e0902b169df559948eeee65d4470 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 22 Jul 2024 10:26:51 +0200 Subject: [PATCH 04/16] EgtGeomKernel : - aggiunta dell'uniformazione delle curve in preparazione ad una superficie skinned. --- SurfBezier.cpp | 47 +++++++++++++++++++++++------------------------ SurfBezier.h | 1 - 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 43e7cdf..21c8934 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -47,6 +47,7 @@ using namespace std ; GEOOBJ_REGISTER( SRF_BEZIER, NGE_S_BEZ, SurfBezier) ; static bool ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, ICurveComposite* pCrvU1) ; +static bool ParametrizeByLen( const ICurveComposite* pCurve, DBLVECTOR& vParam) ; //---------------------------------------------------------------------------- SurfBezier::SurfBezier( void) @@ -4529,32 +4530,29 @@ SurfBezier::FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTO } //---------------------------------------------------------------------------- -bool -SurfBezier::ParametrizeByLen( const ICurveComposite* pCurve0, const ICurveComposite* pCurve1, DBLVECTOR& vParam0, DBLVECTOR& vParam1) const +static bool +ParametrizeByLen( const ICurveComposite* pCurve, DBLVECTOR& vParam) { - int nSpanU0 = pCurve0->GetCurveCount() ; - int nSpanU1 = pCurve1->GetCurveCount() ; - DBLVECTOR vLen0 ; - DBLVECTOR vLen1 ; - double dLenTot0 = 0 ; - double dLenTot1 = 0 ; - for( int i = 0 ; i < nSpanU0 ; ++i) { - const ICurve* pSubCrv0 = pCurve0->GetCurve( i) ; - double dLen ; pSubCrv0->GetLength( dLen) ; - dLenTot0 += dLen ; - vLen0.push_back( dLen) ; - } - for( int i = 0 ; i < nSpanU1 ; ++i) { - const ICurve* pSubCrv1 = pCurve1->GetCurve( i) ; - double dLen ; pSubCrv1->GetLength( dLen) ; - dLenTot1 += dLen ; - vLen1.push_back( dLen) ; + int nSpanU = pCurve->GetCurveCount() ; + DBLVECTOR vLen ; + double dLenTot = 0 ; + for( int i = 0 ; i < nSpanU ; ++i) { + const ICurve* pSubCrv = pCurve->GetCurve( i) ; + double dLen ; pSubCrv->GetLength( dLen) ; + dLenTot += dLen ; + vLen.push_back( dLen) ; } // determino il parametro di ogni curva rispetto alla lunghezza totale - for ( int i = 0 ; i < nSpanU0 ; ++i) - vParam0.push_back( vLen0[i] / dLenTot0) ; - for ( int i = 0 ; i < nSpanU1 ; ++i) - vParam1.push_back( vLen1[i] / dLenTot1) ; + for ( int i = 0 ; i < nSpanU ; ++i) + vParam.push_back( vLen[i] / dLenTot) ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +FindCommonParametrization( const DBLMATRIX& mParam, DBLVECTOR& vCommonParam) +{ return true ; } @@ -4587,7 +4585,8 @@ SurfBezier::ParametrizeByLen( const ICurveComposite* pCurve0, const ICurveCompos // return true ; //} -static bool ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, ICurveComposite* pCrvU1) { +static bool +ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, ICurveComposite* pCrvU1) { // se sono chiuse devo controllare che gli start siano il più allineati possibile, se non lo sono cambio gli start if ( plU0.IsClosed() && plU1.IsClosed()) { vector> vDistVert ; diff --git a/SurfBezier.h b/SurfBezier.h index 37c716b..86f5b54 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -203,7 +203,6 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW // funzione che calcola se gli edge sono collassati in poli bool CalcPoles( void) const ; bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ; - bool ParametrizeByLen( const ICurveComposite* pCurve0, const ICurveComposite* pCurve1, DBLVECTOR& vParam0, DBLVECTOR& vParam1) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto From e68465c80b2a29972db06603f326dfb7c83d5722 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 22 Jul 2024 11:18:01 +0200 Subject: [PATCH 05/16] EgtGeomKernel : - piccola aggiunta al CopyFrom delle Surf Bezier. --- SurfBezier.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 21c8934..e0c2bf9 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -629,6 +629,8 @@ SurfBezier::CopyFrom( const SurfBezier& sbSrc) m_bTrimmed = true ; m_pTrimReg = sbSrc.m_pTrimReg->Clone() ; } + if ( sbSrc.m_pSTM != nullptr) + m_pSTM = sbSrc.m_pSTM->Clone() ; m_nTempProp[0] = sbSrc.m_nTempProp[0] ; m_nTempProp[1] = sbSrc.m_nTempProp[1] ; m_dTempParam[0] = sbSrc.m_dTempParam[0] ; From 0a8f26c9933718e03525b28bd14e9cc7b6e7a528 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 23 Jul 2024 09:47:19 +0200 Subject: [PATCH 06/16] EgtGeomKernel : - correzioni alla triangolazione delle bezier. --- Tree.cpp | 179 +++++++++++++++++++++++++++++++++---------------------- Tree.h | 4 +- 2 files changed, 111 insertions(+), 72 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 3f9ee28..34cd085 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -242,8 +242,9 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi // creo la cella Root Point3d ptTop( nSpanU * SBZ_TREG_COEFF, nSpanV * SBZ_TREG_COEFF) ; bool bLimited = false ; - if ( ! AreSamePointExact( ptMax,ORIG) && ! AreSamePointExact( ptMax,ptTop)) { - ptTop = ptMax ; + if ( ! AreSamePointExact( ptMax,ORIG)) { + if ( ! AreSamePointExact( ptMax,ptTop)) + ptTop = ptMax ; bLimited = true ; } Cell cRoot( ptMin, ptTop) ; @@ -1860,6 +1861,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL BOOLVECTOR vbKeepPoint( vVertices.size()) ; fill( vbKeepPoint.begin(), vbKeepPoint.end(), true) ; + // se non è trimmata aggiusto subito il vettore dei vertici, sennò i salvo le informazioni per qunado creerò il poligoni trimmato if ( bForTriangulation){ // ora devo controllare se uno dei lati della cella è collassato in un punto. // se così, devo guardare se sui due lati adiacenti a quello di polo ho messo dei punti extra @@ -1869,17 +1871,21 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[1] ) {// lati contati a partire da quello sopra in senso CCW - //vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW - //vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; + if ( ! m_bTrimmed) { + vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; + } vbKeepPoint[vnVert[1]] = false ; m_mTree[nId].m_nVertToErase = 1 ; // ptBr } else if ( vbBonusVert[3] ) { - //// dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto - //vVertices.pop_back() ; - //vVertices[0] = vVertices.end()[-1] ; - //vVertices3d.pop_back() ; - //vVertices3d[0] = vVertices3d.end()[-1] ; + if ( ! m_bTrimmed) { + // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto + vVertices.pop_back() ; + vVertices[0] = vVertices.end()[-1] ; + vVertices3d.pop_back() ; + vVertices3d[0] = vVertices3d.end()[-1] ; + } vbKeepPoint[0] = false ; vbKeepPoint.back() = false ; m_mTree[nId].m_nVertToErase = 0 ; // ptBL @@ -1891,14 +1897,18 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[0] ){ // lati contati a partire da quello sopra in senso CCW - //vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW - //vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; + if ( ! m_bTrimmed) { + vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; + } vbKeepPoint[vnVert[1]] = false ; m_mTree[nId].m_nVertToErase = 1 ; // ptBr } else if ( vbBonusVert[2] ){ - //vVertices.erase(vVertices.begin() + vnVert[2]) ; - //vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; + if ( ! m_bTrimmed) { + vVertices.erase(vVertices.begin() + vnVert[2]) ; + vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; + } vbKeepPoint[vnVert[2]] = false ; m_mTree[nId].m_nVertToErase = 2 ; // ptTR } @@ -1909,14 +1919,18 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[1] ){ // lati contati a partire da quello sopra in senso CCW - //vVertices.erase(vVertices.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW - //vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; + if ( ! m_bTrimmed) { + vVertices.erase(vVertices.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW + vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; + } vbKeepPoint[vnVert[2]] = false ; m_mTree[nId].m_nVertToErase = 2 ; // ptTR } else if ( vbBonusVert[3] ) { - //vVertices.erase(vVertices.begin() + vnVert[3]) ; - //vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; + if ( ! m_bTrimmed) { + vVertices.erase(vVertices.begin() + vnVert[3]) ; + vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; + } vbKeepPoint[vnVert[3]] = false ; m_mTree[nId].m_nVertToErase = 3 ; // ptTl } @@ -1927,18 +1941,22 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[0] ) { // lati contati a partire da quello sopra in senso CCW - //// dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto - //vVertices.pop_back() ; - //vVertices[0] = vVertices.end()[-1] ; - //vVertices3d.pop_back() ; - //vVertices3d[0] = vVertices3d.end()[-1] ; + if ( ! m_bTrimmed) { + // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto + vVertices.pop_back() ; + vVertices[0] = vVertices.end()[-1] ; + vVertices3d.pop_back() ; + vVertices3d[0] = vVertices3d.end()[-1] ; + } vbKeepPoint[0] = false ; vbKeepPoint.back() = false ; m_mTree[nId].m_nVertToErase = 0 ; // ptBL } else if ( vbBonusVert[2] ) { - //vVertices.erase(vVertices.begin() + vnVert[3]) ; - //vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; + if ( ! m_bTrimmed) { + vVertices.erase(vVertices.begin() + vnVert[3]) ; + vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; + } vbKeepPoint[vnVert[3]] = false ; m_mTree[nId].m_nVertToErase = 3 ; // ptTl } @@ -3115,12 +3133,14 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX vLast.Normalize() ; Vector3d vEdge ; // estendo: se l'ultimo tratto è sovrapposto e controverso allora elimino l'ultimo punto + bool bNotEquiverseOverlap = false ; if ( nEdge == 0 || nEdge == 7 ) { vEdge.Set( 1,0,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; plTrimmedPoly3d.EraseLastUPoint() ; nEdge = 0 ; + bNotEquiverseOverlap = true ; } } else if ( nEdge == 1 || nEdge == 4 ) { @@ -3129,6 +3149,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX plTrimmedPoly.EraseLastUPoint() ; plTrimmedPoly3d.EraseLastUPoint() ; nEdge = 1 ; + bNotEquiverseOverlap = true ; } } else if ( nEdge == 2 || nEdge == 5 ) { @@ -3137,6 +3158,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX plTrimmedPoly.EraseLastUPoint() ; plTrimmedPoly3d.EraseLastUPoint() ; nEdge = 2 ; + bNotEquiverseOverlap = true ; } } else if ( nEdge == 3 || nEdge == 6 ) { @@ -3145,12 +3167,13 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX plTrimmedPoly.EraseLastUPoint() ; plTrimmedPoly3d.EraseLastUPoint() ; nEdge = 3 ; + bNotEquiverseOverlap = true ; } } // se mi è rimasto solo un punto sulla polyline vuol dire che avevo solo un tratto parallelo ad lato // quindi salto al prossimo loop - if ( plTrimmedPoly.GetPointNbr() == 1) { + if ( plTrimmedPoly.GetPointNbr() == 1 && bNotEquiverseOverlap) { plTrimmedPoly.Clear() ; plTrimmedPoly3d.Clear() ; if ( j == nFirstLoopInPoly) @@ -3613,6 +3636,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe Point3d ptTR = m_mTree.at(nId).GetTopRight() ; Point3d ptTl = m_mTree.at(nId).GetTopLeft() ; Point3d ptBL = m_mTree.at(nId).GetBottomLeft() ; + int nVertToSkip = m_mTree.at(nId).m_nVertToErase ; Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ; // verifico di essere allineato con un lato, sennò aggiungo e basta @@ -3624,6 +3648,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe // se non riesco a normalizzare perché sono troppo vicino ad un vertice allora aggiungo direttamente il vertice if ( ! vDir.Normalize()) { plTrimmedPoly.EraseLastUPoint() ; + plTrimmedPoly3d.EraseLastUPoint() ; Point3d ptVert ; int nVert = -1 ; if ( AreSamePointApprox( ptToAdd, ptBr)){ @@ -3644,16 +3669,18 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe } else ptVert = ptToAdd ; - plTrimmedPoly.AddUPoint( c, ptVert) ; - if( bForTriangulation){ - Point3d pt3d ; - if ( nVert != -1) - pt3d = m_mVert.at(nId)[nVert] ; - else - m_pSrfBz->GetPointD1D2( ptVert.x, ptVert.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + if ( nVert != nVertToSkip) { + plTrimmedPoly.AddUPoint( c, ptVert) ; + if( bForTriangulation){ + Point3d pt3d ; + if ( nVert != -1) + pt3d = m_mVert.at(nId)[nVert] ; + else + m_pSrfBz->GetPointD1D2( ptVert.x, ptVert.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } + ++ c ; } - ++ c ; return true ; } if ( abs( vDir.x) > 1 - EPS_SMALL || abs( vDir.y) > 1 - EPS_SMALL) { @@ -3669,16 +3696,19 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ++ c ; } } - plTrimmedPoly.AddUPoint( c, ptToAdd) ; - if( bForTriangulation){ - Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, ptTl)) - m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - else - pt3d = vEdgeVertex3d[1][0] ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + bool bVert = AreSamePointApprox( ptToAdd, ptTl) ; + if ( ! ( nVertToSkip == 3 && bVert)) { + plTrimmedPoly.AddUPoint( c, ptToAdd) ; + if( bForTriangulation){ + Point3d pt3d ; + if( ! bVert) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[1][0] ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } + ++ c ; } - ++ c ; } // edge 1 else if ( ptToAdd.y >= ptBL.y && ptToAdd.y <= ptTR.y && ptToAdd.x == ptBL.x && abs( vDir.y) > 1 - EPS_SMALL) { @@ -3691,16 +3721,19 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ++ c ; } } - plTrimmedPoly.AddUPoint( c, ptToAdd) ; - if( bForTriangulation) { - Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, ptBL)) - m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - else - pt3d = vEdgeVertex3d[2][0] ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + bool bVert = AreSamePointApprox( ptToAdd, ptBL) ; + if ( ! ( nVertToSkip == 0 && bVert)) { + plTrimmedPoly.AddUPoint( c, ptToAdd) ; + if( bForTriangulation) { + Point3d pt3d ; + if( ! bVert) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[2][0] ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } + ++ c ; } - ++ c ; } // edge 2 else if ( ptToAdd.x >= ptBL.x && ptToAdd.x <= ptTR.x && ptToAdd.y == ptBL.y && abs( vDir.x) > 1 - EPS_SMALL) { @@ -3713,16 +3746,19 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ++ c ; } } - plTrimmedPoly.AddUPoint( c, ptToAdd) ; - if( bForTriangulation){ - Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, ptBr)) - m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - else - pt3d = vEdgeVertex3d[3][0] ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + bool bVert = AreSamePointApprox( ptToAdd, ptBr) ; + if ( ! ( nVertToSkip == 1 && bVert)) { + plTrimmedPoly.AddUPoint( c, ptToAdd) ; + if( bForTriangulation){ + Point3d pt3d ; + if( ! bVert) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[3][0] ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } + ++ c ; } - ++ c ; } // edge 3 else if ( ptToAdd.y >= ptBL.y && ptToAdd.y <= ptTR.y && ptToAdd.x == ptTR.x && abs( vDir.y) > 1 - EPS_SMALL) { @@ -3735,16 +3771,19 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ++ c ; } } - plTrimmedPoly.AddUPoint( c, ptToAdd) ; - if( bForTriangulation) { - Point3d pt3d ; - if( ! AreSamePointApprox(ptToAdd, ptTR)) - m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - else - pt3d = vEdgeVertex3d[0][0] ; - plTrimmedPoly3d.AddUPoint( c, pt3d) ; + bool bVert = AreSamePointApprox( ptToAdd, ptTR) ; + if ( ! ( nVertToSkip == 2 && bVert)) { + plTrimmedPoly.AddUPoint( c, ptToAdd) ; + if( bForTriangulation) { + Point3d pt3d ; + if( ! bVert) + m_pSrfBz->GetPointD1D2( ptToAdd.x / SBZ_TREG_COEFF, ptToAdd.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + else + pt3d = vEdgeVertex3d[0][0] ; + plTrimmedPoly3d.AddUPoint( c, pt3d) ; + } + ++ c ; } - ++ c ; } // sono allineato con un lato, ma NON sono su un lato // aggiungo e basta diff --git a/Tree.h b/Tree.h index 7d6a1e8..4cbc176 100644 --- a/Tree.h +++ b/Tree.h @@ -318,8 +318,8 @@ class Tree int m_nSpanV ; // numero di span lungo il parametro V POLYLINEMATRIX m_vPolygons ; // matrice dei poligoni del tree POLYLINEMATRIX m_vPolygons3d ; // matrice dei poligoni3d del tree - std::map m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root - std::map m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id è lo stesso che la cella ha in m_mTree. I punti sono nell'ordine P00, P10, P11, P01 + std::unordered_map m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root + std::unordered_map m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id è lo stesso che la cella ha in m_mTree. I punti sono nell'ordine P00, P10, P11, P01 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 From 89c22ffd0677730304be98b2cfb199735ddd7dea Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 24 Jul 2024 09:27:38 +0200 Subject: [PATCH 07/16] EgtGeomKernel : - correzioni e miglioramenti per la triangolazione bezier. --- Tree.cpp | 126 +++++++++++++++++++++++++++++++++++++------------------ Tree.h | 9 ++-- 2 files changed, 91 insertions(+), 44 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 34cd085..8e72991 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -222,6 +222,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi m_mChunk.clear() ; m_vPlApprox.clear() ; m_vPolygons.clear() ; + m_vPolygonsCorr.clear() ; m_vPlLoop2D.clear() ; m_pSrfBz = pSrfBz ; @@ -1589,33 +1590,43 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM if ( ! m_bTrimmed) { vvPolygons.clear() ; POLYLINEVECTOR vPolygonsBasic ; + POLYLINEVECTOR vPolygonsCorrected ; POLYLINEVECTOR vPolygonsBasic3d ; if ( bForTriangulation) - GetPolygonsBasic( vPolygonsBasic, vPolygonsBasic3d) ; + GetPolygonsBasic( vPolygonsBasic, vPolygonsCorrected, vPolygonsBasic3d) ; else GetPolygonsBasic( vPolygonsBasic) ; int c = 0; - for ( PolyLine pl : vPolygonsBasic) { - POLYLINEVECTOR vSinglePolygon ; - vSinglePolygon.push_back( pl) ; - vvPolygons.push_back( vSinglePolygon) ; - if ( bForTriangulation) { + if( bForTriangulation) { + for ( PolyLine pl : vPolygonsCorrected) { + POLYLINEVECTOR vSinglePolygon ; + vSinglePolygon.push_back( pl) ; + vvPolygons.push_back( vSinglePolygon) ; POLYLINEVECTOR vSinglePolygon3d ; vSinglePolygon3d.push_back( vPolygonsBasic3d[c]) ; vvPolygons3d.push_back( vSinglePolygon3d) ; + ++c ; + } + } + else { + for ( PolyLine pl : vPolygonsBasic) { + POLYLINEVECTOR vSinglePolygon ; + vSinglePolygon.push_back( pl) ; + vvPolygons.push_back( vSinglePolygon) ; + ++c ; } - ++c ; } return true ; } // trimmata else { POLYLINEVECTOR vPolygonsBasic ; - GetPolygonsBasic( vPolygonsBasic) ; - POLYLINEVECTOR vPolygons ; + POLYLINEVECTOR vPolygonsCorrected ; POLYLINEVECTOR vPolygonsBasic3d ; if ( bForTriangulation) - GetPolygonsBasic( vPolygons, vPolygonsBasic3d) ; + GetPolygonsBasic( vPolygonsBasic, vPolygonsCorrected, vPolygonsBasic3d) ; + else + GetPolygonsBasic( vPolygonsBasic) ; // aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim m_vCEdge2D.clear() ; for ( int i = 0 ; i < 4 ; ++i) { @@ -1633,7 +1644,10 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM if ( m_mTree[nId].m_nFlag == 4) { // vettore dei poligoni ( loop) della cella nId POLYLINEVECTOR vCellPolygons ; - vCellPolygons.push_back( vPolygonsBasic[i]) ; + if( bForTriangulation) + vCellPolygons.push_back( vPolygonsCorrected[i]) ; + else + vCellPolygons.push_back( vPolygonsBasic[i]) ; vvPolygons.push_back( vCellPolygons) ; if ( bForTriangulation ) { POLYLINEVECTOR vCellPolygons3d ; @@ -1642,6 +1656,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM plPolygon3d.AddUPoint( 1, m_mVert[nId][1]) ; plPolygon3d.AddUPoint( 2, m_mVert[nId][2]) ; plPolygon3d.AddUPoint( 3, m_mVert[nId][3]) ; + plPolygon3d.AddUPoint( 0, m_mVert[nId][0]) ; vCellPolygons3d.push_back( plPolygon3d) ; vvPolygons3d.push_back( vCellPolygons3d) ; } @@ -1664,7 +1679,10 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM PolyLine pl3d ; if( bForTriangulation) pl3d = vPolygonsBasic3d[i] ; - CreateCellPolygons( i, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i], pl3d) ; + if( bForTriangulation) + CreateCellPolygons( i, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsCorrected[i], pl3d) ; + else + CreateCellPolygons( i, vvPolygons, vvPolygons3d, vToCheck, nPoly, vnParentChunk, vPolygonsBasic[i], pl3d) ; if ( nPolyBefore == nPoly) break ; } @@ -1683,24 +1701,28 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM //---------------------------------------------------------------------------- bool -Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygons3d) +Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygonsCorrected, POLYLINEVECTOR& vPolygons3d) { - return GetPolygonsBasic( vPolygons, true, vPolygons3d) ; + return GetPolygonsBasic( vPolygonsBasic, vPolygonsCorrected, true, vPolygons3d) ; } //---------------------------------------------------------------------------- bool -Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) +Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, INTVECTOR vCells) { POLYLINEVECTOR vPolygons3d ; - return GetPolygonsBasic( vPolygons, false, vPolygons3d, vCells) ; + POLYLINEVECTOR vPolygonsCorrected ; + return GetPolygonsBasic( vPolygonsBasic, vPolygonsCorrected, false, vPolygons3d, vCells) ; } //---------------------------------------------------------------------------- bool -Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYLINEVECTOR& vPolygons3d, INTVECTOR vCells) +Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygonsCorrected, bool bForTriangulation, POLYLINEVECTOR& vPolygons3d, INTVECTOR vCells) { // condizioni per il calcolo dei poligoni di base + PNTVECTOR vVertices ; + PNTVECTOR vVerticesCorr ; + PNTVECTOR vVertices3d ; if ( m_vPolygons.empty() || // se non li ho mai calcolati ( ! m_vPolygons.empty() && ! vCells.empty()) || // se ho già calcolato dei poligoni ma ne sto chiedendo di un altro gruppo di celle ( vCells.empty() && m_vPolygons.size() != m_vnLeaves.size()) || // se sto chiedendo i poligoni di tutte le celle, ma i poligoni già calcolati sono meno delle celle @@ -1711,8 +1733,6 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( vCells.empty()) vCells = m_vnLeaves ; - PNTVECTOR vVertices ; - PNTVECTOR vVertices3d ; INTVECTOR vNeigh ; // setto le celle che sono sul LeftEdge e sul TopEdge if ( m_bClosedU) { @@ -1861,7 +1881,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL BOOLVECTOR vbKeepPoint( vVertices.size()) ; fill( vbKeepPoint.begin(), vbKeepPoint.end(), true) ; - // se non è trimmata aggiusto subito il vettore dei vertici, sennò i salvo le informazioni per qunado creerò il poligoni trimmato + // se non è trimmata aggiusto subito il vettore dei vertici, sennò i salvo le informazioni per quando creerò i poligoni trimmato + vVerticesCorr = vVertices ; if ( bForTriangulation){ // ora devo controllare se uno dei lati della cella è collassato in un punto. // se così, devo guardare se sui due lati adiacenti a quello di polo ho messo dei punti extra @@ -1872,7 +1893,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[1] ) {// lati contati a partire da quello sopra in senso CCW if ( ! m_bTrimmed) { - vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; } vbKeepPoint[vnVert[1]] = false ; @@ -1881,8 +1902,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL else if ( vbBonusVert[3] ) { if ( ! m_bTrimmed) { // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto - vVertices.pop_back() ; - vVertices[0] = vVertices.end()[-1] ; + vVerticesCorr.pop_back() ; + vVerticesCorr[0] = vVerticesCorr.end()[-1] ; vVertices3d.pop_back() ; vVertices3d[0] = vVertices3d.end()[-1] ; } @@ -1898,7 +1919,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[0] ){ // lati contati a partire da quello sopra in senso CCW if ( ! m_bTrimmed) { - vVertices.erase(vVertices.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; } vbKeepPoint[vnVert[1]] = false ; @@ -1906,7 +1927,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL } else if ( vbBonusVert[2] ){ if ( ! m_bTrimmed) { - vVertices.erase(vVertices.begin() + vnVert[2]) ; + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[2]) ; vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; } vbKeepPoint[vnVert[2]] = false ; @@ -1920,7 +1941,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL // sennò devo togliere l'estremo del lato su cui NON ho punti bonus if ( vbBonusVert[1] ){ // lati contati a partire da quello sopra in senso CCW if ( ! m_bTrimmed) { - vVertices.erase(vVertices.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; } vbKeepPoint[vnVert[2]] = false ; @@ -1928,7 +1949,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL } else if ( vbBonusVert[3] ) { if ( ! m_bTrimmed) { - vVertices.erase(vVertices.begin() + vnVert[3]) ; + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[3]) ; vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; } vbKeepPoint[vnVert[3]] = false ; @@ -1943,8 +1964,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( vbBonusVert[0] ) { // lati contati a partire da quello sopra in senso CCW if ( ! m_bTrimmed) { // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto - vVertices.pop_back() ; - vVertices[0] = vVertices.end()[-1] ; + vVerticesCorr.pop_back() ; + vVerticesCorr[0] = vVerticesCorr.end()[-1] ; vVertices3d.pop_back() ; vVertices3d[0] = vVertices3d.end()[-1] ; } @@ -1954,7 +1975,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL } else if ( vbBonusVert[2] ) { if ( ! m_bTrimmed) { - vVertices.erase(vVertices.begin() + vnVert[3]) ; + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[3]) ; vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; } vbKeepPoint[vnVert[3]] = false ; @@ -1967,7 +1988,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL if ( ! m_bTrimmed) { // se ho una cella con vicino dello stesso grado ( quindi il poligono ha solo 5 punti) controllo la curvatura nella cella e // se necessario cambio l'ordine dei vertici per scegliere la diagonale di split migliore - if ( vVertices.size() == 5) { + if ( vVertices.size() == 5 && ( ! bForTriangulation || (bForTriangulation && vVerticesCorr.size() == 5))) { Point3d ptPSrf, ptP00, ptP10, ptP11, ptP01 ; double dU, dV ; dU = ( m_mTree.at( nId).GetBottomLeft().x + m_mTree.at( nId).GetTopRight().x) / 2 / SBZ_TREG_COEFF ; @@ -1987,20 +2008,28 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL vVertices3d.back() = vVertices3d.at( 0) ; rotate( vbKeepPoint.begin(), vbKeepPoint.begin() + 1,vbKeepPoint.end()) ; vbKeepPoint.back() = vbKeepPoint.at( 0) ; + rotate( vVerticesCorr.begin(), vVerticesCorr.begin() + 1,vVerticesCorr.end()) ; + vVerticesCorr.back() = vVerticesCorr.at( 0) ; } } } m_vPolygons.emplace_back() ; m_vPolygons.back().emplace_back() ; + m_vPolygonsCorr.emplace_back() ; + m_vPolygonsCorr.back().emplace_back() ; m_vPolygons3d.emplace_back() ; m_vPolygons3d.back().emplace_back() ; + int nVertCorr = int(vVerticesCorr.size()); for ( int i = 0 ; i < (int) vVertices.size() ; ++i) { int dPar = i ; if( ! vbKeepPoint[i]) dPar = -1 ; m_vPolygons.back().back().AddUPoint( dPar, vVertices.at( i)) ; - m_vPolygons3d.back().back().AddUPoint( dPar, vVertices3d.at( i)) ; + if( bForTriangulation && i < nVertCorr){ + m_vPolygonsCorr.back().back().AddUPoint( dPar, vVerticesCorr.at( i)) ; + m_vPolygons3d.back().back().AddUPoint( dPar, vVertices3d.at( i)) ; + } } } @@ -2009,8 +2038,11 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYL // restituisco i poligoni delle celle del tree nello spazio parametrico for ( int t = 0 ; t < (int)m_vPolygons.size() ; ++ t) { for ( int z = 0 ; z < (int)m_vPolygons[t].size() ; ++z) { - vPolygons.push_back( m_vPolygons[t][z]) ; - vPolygons3d.push_back( m_vPolygons3d[t][z]) ; + vPolygonsBasic.push_back( m_vPolygons[t][z]) ; + if( bForTriangulation) { + vPolygonsCorrected.push_back( m_vPolygonsCorr[t][z]) ; + vPolygons3d.push_back( m_vPolygons3d[t][z]) ; + } } } return true ; @@ -3082,10 +3114,17 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX vEdgeVertex[j].push_back( ptToAdd) ; } else { - while ( plCell.GetNextPoint( ptToAdd) && plCell3d.GetNextPoint( pt3d) && ! AreSamePointExact( ptToAdd, ptNextVert)) { + double dPar = 0 ; + bool bAdvanced = false ; + while ( plCell.GetNextUPoint( &dPar, &ptToAdd) && ! AreSamePointExact( ptToAdd, ptNextVert)) { vEdgeVertex[j].push_back( ptToAdd) ; + if ( dPar > 0) + plCell3d.GetNextPoint( pt3d) ; vEdgeVertex3d[j].push_back( pt3d) ; + bAdvanced = true ; } + if ( ! bAdvanced && dPar > 0) + plCell3d.GetNextPoint( pt3d) ; } } @@ -3621,8 +3660,20 @@ bool Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool bForTriangulation) const { + Point3d ptBr = m_mTree.at(nId).GetBottomRight() ; + Point3d ptTR = m_mTree.at(nId).GetTopRight() ; + Point3d ptTl = m_mTree.at(nId).GetTopLeft() ; + Point3d ptBL = m_mTree.at(nId).GetBottomLeft() ; + int nVertToSkip = m_mTree.at(nId).m_nVertToErase ; // se è il primo punto della PolyLine lo aggiungo if ( plTrimmedPoly.GetPointNbr() == 0) { + // se cerco di aggiungere il vertice che devo saltare, non faccio nulla + if( ( nVertToSkip == 0 && AreSamePointApprox( ptToAdd, ptBL)) || + ( nVertToSkip == 1 && AreSamePointApprox( ptToAdd, ptBr)) || + ( nVertToSkip == 2 && AreSamePointApprox( ptToAdd, ptTR)) || + ( nVertToSkip == 3 && AreSamePointApprox( ptToAdd, ptTl))) + return true ; + plTrimmedPoly.AddUPoint( c, ptToAdd) ; if ( bForTriangulation) { Point3d pt3d ; @@ -3632,11 +3683,6 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ++ c ; return true ; } - Point3d ptBr = m_mTree.at(nId).GetBottomRight() ; - Point3d ptTR = m_mTree.at(nId).GetTopRight() ; - Point3d ptTl = m_mTree.at(nId).GetTopLeft() ; - Point3d ptBL = m_mTree.at(nId).GetBottomLeft() ; - int nVertToSkip = m_mTree.at(nId).m_nVertToErase ; Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ; // verifico di essere allineato con un lato, sennò aggiungo e basta diff --git a/Tree.h b/Tree.h index 4cbc176..59d769c 100644 --- a/Tree.h +++ b/Tree.h @@ -242,10 +242,10 @@ class Tree bool GetPolygons( POLYLINEMATRIX& vvPolygons) ; bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d) ; bool GetPolygons( POLYLINEMATRIX& vPolygons, bool bForTriangulation, POLYLINEMATRIX& vvPolygons3d) ; - bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYLINEVECTOR& vPolygons3d, 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 - // se richiesti per la triangolazione ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico - bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygons3d) ; + bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, // restituisce il poligono corrispondente ad ogni cella foglia dell'albero + bool bForTriangulation, POLYLINEVECTOR& vPolygons3d, INTVECTOR vCells = {}) ; // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati + // se richiesti per la triangolazione ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico + bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygonsCorrected, POLYLINEVECTOR& vPolygons3d) ; bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; bool GetLeaves ( std::vector& vLeaves) const ; // restituisce gli indici delle foglie nell'albero bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline @@ -317,6 +317,7 @@ class Tree int m_nSpanU ; // numero di span lungo il parametro U int m_nSpanV ; // numero di span lungo il parametro V POLYLINEMATRIX m_vPolygons ; // matrice dei poligoni del tree + POLYLINEMATRIX m_vPolygonsCorr ; // matrice dei poligoni del tree, corretti per i punti che sono nei poli POLYLINEMATRIX m_vPolygons3d ; // matrice dei poligoni3d del tree std::unordered_map m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root std::unordered_map m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id è lo stesso che la cella ha in m_mTree. I punti sono nell'ordine P00, P10, P11, P01 From c3e7d3d8c7837b1233f46420968434eb64196c24 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 24 Jul 2024 10:13:45 +0200 Subject: [PATCH 08/16] EgtGeomKernel : - miglioramenti alla triangolazione delle bezier. --- Tree.cpp | 47 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/Tree.cpp b/Tree.cpp index 8e72991..1e19fe5 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1651,13 +1651,14 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM vvPolygons.push_back( vCellPolygons) ; if ( bForTriangulation ) { POLYLINEVECTOR vCellPolygons3d ; - PolyLine plPolygon3d ; - plPolygon3d.AddUPoint( 0, m_mVert[nId][0]) ; - plPolygon3d.AddUPoint( 1, m_mVert[nId][1]) ; - plPolygon3d.AddUPoint( 2, m_mVert[nId][2]) ; - plPolygon3d.AddUPoint( 3, m_mVert[nId][3]) ; - plPolygon3d.AddUPoint( 0, m_mVert[nId][0]) ; - vCellPolygons3d.push_back( plPolygon3d) ; + //PolyLine plPolygon3d ; + //plPolygon3d.AddUPoint( 0, m_mVert[nId][0]) ; + //plPolygon3d.AddUPoint( 1, m_mVert[nId][1]) ; + //plPolygon3d.AddUPoint( 2, m_mVert[nId][2]) ; + //plPolygon3d.AddUPoint( 3, m_mVert[nId][3]) ; + //plPolygon3d.AddUPoint( 0, m_mVert[nId][0]) ; + //vCellPolygons3d.push_back( plPolygon3d) ; + vCellPolygons3d.push_back( vPolygonsBasic3d[i]) ; vvPolygons3d.push_back( vCellPolygons3d) ; } } @@ -1887,7 +1888,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon // ora devo controllare se uno dei lati della cella è collassato in un punto. // se così, devo guardare se sui due lati adiacenti a quello di polo ho messo dei punti extra // se ne ho messi solo su uno dei due allora devo togliere il vertice dell'altro lato - if ( AreSamePointApprox(m_mVert.at(nId).at(0), m_mVert.at(nId).at(1)) && ( vbBonusVert[1] || vbBonusVert[3] ) ) { + if ( AreSamePointApprox(m_mVert.at(nId).at(0), m_mVert.at(nId).at(1))) { // se ho punti bonus su entrambi i lati non devo fare nulla if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus @@ -1911,9 +1912,15 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vbKeepPoint.back() = false ; m_mTree[nId].m_nVertToErase = 0 ; // ptBL } + // se non ho bonus su nessuno dei due + else { + // ne scelgo uno dei due da togliere + vbKeepPoint[vnVert[1]] = false ; + m_mTree[nId].m_nVertToErase = 1 ; // ptBr + } } } - if ( AreSamePointApprox(m_mVert.at(nId).at(1), m_mVert.at(nId).at(2)) && ( vbBonusVert[0] || vbBonusVert[2] ) ) { + if ( AreSamePointApprox(m_mVert.at(nId).at(1), m_mVert.at(nId).at(2))) { // se ho punti bonus su entrambi i lati non devo fare nulla if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus @@ -1933,9 +1940,15 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vbKeepPoint[vnVert[2]] = false ; m_mTree[nId].m_nVertToErase = 2 ; // ptTR } + // se non ho bonus su nessuno dei due + else { + // ne scelgo uno dei due da togliere + vbKeepPoint[vnVert[2]] = false ; + m_mTree[nId].m_nVertToErase = 2 ; // ptTR + } } } - if ( AreSamePointApprox(m_mVert.at(nId).at(2), m_mVert.at(nId).at(3)) && ( vbBonusVert[1] || vbBonusVert[3] ) ) { + if ( AreSamePointApprox(m_mVert.at(nId).at(2), m_mVert.at(nId).at(3))) { // se ho punti bonus su entrambi i lati non devo fare nulla if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus @@ -1955,9 +1968,15 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vbKeepPoint[vnVert[3]] = false ; m_mTree[nId].m_nVertToErase = 3 ; // ptTl } + // se non ho bonus su nessuno dei due + else { + // ne scelgo uno dei due da togliere + vbKeepPoint[vnVert[3]] = false ; + m_mTree[nId].m_nVertToErase = 3 ; // ptTl + } } } - if ( AreSamePointApprox(m_mVert.at(nId).at(3), m_mVert.at(nId).at(0)) && ( vbBonusVert[0] || vbBonusVert[2] ) ) { + if ( AreSamePointApprox(m_mVert.at(nId).at(3), m_mVert.at(nId).at(0))) { // se ho punti bonus su entrambi i lati non devo fare nulla if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { // sennò devo togliere l'estremo del lato su cui NON ho punti bonus @@ -1981,6 +2000,12 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vbKeepPoint[vnVert[3]] = false ; m_mTree[nId].m_nVertToErase = 3 ; // ptTl } + // se non ho bonus su nessuno dei due + else { + // ne scelgo uno dei due da togliere + vbKeepPoint[vnVert[3]] = false ; + m_mTree[nId].m_nVertToErase = 3 ; // ptTl + } } } } From 9b87de9fa284c86ac4fae0b50f03db00262a03e4 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 25 Jul 2024 16:25:05 +0200 Subject: [PATCH 09/16] EgtGeomKernel : - correzioni e migliorie alla triangolazione con le bezier. --- SurfBezier.cpp | 63 ++++++-- SurfBezier.h | 1 + Tree.cpp | 418 +++++++++++++++---------------------------------- 3 files changed, 178 insertions(+), 304 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index e0c2bf9..b1316f7 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -88,6 +88,7 @@ SurfBezier::Init( int nDegU, int nDegV, int nSpanU, int nSpanV, bool bIsRational else m_vWeCtrl.clear() ; m_nStatus = TO_VERIFY ; + m_nIsPlanar = NOT_CALCULATED ; // imposto ricalcolo della grafica ResetAuxSurf() ; @@ -1583,7 +1584,6 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const if ( ! Tri.Make( vPL, vPnt, vTria)) return nullptr ; - //vedo se la polyline 3d che passo io corrisponde a quella che usavo prima POLYLINEVECTOR vPL3d = vvPL3d[c] ; // porto i punti in 3d @@ -1598,6 +1598,17 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const } } + // se ho ottenuto meno triangoli di quelli che avrei dovuto avere allora potrei aver avuto un problema in prossimità di un polo + // se comunque ho corrispondenza tra vPnt e vPnt3d allora eseguo la trinagolazione in 3d + if ( ( vPnt.size() - 2 ) != ( vTria.size() ) / 3 && vPnt.size() == vPnt3d.size() ) { + if ( ! Tri.Make( vPL3d, vPnt, vTria)) + return nullptr ; + if ( ( vPnt.size() - 2 ) == ( vTria.size() ) / 3 ) + LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) RESOLVED") + else + LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) is the same as the previous one") + } + // controllo per ogni polyline se è stato invertito il vettore dei punti int nCurrPoint = 0 ; for( int i = 0 ; i < int( vPL.size()) ; ++i) { @@ -3197,6 +3208,7 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const else pCrvBz0->SetControlPoint( p, GetControlPoint( nIndex, nullptr), GetControlWeight( nIndex, nullptr)) ; } + pCrvBz0->Invert() ; pCrvCompo->AddCurve( Release( pCrvBz0)) ; } } @@ -3218,6 +3230,7 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const else pCrvBz1->SetControlPoint( p, GetControlPoint( nIndex, nullptr), GetControlWeight( nIndex, nullptr)) ; } + pCrvBz1->Invert() ; pCrvCompo->AddCurve( Release( pCrvBz1)) ; } } @@ -3272,19 +3285,40 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const bool SurfBezier::IsPlanar( void) const { - // costruisco il contorno della superficie unendo gli edge e chiedo se la polyline è piana. - PtrOwner pCCEdge( GetSingleEdge3D( false, 0)) ; - pCCEdge->AddCurve( GetSingleEdge3D( false, 1)) ; - pCCEdge->AddCurve( GetSingleEdge3D( false, 2)) ; - pCCEdge->AddCurve( GetSingleEdge3D( false, 3)) ; + if ( m_nIsPlanar != NOT_CALCULATED) { + switch ( m_nIsPlanar ) { + case PLANAR_SURF : return true ; break ; + case NOT_PLANAR_SURF : return false ; break ; + } + } + PolyLine plApprox ; - pCCEdge->ApproxWithLines( 0.01, 15, 0, plApprox) ; Plane3d plPlane ; - if ( ! plApprox.IsFlat( plPlane, 2 * EPS_SMALL)) - return false ; - // in questo caso se è grado 1 in U e V e ho un unica Patch allora sono sicuro sia piana - if ( m_nDegU == 1 && m_nSpanU == 1 && m_nDegV == 1 && m_nSpanV == 1) // questa condizione da sola non è sufficiente ( posso avere superfici torte anche se i lati sono segmenti) - return true ; + if( ! m_bTrimmed) { + // costruisco il contorno della superficie unendo gli edge e chiedo se la polyline è piana. + PtrOwner pCCEdge( GetSingleEdge3D( false, 0)) ; + pCCEdge->AddCurve( GetSingleEdge3D( false, 1)) ; + pCCEdge->AddCurve( GetSingleEdge3D( false, 2)) ; + pCCEdge->AddCurve( GetSingleEdge3D( false, 3)) ; + pCCEdge->ApproxWithLines( 0.01, 15, 0, plApprox) ; + if ( ! plApprox.IsFlat( plPlane, 2 * EPS_SMALL)){ + m_nIsPlanar = 0 ; + return false ; + } + // in questo caso se è grado 1 in U e V e ho un unica Patch allora sono sicuro sia piana + if ( m_nDegU == 1 && m_nSpanU == 1 && m_nDegV == 1 && m_nSpanV == 1) { + m_nIsPlanar = 1 ; + return true ; + } + } + else { + Point3d ptCtrl ; + bool bOk = true ; + plApprox.AddUPoint( 0, GetControlPoint(0, &bOk)) ; + plApprox.AddUPoint( 1, GetControlPoint(m_nDegU * m_nSpanU, &bOk)) ; + plApprox.AddUPoint( 2, GetControlPoint(( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV + 1), &bOk)) ; + plApprox.AddUPoint( 3, GetControlPoint(( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV), &bOk)) ; + } double dULast ; plApprox.GetLastU( dULast) ; ++ dULast ; @@ -3299,10 +3333,13 @@ SurfBezier::IsPlanar( void) const } } plPlane.Reset() ; - if ( plApprox.IsFlat( plPlane, 2 * EPS_SMALL)) + if ( plApprox.IsFlat( plPlane, 2 * EPS_SMALL)) { + m_nIsPlanar = 1 ; return true ; + } // nel dubbio restituisco false + m_nIsPlanar = 0 ; return false ; } diff --git a/SurfBezier.h b/SurfBezier.h index 86f5b54..9285813 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -224,6 +224,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW double m_dTempParam[2] ; // vettore parametri temporanei mutable vector m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata + mutable int m_nIsPlanar ; // enum che indica se la superficie è piana ( -1, non è stato calcolato) } ; //----------------------------------------------------------------------------- diff --git a/Tree.cpp b/Tree.cpp index 1e19fe5..de68f01 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -68,43 +68,6 @@ Tree::Tree( const Point3d ptBl, const Point3d ptTr) bool Tree::LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const { - // //questo metodo NON VA BENE perchè tiene anche parte dei loop che stanno fuori dal parametrico e quindi il FINDCELL può fallire - // - //// creo la flat region di trim, quella del parametrico e li interseco - //PtrOwner pSfrTrim( GetSurfFlatRegionFromPolyLine( pl)) ; - //bool bInverted = false ; - //if ( ! pSfrTrim->GetNormVersor().IsZplus()) { - // pSfrTrim->Invert() ; - // bInverted = true ; - //} - //PtrOwner pParamTrim( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; - //if ( ! pParamTrim->Intersect( *pSfrTrim) || ! pParamTrim->IsValid()) { - // if ( ! pParamTrim->Offset( 10 * EPS_SMALL, ICurve::OFF_EXTEND)) - // return false ; - // if ( ! pParamTrim->Intersect( *pSfrTrim) || ! pParamTrim->IsValid()) - // return false ; - // if ( ! pParamTrim->Offset( -10 * EPS_SMALL, ICurve::OFF_EXTEND)) - // return false ; - //} - - //// ricostruisco la curva tenendo solo le parti dentro lo spazio parametrico - //// devo recuperare la polyline dei bordi dei vari chunk creati - //for ( int c = 0 ; c < int( pParamTrim->GetChunkCount()) ; ++c) { - // for ( int l = 0 ; l < pParamTrim->GetLoopCount(c) ; ++l) { - // PtrOwner pCrv ( pParamTrim->GetLoop( c, l)) ; - // if ( bInverted) - // pCrv->Invert() ; - // PolyLine plApprox ; - // double dLinTol = 10 * EPS_SMALL, dAngTolDeg = 5 ; - // int nType = 0 ; - // pCrv->ApproxWithLines( dLinTol, dAngTolDeg, nType, plApprox) ; - // // aggiungo la polyline del chunk - // vPl.push_back( plApprox) ; - // } - //} - - - //// CON LE CURVE ( INTERSEZIONI CON BORDO PARAMETRICO) PtrOwner pCCEdge( CreateCurveComposite()) ; pCCEdge->AddPoint( m_mTree.at(-1).GetTopRight()) ; @@ -321,121 +284,124 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi m_mVert.insert( pair( -1, vVert)) ; // se richiesto divido preliminarmente le patches m_vnParents.clear() ; - if ( m_bSplitPatches && ( nSpanU > 1 || nSpanV > 1)) { - int nId = -1 ; - // se la superficie è chiusa lungo il parametro U, sistemo le adiacenze al bordo - if ( AreSamePointApprox(ptP00, ptP10) && AreSamePointApprox(ptP01, ptP11) ) { - m_mTree[-1].m_nLeft = -1 ; - m_mTree[-1].m_nRight = -1 ; - m_bClosedU = true ; - } - // se la superficie è chiusa lungo il parametro V, sistemo le adiacenze al bordo - if ( ( AreSamePointApprox(ptP00, ptP01) && AreSamePointApprox(ptP10, ptP11) ) ) { - m_mTree[-1].m_nTop = -1 ; - m_mTree[-1].m_nBottom = -1 ; - m_bClosedV = true ; - } - for ( int i = 1 ; i < nSpanU ; ++i) { - // chiedo che il taglio disti dal bordo almeno il 2% della singola patch (1000 x 1000) - if ( i * SBZ_TREG_COEFF > ptMin.x + 5 && i * SBZ_TREG_COEFF < ptTop.x - 5){ - m_mTree[nId].SetSplitDirVert( true) ; - if ( Split( nId, i * SBZ_TREG_COEFF)) { - ++ nId ; - ++ nId ; - } + bool bIsPlanar = m_pSrfBz->IsPlanar() ; + if( ! bIsPlanar) { + if ( m_bSplitPatches && ( nSpanU > 1 || nSpanV > 1)) { + int nId = -1 ; + // se la superficie è chiusa lungo il parametro U, sistemo le adiacenze al bordo + if ( AreSamePointApprox(ptP00, ptP10) && AreSamePointApprox(ptP01, ptP11) ) { + m_mTree[-1].m_nLeft = -1 ; + m_mTree[-1].m_nRight = -1 ; + m_bClosedU = true ; } - } - INTVECTOR vLeaves ; - GetHeightLeaves( -1, vLeaves) ; - for ( int nId : vLeaves) { - for ( int j = nSpanV - 1 ; j > 0 ; --j) { - // chiedo che il taglio disti dal bordo almeno il 2% della singola patch (1000 x 1000) - if ( j * SBZ_TREG_COEFF > ptMin.y + 5 && j * SBZ_TREG_COEFF < ptTop.y - 5){ - m_mTree[nId].SetSplitDirVert( false) ; - if ( Split( nId, j * SBZ_TREG_COEFF)) - nId = m_mTree[nId].m_nChild2 ; - } - } - } - vLeaves.clear() ; - } - // controllo se la superficie è chiusa. - // se è chiusa e non ho già fatto split preliminare, splitto sul parametro su cui è chiusa - // e sistemo le adiacenze - if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) || - ( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11))) { - // m_bClosed = true ; - if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) && (int) m_mTree.size() == 1) { - if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) { + // se la superficie è chiusa lungo il parametro V, sistemo le adiacenze al bordo + if ( ( AreSamePointApprox(ptP00, ptP01) && AreSamePointApprox(ptP10, ptP11) ) ) { m_mTree[-1].m_nTop = -1 ; m_mTree[-1].m_nBottom = -1 ; m_bClosedV = true ; } - m_mTree[-1].SetSplitDirVert( false) ; - Split( -1) ; - // qui devo fare il controllo capped ( chiusura a semisfera) - // devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti - // in caso devo fare uno split nell'altra direzione - bool bOk = false ; - bool bPole0 = true, bPole1 = true ; - Point3d ptU0, ptU1 ; - // controllo se tutti i punti di controllo sull'isoparametrica sono uguali - for ( int i = 1 ; i < nDegV * nSpanV + 1 ; ++ i) { - ptU0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ; - bPole0 = bPole0 && AreSamePointApprox( ptP00, ptU0) ; - ptU1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ; - bPole1 = bPole1 && AreSamePointApprox( ptP10, ptU1) ; - } - m_vbPole[1] = bPole0 ; - m_vbPole[3] = bPole1 ; - if ( bPole0 && bPole1) { - m_mTree[0].SetSplitDirVert( true) ; - Split( 0) ; - m_mTree[1].SetSplitDirVert( true) ; - Split( 1) ; - } - } - // nella condizione di questo if non controllo eventuali divisioni preliminari, perché ne tengo conto dopo - if ( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11)) { - if ( m_mTree.size() == 1) { - if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) { - m_mTree[-1].m_nLeft = -1 ; - m_mTree[-1].m_nRight = -1 ; - m_bClosedU = true ; + for ( int i = 1 ; i < nSpanU ; ++i) { + // chiedo che il taglio disti dal bordo almeno il 2% della singola patch (1000 x 1000) + if ( i * SBZ_TREG_COEFF > ptMin.x + 5 && i * SBZ_TREG_COEFF < ptTop.x - 5){ + m_mTree[nId].SetSplitDirVert( true) ; + if ( Split( nId, i * SBZ_TREG_COEFF)) { + ++ nId ; + ++ nId ; + } } - m_mTree[-1].SetSplitDirVert( true) ; + } + INTVECTOR vLeaves ; + GetHeightLeaves( -1, vLeaves) ; + for ( int nId : vLeaves) { + for ( int j = nSpanV - 1 ; j > 0 ; --j) { + // chiedo che il taglio disti dal bordo almeno il 2% della singola patch (1000 x 1000) + if ( j * SBZ_TREG_COEFF > ptMin.y + 5 && j * SBZ_TREG_COEFF < ptTop.y - 5){ + m_mTree[nId].SetSplitDirVert( false) ; + if ( Split( nId, j * SBZ_TREG_COEFF)) + nId = m_mTree[nId].m_nChild2 ; + } + } + } + vLeaves.clear() ; + } + // controllo se la superficie è chiusa. + // se è chiusa e non ho già fatto split preliminare, splitto sul parametro su cui è chiusa + // e sistemo le adiacenze + if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) || + ( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11))) { + // m_bClosed = true ; + if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) && (int) m_mTree.size() == 1) { + if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) { + m_mTree[-1].m_nTop = -1 ; + m_mTree[-1].m_nBottom = -1 ; + m_bClosedV = true ; + } + m_mTree[-1].SetSplitDirVert( false) ; Split( -1) ; - // devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti + // qui devo fare il controllo capped ( chiusura a semisfera) + // devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti // in caso devo fare uno split nell'altra direzione bool bOk = false ; bool bPole0 = true, bPole1 = true ; - Point3d ptV0, ptV1 ; - // controllo se tutti i punti sull'isoparametrica sono uguali - for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) { - ptV0 = m_pSrfBz->GetControlPoint( i, &bOk) ; - bPole0 = bPole0 && AreSamePointApprox( ptP00, ptV0) ; - ptV1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ; - bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ; + Point3d ptU0, ptU1 ; + // controllo se tutti i punti di controllo sull'isoparametrica sono uguali + for ( int i = 1 ; i < nDegV * nSpanV + 1 ; ++ i) { + ptU0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ; + bPole0 = bPole0 && AreSamePointApprox( ptP00, ptU0) ; + ptU1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ; + bPole1 = bPole1 && AreSamePointApprox( ptP10, ptU1) ; } - m_vbPole[0] = bPole0 ; - m_vbPole[2] = bPole1 ; + m_vbPole[1] = bPole0 ; + m_vbPole[3] = bPole1 ; if ( bPole0 && bPole1) { - m_mTree[0].SetSplitDirVert( false) ; + m_mTree[0].SetSplitDirVert( true) ; Split( 0) ; - m_mTree[1].SetSplitDirVert( false) ; + m_mTree[1].SetSplitDirVert( true) ; Split( 1) ; } } - // se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1 - else if ( (int) m_mTree.size() > 1 && (int) m_mTree.size() < 4 && ! m_mTree.at(-1).IsSplitVert()) { // si può mettere anche < 5 - m_mTree[0].m_nLeft = -1 ; - m_mTree[0].m_nRight = -1 ; - m_mTree[1].m_nLeft = -1 ; - m_mTree[1].m_nRight = -1 ; - m_mTree[0].SetSplitDirVert( true) ; - Split( 0) ; - m_mTree[1].SetSplitDirVert( true) ; - Split( 1) ; + // nella condizione di questo if non controllo eventuali divisioni preliminari, perché ne tengo conto dopo + if ( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11)) { + if ( m_mTree.size() == 1) { + if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11)) { + m_mTree[-1].m_nLeft = -1 ; + m_mTree[-1].m_nRight = -1 ; + m_bClosedU = true ; + } + m_mTree[-1].SetSplitDirVert( true) ; + Split( -1) ; + // devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti + // in caso devo fare uno split nell'altra direzione + bool bOk = false ; + bool bPole0 = true, bPole1 = true ; + Point3d ptV0, ptV1 ; + // controllo se tutti i punti sull'isoparametrica sono uguali + for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) { + ptV0 = m_pSrfBz->GetControlPoint( i, &bOk) ; + bPole0 = bPole0 && AreSamePointApprox( ptP00, ptV0) ; + ptV1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ; + bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ; + } + m_vbPole[0] = bPole0 ; + m_vbPole[2] = bPole1 ; + if ( bPole0 && bPole1) { + m_mTree[0].SetSplitDirVert( false) ; + Split( 0) ; + m_mTree[1].SetSplitDirVert( false) ; + Split( 1) ; + } + } + // se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1 + else if ( (int) m_mTree.size() > 1 && (int) m_mTree.size() < 4 && ! m_mTree.at(-1).IsSplitVert()) { // si può mettere anche < 5 + m_mTree[0].m_nLeft = -1 ; + m_mTree[0].m_nRight = -1 ; + m_mTree[1].m_nLeft = -1 ; + m_mTree[1].m_nRight = -1 ; + m_mTree[0].SetSplitDirVert( true) ; + Split( 0) ; + m_mTree[1].SetSplitDirVert( true) ; + Split( 1) ; + } } } } @@ -1003,6 +969,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } // bilineare else { + bool bIsPlanar = m_pSrfBz->IsPlanar() ; + while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) { if ( m_mTree[nCToSplit].IsLeaf()) { // vertici della cella @@ -1079,7 +1047,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } } } - else { + else if ( ! bIsPlanar){ dErr = 1. / 4. * ( ( ptP00 - ptP01) + ( ptP11 - ptP10)).Len() ; //int dErr2 = 1. / 4. * ( ( ptP10 - ptP01) + ( ptP11 - ptP00)).Len() ; //correzione che mi verrebbe intuitiva, ma che fa dividere la superficie molto di più ( probabilmente troppo)!! quindi probabilmente sbagliata } @@ -1557,16 +1525,6 @@ Tree::GetDepth( int nId, int nRef = -2) const return i ; } -////---------------------------------------------------------------------------- -//struct generator -//{ -// int value ; -// generator( void) -// { value = -1 ; } -// int operator() () -// { return ++value ; } -//} ; - //---------------------------------------------------------------------------- bool Tree::GetPolygons( POLYLINEMATRIX& vvPolygons) @@ -1792,7 +1750,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){ // se la superficie è chiusa lungo il parametro U e le celle vicine right sono sul lato Left // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. - vnVert.push_back( int(vVertices.size())) ; + vnVert.push_back( int(vVertices.size() - 1)) ; if ( m_bClosedU && m_mTree.at( vNeigh[0]).m_bOnLeftEdge ) { for ( int j : vNeigh) { Point3d pt( m_mTree.at( nId).GetTopRight().x, m_mTree.at(j).GetBottomLeft().y) ; @@ -1825,7 +1783,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon if ( ! vNeigh.empty() && vNeigh.size() != 1) { // se la superficie è chiusa lungo il parametro V e la cella è sul lato top // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. - vnVert.push_back( int(vVertices.size())) ; + vnVert.push_back( int(vVertices.size() - 1)) ; if ( m_bClosedV && m_mTree.at( nId).m_bOnTopEdge) { for ( int j : vNeigh) { Point3d pt( m_mTree.at( j).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; @@ -1851,7 +1809,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) { // se la superficie è chiusa lungo il parametro U e la cella è sul lato left // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. - vnVert.push_back( int(vVertices.size())) ; + vnVert.push_back( int(vVertices.size() - 1)) ; if ( m_bClosedU && m_mTree.at( nId).m_bOnLeftEdge) { for ( int j : vNeigh) { Point3d pt( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at(j).GetTopRight().y) ; @@ -2236,40 +2194,6 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells } // rilancio la rigida ricerca nCells = FindCell( ptIntersPlus, cl, vCells, true) ; - - /////////////////////////// questa versione funziona, ma forse potrebbe fallire in alcuni casi/// - // for ( int nCell : vCells) { - // if ( ptToAssign.x > m_mTree.at( nCell).GetBottomLeft().x - EPS_SMALL && ptToAssign.x < m_mTree.at( nCell).GetTopRight().x + EPS_SMALL && - // ptToAssign.y > m_mTree.at( nCell).GetBottomLeft().y - EPS_SMALL && ptToAssign.y < m_mTree.at( nCell).GetTopRight().y + EPS_SMALL) { - // nId = nCell ; - // nCells.push_back( nId) ; - // } - // } - // if ( (int)nCells.size() == 1) - // return nCells ; - // // sono su vertice o un lato, quindi avanzo con il parametro lungo la curva - // else if ( (int)nCells.size() > 1 ) { - // // la CurveLine è il segmento di trim su cui giace ptToAssign - // Point3d ptIntersPlus ; - // Vector3d vtDir ; - // cl.GetStartDir( vtDir) ; - // // mi sposto appena più avanti di ptToAssign - // // se la curva è orientata come l'asse x o y mi sto muovendo su un lato e sarò ancora sul lato, quindi dovrei ruotare il vettore a destra prima di spostarmi - // if ( abs( vtDir.x) >= 1 - EPS_SMALL || abs( vtDir.y) >= 1 - EPS_SMALL) - // vtDir.Rotate( Z_AX, -45) ; - // ptIntersPlus = ptToAssign + vtDir * EPS_SMALL ; - // // se sono finito fuori dallo spazio parametrico giro invece a sinistra - // if ( ptIntersPlus.x < m_mTree.at( -1).GetBottomLeft().x - EPS_SMALL || ptIntersPlus.x > m_mTree.at( -1).GetTopRight().x + EPS_SMALL|| - // ptIntersPlus.y < m_mTree.at( -1).GetBottomLeft().y - EPS_SMALL || ptIntersPlus.y > m_mTree.at( -1).GetTopRight().y + EPS_SMALL) { - // vtDir.Rotate( Z_AX, 90) ; - // ptIntersPlus = ptToAssign + vtDir * EPS_SMALL ; - // } - // nCells = FindCell( ptIntersPlus, cl, vCells) ; - // } - //// se vuoto allora il punto non è in nessuna delle celle passate in input - // else - // return nCells ; - ////////////////////////////////////////////////////////////////////////// } return nCells ; @@ -2405,19 +2329,13 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // aggiorno la polyline splittata UpdateSplitLoop( plLoopSplit, nPtLoopSplit, vptInters.back()) ; } - // VERSIONE NUOVA // controllo di aggiungere un punto abbastanza distante dal precedente - if( ! AreSamePointEpsilon( vptInters.back(), ptCurr, 2 * EPS_SMALL)) { + if( ! AreSamePointEpsilon( vptInters.back(), ptCurr, 10 * EPS_SMALL)) { // aggiungo la fine del segmento nel vettore delle intersezioni vptInters.push_back( ptCurr) ; // aggiorno la polyline splittata UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ; } - ////VECCHIA VERSIONE - //// aggiungo la fine del segmento nel vettore delle intersezioni - //vptInters.push_back( ptCurr) ; - //// aggiorno la polyline splittata - //UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ; } if ( nId == nFirstCell) vptInters.pop_back() ; @@ -2626,91 +2544,6 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, int nEdge ; // flag che indica il lato su cui ho l'intersezione a partire dal lato top in senso antiorario Point3d ptInters ; - //CurveLine clEdge , clEdge2 ; - //Point3d ptStart , ptEnd ; - //clTrim.GetStartPoint( ptStart) ; - //clTrim.GetEndPoint( ptEnd) ; - //// trovo da quale lato sto uscendo - ////int nEdge ; // flag che indica il lato su cui ho l'intersezione 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 - ////int nEdge2 ; - //if ( ptEnd.y >= ptTR.y && ptEnd.x <= ptTR.x) { - // //nEdge = 0 ; - // // lato sopra - // clEdge.Set( ptTR, ptTl) ; - // // lato sinistro - // if ( ptEnd.x < ptBL.x) { - // //nEdge2 = 1 ; - // clEdge2.Set( ptTl, ptBL) ; - // } - //} - //else if ( ptEnd.x <= ptBL.x && ptEnd.y <= ptTR.y) { - // nEdge = 1 ; - // // lato sinistro - // clEdge.Set( ptTl, ptBL) ; - // // lato sotto - // if ( ptEnd.y < ptBL.y) { - // //nEdge2 = 2 ; - // clEdge2.Set( ptBL, ptBr) ; - // } - //} - //else if ( ptEnd.y <= ptBL.y && ptEnd.x >= ptBL.x) { - // nEdge = 2 ; - // // lato sotto - // clEdge.Set( ptBL, ptBr) ; - // // lato destro - // if ( ptEnd.x > ptTR.x) { - // //nEdge2 = 3 ; - // clEdge2.Set( ptBr, ptTR) ; - // } - //} - //else if ( ptEnd.x >= ptTR.x && ptEnd.y >= ptBL.y) { - // nEdge = 3 ; - // // lato desto - // clEdge.Set( ptBr, ptTR) ; - // // lato sopra - // if ( ptEnd.y > ptTR.y) { - // //nEdge2 = 0 ; - // clEdge2.Set( ptTR, ptTl) ; - // } - //} - //else - // return false ; - - //bool bIntersFound = false ; - //// intersezione e controlli - //IntersLineLine illExit( clTrim, clEdge, true) ; - //IntCrvCrvInfo aInfo, aInfo2 ; - //if ( ! illExit.GetIntCrvCrvInfo( aInfo)) { - // bIntersFound = false ; - // if ( ! clEdge2.IsValid()) - // return false ; - //} - //else { - // bIntersFound = true ; - // if ( aInfo.bOverlap) - // ptInters = aInfo.IciA[1].ptI ; - // else - // ptInters = aInfo.IciA[0].ptI ; - //} - //if ( clEdge2.IsValid() && ! bIntersFound){ - // IntersLineLine illExit2( clTrim, clEdge2, true) ; - // // verifico su quale dei due lati ho l'intersezione - // if ( ! illExit2.GetIntCrvCrvInfo( aInfo2)) - // bIntersFound = false ; - // else { - // bIntersFound = true ; - // //// solo intersezione sul lato 2 - // if ( aInfo2.bOverlap) - // ptInters = aInfo2.IciA[1].ptI ; - // else - // ptInters = aInfo2.IciA[0].ptI ; - // } - //} - //if ( ! bIntersFound) - // return false ; - PtrOwner pCC( CreateCurveComposite()) ; PolyLine plSimplePolygon ; plSimplePolygon = plPolygon ; @@ -2765,7 +2598,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, else if ( nEdge == 7) ptInters = ptTR ; // aggiungo il nuovo punto al vettore delle intersezioni - if ( (int)vptInters.size() == 0 || ! AreSamePointEpsilon( ptInters , vptInters.back(), 2 * EPS_SMALL)) + if ( (int)vptInters.size() == 0 || ! AreSamePointEpsilon( ptInters , vptInters.back(), 10 * EPS_SMALL)) vptInters.push_back( ptInters) ; else { // se l'ultimo punto del vettore delle intersezioni è quasi uguale al punto che devo aggiungere allora lo sostituisco con quest'ultimo @@ -3140,15 +2973,13 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX } else { double dPar = 0 ; - bool bAdvanced = false ; while ( plCell.GetNextUPoint( &dPar, &ptToAdd) && ! AreSamePointExact( ptToAdd, ptNextVert)) { vEdgeVertex[j].push_back( ptToAdd) ; if ( dPar > 0) plCell3d.GetNextPoint( pt3d) ; vEdgeVertex3d[j].push_back( pt3d) ; - bAdvanced = true ; } - if ( ! bAdvanced && dPar > 0) + if ( dPar > 0) plCell3d.GetNextPoint( pt3d) ; } } @@ -3198,7 +3029,9 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX Vector3d vEdge ; // estendo: se l'ultimo tratto è sovrapposto e controverso allora elimino l'ultimo punto bool bNotEquiverseOverlap = false ; - if ( nEdge == 0 || nEdge == 7 ) { + int nEdgeLast = -1 ; + OnWhichEdge(nId,ptLast, nEdgeLast) ; + if ( (nEdge == 0 || nEdge == 7) && nEdge == nEdgeLast) { vEdge.Set( 1,0,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; @@ -3207,7 +3040,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX bNotEquiverseOverlap = true ; } } - else if ( nEdge == 1 || nEdge == 4 ) { + else if ( ( nEdge == 1 || nEdge == 4 ) && nEdge == nEdgeLast) { vEdge.Set( 0,-1,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; @@ -3216,7 +3049,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX bNotEquiverseOverlap = true ; } } - else if ( nEdge == 2 || nEdge == 5 ) { + else if ( ( nEdge == 2 || nEdge == 5) && nEdge == nEdgeLast) { vEdge.Set( -1,0,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; @@ -3225,7 +3058,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX bNotEquiverseOverlap = true ; } } - else if ( nEdge == 3 || nEdge == 6 ) { + else if ( ( nEdge == 3 || nEdge == 6) && nEdge == nEdgeLast) { vEdge.Set( 0,1,0) ; if ( AreOppositeVectorApprox( vLast, vEdge)) { plTrimmedPoly.EraseLastUPoint() ; @@ -3313,8 +3146,9 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX else if ( ! bNotCameBack){ Point3d ptStart ; plTrimmedPoly.GetFirstPoint( ptStart) ; + Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ; for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { - if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart)) { + if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart) && CheckIfBefore( nEdge, ptLast, vEdgeVertex[nEdge][p])) { plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ; ++ c ; @@ -3348,8 +3182,9 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX // aggiorno le condizioni per il while bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; } + Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ; for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { - if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart)) { + if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart) && CheckIfBefore( nEdge, ptLast, vEdgeVertex[nEdge][p])) { plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ; ++ c ; @@ -3458,10 +3293,11 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR vPolygons.push_back( vCellPolygons) ; ++ nPoly ; if ( bForTriangulation) { - plInLoop3d.AddUPoint( 0, m_mVert[nId][2]); - plInLoop3d.AddUPoint( 1, m_mVert[nId][3]); - plInLoop3d.AddUPoint( 2, m_mVert[nId][0]); - plInLoop3d.AddUPoint( 3, m_mVert[nId][1]); + plInLoop3d.AddUPoint( 0, m_mVert[nId][2]) ; + plInLoop3d.AddUPoint( 1, m_mVert[nId][3]) ; + plInLoop3d.AddUPoint( 2, m_mVert[nId][0]) ; + plInLoop3d.AddUPoint( 3, m_mVert[nId][1]) ; + plInLoop3d.Close() ; vCellPolygons3d.push_back( plInLoop3d) ; vPolygons3d.push_back( vCellPolygons3d) ; vCellPolygons3d.clear() ; @@ -3884,7 +3720,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe bool Tree::SetRightEdgeIn( int nId) { - // categorizzo la cella in base a quanta parte del lato destro è conenuta all'interno delle curve di trim + // categorizzo la cella in base a quanta parte del lato destro è contenuta all'interno delle curve di trim // RightEdgeIn -> 0 non contenuto ; 1 contenuto ; 2 in parte contenuto int nPass = (int) m_mTree[nId].m_vInters.size() ; if ( nPass == 0) { From b50588f9741db50d837f54d4346a3d28d45a38f9 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 26 Jul 2024 17:28:29 +0200 Subject: [PATCH 10/16] EgtGeomKernel : - correzioni e migliorie alla triangolazione delle bezier. --- SurfBezier.cpp | 51 ++++++--- Tree.cpp | 277 +++++++++++++++++++++++++++---------------------- Tree.h | 3 +- 3 files changed, 191 insertions(+), 140 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index b1316f7..b9c07e0 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1577,7 +1577,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const // prendo i punti di ogni polyline dell'albero, li triangolo e li porto in 3d int c = 0 ; - for ( POLYLINEVECTOR vPL : vvPL) { + for ( POLYLINEVECTOR& vPL : vvPL) { PNTVECTOR vPnt ; INTVECTOR vTria ; Triangulate Tri ; @@ -1590,7 +1590,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const PNTVECTOR vPnt3d ; for( int i = 0 ; i < int( vPL3d.size()) ; ++i) { - PolyLine pl3d = vPL3d[i] ; + PolyLine& pl3d = vPL3d[i] ; Point3d pt3d ; pl3d.GetFirstPoint( pt3d) ; //vPnt3d.push_back( pt3d) ; while ( pl3d.GetNextPoint( pt3d)) { @@ -1600,29 +1600,52 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const // se ho ottenuto meno triangoli di quelli che avrei dovuto avere allora potrei aver avuto un problema in prossimità di un polo // se comunque ho corrispondenza tra vPnt e vPnt3d allora eseguo la trinagolazione in 3d - if ( ( vPnt.size() - 2 ) != ( vTria.size() ) / 3 && vPnt.size() == vPnt3d.size() ) { + bool bTriangulationFailedIn2D = ( vPnt.size() - 2) != ( vTria.size()) / 3 ; + bool bMismatch2D3D = vPnt.size() != vPnt3d.size() ; + bool bTriangulatedIn3D = false ; + if ( bTriangulationFailedIn2D || bMismatch2D3D) { + PNTVECTOR vPntBackup ; + if( ! bTriangulationFailedIn2D && bMismatch2D3D) + vPntBackup = vPnt ; if ( ! Tri.Make( vPL3d, vPnt, vTria)) return nullptr ; - if ( ( vPnt.size() - 2 ) == ( vTria.size() ) / 3 ) - LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) RESOLVED") - else - LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) is the same as the previous one") + bool bTriangulationSucceded = ( vPnt.size() - 2 ) == ( vTria.size() ) / 3 ; + if( bTriangulationFailedIn2D) { + if ( bTriangulationSucceded) + LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) RESOLVED") + else + LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) is the same as the previous one") + } + if( bMismatch2D3D && ! bTriangulationSucceded) + vPnt = vPntBackup ; + else if( bTriangulationSucceded) + bTriangulatedIn3D = true ; } // controllo per ogni polyline se è stato invertito il vettore dei punti int nCurrPoint = 0 ; for( int i = 0 ; i < int( vPL.size()) ; ++i) { - Point3d pt3d ; vPL[i].GetFirstPoint( pt3d) ; - vPL[i].GetNextPoint( pt3d) ; - int nPoints = vPL[i].GetPointNbr() - 2 ; - if ( ! AreSamePointApprox( vPnt[nCurrPoint], pt3d)) - reverse( vPnt3d.begin() + nCurrPoint, vPnt3d.begin() + nCurrPoint + nPoints) ; - nCurrPoint += nPoints ; + if( ! bTriangulatedIn3D) { + Point3d pt ; vPL[i].GetFirstPoint( pt) ; + vPL[i].GetNextPoint( pt) ; + int nPoints = vPL[i].GetPointNbr() - 2 ; + if ( ! AreSamePointApprox( vPnt[nCurrPoint], pt)) + reverse( vPnt3d.begin() + nCurrPoint, vPnt3d.begin() + nCurrPoint + nPoints) ; + nCurrPoint += nPoints ; + } + else { + Point3d pt ; vPL3d[i].GetFirstPoint( pt) ; + vPL3d[i].GetNextPoint( pt) ; + int nPoints = vPL3d[i].GetPointNbr() - 2 ; + if ( ! AreSamePointApprox( vPnt[nCurrPoint], pt)) + reverse( vPnt3d.begin() + nCurrPoint, vPnt3d.begin() + nCurrPoint + nPoints) ; + nCurrPoint += nPoints ; + } } //controllo che i due vettori vPnt e vPnt3d abbiano la stessa lunghezza, sennò vuol dire che nel vettore vPnt3d ho avuto dei Rejected e devo ricalcolarli // i punti in eccesso verranno poi scartati dalla trimesh - if( vPnt.size() != vPnt3d.size()) { + if( vPnt.size() != vPnt3d.size() && ! bTriangulatedIn3D) { vPnt3d.clear() ; for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) { Point3d pt3d ; diff --git a/Tree.cpp b/Tree.cpp index de68f01..9a4b186 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -224,18 +224,15 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi PtrOwner pChunk( pTrimReg->CloneChunk( i)) ; for ( int j = 0 ; j < pChunk->GetLoopCount( 0) ; ++ j) { // i chunk della falt region sono ancora flat region composte da 1 chunk - PtrOwner pLoop ( pChunk->GetLoop( 0, j)) ; // rimuovo i difetti dei loop prima di salvarli - PtrOwner pCrvCompo( GetBasicCurveComposite(pLoop->Clone())) ; - pCrvCompo->MergeCurves( dLinTol, dAngTolDeg) ; - pCrvCompo->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ; - pCrvCompo->RemoveSmallParts( dLinTol, dAngTolDeg) ; - PtrOwner pCrv( pCrvCompo->Clone()) ; - + PtrOwner pLoop( GetBasicCurveComposite( pChunk->GetLoop( 0, j))) ; + pLoop->MergeCurves( dLinTol, dAngTolDeg) ; + pLoop->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ; + pLoop->RemoveSmallParts( dLinTol, dAngTolDeg) ; // approssimo i loop di trim con delle spezzate PolyLine plApprox ; int nType = 0 ; - pCrv->ApproxWithLines( dLinTol,dAngTolDeg, nType, plApprox) ; + pLoop->ApproxWithLines( dLinTol,dAngTolDeg, nType, plApprox) ; // calcolo se il loop è CCW o CW double dArea ; Plane3d plExtPlane ; @@ -444,7 +441,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi } //---------------------------------------------------------------------------- -bool +static bool AddOrMergeBBox( const BBox3d& bBox3dA, vector& vBBox, bool bAdd = true, int nInd = 0) { Point3d ptMin = bBox3dA.GetMin() ; @@ -487,7 +484,7 @@ Tree::GetIndependentTrees( BIPNTVECTOR& vTrees) // se ho dei loop di trim trovo le loro BBox3d per costruire l'albero solo all'interno di queste BBox BOXVECTOR vBBox ; for ( int i = 0 ; i < int( m_vPlApprox.size()) ; ++ i) { - PolyLine plLoop = get<0>( m_vPlApprox[i]) ; + PolyLine& plLoop = get<0>( m_vPlApprox[i]) ; // calcolo la BBox3d Point3d ptP ; plLoop.GetFirstPoint( ptP) ; @@ -502,7 +499,7 @@ Tree::GetIndependentTrees( BIPNTVECTOR& vTrees) bool bIsRoot = false ; Point3d ptTR( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF) ; for ( int i = 0 ; i < int( vBBox.size()) ; ++ i) { - BBox3d bBox3d = vBBox[i] ; + BBox3d& bBox3d = vBBox[i] ; if ( AreSamePointEpsilon( bBox3d.GetMin(), ORIG, 10) && AreSamePointEpsilon( bBox3d.GetMax(), ptTR, 10)) { bIsRoot = true ; break ; @@ -1750,7 +1747,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1){ // se la superficie è chiusa lungo il parametro U e le celle vicine right sono sul lato Left // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. - vnVert.push_back( int(vVertices.size() - 1)) ; + vnVert.push_back( int(vVertices.size())) ; if ( m_bClosedU && m_mTree.at( vNeigh[0]).m_bOnLeftEdge ) { for ( int j : vNeigh) { Point3d pt( m_mTree.at( nId).GetTopRight().x, m_mTree.at(j).GetBottomLeft().y) ; @@ -1783,7 +1780,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon if ( ! vNeigh.empty() && vNeigh.size() != 1) { // se la superficie è chiusa lungo il parametro V e la cella è sul lato top // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. - vnVert.push_back( int(vVertices.size() - 1)) ; + vnVert.push_back( int(vVertices.size())) ; if ( m_bClosedV && m_mTree.at( nId).m_bOnTopEdge) { for ( int j : vNeigh) { Point3d pt( m_mTree.at( j).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; @@ -1809,7 +1806,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon if ( (int) vNeigh.size() != 0 && (int) vNeigh.size() != 1) { // se la superficie è chiusa lungo il parametro U e la cella è sul lato left // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. - vnVert.push_back( int(vVertices.size() - 1)) ; + vnVert.push_back( int(vVertices.size())) ; if ( m_bClosedU && m_mTree.at( nId).m_bOnLeftEdge) { for ( int j : vNeigh) { Point3d pt( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at(j).GetTopRight().y) ; @@ -1847,123 +1844,111 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon // se così, devo guardare se sui due lati adiacenti a quello di polo ho messo dei punti extra // se ne ho messi solo su uno dei due allora devo togliere il vertice dell'altro lato if ( AreSamePointApprox(m_mVert.at(nId).at(0), m_mVert.at(nId).at(1))) { - // se ho punti bonus su entrambi i lati non devo fare nulla - if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { - // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if ( vbBonusVert[1] ) {// lati contati a partire da quello sopra in senso CCW - if ( ! m_bTrimmed) { - vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW - vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; - } - vbKeepPoint[vnVert[1]] = false ; - m_mTree[nId].m_nVertToErase = 1 ; // ptBr + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if ( vbBonusVert[1] && ! vbBonusVert[3]) {// lati contati a partire da quello sopra in senso CCW + if ( ! m_bTrimmed) { + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; } - else if ( vbBonusVert[3] ) { - if ( ! m_bTrimmed) { - // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto - vVerticesCorr.pop_back() ; - vVerticesCorr[0] = vVerticesCorr.end()[-1] ; - vVertices3d.pop_back() ; - vVertices3d[0] = vVertices3d.end()[-1] ; - } - vbKeepPoint[0] = false ; - vbKeepPoint.back() = false ; - m_mTree[nId].m_nVertToErase = 0 ; // ptBL - } - // se non ho bonus su nessuno dei due - else { - // ne scelgo uno dei due da togliere - vbKeepPoint[vnVert[1]] = false ; - m_mTree[nId].m_nVertToErase = 1 ; // ptBr + vbKeepPoint[vnVert[1]] = false ; + m_mTree[nId].m_nVertToErase = 1 ; // ptBr + } + else if ( ! vbBonusVert[1] && vbBonusVert[3] ) { + if ( ! m_bTrimmed) { + // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto + vVerticesCorr.pop_back() ; + vVerticesCorr[0] = vVerticesCorr.end()[-1] ; + vVertices3d.pop_back() ; + vVertices3d[0] = vVertices3d.end()[-1] ; } + vbKeepPoint[0] = false ; + vbKeepPoint.back() = false ; + m_mTree[nId].m_nVertToErase = 0 ; // ptBL + } + // se non ho bonus su nessuno dei due + else { + // ne scelgo uno dei due da togliere + vbKeepPoint[vnVert[1]] = false ; + m_mTree[nId].m_nVertToErase = 1 ; // ptBr } } if ( AreSamePointApprox(m_mVert.at(nId).at(1), m_mVert.at(nId).at(2))) { - // se ho punti bonus su entrambi i lati non devo fare nulla - if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { - // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if ( vbBonusVert[0] ){ // lati contati a partire da quello sopra in senso CCW - if ( ! m_bTrimmed) { - vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW - vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; - } - vbKeepPoint[vnVert[1]] = false ; - m_mTree[nId].m_nVertToErase = 1 ; // ptBr + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if ( vbBonusVert[0] && ! vbBonusVert[2]){ // lati contati a partire da quello sopra in senso CCW + if ( ! m_bTrimmed) { + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[1]) ; // vertici della cella contati a partire da ptBL in senso CCW + vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; } - else if ( vbBonusVert[2] ){ - if ( ! m_bTrimmed) { - vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[2]) ; - vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; - } - vbKeepPoint[vnVert[2]] = false ; - m_mTree[nId].m_nVertToErase = 2 ; // ptTR - } - // se non ho bonus su nessuno dei due - else { - // ne scelgo uno dei due da togliere - vbKeepPoint[vnVert[2]] = false ; - m_mTree[nId].m_nVertToErase = 2 ; // ptTR + vbKeepPoint[vnVert[1]] = false ; + m_mTree[nId].m_nVertToErase = 1 ; // ptBr + } + else if ( ! vbBonusVert[0] && vbBonusVert[2] ){ + if ( ! m_bTrimmed) { + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[2]) ; + vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; } + vbKeepPoint[vnVert[2]] = false ; + m_mTree[nId].m_nVertToErase = 2 ; // ptTR + } + // se non ho bonus su nessuno dei due + else { + // ne scelgo uno dei due da togliere + vbKeepPoint[vnVert[2]] = false ; + m_mTree[nId].m_nVertToErase = 2 ; // ptTR } } if ( AreSamePointApprox(m_mVert.at(nId).at(2), m_mVert.at(nId).at(3))) { - // se ho punti bonus su entrambi i lati non devo fare nulla - if ( !( vbBonusVert[1] && vbBonusVert[3] ) ) { - // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if ( vbBonusVert[1] ){ // lati contati a partire da quello sopra in senso CCW - if ( ! m_bTrimmed) { - vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW - vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; - } - vbKeepPoint[vnVert[2]] = false ; - m_mTree[nId].m_nVertToErase = 2 ; // ptTR + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if ( vbBonusVert[1] && ! vbBonusVert[3]){ // lati contati a partire da quello sopra in senso CCW + if ( ! m_bTrimmed) { + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[2]) ; // vertici della cella contati a partire da ptBL in senso CCW + vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; } - else if ( vbBonusVert[3] ) { - if ( ! m_bTrimmed) { - vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[3]) ; - vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; - } - vbKeepPoint[vnVert[3]] = false ; - m_mTree[nId].m_nVertToErase = 3 ; // ptTl - } - // se non ho bonus su nessuno dei due - else { - // ne scelgo uno dei due da togliere - vbKeepPoint[vnVert[3]] = false ; - m_mTree[nId].m_nVertToErase = 3 ; // ptTl + vbKeepPoint[vnVert[2]] = false ; + m_mTree[nId].m_nVertToErase = 2 ; // ptTR + } + else if ( ! vbBonusVert[1] && vbBonusVert[3]) { + if ( ! m_bTrimmed) { + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[3]) ; + vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; } + vbKeepPoint[vnVert[3]] = false ; + m_mTree[nId].m_nVertToErase = 3 ; // ptTl + } + // se non ho bonus su nessuno dei due + else { + // ne scelgo uno dei due da togliere + vbKeepPoint[vnVert[3]] = false ; + m_mTree[nId].m_nVertToErase = 3 ; // ptTl } } if ( AreSamePointApprox(m_mVert.at(nId).at(3), m_mVert.at(nId).at(0))) { - // se ho punti bonus su entrambi i lati non devo fare nulla - if ( !( vbBonusVert[0] && vbBonusVert[2] ) ) { - // sennò devo togliere l'estremo del lato su cui NON ho punti bonus - if ( vbBonusVert[0] ) { // lati contati a partire da quello sopra in senso CCW - if ( ! m_bTrimmed) { - // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto - vVerticesCorr.pop_back() ; - vVerticesCorr[0] = vVerticesCorr.end()[-1] ; - vVertices3d.pop_back() ; - vVertices3d[0] = vVertices3d.end()[-1] ; - } - vbKeepPoint[0] = false ; - vbKeepPoint.back() = false ; - m_mTree[nId].m_nVertToErase = 0 ; // ptBL + // sennò devo togliere l'estremo del lato su cui NON ho punti bonus + if ( vbBonusVert[0] && ! vbBonusVert[2]) { // lati contati a partire da quello sopra in senso CCW + if ( ! m_bTrimmed) { + // dovrei eliminare ptBL, quindi devo eliminare il primo e l'ultimo punto della polyline e poi chiuderla con quello che era il penultimo punto + vVerticesCorr.pop_back() ; + vVerticesCorr[0] = vVerticesCorr.end()[-1] ; + vVertices3d.pop_back() ; + vVertices3d[0] = vVertices3d.end()[-1] ; } - else if ( vbBonusVert[2] ) { - if ( ! m_bTrimmed) { - vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[3]) ; - vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; - } - vbKeepPoint[vnVert[3]] = false ; - m_mTree[nId].m_nVertToErase = 3 ; // ptTl - } - // se non ho bonus su nessuno dei due - else { - // ne scelgo uno dei due da togliere - vbKeepPoint[vnVert[3]] = false ; - m_mTree[nId].m_nVertToErase = 3 ; // ptTl + vbKeepPoint[0] = false ; + vbKeepPoint.back() = false ; + m_mTree[nId].m_nVertToErase = 0 ; // ptBL + } + else if ( ! vbBonusVert[0] && vbBonusVert[2]) { + if ( ! m_bTrimmed) { + vVerticesCorr.erase(vVerticesCorr.begin() + vnVert[3]) ; + vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; } + vbKeepPoint[vnVert[3]] = false ; + m_mTree[nId].m_nVertToErase = 3 ; // ptTl + } + // se non ho bonus su nessuno dei due + else { + // ne scelgo uno dei due da togliere + vbKeepPoint[vnVert[3]] = false ; + m_mTree[nId].m_nVertToErase = 3 ; // ptTl } } } @@ -3001,6 +2986,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX int nEdgeIn = -1 ; int nFirstLoopInPoly = -1 ; INTVECTOR vAddedLoops ; + Point3d ptLastAdded( -1, -1, 0) ; for ( int w = 0 ; w < (int)vToCheckNow.size() ; ++ w) { if ( m_mTree[nId].m_vInters[w].vpt.size() < 2) { continue ; @@ -3016,7 +3002,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX nFirstLoopInPoly = j ; } for ( Point3d ptInt : inA.vpt) { - AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptInt, plTrimmedPoly3d, bForTriangulation) ; + AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptInt, plTrimmedPoly3d, bForTriangulation, ptLastAdded) ; } vAddedLoops.push_back( j) ; nEdge = inA.nOut ; @@ -3115,7 +3101,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX ptVert = ptBr ; else if ( nEdge == 3) ptVert = ptTR ; - AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d, bForTriangulation) ; + AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d, bForTriangulation, ptLastAdded) ; if ( nEdge > 3 && nEdge != 7) nEdge = nEdge - 4 ; else if ( nEdge < 3) @@ -3172,7 +3158,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX ptVert = ptBr ; else if ( nEdge == 3) ptVert = ptTR ; - AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d, bForTriangulation) ; + AddVertex( nId, vEdgeVertex, vEdgeVertex3d, plTrimmedPoly, c, ptVert, plTrimmedPoly3d, bForTriangulation, ptLastAdded) ; if ( nEdge > 3 && nEdge != 7) nEdge = nEdge - 4 ; else if ( nEdge < 3) @@ -3194,6 +3180,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX } plTrimmedPoly.Close() ; plTrimmedPoly3d.Close() ; + ptLast.Set( -1,-1,0) ; // controllo sull'area del poligono, se è 0 ( quindi un segmento), non lo aggiungo double dArea ; plTrimmedPoly.GetAreaXY( dArea) ; @@ -3519,7 +3506,7 @@ Tree::AreSameEdge( int nEdge1, int nEdge2) const //---------------------------------------------------------------------------- bool Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, - const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool bForTriangulation) const + const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool bForTriangulation, Point3d& ptLast) const { Point3d ptBr = m_mTree.at(nId).GetBottomRight() ; Point3d ptTR = m_mTree.at(nId).GetTopRight() ; @@ -3532,8 +3519,11 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe if( ( nVertToSkip == 0 && AreSamePointApprox( ptToAdd, ptBL)) || ( nVertToSkip == 1 && AreSamePointApprox( ptToAdd, ptBr)) || ( nVertToSkip == 2 && AreSamePointApprox( ptToAdd, ptTR)) || - ( nVertToSkip == 3 && AreSamePointApprox( ptToAdd, ptTl))) + ( nVertToSkip == 3 && AreSamePointApprox( ptToAdd, ptTl))) { + // aggiorno l'ultimo punto aggiunto + ptLast.Set( ptToAdd.x, ptToAdd.y, 0) ; return true ; + } plTrimmedPoly.AddUPoint( c, ptToAdd) ; if ( bForTriangulation) { @@ -3542,10 +3532,13 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe plTrimmedPoly3d.AddUPoint( c, pt3d) ; } ++ c ; + // aggiorno l'ultimo punto aggiunto + ptLast.Set( ptToAdd.x, ptToAdd.y, 0) ; return true ; } - Point3d ptLast ; - plTrimmedPoly.GetLastPoint( ptLast) ; + //Point3d ptLast ; + //plTrimmedPoly.GetLastPoint( ptLast) ; + // verifico di essere allineato con un lato, sennò aggiungo e basta Vector3d vDir ; if ( ! AreSamePointApprox( ptToAdd, ptLast)) @@ -3588,13 +3581,15 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe } ++ c ; } + // aggiorno l'ultimo punto aggiunto + ptLast.Set( ptToAdd.x, ptToAdd.y, 0) ; return true ; } if ( abs( vDir.x) > 1 - EPS_SMALL || abs( vDir.y) > 1 - EPS_SMALL) { // se su un edge devo fare dei controlli // edge 0 if ( ptToAdd.x >= ptBL.x && ptToAdd.x <= ptTR.x && ptToAdd.y == ptTR.y && abs( vDir.x) > 1 - EPS_SMALL) { - for ( int t = 1 ; t < (int)vEdgeVertex[0].size() ; ++ t) { + for ( int t = nVertToSkip == 2 ? 0 : 1 ; t < (int)vEdgeVertex[0].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[0][t] ; if ( ptIntermed.x > ptToAdd.x && ptIntermed.x < ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; @@ -3619,7 +3614,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe } // edge 1 else if ( ptToAdd.y >= ptBL.y && ptToAdd.y <= ptTR.y && ptToAdd.x == ptBL.x && abs( vDir.y) > 1 - EPS_SMALL) { - for ( int t = 1 ; t < (int)vEdgeVertex[1].size() ; ++ t) { + for ( int t = nVertToSkip == 3 ? 0 : 1 ; t < (int)vEdgeVertex[1].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[1][t] ; if ( ptIntermed.y > ptToAdd.y && ptIntermed.y < ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; @@ -3644,7 +3639,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe } // edge 2 else if ( ptToAdd.x >= ptBL.x && ptToAdd.x <= ptTR.x && ptToAdd.y == ptBL.y && abs( vDir.x) > 1 - EPS_SMALL) { - for ( int t = 1 ; t < (int)vEdgeVertex[2].size() ; ++ t) { + for ( int t = nVertToSkip == 0 ? 0 : 1 ; t < (int)vEdgeVertex[2].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[2][t] ; if ( ptIntermed.x < ptToAdd.x && ptIntermed.x > ptLast.x) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; @@ -3669,7 +3664,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe } // edge 3 else if ( ptToAdd.y >= ptBL.y && ptToAdd.y <= ptTR.y && ptToAdd.x == ptTR.x && abs( vDir.y) > 1 - EPS_SMALL) { - for ( int t = 1 ; t < (int)vEdgeVertex[3].size() ; ++ t) { + for ( int t = nVertToSkip == 1 ? 0 : 1 ; t < (int)vEdgeVertex[3].size() ; ++ t) { Point3d ptIntermed = vEdgeVertex[3][t] ; if ( ptIntermed.y < ptToAdd.y && ptIntermed.y > ptLast.y) { plTrimmedPoly.AddUPoint( c, ptIntermed) ; @@ -3712,6 +3707,8 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe } ++ c ; } + // aggiorno l'ultimo punto aggiunto + ptLast.Set( ptToAdd.x, ptToAdd.y, 0) ; return true ; } @@ -4060,6 +4057,36 @@ Tree::CheckIfBetween( const Inters& inA, const Inters& inB) const return bFound ; } +//---------------------------------------------------------------------------- +bool +Tree::CheckIfBefore( int nEdgeA, int nEdgeB) const +{ + // questa funzione è pensata per edge che sono uguali per la funzione AreSameEdge + // su quell'edge verifico se EdgeA viene prima di EdgeB ( il senso di precorrenza è sempre antiorario) + switch ( nEdgeA ) { + case 0 : return nEdgeB == 4 ? true : false ; break ; + case 1 : return nEdgeB == 5 ? true : false ; break ; + case 2 : return nEdgeB == 6 ? true : false ; break ; + case 3 : return nEdgeB == 7 ? true : false ; break ; + case 4 : + if ( nEdgeB == 1 || nEdgeB == 5) + return true ; + break ; + case 5 : + if ( nEdgeB == 2 || nEdgeB == 6) + return true ; + break ; + case 6 : + if ( nEdgeB == 3 || nEdgeB == 7) + return true ; + break ; + case 7 : + if ( nEdgeB == 0 || nEdgeB == 4) + return true ; + break ; + } +} + //---------------------------------------------------------------------------- bool Tree::GetLeaves( vector& vLeaves) const diff --git a/Tree.h b/Tree.h index 59d769c..20d6e2f 100644 --- a/Tree.h +++ b/Tree.h @@ -284,8 +284,9 @@ class Tree bool CheckIfBefore( int nEdge1, const Point3d& ptP1, int nEdge2, const Point3d& ptP2) const ; // verifico quale punto viene prima tra pt1 e pt2 a partire da ptTR girando in senso CCW (punto 1 su edge 1 e punto 2 su edge 2, rispetto al lato 3) bool CheckIfBefore( int nEdge, const Point3d& ptP1, const Point3d& ptP2, int nEdge2 = -1) const ; // sul lato nEdge controllo se ptP1 viene prima di ptP2. bool AreSameEdge( int nEdge1, int nEdge2) const ; // indica se i due edge sono lo stesso. Un vertice adiacente ad un edge viene considerato uguale a questo edge + bool CheckIfBefore( int nEdgeA, int nEdgeB) const ; // per due edge uguali per la funzione AreSameEdge chiedo se EdgeA viene prima di EdgeB bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c, - const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool ForTriangulation) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto + const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool ForTriangulation, Point3d& ptLast) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto bool SetRightEdgeIn( int nId) ; // categorizza la cella in base all'edge destro per poter poi definire m_nFlag bool CategorizeCell( int nId) ; // categorizza la cella in base al flag m_nFlag (dentro, fuori, intersecata) bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW) From 742305b99b251f6ee9467584f10faa38d1a28c54 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 29 Jul 2024 15:25:28 +0200 Subject: [PATCH 11/16] EgtGeomKernel : - correzioni e miglioramenti alla triangolazione delle bezier. --- SurfBezier.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++------ Tree.cpp | 24 ++++++++++++++---- Tree.h | 3 ++- 3 files changed, 79 insertions(+), 14 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index b9c07e0..9d3b536 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1586,9 +1586,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const POLYLINEVECTOR vPL3d = vvPL3d[c] ; - // porto i punti in 3d PNTVECTOR vPnt3d ; - for( int i = 0 ; i < int( vPL3d.size()) ; ++i) { PolyLine& pl3d = vPL3d[i] ; Point3d pt3d ; pl3d.GetFirstPoint( pt3d) ; @@ -1598,12 +1596,18 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const } } + // conto quanti punti ho in totale, senza eliminare le ripetizioni + int nTotPnt = 0 ; + for ( PolyLine& pl2D : vPL) + nTotPnt+= pl2D.GetPointNbr() ; + // se ho ottenuto meno triangoli di quelli che avrei dovuto avere allora potrei aver avuto un problema in prossimità di un polo // se comunque ho corrispondenza tra vPnt e vPnt3d allora eseguo la trinagolazione in 3d bool bTriangulationFailedIn2D = ( vPnt.size() - 2) != ( vTria.size()) / 3 ; bool bMismatch2D3D = vPnt.size() != vPnt3d.size() ; bool bTriangulatedIn3D = false ; - if ( bTriangulationFailedIn2D || bMismatch2D3D) { + PNTVECTOR vPnt2d ; + if ( bTriangulationFailedIn2D || (bMismatch2D3D && vPnt.size() != nTotPnt)) { PNTVECTOR vPntBackup ; if( ! bTriangulationFailedIn2D && bMismatch2D3D) vPntBackup = vPnt ; @@ -1618,30 +1622,76 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const } if( bMismatch2D3D && ! bTriangulationSucceded) vPnt = vPntBackup ; - else if( bTriangulationSucceded) + else if( bTriangulationSucceded) { bTriangulatedIn3D = true ; + for( int i = 0 ; i < int( vPL.size()) ; ++i) { + PolyLine& pl = vPL[i] ; + Point3d pt ; pl.GetFirstPoint( pt) ; + //vPnt2D.push_back( pt) ; + while ( pl.GetNextPoint( pt)) { + vPnt2d.push_back( pt) ; + } + } + } } - // controllo per ogni polyline se è stato invertito il vettore dei punti + // controllo se devo riordinare il vettore dei punti + // se le polyline sono state invertite o ne è stato cambiato il punto di start int nCurrPoint = 0 ; for( int i = 0 ; i < int( vPL.size()) ; ++i) { if( ! bTriangulatedIn3D) { Point3d pt ; vPL[i].GetFirstPoint( pt) ; vPL[i].GetNextPoint( pt) ; int nPoints = vPL[i].GetPointNbr() - 2 ; - if ( ! AreSamePointApprox( vPnt[nCurrPoint], pt)) + if ( AreSamePointApprox( vPnt[nCurrPoint], pt)) + continue ; + else if ( AreSamePointApprox( vPnt[nCurrPoint + nPoints], pt)) reverse( vPnt3d.begin() + nCurrPoint, vPnt3d.begin() + nCurrPoint + nPoints) ; + else { + // se la polyline non è stata semplicemente invertita allora vuol dire che ne è stato cambiato lo start point + // in questo caso il punto di chiusura non è stato eliminato + nPoints += 2 ; + vPL[i].GetPrevPoint( pt) ; + int nPoints = vPL[i].GetPointNbr() - 1 ; + for ( int j = 0 ; j < nPoints ; ++j ) { + if ( AreSamePointApprox( vPnt[nCurrPoint + j], pt)) { + rotate( vPnt3d.begin() + nCurrPoint, vPnt3d.begin() + nCurrPoint + nPoints - j - 1, vPnt3d.begin() + nCurrPoint + nPoints) ; + vPnt3d.insert( vPnt3d.begin() + nCurrPoint + nPoints, vPnt3d[nCurrPoint]) ; + break ; + } + } + } nCurrPoint += nPoints ; } else { Point3d pt ; vPL3d[i].GetFirstPoint( pt) ; vPL3d[i].GetNextPoint( pt) ; int nPoints = vPL3d[i].GetPointNbr() - 2 ; - if ( ! AreSamePointApprox( vPnt[nCurrPoint], pt)) - reverse( vPnt3d.begin() + nCurrPoint, vPnt3d.begin() + nCurrPoint + nPoints) ; + if ( AreSamePointApprox( vPnt[nCurrPoint], pt)) + continue ; + else if ( AreSamePointApprox( vPnt[nCurrPoint + nPoints], pt)) + reverse( vPnt2d.begin() + nCurrPoint, vPnt2d.begin() + nCurrPoint + nPoints) ; + else { + // se la polyline non è stata semplicemente invertita allora vuol dire che ne è stato cambiato lo start point + // in questo caso il punto di chiusura non è stato eliminato + nPoints += 2 ; + vPL3d[i].GetPrevPoint( pt) ; + int nPoints = vPL3d[i].GetPointNbr() - 1 ; + for ( int j = 0 ; j < nPoints ; ++j ) { + if ( AreSamePointApprox( vPnt[nCurrPoint + j], pt)) { + rotate( vPnt2d.begin() + nCurrPoint, vPnt2d.begin() + nCurrPoint + nPoints - j - 1, vPnt2d.begin() + nCurrPoint + nPoints) ; + vPnt2d.insert( vPnt2d.begin() + nCurrPoint + nPoints, vPnt2d[nCurrPoint]) ; + break ; + } + } + } nCurrPoint += nPoints ; } } + if ( bTriangulatedIn3D) { + vPnt3d = vPnt ; + vPnt = vPnt2d ; + } //controllo che i due vettori vPnt e vPnt3d abbiano la stessa lunghezza, sennò vuol dire che nel vettore vPnt3d ho avuto dei Rejected e devo ricalcolarli // i punti in eccesso verranno poi scartati dalla trimesh diff --git a/Tree.cpp b/Tree.cpp index 9a4b186..3fe6235 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1643,7 +1643,10 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, bool bForTriangulation, POLYLINEM break ; } // ora analizzo anche i loop che sono contenuti nella cella - CreateIslandAndHoles( i, vvPolygons, vvPolygons3d, nPoly, vnParentChunk, bForTriangulation) ; + if( bForTriangulation) + CreateIslandAndHoles( i, vvPolygons, vvPolygons3d, nPoly, vnParentChunk, bForTriangulation, vPolygonsCorrected[i], vPolygonsBasic3d[i]) ; + else + CreateIslandAndHoles( i, vvPolygons, vvPolygons3d, nPoly, vnParentChunk, bForTriangulation, vPolygonsBasic[i], vPolygonsBasic3d[i]) ; } } return true ; @@ -3073,6 +3076,14 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX bool bNotCameBack = true ; bool bValidNextStart = false ; bool bAtNextStart = false ; + int nEdgeWithVertexSkipped ; + switch ( nVertToErase) { + case 0 : nEdgeWithVertexSkipped = 2 ; break ; + case 1 : nEdgeWithVertexSkipped = 3 ; break ; + case 2 : nEdgeWithVertexSkipped = 0 ; break ; + case 3 : nEdgeWithVertexSkipped = 1 ; break ; + default : nEdgeWithVertexSkipped = -1 ; break ; + } if ( w < nPassToCheck - 1) { int nSecondCheck = 0 ; int nNext ; @@ -3118,7 +3129,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX // se ho trovato un altro loop salto all'inizio del for, dopo aver aggiunto eventuali punti intermedi if ( bValidNextStart) { - for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { + for ( int p = nEdge == nEdgeWithVertexSkipped ? 0 : 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], m_mTree[nId].m_vInters[vToCheckNow[nNext]].vpt[0])) { plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ; @@ -3133,7 +3144,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX Point3d ptStart ; plTrimmedPoly.GetFirstPoint( ptStart) ; Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ; - for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { + for ( int p = nEdge == nEdgeWithVertexSkipped ? 0 : 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart) && CheckIfBefore( nEdge, ptLast, vEdgeVertex[nEdge][p])) { plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ; @@ -3169,7 +3180,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; } Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ; - for ( int p = 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { + for ( int p = nEdge == nEdgeWithVertexSkipped ? 0 : 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], ptStart) && CheckIfBefore( nEdge, ptLast, vEdgeVertex[nEdge][p])) { plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ; @@ -3219,7 +3230,8 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX //---------------------------------------------------------------------------- bool -Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk, bool bForTriangulation) +Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, int& nPoly, INTVECTOR& vnParentChunk, bool bForTriangulation, + const PolyLine& plPolygonsBasic, const PolyLine& plPolygonsBasic3d) { // vettore dei poligoni ( loop) della cella nId POLYLINEVECTOR vCellPolygons ; @@ -4084,7 +4096,9 @@ Tree::CheckIfBefore( int nEdgeA, int nEdgeB) const if ( nEdgeB == 0 || nEdgeB == 4) return true ; break ; + default : return false ; } + return false ; } //---------------------------------------------------------------------------- diff --git a/Tree.h b/Tree.h index 20d6e2f..fd8b8a1 100644 --- a/Tree.h +++ b/Tree.h @@ -278,7 +278,8 @@ class Tree bool FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim // resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni. - bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk, bool bForTriangulation) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella + bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk, bool bForTriangulation, + const PolyLine& plPolygonsBasic, const PolyLine& plPolygonsBasic3d) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella bool CheckIfBefore( const PolyLine& pl, int nEdge) const ; // controllo se ptEnd è prima di ptStart sul lato nEdge rispetto al senso antiorario bool CheckIfBefore( const Inters& inA) const ; // controlla se l'ingresso è prima dell'uscita in senso antiorario a partire da ptTR. bool CheckIfBefore( int nEdge1, const Point3d& ptP1, int nEdge2, const Point3d& ptP2) const ; // verifico quale punto viene prima tra pt1 e pt2 a partire da ptTR girando in senso CCW (punto 1 su edge 1 e punto 2 su edge 2, rispetto al lato 3) From 1b13580340b151c77141639f67ae88ccae815955 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 29 Jul 2024 17:32:04 +0200 Subject: [PATCH 12/16] EgtGeomKernel : - correzioni alla triangolazione con le bezier. --- SurfBezier.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 9d3b536..003195c 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1609,8 +1609,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const PNTVECTOR vPnt2d ; if ( bTriangulationFailedIn2D || (bMismatch2D3D && vPnt.size() != nTotPnt)) { PNTVECTOR vPntBackup ; - if( ! bTriangulationFailedIn2D && bMismatch2D3D) - vPntBackup = vPnt ; + vPntBackup = vPnt ; if ( ! Tri.Make( vPL3d, vPnt, vTria)) return nullptr ; bool bTriangulationSucceded = ( vPnt.size() - 2 ) == ( vTria.size() ) / 3 ; @@ -1620,7 +1619,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const else LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) is the same as the previous one") } - if( bMismatch2D3D && ! bTriangulationSucceded) + if( ! bTriangulationSucceded) vPnt = vPntBackup ; else if( bTriangulationSucceded) { bTriangulatedIn3D = true ; From f46db233dc9e57e095b71fa6b36fd0918b033424 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 30 Jul 2024 16:23:35 +0200 Subject: [PATCH 13/16] EgtGeomKernel : - ottimizzazione della triangolazione bezier. --- SurfBezier.cpp | 167 +++++++++++++++++++++++++++++++------------------ SurfBezier.h | 1 + Tree.cpp | 114 ++++++++++++++++----------------- 3 files changed, 165 insertions(+), 117 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 003195c..d9c6b61 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1607,9 +1607,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const bool bMismatch2D3D = vPnt.size() != vPnt3d.size() ; bool bTriangulatedIn3D = false ; PNTVECTOR vPnt2d ; - if ( bTriangulationFailedIn2D || (bMismatch2D3D && vPnt.size() != nTotPnt)) { - PNTVECTOR vPntBackup ; - vPntBackup = vPnt ; + if ( bTriangulationFailedIn2D) { if ( ! Tri.Make( vPL3d, vPnt, vTria)) return nullptr ; bool bTriangulationSucceded = ( vPnt.size() - 2 ) == ( vTria.size() ) / 3 ; @@ -1619,10 +1617,17 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const else LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) is the same as the previous one") } - if( ! bTriangulationSucceded) - vPnt = vPntBackup ; - else if( bTriangulationSucceded) { + if( bTriangulationSucceded) { bTriangulatedIn3D = true ; + // calcolo la normale della polyline per flippare eventualmente i triangoli se hanno la normale sbagliata + PolyLine& pl3d = vPL3d[0] ; + Plane3d plPlane ; double dArea = 0 ; + pl3d.IsClosedAndFlat( plPlane, dArea) ; + Vector3d vtN = plPlane.GetVersN() ; + Triangle3d tria ; + tria.Set( vPnt[vTria[0]], vPnt[vTria[1]], vPnt[vTria[2]]) ; + if( tria.GetN() * vtN < 0) + reverse( vTria.begin(), vTria.end()) ; for( int i = 0 ; i < int( vPL.size()) ; ++i) { PolyLine& pl = vPL[i] ; Point3d pt ; pl.GetFirstPoint( pt) ; @@ -1634,67 +1639,25 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const } } - // controllo se devo riordinare il vettore dei punti - // se le polyline sono state invertite o ne è stato cambiato il punto di start - int nCurrPoint = 0 ; - for( int i = 0 ; i < int( vPL.size()) ; ++i) { - if( ! bTriangulatedIn3D) { - Point3d pt ; vPL[i].GetFirstPoint( pt) ; - vPL[i].GetNextPoint( pt) ; - int nPoints = vPL[i].GetPointNbr() - 2 ; - if ( AreSamePointApprox( vPnt[nCurrPoint], pt)) - continue ; - else if ( AreSamePointApprox( vPnt[nCurrPoint + nPoints], pt)) - reverse( vPnt3d.begin() + nCurrPoint, vPnt3d.begin() + nCurrPoint + nPoints) ; - else { - // se la polyline non è stata semplicemente invertita allora vuol dire che ne è stato cambiato lo start point - // in questo caso il punto di chiusura non è stato eliminato - nPoints += 2 ; - vPL[i].GetPrevPoint( pt) ; - int nPoints = vPL[i].GetPointNbr() - 1 ; - for ( int j = 0 ; j < nPoints ; ++j ) { - if ( AreSamePointApprox( vPnt[nCurrPoint + j], pt)) { - rotate( vPnt3d.begin() + nCurrPoint, vPnt3d.begin() + nCurrPoint + nPoints - j - 1, vPnt3d.begin() + nCurrPoint + nPoints) ; - vPnt3d.insert( vPnt3d.begin() + nCurrPoint + nPoints, vPnt3d[nCurrPoint]) ; - break ; - } - } - } - nCurrPoint += nPoints ; + // riordino il vettore dei punti su cui non ho fatto la triangolazione + if( int(vPL.size()) > 1 || bTriangulatedIn3D) { + //if( vPnt.size() != vPnt3d.size()) + // return nullptr ; + PNTVECTOR vPntOrd ; + if( bTriangulatedIn3D) { + ReorderPntVector( vPL3d, true, vPnt, vPL, vPntOrd) ; + vPnt3d = vPnt ; + vPnt = vPntOrd ; } else { - Point3d pt ; vPL3d[i].GetFirstPoint( pt) ; - vPL3d[i].GetNextPoint( pt) ; - int nPoints = vPL3d[i].GetPointNbr() - 2 ; - if ( AreSamePointApprox( vPnt[nCurrPoint], pt)) - continue ; - else if ( AreSamePointApprox( vPnt[nCurrPoint + nPoints], pt)) - reverse( vPnt2d.begin() + nCurrPoint, vPnt2d.begin() + nCurrPoint + nPoints) ; - else { - // se la polyline non è stata semplicemente invertita allora vuol dire che ne è stato cambiato lo start point - // in questo caso il punto di chiusura non è stato eliminato - nPoints += 2 ; - vPL3d[i].GetPrevPoint( pt) ; - int nPoints = vPL3d[i].GetPointNbr() - 1 ; - for ( int j = 0 ; j < nPoints ; ++j ) { - if ( AreSamePointApprox( vPnt[nCurrPoint + j], pt)) { - rotate( vPnt2d.begin() + nCurrPoint, vPnt2d.begin() + nCurrPoint + nPoints - j - 1, vPnt2d.begin() + nCurrPoint + nPoints) ; - vPnt2d.insert( vPnt2d.begin() + nCurrPoint + nPoints, vPnt2d[nCurrPoint]) ; - break ; - } - } - } - nCurrPoint += nPoints ; + ReorderPntVector( vPL, false, vPnt, vPL3d, vPntOrd) ; + vPnt3d = vPntOrd ; } } - if ( bTriangulatedIn3D) { - vPnt3d = vPnt ; - vPnt = vPnt2d ; - } //controllo che i due vettori vPnt e vPnt3d abbiano la stessa lunghezza, sennò vuol dire che nel vettore vPnt3d ho avuto dei Rejected e devo ricalcolarli // i punti in eccesso verranno poi scartati dalla trimesh - if( vPnt.size() != vPnt3d.size() && ! bTriangulatedIn3D) { + if( vPnt.size() != vPnt3d.size()) { vPnt3d.clear() ; for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) { Point3d pt3d ; @@ -1722,6 +1685,90 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const return GetBasicSurfTriMesh( stmSoup.GetSurf()) ; } +//---------------------------------------------------------------------------- +bool +SurfBezier::ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const +{ + int nCurrPoint = 0 ; + BOOLVECTOR vbPolyChecked( vPL.size()) ; + fill( vbPolyChecked.begin(), vbPolyChecked.end(), false) ; + for ( int p = 0 ; p < int(vPnt.size()) ; ++p) { + Point3d pt = vPnt[p] ; + int nInd = 0 ; + int nPoly = 0 ; + int nPoints = 0 ; + bool bInverted = false ; + for ( int poly = 0 ; poly < int( vPL.size()) ; ++poly ) { + if( vbPolyChecked[poly]) + continue ; + PolyLine pl = vPL[poly] ; + nInd = 0 ; + Point3d ptPoly ; pl.GetFirstPoint( ptPoly) ; + bool bFound = false ; + if( AreSamePointStepApprox( pt, ptPoly)){ + nPoints = pl.GetPointNbr() ; + nPoly = poly ; + bFound = true ; + pl.GetNextPoint( ptPoly) ; + if( ! AreSamePointStepApprox( vPnt[p+1], ptPoly)) + bInverted = true ; + break ; + } + while ( pl.GetNextPoint( ptPoly) && ! bFound) { + ++ nInd ; + if( AreSamePointStepApprox( pt, ptPoly)) { + nPoints = pl.GetPointNbr() ; + nPoly = poly ; + bFound = true ; + pl.GetNextPoint( ptPoly) ; + if( ! AreSamePointStepApprox( vPnt[p+1], ptPoly)) + bInverted = true ; + break ; + } + } + if( bFound) + break ; + } + if( nInd == 0) { + Point3d ptPoly ; + vPLToOrd[nPoly].GetFirstPoint( ptPoly) ; + vPntOrd.push_back( ptPoly) ; + while ( vPLToOrd[nPoly].GetNextPoint( ptPoly)) + vPntOrd.push_back( ptPoly) ; + } + else if ( nInd == nPoints - 1 ) { + Point3d ptPoly ; + vPLToOrd[nPoly].GetLastPoint( ptPoly) ; + vPntOrd.push_back( ptPoly) ; + while ( vPLToOrd[nPoly].GetPrevPoint( ptPoly)) + vPntOrd.push_back( ptPoly) ; + } + else { + PNTVECTOR vPntToRotate ; + Point3d ptPoly ; + if( ! bInverted) { + vPLToOrd[nPoly].GetFirstPoint( ptPoly) ; + vPntToRotate.push_back( ptPoly) ; + while ( vPLToOrd[nPoly].GetNextPoint( ptPoly)) + vPntToRotate.push_back( ptPoly) ; + } + else { + vPLToOrd[nPoly].GetLastPoint( ptPoly) ; + vPntToRotate.push_back( ptPoly) ; + while ( vPLToOrd[nPoly].GetPrevPoint( ptPoly)) + vPntToRotate.push_back( ptPoly) ; + } + vPntToRotate.pop_back() ; + rotate( vPntToRotate.begin(), vPntToRotate.begin() + nInd, vPntToRotate.end()) ; + vPntToRotate.push_back( vPntToRotate[0]) ; + vPntOrd.insert( vPntOrd.end(), vPntToRotate.begin(), vPntToRotate.end()) ; + } + vbPolyChecked[nPoly] = true ; + p += nPoints - 1; + } + return true ; +} + //---------------------------------------------------------------------------- bool SurfBezier::GetLeaves( vector>& vLeaves) const diff --git a/SurfBezier.h b/SurfBezier.h index 9285813..32fc6e2 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -203,6 +203,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW // funzione che calcola se gli edge sono collassati in poli bool CalcPoles( void) const ; bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ; + bool ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto diff --git a/Tree.cpp b/Tree.cpp index 3fe6235..0273ea6 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -206,8 +206,8 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi // creo la cella Root Point3d ptTop( nSpanU * SBZ_TREG_COEFF, nSpanV * SBZ_TREG_COEFF) ; bool bLimited = false ; - if ( ! AreSamePointExact( ptMax,ORIG)) { - if ( ! AreSamePointExact( ptMax,ptTop)) + if ( ! AreSamePointXYExact( ptMax,ORIG)) { + if ( ! AreSamePointXYExact( ptMax,ptTop)) ptTop = ptMax ; bLimited = true ; } @@ -455,7 +455,7 @@ AddOrMergeBBox( const BBox3d& bBox3dA, vector& vBBox, bool bAdd = true, BBox3d bBox3dB = vBBox[b] ; BBox3d b3Int ; // se sono celle diverse e ho un'intersezione faccio il merge - if ( ! ( AreSamePointExact( ptMin, bBox3dB.GetMin()) && AreSamePointExact( ptMax, bBox3dB.GetMax())) && + if ( ! ( AreSamePointXYExact( ptMin, bBox3dB.GetMin()) && AreSamePointXYExact( ptMax, bBox3dB.GetMax())) && bBox3dA.FindIntersectionXY( bBox3dB, b3Int)) { vBBox[b].Add( bBox3dA) ; if ( ! bAdd ) { @@ -500,7 +500,7 @@ Tree::GetIndependentTrees( BIPNTVECTOR& vTrees) Point3d ptTR( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF) ; for ( int i = 0 ; i < int( vBBox.size()) ; ++ i) { BBox3d& bBox3d = vBBox[i] ; - if ( AreSamePointEpsilon( bBox3d.GetMin(), ORIG, 10) && AreSamePointEpsilon( bBox3d.GetMax(), ptTR, 10)) { + if ( AreSamePointXYEpsilon( bBox3d.GetMin(), ORIG, 10) && AreSamePointXYEpsilon( bBox3d.GetMax(), ptTR, 10)) { bIsRoot = true ; break ; } @@ -2318,7 +2318,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) UpdateSplitLoop( plLoopSplit, nPtLoopSplit, vptInters.back()) ; } // controllo di aggiungere un punto abbastanza distante dal precedente - if( ! AreSamePointEpsilon( vptInters.back(), ptCurr, 10 * EPS_SMALL)) { + if( ! AreSamePointXYEpsilon( vptInters.back(), ptCurr, 10 * EPS_SMALL)) { // aggiungo la fine del segmento nel vettore delle intersezioni vptInters.push_back( ptCurr) ; // aggiorno la polyline splittata @@ -2586,7 +2586,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, else if ( nEdge == 7) ptInters = ptTR ; // aggiungo il nuovo punto al vettore delle intersezioni - if ( (int)vptInters.size() == 0 || ! AreSamePointEpsilon( ptInters , vptInters.back(), 10 * EPS_SMALL)) + if ( (int)vptInters.size() == 0 || ! AreSamePointXYEpsilon( ptInters , vptInters.back(), 10 * EPS_SMALL)) vptInters.push_back( ptInters) ; else { // se l'ultimo punto del vettore delle intersezioni è quasi uguale al punto che devo aggiungere allora lo sostituisco con quest'ultimo @@ -2624,9 +2624,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; if ( ptInters.x > m_mTree[nId].GetBottomLeft().x + EPS_SMALL && ptInters.x < m_mTree[nId].GetTopRight().x - EPS_SMALL) m_mTree[nId].m_vInters.back().nIn = 2 ; - else if ( AreSamePointApprox( ptInters, m_mTree[nId].GetBottomLeft())) + else if ( AreSamePointXYApprox( ptInters, m_mTree[nId].GetBottomLeft())) m_mTree[nId].m_vInters.back().nIn = 5 ; - else if ( AreSamePointApprox( ptInters, ptBr)) + else if ( AreSamePointXYApprox( ptInters, ptBr)) m_mTree[nId].m_vInters.back().nIn = 6 ; else m_mTree[nId].m_vInters.back().nIn = 2 ; @@ -2644,9 +2644,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; if ( ptInters.y > m_mTree[nId].GetBottomLeft().y + EPS_SMALL && ptInters.y < m_mTree[nId].GetTopRight().y - EPS_SMALL) m_mTree[nId].m_vInters.back().nIn = 3 ; - else if ( AreSamePointApprox( ptInters, ptBr)) + else if ( AreSamePointXYApprox( ptInters, ptBr)) m_mTree[nId].m_vInters.back().nIn = 6 ; - else if ( AreSamePointApprox( ptInters, m_mTree[nId].GetTopRight())) + else if ( AreSamePointXYApprox( ptInters, m_mTree[nId].GetTopRight())) m_mTree[nId].m_vInters.back().nIn = 7 ; else m_mTree[nId].m_vInters.back().nIn = 3 ; @@ -2663,9 +2663,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; if ( ptInters.x > m_mTree[nId].GetBottomLeft().x + EPS_SMALL && ptInters.x < m_mTree[nId].GetTopRight().x - EPS_SMALL) m_mTree[nId].m_vInters.back().nIn = 0 ; - else if ( AreSamePointApprox( ptInters, ptTl)) + else if ( AreSamePointXYApprox( ptInters, ptTl)) m_mTree[nId].m_vInters.back().nIn = 4 ; - else if ( AreSamePointApprox( ptInters, m_mTree[nId].GetTopRight())) + else if ( AreSamePointXYApprox( ptInters, m_mTree[nId].GetTopRight())) m_mTree[nId].m_vInters.back().nIn = 7 ; else m_mTree[nId].m_vInters.back().nIn = 0 ; @@ -2682,9 +2682,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; if ( ptInters.y > m_mTree[nId].GetBottomLeft().y + EPS_SMALL && ptInters.y < m_mTree[nId].GetTopRight().y - EPS_SMALL) m_mTree[nId].m_vInters.back().nIn = 1 ; - else if ( AreSamePointApprox( ptInters, m_mTree[nId].GetBottomLeft())) + else if ( AreSamePointXYApprox( ptInters, m_mTree[nId].GetBottomLeft())) m_mTree[nId].m_vInters.back().nIn = 5 ; - else if ( AreSamePointApprox( ptInters, ptTl)) + else if ( AreSamePointXYApprox( ptInters, ptTl)) m_mTree[nId].m_vInters.back().nIn = 4 ; else m_mTree[nId].m_vInters.back().nIn = 1 ; @@ -2702,9 +2702,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, m_mTree[nId].m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - if ( AreSamePointExact( ptInters, ptBr)) + if ( AreSamePointXYExact( ptInters, ptBr)) m_mTree[nId].m_vInters.back().nIn = 6 ; - else if ( AreSamePointExact( ptInters, m_mTree[nId].GetBottomLeft())) + else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetBottomLeft())) m_mTree[nId].m_vInters.back().nIn = 5 ; else m_mTree[nId].m_vInters.back().nIn = 2 ; @@ -2715,9 +2715,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, m_mTree[nId].m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - if ( AreSamePointExact( ptInters, ptBr)) + if ( AreSamePointXYExact( ptInters, ptBr)) m_mTree[nId].m_vInters.back().nIn = 6 ; - else if ( AreSamePointExact( ptInters, m_mTree[nId].GetTopRight())) + else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetTopRight())) m_mTree[nId].m_vInters.back().nIn = 7 ; else m_mTree[nId].m_vInters.back().nIn = 3 ; @@ -2753,9 +2753,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, m_mTree[nId].m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - if ( AreSamePointExact( ptInters, ptBr)) + if ( AreSamePointXYExact( ptInters, ptBr)) m_mTree[nId].m_vInters.back().nIn = 6 ; - else if ( AreSamePointExact( ptInters, m_mTree[nId].GetTopRight())) + else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetTopRight())) m_mTree[nId].m_vInters.back().nIn = 7 ; else m_mTree[nId].m_vInters.back().nIn = 3 ; @@ -2766,9 +2766,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, m_mTree[nId].m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - if ( AreSamePointExact( ptInters, ptTl)) + if ( AreSamePointXYExact( ptInters, ptTl)) m_mTree[nId].m_vInters.back().nIn = 4 ; - else if ( AreSamePointExact( ptInters, m_mTree[nId].GetTopRight())) + else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetTopRight())) m_mTree[nId].m_vInters.back().nIn = 7 ; else m_mTree[nId].m_vInters.back().nIn = 0 ; @@ -2804,9 +2804,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, m_mTree[nId].m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - if ( AreSamePointExact( ptInters, ptTl)) + if ( AreSamePointXYExact( ptInters, ptTl)) m_mTree[nId].m_vInters.back().nIn = 4 ; - else if ( AreSamePointExact( ptInters, m_mTree[nId].GetTopRight())) + else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetTopRight())) m_mTree[nId].m_vInters.back().nIn = 7 ; else m_mTree[nId].m_vInters.back().nIn = 0 ; @@ -2817,9 +2817,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, m_mTree[nId].m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - if ( AreSamePointExact( ptInters, ptTl)) + if ( AreSamePointXYExact( ptInters, ptTl)) m_mTree[nId].m_vInters.back().nIn = 4 ; - else if ( AreSamePointExact( ptInters, m_mTree[nId].GetBottomLeft())) + else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetBottomLeft())) m_mTree[nId].m_vInters.back().nIn = 5 ; else m_mTree[nId].m_vInters.back().nIn = 1 ; @@ -2855,9 +2855,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, m_mTree[nId].m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - if ( AreSamePointExact( ptInters, ptTl)) + if ( AreSamePointXYExact( ptInters, ptTl)) m_mTree[nId].m_vInters.back().nIn = 4 ; - else if ( AreSamePointExact( ptInters, m_mTree[nId].GetBottomLeft())) + else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetBottomLeft())) m_mTree[nId].m_vInters.back().nIn = 5 ; else m_mTree[nId].m_vInters.back().nIn = 1 ; @@ -2868,9 +2868,9 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, m_mTree[nId].m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - if ( AreSamePointExact( ptInters, ptBr)) + if ( AreSamePointXYExact( ptInters, ptBr)) m_mTree[nId].m_vInters.back().nIn = 6 ; - else if ( AreSamePointExact( ptInters, m_mTree[nId].GetBottomLeft())) + else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetBottomLeft())) m_mTree[nId].m_vInters.back().nIn = 5 ; else m_mTree[nId].m_vInters.back().nIn = 2 ; @@ -2956,12 +2956,12 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX case 3 : ptNextVert = ptBr ; break ; } if ( ! bForTriangulation) { - while ( plCell.GetNextPoint( ptToAdd) && ! AreSamePointExact( ptToAdd, ptNextVert)) + while ( plCell.GetNextPoint( ptToAdd) && ! AreSamePointXYExact( ptToAdd, ptNextVert)) vEdgeVertex[j].push_back( ptToAdd) ; } else { double dPar = 0 ; - while ( plCell.GetNextUPoint( &dPar, &ptToAdd) && ! AreSamePointExact( ptToAdd, ptNextVert)) { + while ( plCell.GetNextUPoint( &dPar, &ptToAdd) && ! AreSamePointXYExact( ptToAdd, ptNextVert)) { vEdgeVertex[j].push_back( ptToAdd) ; if ( dPar > 0) plCell3d.GetNextPoint( pt3d) ; @@ -3528,10 +3528,10 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe // se è il primo punto della PolyLine lo aggiungo if ( plTrimmedPoly.GetPointNbr() == 0) { // se cerco di aggiungere il vertice che devo saltare, non faccio nulla - if( ( nVertToSkip == 0 && AreSamePointApprox( ptToAdd, ptBL)) || - ( nVertToSkip == 1 && AreSamePointApprox( ptToAdd, ptBr)) || - ( nVertToSkip == 2 && AreSamePointApprox( ptToAdd, ptTR)) || - ( nVertToSkip == 3 && AreSamePointApprox( ptToAdd, ptTl))) { + if( ( nVertToSkip == 0 && AreSamePointXYApprox( ptToAdd, ptBL)) || + ( nVertToSkip == 1 && AreSamePointXYApprox( ptToAdd, ptBr)) || + ( nVertToSkip == 2 && AreSamePointXYApprox( ptToAdd, ptTR)) || + ( nVertToSkip == 3 && AreSamePointXYApprox( ptToAdd, ptTl))) { // aggiorno l'ultimo punto aggiunto ptLast.Set( ptToAdd.x, ptToAdd.y, 0) ; return true ; @@ -3553,7 +3553,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe // verifico di essere allineato con un lato, sennò aggiungo e basta Vector3d vDir ; - if ( ! AreSamePointApprox( ptToAdd, ptLast)) + if ( ! AreSamePointXYApprox( ptToAdd, ptLast)) vDir = ptToAdd - ptLast ; else return false ; @@ -3563,19 +3563,19 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe plTrimmedPoly3d.EraseLastUPoint() ; Point3d ptVert ; int nVert = -1 ; - if ( AreSamePointApprox( ptToAdd, ptBr)){ + if ( AreSamePointXYApprox( ptToAdd, ptBr)){ ptVert = ptBr ; nVert = 1 ; } - else if ( AreSamePointApprox( ptToAdd, ptTR)) { + else if ( AreSamePointXYApprox( ptToAdd, ptTR)) { ptVert = ptTR ; nVert = 2 ; } - else if ( AreSamePointApprox( ptToAdd, ptTl)) { + else if ( AreSamePointXYApprox( ptToAdd, ptTl)) { ptVert = ptTl ; nVert = 3 ; } - else if ( AreSamePointApprox( ptToAdd, ptBL)) { + else if ( AreSamePointXYApprox( ptToAdd, ptBL)) { ptVert = ptBL ; nVert = 0 ; } @@ -3610,7 +3610,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ++ c ; } } - bool bVert = AreSamePointApprox( ptToAdd, ptTl) ; + bool bVert = AreSamePointXYApprox( ptToAdd, ptTl) ; if ( ! ( nVertToSkip == 3 && bVert)) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; if( bForTriangulation){ @@ -3635,7 +3635,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ++ c ; } } - bool bVert = AreSamePointApprox( ptToAdd, ptBL) ; + bool bVert = AreSamePointXYApprox( ptToAdd, ptBL) ; if ( ! ( nVertToSkip == 0 && bVert)) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; if( bForTriangulation) { @@ -3660,7 +3660,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ++ c ; } } - bool bVert = AreSamePointApprox( ptToAdd, ptBr) ; + bool bVert = AreSamePointXYApprox( ptToAdd, ptBr) ; if ( ! ( nVertToSkip == 1 && bVert)) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; if( bForTriangulation){ @@ -3685,7 +3685,7 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe ++ c ; } } - bool bVert = AreSamePointApprox( ptToAdd, ptTR) ; + bool bVert = AreSamePointXYApprox( ptToAdd, ptTR) ; if ( ! ( nVertToSkip == 2 && bVert)) { plTrimmedPoly.AddUPoint( c, ptToAdd) ; if( bForTriangulation) { @@ -4123,13 +4123,13 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const Point3d ptTl ( ptBL.x, ptTR.y) ; Point3d ptBr ( ptTR.x, ptBL.y) ; - if ( AreSamePointApprox( ptToAssign, ptTR)) + if ( AreSamePointXYApprox( ptToAssign, ptTR)) nEdge = 7 ; - else if ( AreSamePointApprox( ptToAssign, ptTl)) + else if ( AreSamePointXYApprox( ptToAssign, ptTl)) nEdge = 4 ; - else if ( AreSamePointApprox( ptToAssign, ptBL)) + else if ( AreSamePointXYApprox( ptToAssign, ptBL)) nEdge = 5 ; - else if ( AreSamePointApprox( ptToAssign, ptBr)) + else if ( AreSamePointXYApprox( ptToAssign, ptBr)) nEdge = 6 ; else if ( ptToAssign.x > ptBL.x && ptToAssign.x < ptTR.x && abs( ptToAssign.y - ptTR.y) < EPS_SMALL) nEdge = 0 ; @@ -4189,13 +4189,13 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) Point3d pt3d ; // a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato if ( i == 0) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) { + while ( ! AreSamePointXYApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) { continue ; } mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[2]) ; ++ nPtCount ; // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft())) { + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointXYApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft())) { m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; @@ -4204,13 +4204,13 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) ++ nPtCount ; } else if ( i == 1 ) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) { + while ( ! AreSamePointXYApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) { continue ; } mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[3]) ; ++ nPtCount ; // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) { + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointXYApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) { m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; @@ -4219,13 +4219,13 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) ++ nPtCount ; } else if ( i == 2) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) { + while ( ! AreSamePointXYApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) { continue ; } mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[0]) ; ++ nPtCount ; // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) { + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointXYApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) { m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; @@ -4234,13 +4234,13 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) ++ nPtCount ; } else if ( i == 3) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) { + while ( ! AreSamePointXYApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) { continue ; } mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[1]) ; ++ nPtCount ; // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) { + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointXYApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) { m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; From ddffbd2c88fa8a2b8ed6378db4e03de793166bea Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 31 Jul 2024 17:43:18 +0200 Subject: [PATCH 14/16] EgtGeomKernel : - correzioni e migliorie alla triangolazione delle bezier. --- SurfBezier.cpp | 97 ++++++++++++++++++++++++++++++++++++++++---------- SurfBezier.h | 1 + 2 files changed, 80 insertions(+), 18 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index d9c6b61..39265ce 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -40,6 +40,7 @@ #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkIntervals.h" #include "/EgtDev/Extern/Eigen/Dense" +#include "EgtDev/Include/EGkGeoObjSave.h" using namespace std ; @@ -1590,7 +1591,8 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const for( int i = 0 ; i < int( vPL3d.size()) ; ++i) { PolyLine& pl3d = vPL3d[i] ; Point3d pt3d ; pl3d.GetFirstPoint( pt3d) ; - //vPnt3d.push_back( pt3d) ; + if( vPL3d.size() > 1) + vPnt3d.push_back( pt3d) ; while ( pl3d.GetNextPoint( pt3d)) { vPnt3d.push_back( pt3d) ; } @@ -1603,14 +1605,16 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const // se ho ottenuto meno triangoli di quelli che avrei dovuto avere allora potrei aver avuto un problema in prossimità di un polo // se comunque ho corrispondenza tra vPnt e vPnt3d allora eseguo la trinagolazione in 3d - bool bTriangulationFailedIn2D = ( vPnt.size() - 2) != ( vTria.size()) / 3 ; - bool bMismatch2D3D = vPnt.size() != vPnt3d.size() ; + int nTriaNumber = ( vPnt.size() - 2) + (2 * (vPL.size() - 1)) - (vPL.size() > 2 ? vPL.size() - 2 : 0) - (vPL.size() != 1 ? vPL.size() : 0) ; + bool bTriangulationFailedIn2D = nTriaNumber != ( vTria.size()) / 3 ; + //bool bMismatch2D3D = vPnt.size() != vPnt3d.size() ; bool bTriangulatedIn3D = false ; - PNTVECTOR vPnt2d ; if ( bTriangulationFailedIn2D) { + PNTVECTOR vPntBackup = vPnt ; + INTVECTOR vTriaBackup = vTria ; if ( ! Tri.Make( vPL3d, vPnt, vTria)) return nullptr ; - bool bTriangulationSucceded = ( vPnt.size() - 2 ) == ( vTria.size() ) / 3 ; + bool bTriangulationSucceded = ( vPnt.size() - 2) + (2 * (vPL.size() - 1)) - (vPL.size() > 2 ? vPL.size() - 2 : 0) - (vPL.size() != 1 ? vPL.size() : 0) == ( vTria.size() ) / 3 ; if( bTriangulationFailedIn2D) { if ( bTriangulationSucceded) LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) RESOLVED") @@ -1628,19 +1632,15 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const tria.Set( vPnt[vTria[0]], vPnt[vTria[1]], vPnt[vTria[2]]) ; if( tria.GetN() * vtN < 0) reverse( vTria.begin(), vTria.end()) ; - for( int i = 0 ; i < int( vPL.size()) ; ++i) { - PolyLine& pl = vPL[i] ; - Point3d pt ; pl.GetFirstPoint( pt) ; - //vPnt2D.push_back( pt) ; - while ( pl.GetNextPoint( pt)) { - vPnt2d.push_back( pt) ; - } - } + } + else { + vPnt = vPntBackup ; + vTria = vTriaBackup ; } } // riordino il vettore dei punti su cui non ho fatto la triangolazione - if( int(vPL.size()) > 1 || bTriangulatedIn3D) { + if( int(vPL.size()) == 2) { //if( vPnt.size() != vPnt3d.size()) // return nullptr ; PNTVECTOR vPntOrd ; @@ -1654,6 +1654,27 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const vPnt3d = vPntOrd ; } } + else if ( bTriangulatedIn3D) { + if( vPL.size() == 1) { + vPnt3d = vPnt ; + PNTVECTOR vPnt2d ; + for( int i = 0 ; i < int( vPL.size()) ; ++i) { + PolyLine& pl = vPL[i] ; + Point3d pt ; pl.GetFirstPoint( pt) ; + //vPnt2D.push_back( pt) ; + while ( pl.GetNextPoint( pt)) { + vPnt2d.push_back( pt) ; + } + } + vPnt = vPnt2d ; + } + else { + PNTVECTOR vPntOrd ; + ReorderPntEnhancedVector( vPL3d, true, vPnt, vPL, vPntOrd) ; + vPnt3d = vPnt ; + vPnt = vPntOrd ; + } + } //controllo che i due vettori vPnt e vPnt3d abbiano la stessa lunghezza, sennò vuol dire che nel vettore vPnt3d ho avuto dei Rejected e devo ricalcolarli // i punti in eccesso verranno poi scartati dalla trimesh @@ -1705,23 +1726,23 @@ SurfBezier::ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, nInd = 0 ; Point3d ptPoly ; pl.GetFirstPoint( ptPoly) ; bool bFound = false ; - if( AreSamePointStepApprox( pt, ptPoly)){ + if( AreSamePointStepExact( pt, ptPoly)){ nPoints = pl.GetPointNbr() ; nPoly = poly ; bFound = true ; pl.GetNextPoint( ptPoly) ; - if( ! AreSamePointStepApprox( vPnt[p+1], ptPoly)) + if( ! AreSamePointStepExact( vPnt[p+1], ptPoly)) bInverted = true ; break ; } while ( pl.GetNextPoint( ptPoly) && ! bFound) { ++ nInd ; - if( AreSamePointStepApprox( pt, ptPoly)) { + if( AreSamePointStepExact( pt, ptPoly)) { nPoints = pl.GetPointNbr() ; nPoly = poly ; bFound = true ; pl.GetNextPoint( ptPoly) ; - if( ! AreSamePointStepApprox( vPnt[p+1], ptPoly)) + if( ! AreSamePointStepExact( vPnt[p+1], ptPoly)) bInverted = true ; break ; } @@ -1769,6 +1790,46 @@ SurfBezier::ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, return true ; } +//---------------------------------------------------------------------------- +bool +SurfBezier::ReorderPntEnhancedVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const +{ + vPntOrd.clear() ; + // costruisco il vettore dei punti da ordinare + PNTVECTOR vPntPolyToOrd ; + for ( int i = 0 ; i < int( vPLToOrd.size()) ; ++i) { + Point3d pt ; vPLToOrd[i].GetFirstPoint( pt) ; + vPntPolyToOrd.push_back( pt) ; + while( vPLToOrd[i].GetNextPoint( pt)) + vPntPolyToOrd.push_back( pt) ; + } + // costruisco il vettore con i punti delle polyline in ordine + PNTVECTOR vPntPoly ; + for ( int i = 0 ; i < int( vPL.size()) ; ++i) { + Point3d pt ; vPL[i].GetFirstPoint( pt) ; + vPntPoly.push_back( pt) ; + while( vPL[i].GetNextPoint( pt)) + vPntPoly.push_back( pt) ; + } + BOOLVECTOR vbPntChecked( vPnt.size()) ; + fill( vbPntChecked.begin(), vbPntChecked.end(), false) ; + // confronto questo vettore con il vettore dei punti in ordine sparso + for ( int p = 0 ; p < int( vPntPoly.size()) ; ++p) { + Point3d pt = vPntPoly[p] ; + for ( int t = 0 ; t < int( vPnt.size()) ; ++t) { + if( vbPntChecked[t]) + continue ; + Point3d ptToCheck = vPnt[t] ; + if ( AreSamePointStepExact( pt, ptToCheck)) { + vbPntChecked[t] = true ; + vPntOrd.push_back( vPntPolyToOrd[p]) ; + } + } + } + // applico la stessa trasformazione al vettore dei punti delle polyline vPLToOrd + return true ; +} + //---------------------------------------------------------------------------- bool SurfBezier::GetLeaves( vector>& vLeaves) const diff --git a/SurfBezier.h b/SurfBezier.h index 32fc6e2..71c3d53 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -204,6 +204,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool CalcPoles( void) const ; bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ; bool ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const ; + bool ReorderPntEnhancedVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto From 2710f735d15b81d3f59b1c5dbf7afbc0a1ef75d4 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 1 Aug 2024 16:24:16 +0200 Subject: [PATCH 15/16] EgtGeomKernel : - correzioni e migliorie alla triangolazione delle bezier. --- SurfBezier.cpp | 11 +- Tree.cpp | 464 ++++++++++++++++++++++++++----------------------- Tree.h | 4 +- 3 files changed, 252 insertions(+), 227 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 39265ce..d454768 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1582,8 +1582,10 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const PNTVECTOR vPnt ; INTVECTOR vTria ; Triangulate Tri ; - if ( ! Tri.Make( vPL, vPnt, vTria)) + if ( ! Tri.Make( vPL, vPnt, vTria)) { + LOG_DBG_ERR( GetEGkLogger(), "ERROR : Triangulation failed in Bezier Surface") ; return nullptr ; + } POLYLINEVECTOR vPL3d = vvPL3d[c] ; @@ -1612,14 +1614,15 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const if ( bTriangulationFailedIn2D) { PNTVECTOR vPntBackup = vPnt ; INTVECTOR vTriaBackup = vTria ; + bool bTriangulationSucceded = true ; if ( ! Tri.Make( vPL3d, vPnt, vTria)) - return nullptr ; - bool bTriangulationSucceded = ( vPnt.size() - 2) + (2 * (vPL.size() - 1)) - (vPL.size() > 2 ? vPL.size() - 2 : 0) - (vPL.size() != 1 ? vPL.size() : 0) == ( vTria.size() ) / 3 ; + bTriangulationSucceded = false ; + bTriangulationSucceded = bTriangulationSucceded && ( vPnt.size() - 2) + (2 * (vPL.size() - 1)) - (vPL.size() > 2 ? vPL.size() - 2 : 0) - (vPL.size() != 1 ? vPL.size() : 0) == ( vTria.size() ) / 3 ; if( bTriangulationFailedIn2D) { if ( bTriangulationSucceded) LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) RESOLVED") else - LOG_INFO( GetEGkLogger(), "Info : Last problem in MakeByEC23(1) is the same as the previous one") + LOG_INFO( GetEGkLogger(), "Info : This problem in MakeByEC23(1) is the same as the previous one") } if( bTriangulationSucceded) { bTriangulatedIn3D = true ; diff --git a/Tree.cpp b/Tree.cpp index 0273ea6..e84fe62 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -523,87 +523,90 @@ Tree::GetIndependentTrees( BIPNTVECTOR& vTrees) bool Tree::Split( int nId, double dSplitValue) { + Cell& cToSplit = m_mTree[nId] ; // controllo che lo split non venga fatto sul lato della cella - if ( ( m_mTree[nId].IsSplitVert() && dSplitValue > m_mTree[nId].GetBottomLeft().x + EPS_SMALL && - dSplitValue < m_mTree[nId].GetTopRight().x - EPS_SMALL) || - ( ! m_mTree[nId].IsSplitVert() && dSplitValue > m_mTree[nId].GetBottomLeft().y + EPS_SMALL && - dSplitValue < m_mTree[nId].GetTopRight().y - EPS_SMALL)) { + if ( ( cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().x + EPS_SMALL && + dSplitValue < cToSplit.GetTopRight().x - EPS_SMALL) || + ( ! cToSplit.IsSplitVert() && dSplitValue > cToSplit.GetBottomLeft().y + EPS_SMALL && + dSplitValue < cToSplit.GetTopRight().y - EPS_SMALL)) { // quando si implementerà lo split a parametro libero bisognerà impedire che si facciano split troppo vicini al bordo della cella!!!!!!!!!!!!!!!!!!! - m_mTree[nId].m_dSplit = dSplitValue ; + cToSplit.m_dSplit = dSplitValue ; Cell cChild1, cChild2 ; - cChild1.m_nDepth = m_mTree[nId].m_nDepth + 1 ; - cChild2.m_nDepth = m_mTree[nId].m_nDepth + 1 ; + cChild1.m_nDepth = cToSplit.m_nDepth + 1 ; + cChild2.m_nDepth = cToSplit.m_nDepth + 1 ; int nNodes = (int) m_mTree.size() ; cChild1.m_nId = nNodes - 1 ; - m_mTree[nId].m_nChild1 = nNodes - 1 ; + cToSplit.m_nChild1 = nNodes - 1 ; cChild2.m_nId = nNodes ; - m_mTree[nId].m_nChild2 = nNodes ; - m_mTree.insert( pair( nNodes - 1, cChild1)) ; - m_mTree.insert( pair( nNodes, cChild2)) ; + cToSplit.m_nChild2 = nNodes ; Point3d ptVert1, ptVert2 ; - PNTVECTOR vVert ; - m_mVert.insert( pair( nNodes - 1, vVert)) ; - m_mVert.insert( pair( nNodes, vVert)) ; - if ( ! m_mTree[nId].IsSplitVert()) { + PNTVECTOR vVert1, vVert2 ; + if ( ! cToSplit.IsSplitVert()) { // la cella figlio 1 è quella sopra - Point3d ptBL( m_mTree[nId].GetBottomLeft().x, dSplitValue) ; - m_mTree[m_mTree[nId].m_nChild1].SetBottomLeft( ptBL) ; - m_mTree[m_mTree[nId].m_nChild1].SetTopRight( m_mTree[nId].GetTopRight()) ; - m_mTree[m_mTree[nId].m_nChild1].m_nTop = m_mTree[nId].m_nTop ; - m_mTree[m_mTree[nId].m_nChild1].m_nBottom = m_mTree[nId].m_nChild2 ; - m_mTree[m_mTree[nId].m_nChild1].m_nLeft = m_mTree[nId].m_nLeft ; - m_mTree[m_mTree[nId].m_nChild1].m_nRight = m_mTree[nId].m_nRight ; - Point3d ptTR( m_mTree[nId].GetTopRight().x, dSplitValue) ; - m_mTree[m_mTree[nId].m_nChild2].SetBottomLeft( m_mTree[nId].GetBottomLeft()) ; - m_mTree[m_mTree[nId].m_nChild2].SetTopRight( ptTR) ; - m_mTree[m_mTree[nId].m_nChild2].m_nTop = m_mTree[nId].m_nChild1 ; - m_mTree[m_mTree[nId].m_nChild2].m_nBottom = m_mTree[nId].m_nBottom ; - m_mTree[m_mTree[nId].m_nChild2].m_nLeft = m_mTree[nId].m_nLeft ; - m_mTree[m_mTree[nId].m_nChild2].m_nRight = m_mTree[nId].m_nRight ; + Point3d ptBL( cToSplit.GetBottomLeft().x, dSplitValue) ; + cChild1.SetBottomLeft( ptBL) ; + cChild1.SetTopRight( cToSplit.GetTopRight()) ; + cChild1.m_nTop = cToSplit.m_nTop ; + cChild1.m_nBottom = cToSplit.m_nChild2 ; + cChild1.m_nLeft = cToSplit.m_nLeft ; + cChild1.m_nRight = cToSplit.m_nRight ; + Point3d ptTR( cToSplit.GetTopRight().x, dSplitValue) ; + cChild2.SetBottomLeft( cToSplit.GetBottomLeft()) ; + cChild2.SetTopRight( ptTR) ; + cChild2.m_nTop = cToSplit.m_nChild1 ; + cChild2.m_nBottom = cToSplit.m_nBottom ; + cChild2.m_nLeft = cToSplit.m_nLeft ; + cChild2.m_nRight = cToSplit.m_nRight ; // metto i corrispondenti 3d dei punti dello split nella mappa m_mVert // per ogni cella i punti devono essere nell'ordine ptP00, ptP10, ptP11, ptP01 - m_pSrfBz->GetPointD1D2( m_mTree[nId].GetBottomLeft().x / SBZ_TREG_COEFF, dSplitValue / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert1) ; - m_pSrfBz->GetPointD1D2( m_mTree[nId].GetTopRight().x / SBZ_TREG_COEFF, dSplitValue / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert2) ; - m_mVert[nNodes - 1].push_back( ptVert1) ; - m_mVert[nNodes - 1].push_back( ptVert2) ; - m_mVert[nNodes - 1].push_back( m_mVert[nId][2]) ; - m_mVert[nNodes - 1].push_back( m_mVert[nId][3]) ; - m_mVert[nNodes].push_back( m_mVert[nId][0]) ; - m_mVert[nNodes].push_back( m_mVert[nId][1]) ; - m_mVert[nNodes].push_back( ptVert2) ; - m_mVert[nNodes].push_back( ptVert1) ; + m_pSrfBz->GetPointD1D2( cToSplit.GetBottomLeft().x / SBZ_TREG_COEFF, dSplitValue / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert1) ; + m_pSrfBz->GetPointD1D2( cToSplit.GetTopRight().x / SBZ_TREG_COEFF, dSplitValue / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert2) ; + vVert1.push_back( ptVert1) ; + vVert1.push_back( ptVert2) ; + vVert1.push_back( m_mVert[nId][2]) ; + vVert1.push_back( m_mVert[nId][3]) ; + vVert2.push_back( m_mVert[nId][0]) ; + vVert2.push_back( m_mVert[nId][1]) ; + vVert2.push_back( ptVert2) ; + vVert2.push_back( ptVert1) ; } else { // la cella figlio 1 è quella di sinistra - Point3d ptTR( dSplitValue, m_mTree[nId].GetTopRight().y) ; - m_mTree[m_mTree[nId].m_nChild1].SetBottomLeft( m_mTree[nId].GetBottomLeft()) ; - m_mTree[m_mTree[nId].m_nChild1].SetTopRight( ptTR) ; - m_mTree[m_mTree[nId].m_nChild1].m_nTop = m_mTree[nId].m_nTop ; - m_mTree[m_mTree[nId].m_nChild1].m_nBottom = m_mTree[nId].m_nBottom ; - m_mTree[m_mTree[nId].m_nChild1].m_nLeft = m_mTree[nId].m_nLeft ; - m_mTree[m_mTree[nId].m_nChild1].m_nRight = m_mTree[nId].m_nChild2 ; - Point3d ptBL( dSplitValue, m_mTree[nId].GetBottomLeft().y) ; - m_mTree[m_mTree[nId].m_nChild2].SetBottomLeft( ptBL) ; - m_mTree[m_mTree[nId].m_nChild2].SetTopRight( m_mTree[nId].GetTopRight()) ; - m_mTree[m_mTree[nId].m_nChild2].m_nTop = m_mTree[nId].m_nTop ; - m_mTree[m_mTree[nId].m_nChild2].m_nBottom = m_mTree[nId].m_nBottom ; - m_mTree[m_mTree[nId].m_nChild2].m_nLeft = m_mTree[nId].m_nChild1 ; - m_mTree[m_mTree[nId].m_nChild2].m_nRight = m_mTree[nId].m_nRight ; + Point3d ptTR( dSplitValue, cToSplit.GetTopRight().y) ; + cChild1.SetBottomLeft( cToSplit.GetBottomLeft()) ; + cChild1.SetTopRight( ptTR) ; + cChild1.m_nTop = cToSplit.m_nTop ; + cChild1.m_nBottom = cToSplit.m_nBottom ; + cChild1.m_nLeft = cToSplit.m_nLeft ; + cChild1.m_nRight = cToSplit.m_nChild2 ; + Point3d ptBL( dSplitValue, cToSplit.GetBottomLeft().y) ; + cChild2.SetBottomLeft( ptBL) ; + cChild2.SetTopRight( cToSplit.GetTopRight()) ; + cChild2.m_nTop = cToSplit.m_nTop ; + cChild2.m_nBottom = cToSplit.m_nBottom ; + cChild2.m_nLeft = cToSplit.m_nChild1 ; + cChild2.m_nRight = cToSplit.m_nRight ; // metto i corrispondenti 3d dei punti dello split nella mappa m_mVert // per ogni cella i punti devono essere nell'ordine ptP00, ptP10, ptP11, ptP01 - m_pSrfBz->GetPointD1D2( dSplitValue / SBZ_TREG_COEFF, m_mTree[nId].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert2) ; - m_pSrfBz->GetPointD1D2( dSplitValue / SBZ_TREG_COEFF, m_mTree[nId].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert1) ; - m_mVert[nNodes - 1].push_back( m_mVert[nId][0]) ; - m_mVert[nNodes - 1].push_back( ptVert2) ; - m_mVert[nNodes - 1].push_back( ptVert1) ; - m_mVert[nNodes - 1].push_back( m_mVert[nId][3]) ; - m_mVert[nNodes].push_back( ptVert2) ; - m_mVert[nNodes].push_back( m_mVert[nId][1]) ; - m_mVert[nNodes].push_back( m_mVert[nId][2]) ; - m_mVert[nNodes].push_back( ptVert1) ; + m_pSrfBz->GetPointD1D2( dSplitValue / SBZ_TREG_COEFF, cToSplit.GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert2) ; + m_pSrfBz->GetPointD1D2( dSplitValue / SBZ_TREG_COEFF, cToSplit.GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptVert1) ; + vVert1.push_back( m_mVert[nId][0]) ; + vVert1.push_back( ptVert2) ; + vVert1.push_back( ptVert1) ; + vVert1.push_back( m_mVert[nId][3]) ; + vVert2.push_back( ptVert2) ; + vVert2.push_back( m_mVert[nId][1]) ; + vVert2.push_back( m_mVert[nId][2]) ; + vVert2.push_back( ptVert1) ; } - m_mTree[m_mTree[nId].m_nChild1].SetParent( nId) ; - m_mTree[m_mTree[nId].m_nChild2].SetParent( nId) ; + cChild1.SetParent( nId) ; + cChild2.SetParent( nId) ; + // inserisco i vertici 3d + m_mVert.insert( pair( nNodes - 1, vVert1)) ; + m_mVert.insert( pair( nNodes, vVert2)) ; + // inserisco nell'albero + m_mTree.insert( pair( nNodes - 1, cChild1)) ; + m_mTree.insert( pair( nNodes, cChild2)) ; return true ; } return false ; @@ -692,26 +695,27 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) { // suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri int nCToSplit = -1 ; + Cell* cToSplit = &m_mTree[nCToSplit] ; if ( ! m_bBilinear) { - while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) { + while ( nCToSplit != -2 && cToSplit->IsProcessed() == false) { // controllo che la cella non sia già stata preliminarmente splittata - if ( m_mTree[nCToSplit].IsLeaf()) { + if ( cToSplit->IsLeaf()) { // calcolo in quale direzione ho più curvatura // ptP00P10 è un punto tra P00 e P10 double dCurvU = 0, dCurvV = 0 ; - double dLenParU = ( m_mTree[nCToSplit].GetTopRight().x - m_mTree[nCToSplit].GetBottomLeft().x) / SBZ_TREG_COEFF ; - double dLenParV = ( m_mTree[nCToSplit].GetTopRight().y - m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ; + double dLenParU = ( cToSplit->GetTopRight().x - cToSplit->GetBottomLeft().x) / SBZ_TREG_COEFF ; + double dLenParV = ( cToSplit->GetTopRight().y - cToSplit->GetBottomLeft().y) / SBZ_TREG_COEFF ; if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU || Dist(m_mVert[nCToSplit][0], m_mVert[nCToSplit][2]) < dSideMin * 2 || Dist(m_mVert[nCToSplit][1], m_mVert[nCToSplit][3]) < dSideMin * 2) { - double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ; - double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ; + double dU = ( cToSplit->GetTopRight().x + cToSplit->GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ; + double dV = ( cToSplit->GetTopRight().y + cToSplit->GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ; double dULoc = 0.5, dVLoc = 0.5 ; Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00 ; m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; - m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; - m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; + m_pSrfBz->GetPointD1D2( dU, cToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; + m_pSrfBz->GetPointD1D2( cToSplit->GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; + m_pSrfBz->GetPointD1D2( dU, cToSplit->GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; + m_pSrfBz->GetPointD1D2( cToSplit->GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; Point3d ptV = ( 1 - dULoc) * ptP00P10 + dULoc * ptP11P01 ; Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ; dCurvV = Dist( ptV, ptPSrf) ; @@ -723,13 +727,13 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00, ptPSrfMid ; double dStep = 1. / ( m_nDegU * 2) ; for ( double k = dStep ; k < 1 + EPS_SMALL ; k = k + dStep) { - double dU = ( k * m_mTree[nCToSplit].GetTopRight().x + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().x) / SBZ_TREG_COEFF ; - double dV = ( m_mTree[nCToSplit].GetTopRight().y + m_mTree[nCToSplit].GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ; + double dU = ( k * cToSplit->GetTopRight().x + ( 1 - k) * cToSplit->GetBottomLeft().x) / SBZ_TREG_COEFF ; + double dV = ( cToSplit->GetTopRight().y + cToSplit->GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ; m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; if ( k == 0.5) ptPSrfMid = ptPSrf ; - m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; - m_pSrfBz->GetPointD1D2( dU, m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; + m_pSrfBz->GetPointD1D2( dU, cToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; + m_pSrfBz->GetPointD1D2( dU, cToSplit->GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; CurveLine clV ; clV.Set( ptP00P10, ptP11P01) ; DistPointCurve dpc( ptPSrf, clV) ; @@ -739,14 +743,14 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } dStep = 1. / ( m_nDegV * 2) ; for ( double k = dStep ; k < 1 + EPS_SMALL ; k = k + dStep) { - double dU = ( m_mTree[nCToSplit].GetTopRight().x + m_mTree[nCToSplit].GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ; - double dV = ( k * m_mTree[nCToSplit].GetTopRight().y + ( 1 - k) * m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ; + double dU = ( cToSplit->GetTopRight().x + cToSplit->GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ; + double dV = ( k * cToSplit->GetTopRight().y + ( 1 - k) * cToSplit->GetBottomLeft().y) / SBZ_TREG_COEFF ; if ( k == 0.5 && ! AreSamePointApprox( ORIG, ptPSrfMid)) ptPSrf = ptPSrfMid ; else m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; - m_pSrfBz->GetPointD1D2( m_mTree[nCToSplit].GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; + m_pSrfBz->GetPointD1D2( cToSplit->GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; + m_pSrfBz->GetPointD1D2( cToSplit->GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; CurveLine clU ; clU.Set( ptP01P00, ptP10P11) ; DistPointCurve dpc( ptPSrf, clU) ; @@ -803,7 +807,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) // lungo la direzione U ho una curvatura maggiore bVert = true ; } - m_mTree[nCToSplit].SetSplitDirVert( bVert) ; + cToSplit->SetSplitDirVert( bVert) ; //Point3d ptP00, ptP10, ptP11, ptP01 ; //ptP00 = m_mVert[nCToSplit][0] ; //ptP10 = m_mVert[nCToSplit][1] ; @@ -815,19 +819,19 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) double dLen2 = Dist( ptP01, ptP11) ; double dLen3 = Dist( ptP00, ptP01) ; if ( dLen0 < EPS_ZERO && dLen2 < EPS_ZERO ) { - double dV = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 / SBZ_TREG_COEFF ; + double dV = ( cToSplit->GetBottomLeft().y + cToSplit->GetTopRight().y) / 2 / SBZ_TREG_COEFF ; PtrOwner pCrvV( m_pSrfBz->GetCurveOnU( dV)) ; double dLenU0, dLenU1 ; - pCrvV->GetLengthAtParam( m_mTree[nCToSplit].GetBottomLeft().x / SBZ_TREG_COEFF, dLenU0) ; - pCrvV->GetLengthAtParam( m_mTree[nCToSplit].GetTopRight().x / SBZ_TREG_COEFF, dLenU1) ; + pCrvV->GetLengthAtParam( cToSplit->GetBottomLeft().x / SBZ_TREG_COEFF, dLenU0) ; + pCrvV->GetLengthAtParam( cToSplit->GetTopRight().x / SBZ_TREG_COEFF, dLenU1) ; dLen0 = abs( dLenU1 - dLenU0) ; } if ( dLen1 < EPS_ZERO && dLen3 < EPS_ZERO ) { - double dU = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 / SBZ_TREG_COEFF ; + double dU = ( cToSplit->GetBottomLeft().x + cToSplit->GetTopRight().x) / 2 / SBZ_TREG_COEFF ; PtrOwner pCrvU( m_pSrfBz->GetCurveOnV( dU)) ; double dLenV0, dLenV1 ; - pCrvU->GetLengthAtParam( m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, dLenV0) ; - pCrvU->GetLengthAtParam( m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, dLenV1) ; + pCrvU->GetLengthAtParam( cToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, dLenV0) ; + pCrvU->GetLengthAtParam( cToSplit->GetTopRight().y / SBZ_TREG_COEFF, dLenV1) ; dLen1 = abs( dLenV1 - dLenV0) ; } // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare @@ -870,9 +874,9 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) int nStepsV = int( 51 * dDimV + 5 * ( 1 - dDimV)) ; for ( int u = 0 ; u < nStepsU && ! bSplit ; ++ u) { double dU = double ( u) / double ( nStepsU - 1) ; - double dULoc = ( ( 1 - dU) * m_mTree[nCToSplit].GetBottomLeft().x + dU * m_mTree[nCToSplit].GetTopRight().x) / SBZ_TREG_COEFF ; - if ( ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) || - ! m_pSrfBz->GetPointD1D2( dULoc, m_mTree[nCToSplit].GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1)) + double dULoc = ( ( 1 - dU) * cToSplit->GetBottomLeft().x + dU * cToSplit->GetTopRight().x) / SBZ_TREG_COEFF ; + if ( ! m_pSrfBz->GetPointD1D2( dULoc, cToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) || + ! m_pSrfBz->GetPointD1D2( dULoc, cToSplit->GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1)) return false ; // verifico che la cella non sia uno spicchio in verticale, cioè con ptP00 == ptP01 && ptP10 == ptP11 // ( vedi disegno sotto per uno spicchio verticale) @@ -893,7 +897,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) clV.Set( pt0010, pt0111) ; for ( int v = 0 ; v < nStepsV ; ++ v) { double dV = double ( v) / double ( nStepsV - 1) ; - double dVLoc = ( ( 1 - dV) * m_mTree[nCToSplit].GetBottomLeft().y + dV * m_mTree[nCToSplit].GetTopRight().y) / SBZ_TREG_COEFF ; + double dVLoc = ( ( 1 - dV) * cToSplit->GetBottomLeft().y + dV * cToSplit->GetTopRight().y) / SBZ_TREG_COEFF ; if ( ! m_pSrfBz->GetPointD1D2( dULoc, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBzV)) return false ; DistPointCurve dpc( ptBzV, clV) ; @@ -930,36 +934,42 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } if ( bSplit || dSideMaxVal > dSideMax) { - m_mTree[nCToSplit].SetSplitDirVert( bVert) ; + cToSplit->SetSplitDirVert( bVert) ; // effettuo lo split Split( nCToSplit) ; // procedo con lo split del Child1 - nCToSplit = m_mTree[nCToSplit].m_nChild1 ; + nCToSplit = cToSplit->m_nChild1 ; + cToSplit = &m_mTree[nCToSplit] ; } else { // sono arrivato ad una cella Leaf, quindi salvo la cella m_vnLeaves.push_back( nCToSplit) ; - m_mTree[nCToSplit].SetProcessed() ; + cToSplit->SetProcessed() ; // risalgo i parent finché non trovo il primo Child2 da processare - nCToSplit = m_mTree[nCToSplit].m_nParent ; + nCToSplit = cToSplit->m_nParent ; + cToSplit = &m_mTree[nCToSplit] ; if ( nCToSplit == -2) return true ; - if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) - m_mTree[nCToSplit].SetProcessed() ; - while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) { - if ( m_mTree[nCToSplit].m_nParent != -2) - nCToSplit = m_mTree[nCToSplit].m_nParent ; - if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) - m_mTree[nCToSplit].SetProcessed() ; - if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) + if ( m_mTree[cToSplit->m_nChild1].IsProcessed() && m_mTree[cToSplit->m_nChild2].IsProcessed()) + cToSplit->SetProcessed() ; + while ( m_mTree[cToSplit->m_nChild2].IsProcessed()) { + if ( cToSplit->m_nParent != -2) { + nCToSplit = cToSplit->m_nParent ; + cToSplit = &m_mTree[nCToSplit] ; + } + if ( m_mTree[cToSplit->m_nChild1].IsProcessed() && m_mTree[cToSplit->m_nChild2].IsProcessed()) + cToSplit->SetProcessed() ; + if ( nCToSplit == -1 && m_mTree[cToSplit->m_nChild2].IsProcessed()) break ; } - nCToSplit = m_mTree[nCToSplit].m_nChild2 ; + nCToSplit = cToSplit->m_nChild2 ; + cToSplit = &m_mTree[nCToSplit] ; } } else { - nCToSplit = m_mTree[nCToSplit].m_nChild1 ; + nCToSplit = cToSplit->m_nChild1 ; + cToSplit = &m_mTree[nCToSplit] ; } } Balance() ; // da implementare quando dividerò ad un parametro a scelta e non a metà // probabilmente mi servirà salvare nella cella il livello di profondità @@ -967,9 +977,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) // bilineare else { bool bIsPlanar = m_pSrfBz->IsPlanar() ; - - while ( nCToSplit != -2 && m_mTree[nCToSplit].IsProcessed() == false) { - if ( m_mTree[nCToSplit].IsLeaf()) { + while ( nCToSplit != -2 && cToSplit->IsProcessed() == false) { + if ( cToSplit->IsLeaf()) { // vertici della cella Point3d ptP00, ptP10, ptP11, ptP01 ; ptP00 = m_mVert[nCToSplit][0] ; @@ -993,10 +1002,10 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } else { for ( double i = 0.25 ; i < 1 ; i = i + 0.25) { - dU = ( ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().x + i * m_mTree[nCToSplit].GetTopRight().x) / SBZ_TREG_COEFF ; - dV = ( ( 1 - i) * m_mTree[nCToSplit].GetBottomLeft().y + i * m_mTree[nCToSplit].GetTopRight().y) / SBZ_TREG_COEFF ; - double dVLoc = ( m_mTree[nCToSplit].GetBottomLeft().y + m_mTree[nCToSplit].GetTopRight().y) / 2 / SBZ_TREG_COEFF ; - double dULoc = ( m_mTree[nCToSplit].GetBottomLeft().x + m_mTree[nCToSplit].GetTopRight().x) / 2 / SBZ_TREG_COEFF ; + dU = ( ( 1 - i) * cToSplit->GetBottomLeft().x + i * cToSplit->GetTopRight().x) / SBZ_TREG_COEFF ; + dV = ( ( 1 - i) * cToSplit->GetBottomLeft().y + i * cToSplit->GetTopRight().y) / SBZ_TREG_COEFF ; + double dVLoc = ( cToSplit->GetBottomLeft().y + cToSplit->GetTopRight().y) / 2 / SBZ_TREG_COEFF ; + double dULoc = ( cToSplit->GetBottomLeft().x + cToSplit->GetTopRight().x) / 2 / SBZ_TREG_COEFF ; m_pSrfBz->GetPointD1D2( dU, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfU) ; m_pSrfBz->GetPointD1D2( dULoc, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfV) ; vPtU.push_back( ptPSrfU) ; @@ -1037,8 +1046,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } for ( double i = 0.25 ; i < 1 ; i = i + 0.25) { for ( double j = 0.25 ; j < 1 ; j = j + 0.25) { - double dU = ( ( 1 - i) * m_mTree[nCToSplit].GetTopRight().x + i * m_mTree[nCToSplit].GetBottomLeft().x) / SBZ_TREG_COEFF ; - double dV = ( ( 1 - j) * m_mTree[nCToSplit].GetTopRight().y + j * m_mTree[nCToSplit].GetBottomLeft().y) / SBZ_TREG_COEFF ; + double dU = ( ( 1 - i) * cToSplit->GetTopRight().x + i * cToSplit->GetBottomLeft().x) / SBZ_TREG_COEFF ; + double dV = ( ( 1 - j) * cToSplit->GetTopRight().y + j * cToSplit->GetBottomLeft().y) / SBZ_TREG_COEFF ; m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; dErr = max( abs( DistPointPlane( ptPSrf, plAppr)), dErr) ; } @@ -1050,36 +1059,42 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } // se la cella è abbastanza grande da poter essere divisa ancora e devo approssimare meglio, la divido if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) { - m_mTree[nCToSplit].SetSplitDirVert( bVert) ; + cToSplit->SetSplitDirVert( bVert) ; // effettuo lo split Split( nCToSplit) ; // procedo con lo split del Child1 - nCToSplit = m_mTree[nCToSplit].m_nChild1 ; + nCToSplit = cToSplit->m_nChild1 ; + cToSplit = &m_mTree[nCToSplit] ; } else { // sono arrivato ad una cella Leaf, quindi salvo la cella m_vnLeaves.push_back( nCToSplit) ; - m_mTree[nCToSplit].SetProcessed() ; + cToSplit->SetProcessed() ; // risalgo i parent finché non trovo il primo Child2 da processare - nCToSplit = m_mTree[nCToSplit].m_nParent ; + nCToSplit = cToSplit->m_nParent ; + cToSplit = &m_mTree[nCToSplit] ; if ( nCToSplit == -2) return true ; - if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) - m_mTree[nCToSplit].SetProcessed() ; - while ( m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) { - if ( m_mTree[nCToSplit].m_nParent != -2) - nCToSplit = m_mTree[nCToSplit].m_nParent ; - if ( m_mTree[m_mTree[nCToSplit].m_nChild1].IsProcessed() && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) - m_mTree[nCToSplit].SetProcessed() ; - if ( nCToSplit == -1 && m_mTree[m_mTree[nCToSplit].m_nChild2].IsProcessed()) + if ( m_mTree[cToSplit->m_nChild1].IsProcessed() && m_mTree[cToSplit->m_nChild2].IsProcessed()) + cToSplit->SetProcessed() ; + while ( m_mTree[cToSplit->m_nChild2].IsProcessed()) { + if ( cToSplit->m_nParent != -2) { + nCToSplit = cToSplit->m_nParent ; + cToSplit = &m_mTree[nCToSplit] ; + } + if ( m_mTree[cToSplit->m_nChild1].IsProcessed() && m_mTree[cToSplit->m_nChild2].IsProcessed()) + cToSplit->SetProcessed() ; + if ( nCToSplit == -1 && m_mTree[cToSplit->m_nChild2].IsProcessed()) break ; } - nCToSplit = m_mTree[nCToSplit].m_nChild2 ; + nCToSplit = cToSplit->m_nChild2 ; + cToSplit = &m_mTree[nCToSplit] ; } } else { - nCToSplit = m_mTree[nCToSplit].m_nChild1 ; + nCToSplit = cToSplit->m_nChild1 ; + cToSplit = &m_mTree[nCToSplit] ; } } } @@ -1103,31 +1118,32 @@ Tree::Balance() void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const { + const Cell& cell = m_mTree.at( nId) ; // le celle restituite sono ordinate per x crescente if ( vTopNeighs.empty()) { - if ( m_mTree.at( nId).m_nTop == -2) + if ( cell.m_nTop == -2) return ; - if ( m_mTree.at( m_mTree.at( nId).m_nTop).IsLeaf()) - vTopNeighs.push_back( m_mTree.at( nId).m_nTop) ; + if ( m_mTree.at( cell.m_nTop).IsLeaf()) + vTopNeighs.push_back( cell.m_nTop) ; else { - if ( m_mTree.at( m_mTree.at( nId).m_nTop).IsSplitVert()) { + if ( m_mTree.at( cell.m_nTop).IsSplitVert()) { // se la cella vicina è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima - if ( m_mTree.at( m_mTree.at( nId).m_nTop).GetTopRight().x - m_mTree.at( m_mTree.at( nId).m_nTop).GetBottomLeft().x <= - m_mTree.at( nId).GetTopRight().x - m_mTree.at( nId).GetBottomLeft().x) { - vTopNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nTop).m_nChild1) ; - vTopNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nTop).m_nChild2) ; + if ( m_mTree.at( cell.m_nTop).GetTopRight().x - m_mTree.at( cell.m_nTop).GetBottomLeft().x <= + cell.GetTopRight().x - cell.GetBottomLeft().x) { + vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild1) ; + vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else { - if ( m_mTree.at( m_mTree.at( m_mTree.at( nId).m_nTop).m_nChild1).GetTopRight().x <= m_mTree.at( nId).GetBottomLeft().x || - m_mTree.at( m_mTree.at( m_mTree.at( nId).m_nTop).m_nChild1).GetBottomLeft().x >= m_mTree.at( nId).GetTopRight().x ) - vTopNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nTop).m_nChild2) ; + if ( m_mTree.at( m_mTree.at( cell.m_nTop).m_nChild1).GetTopRight().x <= cell.GetBottomLeft().x || + m_mTree.at( m_mTree.at( cell.m_nTop).m_nChild1).GetBottomLeft().x >= cell.GetTopRight().x ) + vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild2) ; else - vTopNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nTop).m_nChild1) ; + vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild1) ; } } else { - vTopNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nTop).m_nChild2) ; + vTopNeighs.push_back( m_mTree.at( cell.m_nTop).m_nChild2) ; } } bool bAllLeaves = true ; @@ -1151,14 +1167,14 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const if ( m_mTree.at( i).IsSplitVert()) { // se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima if ( m_mTree.at( i).GetTopRight().x - m_mTree.at( i).GetBottomLeft().x <= - m_mTree.at( nId).GetTopRight().x - m_mTree.at( nId).GetBottomLeft().x) { + cell.GetTopRight().x - cell.GetBottomLeft().x) { vTopNeighs.push_back( m_mTree.at( i).m_nChild1) ; vTopNeighs.push_back( m_mTree.at( i).m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else { - if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().x <= m_mTree.at( nId).GetBottomLeft().x || - m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().x >= m_mTree.at( nId).GetTopRight().x ) + if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().x <= cell.GetBottomLeft().x || + m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().x >= cell.GetTopRight().x ) vTopNeighs.push_back( m_mTree.at( i).m_nChild2) ; else vTopNeighs.push_back( m_mTree.at( i).m_nChild1) ; @@ -1185,31 +1201,32 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const { + const Cell& cell = m_mTree.at( nId) ; // le celle restituite sono ordinate per x crescente if ( vBottomNeighs.empty()) { - if ( m_mTree.at( nId).m_nBottom == -2) + if ( cell.m_nBottom == -2) return ; - if ( m_mTree.at( m_mTree.at( nId).m_nBottom).IsLeaf()) - vBottomNeighs.push_back( m_mTree.at( nId).m_nBottom) ; + if ( m_mTree.at( cell.m_nBottom).IsLeaf()) + vBottomNeighs.push_back( cell.m_nBottom) ; else { - if ( m_mTree.at( m_mTree.at( nId).m_nBottom).IsSplitVert()) { + if ( m_mTree.at( cell.m_nBottom).IsSplitVert()) { // se la cella vicina è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima - if ( m_mTree.at( m_mTree.at( nId).m_nBottom).GetTopRight().x - m_mTree.at( m_mTree.at( nId).m_nBottom).GetBottomLeft().x <= - m_mTree.at( nId).GetTopRight().x - m_mTree.at( nId).GetBottomLeft().x) { - vBottomNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nBottom).m_nChild1) ; - vBottomNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nBottom).m_nChild2) ; + if ( m_mTree.at( cell.m_nBottom).GetTopRight().x - m_mTree.at( cell.m_nBottom).GetBottomLeft().x <= + cell.GetTopRight().x - cell.GetBottomLeft().x) { + vBottomNeighs.push_back( m_mTree.at( cell.m_nBottom).m_nChild1) ; + vBottomNeighs.push_back( m_mTree.at( cell.m_nBottom).m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else{ - if ( m_mTree.at( m_mTree.at( m_mTree.at( nId).m_nBottom).m_nChild1).GetTopRight().x <= m_mTree.at( nId).GetBottomLeft().x || - m_mTree.at( m_mTree.at( m_mTree.at( nId).m_nBottom).m_nChild1).GetBottomLeft().x >= m_mTree.at( nId).GetTopRight().x ) - vBottomNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nBottom).m_nChild2) ; + if ( m_mTree.at( m_mTree.at( cell.m_nBottom).m_nChild1).GetTopRight().x <= cell.GetBottomLeft().x || + m_mTree.at( m_mTree.at( cell.m_nBottom).m_nChild1).GetBottomLeft().x >= cell.GetTopRight().x ) + vBottomNeighs.push_back( m_mTree.at( cell.m_nBottom).m_nChild2) ; else - vBottomNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nBottom).m_nChild1) ; + vBottomNeighs.push_back( m_mTree.at( cell.m_nBottom).m_nChild1) ; } } else { - vBottomNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nBottom).m_nChild1) ; + vBottomNeighs.push_back( m_mTree.at( cell.m_nBottom).m_nChild1) ; } } bool bAllLeaves = true ; @@ -1233,14 +1250,14 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const if ( m_mTree.at( i).IsSplitVert()) { // se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima if ( m_mTree.at( i).GetTopRight().x - m_mTree.at( i).GetBottomLeft().x <= - m_mTree.at( nId).GetTopRight().x - m_mTree.at( nId).GetBottomLeft().x) { + cell.GetTopRight().x - cell.GetBottomLeft().x) { vBottomNeighs.push_back( m_mTree.at( i).m_nChild1) ; vBottomNeighs.push_back( m_mTree.at( i).m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else { - if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().x <= m_mTree.at( nId).GetBottomLeft().x || - m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().x >= m_mTree.at( nId).GetTopRight().x) + if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().x <= cell.GetBottomLeft().x || + m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().x >= cell.GetTopRight().x) vBottomNeighs.push_back( m_mTree.at( i).m_nChild2) ; else vBottomNeighs.push_back( m_mTree.at( i).m_nChild1) ; @@ -1266,31 +1283,32 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const { + const Cell& cell = m_mTree.at( nId) ; // le celle restituite sono ordinate per y crescente if ( vLeftNeighs.empty()) { - if ( m_mTree.at( nId).m_nLeft == -2) + if ( cell.m_nLeft == -2) return ; - if ( m_mTree.at( m_mTree.at( nId).m_nLeft).IsLeaf()) - vLeftNeighs.push_back( m_mTree.at( nId).m_nLeft) ; + if ( m_mTree.at( cell.m_nLeft).IsLeaf()) + vLeftNeighs.push_back( cell.m_nLeft) ; else { - if ( ! m_mTree.at( m_mTree.at( nId).m_nLeft).IsSplitVert()) { + if ( ! m_mTree.at( cell.m_nLeft).IsSplitVert()) { // se la cella vicina è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima - if ( m_mTree.at( m_mTree.at( nId).m_nLeft).GetTopRight().y - m_mTree.at( m_mTree.at( nId).m_nLeft).GetBottomLeft().y <= - m_mTree.at( nId).GetTopRight().y - m_mTree.at( nId).GetBottomLeft().y) { - vLeftNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nLeft).m_nChild1) ; - vLeftNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nLeft).m_nChild2) ; + if ( m_mTree.at( cell.m_nLeft).GetTopRight().y - m_mTree.at( cell.m_nLeft).GetBottomLeft().y <= + cell.GetTopRight().y - cell.GetBottomLeft().y) { + vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild1) ; + vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else{ - if ( m_mTree.at( m_mTree.at( m_mTree.at( nId).m_nLeft).m_nChild1).GetTopRight().y <= m_mTree.at( nId).GetBottomLeft().y || - m_mTree.at( m_mTree.at( m_mTree.at( nId).m_nLeft).m_nChild1).GetBottomLeft().y >= m_mTree.at( nId).GetTopRight().y) - vLeftNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nLeft).m_nChild2) ; + if ( m_mTree.at( m_mTree.at( cell.m_nLeft).m_nChild1).GetTopRight().y <= cell.GetBottomLeft().y || + m_mTree.at( m_mTree.at( cell.m_nLeft).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y) + vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild2) ; else - vLeftNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nLeft).m_nChild1) ; + vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild1) ; } } else { - vLeftNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nLeft).m_nChild2) ; + vLeftNeighs.push_back( m_mTree.at( cell.m_nLeft).m_nChild2) ; } } bool bAllLeaves = true ; @@ -1314,14 +1332,14 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const if ( ! m_mTree.at( i).IsSplitVert()) { // se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima if ( m_mTree.at( i).GetTopRight().y - m_mTree.at( i).GetBottomLeft().y <= - m_mTree.at( nId).GetTopRight().y - m_mTree.at( nId).GetBottomLeft().y) { + cell.GetTopRight().y - cell.GetBottomLeft().y) { vLeftNeighs.push_back( m_mTree.at( i).m_nChild1) ; vLeftNeighs.push_back( m_mTree.at( i).m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else { - if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().y <= m_mTree.at( nId).GetBottomLeft().y || - m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().y >= m_mTree.at( nId).GetTopRight().y) + if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().y <= cell.GetBottomLeft().y || + m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y) vLeftNeighs.push_back( m_mTree.at( i).m_nChild2) ; else vLeftNeighs.push_back( m_mTree.at( i).m_nChild1) ; @@ -1347,31 +1365,32 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const { + const Cell& cell = m_mTree.at( nId) ; // le celle restituite sono ordinate per y crescente if ( vRightNeighs.empty()) { - if ( m_mTree.at( nId).m_nRight == -2) + if ( cell.m_nRight == -2) return ; - if ( m_mTree.at( m_mTree.at( nId).m_nRight).IsLeaf()) - vRightNeighs.push_back( m_mTree.at( nId).m_nRight) ; + if ( m_mTree.at( cell.m_nRight).IsLeaf()) + vRightNeighs.push_back( cell.m_nRight) ; else { - if ( ! m_mTree.at( m_mTree.at( nId).m_nRight).IsSplitVert()) { + if ( ! m_mTree.at( cell.m_nRight).IsSplitVert()) { // se la cella vicina è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima - if ( m_mTree.at( m_mTree.at( nId).m_nRight).GetTopRight().y - m_mTree.at( m_mTree.at( nId).m_nRight).GetBottomLeft().y <= - m_mTree.at( nId).GetTopRight().y - m_mTree.at( nId).GetBottomLeft().y) { - vRightNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nRight).m_nChild1) ; - vRightNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nRight).m_nChild2) ; + if ( m_mTree.at( cell.m_nRight).GetTopRight().y - m_mTree.at( cell.m_nRight).GetBottomLeft().y <= + cell.GetTopRight().y - cell.GetBottomLeft().y) { + vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild1) ; + vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else{ - if ( m_mTree.at( m_mTree.at( m_mTree.at( nId).m_nRight).m_nChild1).GetTopRight().y <= m_mTree.at( nId).GetBottomLeft().y || - m_mTree.at( m_mTree.at( m_mTree.at( nId).m_nRight).m_nChild1).GetBottomLeft().y >= m_mTree.at( nId).GetTopRight().y) - vRightNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nRight).m_nChild2) ; + if ( m_mTree.at( m_mTree.at( cell.m_nRight).m_nChild1).GetTopRight().y <= cell.GetBottomLeft().y || + m_mTree.at( m_mTree.at( cell.m_nRight).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y) + vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild2) ; else - vRightNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nRight).m_nChild1) ; + vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild1) ; } } else { - vRightNeighs.push_back( m_mTree.at( m_mTree.at( nId).m_nRight).m_nChild1) ; + vRightNeighs.push_back( m_mTree.at( cell.m_nRight).m_nChild1) ; } } bool bAllLeaves = true ; @@ -1395,14 +1414,14 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const if ( ! m_mTree.at( i).IsSplitVert()) { // se la cella è più piccola della cella indagata, allora entrambi i figli saranno vicini di quest'ultima if ( m_mTree.at( i).GetTopRight().y - m_mTree.at( i).GetBottomLeft().y <= - m_mTree.at( nId).GetTopRight().y - m_mTree.at( nId).GetBottomLeft().y) { + cell.GetTopRight().y - cell.GetBottomLeft().y) { vRightNeighs.push_back( m_mTree.at( i).m_nChild1) ; vRightNeighs.push_back( m_mTree.at( i).m_nChild2) ; } // altrimenti solo uno dei figli lo sarà else { - if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().y <= m_mTree.at( nId).GetBottomLeft().y || - m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().y >= m_mTree.at( nId).GetTopRight().y) + if ( m_mTree.at( m_mTree.at( i).m_nChild1).GetTopRight().y <= cell.GetBottomLeft().y || + m_mTree.at( m_mTree.at( i).m_nChild1).GetBottomLeft().y >= cell.GetTopRight().y) vRightNeighs.push_back( m_mTree.at( i).m_nChild2) ; else vRightNeighs.push_back( m_mTree.at( i).m_nChild1) ; @@ -1712,10 +1731,11 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon // che sono sui lati della cella corrente // N.B. :i poligoni sono costruiti a partire dal ptBL !!! for ( int nId : vCells) { + Cell& cell = m_mTree.at( nId) ; vVertices.clear() ; vVertices3d.clear() ; vNeigh.clear() ; - vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; + vVertices.push_back( cell.GetBottomLeft()) ; vVertices3d.push_back( m_mVert.at( nId)[0]) ; INTVECTOR vnVert ; BOOLVECTOR vbBonusVert(4) ; @@ -1728,7 +1748,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. if ( m_bClosedV && m_mTree.at(vNeigh[0]).m_bOnTopEdge) { for ( int j : vNeigh) { - Point3d pt( m_mTree.at( j).GetTopRight().x, m_mTree.at( nId).GetBottomLeft().y) ; + Point3d pt( m_mTree.at( j).GetTopRight().x, cell.GetBottomLeft().y) ; vVertices.push_back( pt) ; vVertices3d.push_back( m_mVert[j][2]) ; } @@ -1753,7 +1773,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vnVert.push_back( int(vVertices.size())) ; if ( m_bClosedU && m_mTree.at( vNeigh[0]).m_bOnLeftEdge ) { for ( int j : vNeigh) { - Point3d pt( m_mTree.at( nId).GetTopRight().x, m_mTree.at(j).GetBottomLeft().y) ; + Point3d pt( cell.GetTopRight().x, m_mTree.at(j).GetBottomLeft().y) ; vVertices.push_back( pt) ; vVertices3d.push_back( m_mVert[j][0]) ; } @@ -1768,13 +1788,13 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon } // se non l'ho già aggiunto tramite i vicini bottom aggiungo il punto bottom right else if ( ! bBottomRight) { - Point3d ptBr( m_mTree.at( nId).GetTopRight().x, m_mTree.at( nId).GetBottomLeft().y) ; + Point3d ptBr( cell.GetTopRight().x, cell.GetBottomLeft().y) ; vVertices.push_back( ptBr) ; vVertices3d.push_back( m_mVert[nId][1]) ; vnVert.push_back( int(vVertices.size()) - 1) ; } vNeigh.clear() ; - vVertices.push_back( m_mTree.at( nId).GetTopRight()) ; + vVertices.push_back( cell.GetTopRight()) ; vVertices3d.push_back( m_mVert[nId][2]) ; vnVert.push_back( int(vVertices.size()) - 1) ; GetTopNeigh ( nId, vNeigh) ; @@ -1784,9 +1804,9 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon // se la superficie è chiusa lungo il parametro V e la cella è sul lato top // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. vnVert.push_back( int(vVertices.size())) ; - if ( m_bClosedV && m_mTree.at( nId).m_bOnTopEdge) { + if ( m_bClosedV && cell.m_bOnTopEdge) { for ( int j : vNeigh) { - Point3d pt( m_mTree.at( j).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; + Point3d pt( m_mTree.at( j).GetBottomLeft().x, cell.GetTopRight().y) ; vVertices.push_back( pt) ; vVertices3d.push_back( m_mVert[j][0]) ; } @@ -1810,9 +1830,9 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon // se la superficie è chiusa lungo il parametro U e la cella è sul lato left // devo aggiungere i vertici tenendo conto della periodicità dello spazio parametrico. vnVert.push_back( int(vVertices.size())) ; - if ( m_bClosedU && m_mTree.at( nId).m_bOnLeftEdge) { + if ( m_bClosedU && cell.m_bOnLeftEdge) { for ( int j : vNeigh) { - Point3d pt( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at(j).GetTopRight().y) ; + Point3d pt( cell.GetBottomLeft().x, m_mTree.at(j).GetTopRight().y) ; vVertices.push_back( pt) ; vVertices3d.push_back( m_mVert[j][2]) ; } @@ -1827,13 +1847,13 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon } // se non l'ho già aggiunto tramite i vicini top aggiungo il punto top left else if ( ! bTopLeft) { - Point3d ptTl( m_mTree.at( nId).GetBottomLeft().x, m_mTree.at( nId).GetTopRight().y) ; + Point3d ptTl( cell.GetBottomLeft().x, cell.GetTopRight().y) ; vVertices.push_back( ptTl) ; vVertices3d.push_back( m_mVert[nId][3]) ; vnVert.push_back( int(vVertices.size()) - 1) ; } vNeigh.clear() ; - vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; + vVertices.push_back( cell.GetBottomLeft()) ; vVertices3d.push_back( m_mVert[nId][0]) ; vnVert.push_back( int(vVertices.size()) - 1) ; @@ -1854,7 +1874,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; } vbKeepPoint[vnVert[1]] = false ; - m_mTree[nId].m_nVertToErase = 1 ; // ptBr + cell.m_nVertToErase = 1 ; // ptBr } else if ( ! vbBonusVert[1] && vbBonusVert[3] ) { if ( ! m_bTrimmed) { @@ -1866,13 +1886,13 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon } vbKeepPoint[0] = false ; vbKeepPoint.back() = false ; - m_mTree[nId].m_nVertToErase = 0 ; // ptBL + cell.m_nVertToErase = 0 ; // ptBL } // se non ho bonus su nessuno dei due else { // ne scelgo uno dei due da togliere vbKeepPoint[vnVert[1]] = false ; - m_mTree[nId].m_nVertToErase = 1 ; // ptBr + cell.m_nVertToErase = 1 ; // ptBr } } if ( AreSamePointApprox(m_mVert.at(nId).at(1), m_mVert.at(nId).at(2))) { @@ -1883,7 +1903,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vVertices3d.erase(vVertices3d.begin() + vnVert[1]) ; } vbKeepPoint[vnVert[1]] = false ; - m_mTree[nId].m_nVertToErase = 1 ; // ptBr + cell.m_nVertToErase = 1 ; // ptBr } else if ( ! vbBonusVert[0] && vbBonusVert[2] ){ if ( ! m_bTrimmed) { @@ -1891,13 +1911,13 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; } vbKeepPoint[vnVert[2]] = false ; - m_mTree[nId].m_nVertToErase = 2 ; // ptTR + cell.m_nVertToErase = 2 ; // ptTR } // se non ho bonus su nessuno dei due else { // ne scelgo uno dei due da togliere vbKeepPoint[vnVert[2]] = false ; - m_mTree[nId].m_nVertToErase = 2 ; // ptTR + cell.m_nVertToErase = 2 ; // ptTR } } if ( AreSamePointApprox(m_mVert.at(nId).at(2), m_mVert.at(nId).at(3))) { @@ -1908,7 +1928,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vVertices3d.erase(vVertices3d.begin() + vnVert[2]) ; } vbKeepPoint[vnVert[2]] = false ; - m_mTree[nId].m_nVertToErase = 2 ; // ptTR + cell.m_nVertToErase = 2 ; // ptTR } else if ( ! vbBonusVert[1] && vbBonusVert[3]) { if ( ! m_bTrimmed) { @@ -1916,13 +1936,13 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; } vbKeepPoint[vnVert[3]] = false ; - m_mTree[nId].m_nVertToErase = 3 ; // ptTl + cell.m_nVertToErase = 3 ; // ptTl } // se non ho bonus su nessuno dei due else { // ne scelgo uno dei due da togliere vbKeepPoint[vnVert[3]] = false ; - m_mTree[nId].m_nVertToErase = 3 ; // ptTl + cell.m_nVertToErase = 3 ; // ptTl } } if ( AreSamePointApprox(m_mVert.at(nId).at(3), m_mVert.at(nId).at(0))) { @@ -1937,7 +1957,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon } vbKeepPoint[0] = false ; vbKeepPoint.back() = false ; - m_mTree[nId].m_nVertToErase = 0 ; // ptBL + cell.m_nVertToErase = 0 ; // ptBL } else if ( ! vbBonusVert[0] && vbBonusVert[2]) { if ( ! m_bTrimmed) { @@ -1945,13 +1965,13 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon vVertices3d.erase(vVertices3d.begin() + vnVert[3]) ; } vbKeepPoint[vnVert[3]] = false ; - m_mTree[nId].m_nVertToErase = 3 ; // ptTl + cell.m_nVertToErase = 3 ; // ptTl } // se non ho bonus su nessuno dei due else { // ne scelgo uno dei due da togliere vbKeepPoint[vnVert[3]] = false ; - m_mTree[nId].m_nVertToErase = 3 ; // ptTl + cell.m_nVertToErase = 3 ; // ptTl } } } @@ -1962,8 +1982,8 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygonsBasic, POLYLINEVECTOR& vPolygon if ( vVertices.size() == 5 && ( ! bForTriangulation || (bForTriangulation && vVerticesCorr.size() == 5))) { Point3d ptPSrf, ptP00, ptP10, ptP11, ptP01 ; double dU, dV ; - dU = ( m_mTree.at( nId).GetBottomLeft().x + m_mTree.at( nId).GetTopRight().x) / 2 / SBZ_TREG_COEFF ; - dV = ( m_mTree.at( nId).GetBottomLeft().y + m_mTree.at( nId).GetTopRight().y) / 2 / SBZ_TREG_COEFF ; + dU = ( cell.GetBottomLeft().x + cell.GetTopRight().x) / 2 / SBZ_TREG_COEFF ; + dV = ( cell.GetBottomLeft().y + cell.GetTopRight().y) / 2 / SBZ_TREG_COEFF ; m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; ptP00 = m_mVert.at( nId).at( 0) ; ptP10 = m_mVert.at( nId).at( 1) ; @@ -3129,8 +3149,10 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX // se ho trovato un altro loop salto all'inizio del for, dopo aver aggiunto eventuali punti intermedi if ( bValidNextStart) { + Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ; for ( int p = nEdge == nEdgeWithVertexSkipped ? 0 : 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { - if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], m_mTree[nId].m_vInters[vToCheckNow[nNext]].vpt[0])) { + if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], m_mTree[nId].m_vInters[vToCheckNow[nNext]].vpt[0]) && + CheckIfBefore( nEdge, ptLast, vEdgeVertex[nEdge][p])) { plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ; ++ c ; diff --git a/Tree.h b/Tree.h index fd8b8a1..e2d5adc 100644 --- a/Tree.h +++ b/Tree.h @@ -197,7 +197,7 @@ class Cell { return c1.m_ptPbl.x < c2.m_ptPbl.x ; } static bool minorY( const Cell& c1, const Cell& c2) { return c1.m_ptPbl.y < c2.m_ptPbl.y ; } - + public : int m_nId ; // Id della cella int m_nTop ; // cella adiacente al lato top @@ -305,7 +305,7 @@ class Tree DBLVECTOR m_vDim ; // distanze tra i vertici della superficie di bezier in 3d in ordine antiorario a partire da ptP00 bool m_bTrimmed ; // superficie trimmata //INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk - std::map m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim + std::unordered_map m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim //ICURVEPOVECTOR m_vLoop ; // curve di loop std::vector> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW bool m_bBilinear ; // superficie bilineare From f0bfbb6c857a164a218b9f472f0e047882d2788e Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 2 Aug 2024 15:12:35 +0200 Subject: [PATCH 16/16] EgtGeomKernel : - correzioni e migliorie alla triangolazione con le bezier. --- SurfBezier.cpp | 15 +- Tree.cpp | 628 ++++++++++++++++++++++++++----------------------- Tree.h | 1 + 3 files changed, 337 insertions(+), 307 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index d454768..626707f 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1600,11 +1600,6 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const } } - // conto quanti punti ho in totale, senza eliminare le ripetizioni - int nTotPnt = 0 ; - for ( PolyLine& pl2D : vPL) - nTotPnt+= pl2D.GetPointNbr() ; - // se ho ottenuto meno triangoli di quelli che avrei dovuto avere allora potrei aver avuto un problema in prossimità di un polo // se comunque ho corrispondenza tra vPnt e vPnt3d allora eseguo la trinagolazione in 3d int nTriaNumber = ( vPnt.size() - 2) + (2 * (vPL.size() - 1)) - (vPL.size() > 2 ? vPL.size() - 2 : 0) - (vPL.size() != 1 ? vPL.size() : 0) ; @@ -1713,7 +1708,6 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin) const bool SurfBezier::ReorderPntVector( const POLYLINEVECTOR& vPL, bool bTriangulatedIn3D, const PNTVECTOR& vPnt, const POLYLINEVECTOR& vPLToOrd, PNTVECTOR& vPntOrd) const { - int nCurrPoint = 0 ; BOOLVECTOR vbPolyChecked( vPL.size()) ; fill( vbPolyChecked.begin(), vbPolyChecked.end(), false) ; for ( int p = 0 ; p < int(vPnt.size()) ; ++p) { @@ -4152,6 +4146,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } // reinizializzo la superficie con il nuovo numero di span in U nSpanU = nSpanU0 + nRep1 ; + if( nSpanU != nSpanU1 + nRep0) + LOG_DBG_ERR( GetEGkLogger(), "There could be an errore in the creation of a ruled surface in mode RLT_B_MINDIST") ; if ( nSpanU < max(nSpanU0, nSpanU1)) nSpanU = max(nSpanU0, nSpanU1) ; nSecondRowInd = nDegU * nSpanU + 1 ; @@ -4413,7 +4409,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int int nAtEnd1 = 0 ; Point3d ptP0 ; plU0.GetFirstPoint( ptP0) ; int c = 0 ; - int nCrvCount = 0 ; int nRep0 = 0 ; // match interni consecutivi uguali di punti della curva U0 con punti della curva U1 int nRep1 = 0 ; double dLastParamMatch = 0 ; @@ -4453,7 +4448,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int else { dLastParamMatch = dParam ; ptLastPointMatch = ptJoint ; - nCrvCount = pCrvU1->GetCurveCount() ; // se sono già troppo vicino ad un split esistente allora non faccio nulla if ( abs(dParam - round( dParam)) < 100 * EPS_PARAM) { ++c ; @@ -4527,7 +4521,6 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int else { dLastParamMatch = dParam ; ptLastPointMatch = ptJoint ; - nCrvCount = pCrvU0->GetCurveCount() ; //se sono troppo vicino ad uno split esistente allora non faccio nulla if( abs(dParam - round( dParam)) < 100 * EPS_PARAM) { ++c ; @@ -4660,6 +4653,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0) nSpanU = nSpanU0 + nAtStart0 + nAtEnd0 + nRep1 ; + if( nSpanU != nSpanU1 + nAtStart1 + nAtEnd1 + nRep0) + LOG_DBG_ERR( GetEGkLogger(), "There could be an error in the creation of a ruled surface in mode RLT_B_MINDIST_PLUS") ; + nSecondRowInd = nDegU * nSpanU + 1 ; // inizializzo la superficie Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; @@ -4912,7 +4908,6 @@ SurfBezier::CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez) } SetControlPoint( n + (s * nDegU) + (nDegU * nSpanU + 1) * (g * 3 + 6), ptCtrl2) ; //// trovo i punti di controllo intermedi tra le curve usando la parabola che unisce queste tre curve//// - double dPar = double(n) / nDegU ; Point3d ptP0 = pCrv0->GetControlPoint( n) ; Point3d ptP1 = pCrv1->GetControlPoint( n) ; Point3d ptP2 = pCrv2->GetControlPoint( n) ; diff --git a/Tree.cpp b/Tree.cpp index e84fe62..3d4f2e9 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -327,14 +327,16 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) || ( AreSamePointApprox( ptP00, ptP10) || AreSamePointApprox( ptP01, ptP11))) { // m_bClosed = true ; - if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11)) && (int) m_mTree.size() == 1) { - if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) { - m_mTree[-1].m_nTop = -1 ; - m_mTree[-1].m_nBottom = -1 ; - m_bClosedV = true ; + if ( ( AreSamePointApprox( ptP00, ptP01) || AreSamePointApprox( ptP10, ptP11))) { + if( int( m_mTree.size()) == 1) { + if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11)) { + m_mTree[-1].m_nTop = -1 ; + m_mTree[-1].m_nBottom = -1 ; + m_bClosedV = true ; + } + m_mTree[-1].SetSplitDirVert( false) ; + Split( -1) ; } - m_mTree[-1].SetSplitDirVert( false) ; - Split( -1) ; // qui devo fare il controllo capped ( chiusura a semisfera) // devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti // in caso devo fare uno split nell'altra direzione @@ -350,7 +352,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi } m_vbPole[1] = bPole0 ; m_vbPole[3] = bPole1 ; - if ( bPole0 && bPole1) { + if ( bPole0 && bPole1 && int( m_mTree.size() == 3)) { m_mTree[0].SetSplitDirVert( true) ; Split( 0) ; m_mTree[1].SetSplitDirVert( true) ; @@ -367,29 +369,29 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi } m_mTree[-1].SetSplitDirVert( true) ; Split( -1) ; - // devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti - // in caso devo fare uno split nell'altra direzione - bool bOk = false ; - bool bPole0 = true, bPole1 = true ; - Point3d ptV0, ptV1 ; - // controllo se tutti i punti sull'isoparametrica sono uguali - for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) { - ptV0 = m_pSrfBz->GetControlPoint( i, &bOk) ; - bPole0 = bPole0 && AreSamePointApprox( ptP00, ptV0) ; - ptV1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ; - bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ; - } - m_vbPole[0] = bPole0 ; - m_vbPole[2] = bPole1 ; - if ( bPole0 && bPole1) { - m_mTree[0].SetSplitDirVert( false) ; - Split( 0) ; - m_mTree[1].SetSplitDirVert( false) ; - Split( 1) ; - } + } + // devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti + // in caso devo fare uno split nell'altra direzione + bool bOk = false ; + bool bPole0 = true, bPole1 = true ; + Point3d ptV0, ptV1 ; + // controllo se tutti i punti sull'isoparametrica sono uguali + for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) { + ptV0 = m_pSrfBz->GetControlPoint( i, &bOk) ; + bPole0 = bPole0 && AreSamePointApprox( ptP00, ptV0) ; + ptV1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ; + bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ; + } + m_vbPole[0] = bPole1 ; + m_vbPole[2] = bPole0 ; + if ( bPole0 && bPole1 && int( m_mTree.size()) == 3) { + m_mTree[0].SetSplitDirVert( false) ; + Split( 0) ; + m_mTree[1].SetSplitDirVert( false) ; + Split( 1) ; } // se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1 - else if ( (int) m_mTree.size() > 1 && (int) m_mTree.size() < 4 && ! m_mTree.at(-1).IsSplitVert()) { // si può mettere anche < 5 + if ( int( m_mTree.size() == 3) && ! m_mTree.at(-1).IsSplitVert()) { m_mTree[0].m_nLeft = -1 ; m_mTree[0].m_nRight = -1 ; m_mTree[1].m_nLeft = -1 ; @@ -695,27 +697,27 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) { // suddivido lo spazio parametrico con divisioni a metà su uno dei due parametri int nCToSplit = -1 ; - Cell* cToSplit = &m_mTree[nCToSplit] ; + Cell* pcToSplit = &m_mTree[nCToSplit] ; if ( ! m_bBilinear) { - while ( nCToSplit != -2 && cToSplit->IsProcessed() == false) { + while ( nCToSplit != -2 && pcToSplit->IsProcessed() == false) { // controllo che la cella non sia già stata preliminarmente splittata - if ( cToSplit->IsLeaf()) { + if ( pcToSplit->IsLeaf()) { // calcolo in quale direzione ho più curvatura // ptP00P10 è un punto tra P00 e P10 double dCurvU = 0, dCurvV = 0 ; - double dLenParU = ( cToSplit->GetTopRight().x - cToSplit->GetBottomLeft().x) / SBZ_TREG_COEFF ; - double dLenParV = ( cToSplit->GetTopRight().y - cToSplit->GetBottomLeft().y) / SBZ_TREG_COEFF ; + double dLenParU = ( pcToSplit->GetTopRight().x - pcToSplit->GetBottomLeft().x) / SBZ_TREG_COEFF ; + double dLenParV = ( pcToSplit->GetTopRight().y - pcToSplit->GetBottomLeft().y) / SBZ_TREG_COEFF ; if ( dLenParU <= 1. / m_nDegV || dLenParV <= 1. / m_nDegU || Dist(m_mVert[nCToSplit][0], m_mVert[nCToSplit][2]) < dSideMin * 2 || Dist(m_mVert[nCToSplit][1], m_mVert[nCToSplit][3]) < dSideMin * 2) { - double dU = ( cToSplit->GetTopRight().x + cToSplit->GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ; - double dV = ( cToSplit->GetTopRight().y + cToSplit->GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ; + double dU = ( pcToSplit->GetTopRight().x + pcToSplit->GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ; + double dV = ( pcToSplit->GetTopRight().y + pcToSplit->GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ; double dULoc = 0.5, dVLoc = 0.5 ; Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00 ; m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; - m_pSrfBz->GetPointD1D2( dU, cToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; - m_pSrfBz->GetPointD1D2( cToSplit->GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; - m_pSrfBz->GetPointD1D2( dU, cToSplit->GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; - m_pSrfBz->GetPointD1D2( cToSplit->GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; + m_pSrfBz->GetPointD1D2( dU, pcToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; + m_pSrfBz->GetPointD1D2( pcToSplit->GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; + m_pSrfBz->GetPointD1D2( dU, pcToSplit->GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; + m_pSrfBz->GetPointD1D2( pcToSplit->GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; Point3d ptV = ( 1 - dULoc) * ptP00P10 + dULoc * ptP11P01 ; Point3d ptU = ( 1 - dVLoc) * ptP10P11 + dVLoc * ptP01P00 ; dCurvV = Dist( ptV, ptPSrf) ; @@ -727,13 +729,13 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) Point3d ptPSrf, ptP00P10, ptP10P11, ptP11P01, ptP01P00, ptPSrfMid ; double dStep = 1. / ( m_nDegU * 2) ; for ( double k = dStep ; k < 1 + EPS_SMALL ; k = k + dStep) { - double dU = ( k * cToSplit->GetTopRight().x + ( 1 - k) * cToSplit->GetBottomLeft().x) / SBZ_TREG_COEFF ; - double dV = ( cToSplit->GetTopRight().y + cToSplit->GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ; + double dU = ( k * pcToSplit->GetTopRight().x + ( 1 - k) * pcToSplit->GetBottomLeft().x) / SBZ_TREG_COEFF ; + double dV = ( pcToSplit->GetTopRight().y + pcToSplit->GetBottomLeft().y) / 2 / SBZ_TREG_COEFF ; m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; if ( k == 0.5) ptPSrfMid = ptPSrf ; - m_pSrfBz->GetPointD1D2( dU, cToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; - m_pSrfBz->GetPointD1D2( dU, cToSplit->GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; + m_pSrfBz->GetPointD1D2( dU, pcToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00P10) ; + m_pSrfBz->GetPointD1D2( dU, pcToSplit->GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP11P01) ; CurveLine clV ; clV.Set( ptP00P10, ptP11P01) ; DistPointCurve dpc( ptPSrf, clV) ; @@ -743,14 +745,14 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } dStep = 1. / ( m_nDegV * 2) ; for ( double k = dStep ; k < 1 + EPS_SMALL ; k = k + dStep) { - double dU = ( cToSplit->GetTopRight().x + cToSplit->GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ; - double dV = ( k * cToSplit->GetTopRight().y + ( 1 - k) * cToSplit->GetBottomLeft().y) / SBZ_TREG_COEFF ; + double dU = ( pcToSplit->GetTopRight().x + pcToSplit->GetBottomLeft().x) / 2 / SBZ_TREG_COEFF ; + double dV = ( k * pcToSplit->GetTopRight().y + ( 1 - k) * pcToSplit->GetBottomLeft().y) / SBZ_TREG_COEFF ; if ( k == 0.5 && ! AreSamePointApprox( ORIG, ptPSrfMid)) ptPSrf = ptPSrfMid ; else m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; - m_pSrfBz->GetPointD1D2( cToSplit->GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; - m_pSrfBz->GetPointD1D2( cToSplit->GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; + m_pSrfBz->GetPointD1D2( pcToSplit->GetTopRight().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10P11) ; + m_pSrfBz->GetPointD1D2( pcToSplit->GetBottomLeft().x / SBZ_TREG_COEFF, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01P00) ; CurveLine clU ; clU.Set( ptP01P00, ptP10P11) ; DistPointCurve dpc( ptPSrf, clU) ; @@ -807,7 +809,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) // lungo la direzione U ho una curvatura maggiore bVert = true ; } - cToSplit->SetSplitDirVert( bVert) ; + pcToSplit->SetSplitDirVert( bVert) ; //Point3d ptP00, ptP10, ptP11, ptP01 ; //ptP00 = m_mVert[nCToSplit][0] ; //ptP10 = m_mVert[nCToSplit][1] ; @@ -819,19 +821,19 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) double dLen2 = Dist( ptP01, ptP11) ; double dLen3 = Dist( ptP00, ptP01) ; if ( dLen0 < EPS_ZERO && dLen2 < EPS_ZERO ) { - double dV = ( cToSplit->GetBottomLeft().y + cToSplit->GetTopRight().y) / 2 / SBZ_TREG_COEFF ; + double dV = ( pcToSplit->GetBottomLeft().y + pcToSplit->GetTopRight().y) / 2 / SBZ_TREG_COEFF ; PtrOwner pCrvV( m_pSrfBz->GetCurveOnU( dV)) ; double dLenU0, dLenU1 ; - pCrvV->GetLengthAtParam( cToSplit->GetBottomLeft().x / SBZ_TREG_COEFF, dLenU0) ; - pCrvV->GetLengthAtParam( cToSplit->GetTopRight().x / SBZ_TREG_COEFF, dLenU1) ; + pCrvV->GetLengthAtParam( pcToSplit->GetBottomLeft().x / SBZ_TREG_COEFF, dLenU0) ; + pCrvV->GetLengthAtParam( pcToSplit->GetTopRight().x / SBZ_TREG_COEFF, dLenU1) ; dLen0 = abs( dLenU1 - dLenU0) ; } if ( dLen1 < EPS_ZERO && dLen3 < EPS_ZERO ) { - double dU = ( cToSplit->GetBottomLeft().x + cToSplit->GetTopRight().x) / 2 / SBZ_TREG_COEFF ; + double dU = ( pcToSplit->GetBottomLeft().x + pcToSplit->GetTopRight().x) / 2 / SBZ_TREG_COEFF ; PtrOwner pCrvU( m_pSrfBz->GetCurveOnV( dU)) ; double dLenV0, dLenV1 ; - pCrvU->GetLengthAtParam( cToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, dLenV0) ; - pCrvU->GetLengthAtParam( cToSplit->GetTopRight().y / SBZ_TREG_COEFF, dLenV1) ; + pCrvU->GetLengthAtParam( pcToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, dLenV0) ; + pCrvU->GetLengthAtParam( pcToSplit->GetTopRight().y / SBZ_TREG_COEFF, dLenV1) ; dLen1 = abs( dLenV1 - dLenV0) ; } // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare @@ -874,9 +876,9 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) int nStepsV = int( 51 * dDimV + 5 * ( 1 - dDimV)) ; for ( int u = 0 ; u < nStepsU && ! bSplit ; ++ u) { double dU = double ( u) / double ( nStepsU - 1) ; - double dULoc = ( ( 1 - dU) * cToSplit->GetBottomLeft().x + dU * cToSplit->GetTopRight().x) / SBZ_TREG_COEFF ; - if ( ! m_pSrfBz->GetPointD1D2( dULoc, cToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) || - ! m_pSrfBz->GetPointD1D2( dULoc, cToSplit->GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1)) + double dULoc = ( ( 1 - dU) * pcToSplit->GetBottomLeft().x + dU * pcToSplit->GetTopRight().x) / SBZ_TREG_COEFF ; + if ( ! m_pSrfBz->GetPointD1D2( dULoc, pcToSplit->GetBottomLeft().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz0) || + ! m_pSrfBz->GetPointD1D2( dULoc, pcToSplit->GetTopRight().y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBz1)) return false ; // verifico che la cella non sia uno spicchio in verticale, cioè con ptP00 == ptP01 && ptP10 == ptP11 // ( vedi disegno sotto per uno spicchio verticale) @@ -897,7 +899,7 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) clV.Set( pt0010, pt0111) ; for ( int v = 0 ; v < nStepsV ; ++ v) { double dV = double ( v) / double ( nStepsV - 1) ; - double dVLoc = ( ( 1 - dV) * cToSplit->GetBottomLeft().y + dV * cToSplit->GetTopRight().y) / SBZ_TREG_COEFF ; + double dVLoc = ( ( 1 - dV) * pcToSplit->GetBottomLeft().y + dV * pcToSplit->GetTopRight().y) / SBZ_TREG_COEFF ; if ( ! m_pSrfBz->GetPointD1D2( dULoc, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBzV)) return false ; DistPointCurve dpc( ptBzV, clV) ; @@ -934,42 +936,42 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } if ( bSplit || dSideMaxVal > dSideMax) { - cToSplit->SetSplitDirVert( bVert) ; + pcToSplit->SetSplitDirVert( bVert) ; // effettuo lo split Split( nCToSplit) ; // procedo con lo split del Child1 - nCToSplit = cToSplit->m_nChild1 ; - cToSplit = &m_mTree[nCToSplit] ; + nCToSplit = pcToSplit->m_nChild1 ; + pcToSplit = &m_mTree[nCToSplit] ; } else { // sono arrivato ad una cella Leaf, quindi salvo la cella m_vnLeaves.push_back( nCToSplit) ; - cToSplit->SetProcessed() ; + pcToSplit->SetProcessed() ; // risalgo i parent finché non trovo il primo Child2 da processare - nCToSplit = cToSplit->m_nParent ; - cToSplit = &m_mTree[nCToSplit] ; + nCToSplit = pcToSplit->m_nParent ; + pcToSplit = &m_mTree[nCToSplit] ; if ( nCToSplit == -2) return true ; - if ( m_mTree[cToSplit->m_nChild1].IsProcessed() && m_mTree[cToSplit->m_nChild2].IsProcessed()) - cToSplit->SetProcessed() ; - while ( m_mTree[cToSplit->m_nChild2].IsProcessed()) { - if ( cToSplit->m_nParent != -2) { - nCToSplit = cToSplit->m_nParent ; - cToSplit = &m_mTree[nCToSplit] ; + if ( m_mTree[pcToSplit->m_nChild1].IsProcessed() && m_mTree[pcToSplit->m_nChild2].IsProcessed()) + pcToSplit->SetProcessed() ; + while ( m_mTree[pcToSplit->m_nChild2].IsProcessed()) { + if ( pcToSplit->m_nParent != -2) { + nCToSplit = pcToSplit->m_nParent ; + pcToSplit = &m_mTree[nCToSplit] ; } - if ( m_mTree[cToSplit->m_nChild1].IsProcessed() && m_mTree[cToSplit->m_nChild2].IsProcessed()) - cToSplit->SetProcessed() ; - if ( nCToSplit == -1 && m_mTree[cToSplit->m_nChild2].IsProcessed()) + if ( m_mTree[pcToSplit->m_nChild1].IsProcessed() && m_mTree[pcToSplit->m_nChild2].IsProcessed()) + pcToSplit->SetProcessed() ; + if ( nCToSplit == -1 && m_mTree[pcToSplit->m_nChild2].IsProcessed()) break ; } - nCToSplit = cToSplit->m_nChild2 ; - cToSplit = &m_mTree[nCToSplit] ; + nCToSplit = pcToSplit->m_nChild2 ; + pcToSplit = &m_mTree[nCToSplit] ; } } else { - nCToSplit = cToSplit->m_nChild1 ; - cToSplit = &m_mTree[nCToSplit] ; + nCToSplit = pcToSplit->m_nChild1 ; + pcToSplit = &m_mTree[nCToSplit] ; } } Balance() ; // da implementare quando dividerò ad un parametro a scelta e non a metà // probabilmente mi servirà salvare nella cella il livello di profondità @@ -977,8 +979,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) // bilineare else { bool bIsPlanar = m_pSrfBz->IsPlanar() ; - while ( nCToSplit != -2 && cToSplit->IsProcessed() == false) { - if ( cToSplit->IsLeaf()) { + while ( nCToSplit != -2 && pcToSplit->IsProcessed() == false) { + if ( pcToSplit->IsLeaf()) { // vertici della cella Point3d ptP00, ptP10, ptP11, ptP01 ; ptP00 = m_mVert[nCToSplit][0] ; @@ -1002,10 +1004,10 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } else { for ( double i = 0.25 ; i < 1 ; i = i + 0.25) { - dU = ( ( 1 - i) * cToSplit->GetBottomLeft().x + i * cToSplit->GetTopRight().x) / SBZ_TREG_COEFF ; - dV = ( ( 1 - i) * cToSplit->GetBottomLeft().y + i * cToSplit->GetTopRight().y) / SBZ_TREG_COEFF ; - double dVLoc = ( cToSplit->GetBottomLeft().y + cToSplit->GetTopRight().y) / 2 / SBZ_TREG_COEFF ; - double dULoc = ( cToSplit->GetBottomLeft().x + cToSplit->GetTopRight().x) / 2 / SBZ_TREG_COEFF ; + dU = ( ( 1 - i) * pcToSplit->GetBottomLeft().x + i * pcToSplit->GetTopRight().x) / SBZ_TREG_COEFF ; + dV = ( ( 1 - i) * pcToSplit->GetBottomLeft().y + i * pcToSplit->GetTopRight().y) / SBZ_TREG_COEFF ; + double dVLoc = ( pcToSplit->GetBottomLeft().y + pcToSplit->GetTopRight().y) / 2 / SBZ_TREG_COEFF ; + double dULoc = ( pcToSplit->GetBottomLeft().x + pcToSplit->GetTopRight().x) / 2 / SBZ_TREG_COEFF ; m_pSrfBz->GetPointD1D2( dU, dVLoc, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfU) ; m_pSrfBz->GetPointD1D2( dULoc, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrfV) ; vPtU.push_back( ptPSrfU) ; @@ -1046,8 +1048,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } for ( double i = 0.25 ; i < 1 ; i = i + 0.25) { for ( double j = 0.25 ; j < 1 ; j = j + 0.25) { - double dU = ( ( 1 - i) * cToSplit->GetTopRight().x + i * cToSplit->GetBottomLeft().x) / SBZ_TREG_COEFF ; - double dV = ( ( 1 - j) * cToSplit->GetTopRight().y + j * cToSplit->GetBottomLeft().y) / SBZ_TREG_COEFF ; + double dU = ( ( 1 - i) * pcToSplit->GetTopRight().x + i * pcToSplit->GetBottomLeft().x) / SBZ_TREG_COEFF ; + double dV = ( ( 1 - j) * pcToSplit->GetTopRight().y + j * pcToSplit->GetBottomLeft().y) / SBZ_TREG_COEFF ; m_pSrfBz->GetPointD1D2( dU, dV, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptPSrf) ; dErr = max( abs( DistPointPlane( ptPSrf, plAppr)), dErr) ; } @@ -1059,42 +1061,42 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } // se la cella è abbastanza grande da poter essere divisa ancora e devo approssimare meglio, la divido if ( dSideMinVal / 2 >= dSideMin && dSideMaxVal < dSideMax && dErr > dLinTol) { - cToSplit->SetSplitDirVert( bVert) ; + pcToSplit->SetSplitDirVert( bVert) ; // effettuo lo split Split( nCToSplit) ; // procedo con lo split del Child1 - nCToSplit = cToSplit->m_nChild1 ; - cToSplit = &m_mTree[nCToSplit] ; + nCToSplit = pcToSplit->m_nChild1 ; + pcToSplit = &m_mTree[nCToSplit] ; } else { // sono arrivato ad una cella Leaf, quindi salvo la cella m_vnLeaves.push_back( nCToSplit) ; - cToSplit->SetProcessed() ; + pcToSplit->SetProcessed() ; // risalgo i parent finché non trovo il primo Child2 da processare - nCToSplit = cToSplit->m_nParent ; - cToSplit = &m_mTree[nCToSplit] ; + nCToSplit = pcToSplit->m_nParent ; + pcToSplit = &m_mTree[nCToSplit] ; if ( nCToSplit == -2) return true ; - if ( m_mTree[cToSplit->m_nChild1].IsProcessed() && m_mTree[cToSplit->m_nChild2].IsProcessed()) - cToSplit->SetProcessed() ; - while ( m_mTree[cToSplit->m_nChild2].IsProcessed()) { - if ( cToSplit->m_nParent != -2) { - nCToSplit = cToSplit->m_nParent ; - cToSplit = &m_mTree[nCToSplit] ; + if ( m_mTree[pcToSplit->m_nChild1].IsProcessed() && m_mTree[pcToSplit->m_nChild2].IsProcessed()) + pcToSplit->SetProcessed() ; + while ( m_mTree[pcToSplit->m_nChild2].IsProcessed()) { + if ( pcToSplit->m_nParent != -2) { + nCToSplit = pcToSplit->m_nParent ; + pcToSplit = &m_mTree[nCToSplit] ; } - if ( m_mTree[cToSplit->m_nChild1].IsProcessed() && m_mTree[cToSplit->m_nChild2].IsProcessed()) - cToSplit->SetProcessed() ; - if ( nCToSplit == -1 && m_mTree[cToSplit->m_nChild2].IsProcessed()) + if ( m_mTree[pcToSplit->m_nChild1].IsProcessed() && m_mTree[pcToSplit->m_nChild2].IsProcessed()) + pcToSplit->SetProcessed() ; + if ( nCToSplit == -1 && m_mTree[pcToSplit->m_nChild2].IsProcessed()) break ; } - nCToSplit = cToSplit->m_nChild2 ; - cToSplit = &m_mTree[nCToSplit] ; + nCToSplit = pcToSplit->m_nChild2 ; + pcToSplit = &m_mTree[nCToSplit] ; } } else { - nCToSplit = cToSplit->m_nChild1 ; - cToSplit = &m_mTree[nCToSplit] ; + nCToSplit = pcToSplit->m_nChild1 ; + pcToSplit = &m_mTree[nCToSplit] ; } } } @@ -2285,12 +2287,13 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // qui mi devo salvare quanti elementi ho già nel vettore m_vInters della cella // per poter fare il merge con l'ultimo vptInters della curva di trim, che sarà ancora in questa cella // e terminerà nel punto di start - int nPass = (int) m_mTree[nId].m_vInters.size() ; - m_mTree[nId].m_vInters.emplace_back() ; + Cell* pCell = &m_mTree[nId] ; + int nPass = (int) pCell->m_vInters.size() ; + pCell->m_vInters.emplace_back() ; // salvo il verso del loop - m_mTree[nId].m_vInters.back().bCCW = bCCW ; + pCell->m_vInters.back().bCCW = bCCW ; // salvo il chunk del loop - m_mTree[nId].m_vInters.back().nChunk = m_mChunk[i] ; + pCell->m_vInters.back().nChunk = m_mChunk[i] ; bool bLoopInside = true ; Point3d ptCurr ; auto iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ; @@ -2330,10 +2333,12 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // ricalcolo la posizione di nId nel vettore delle foglie iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ; nIdPolygon = distance( m_vnLeaves.begin(), iter) ; + // aggiorno il puntatore alla cella + pCell = &m_mTree[nId] ; // salvo il verso del loop - m_mTree[nId].m_vInters.back().bCCW = bCCW ; + pCell->m_vInters.back().bCCW = bCCW ; // salvo il chunk del loop - m_mTree[nId].m_vInters.back().nChunk = m_mChunk[i] ; + pCell->m_vInters.back().nChunk = m_mChunk[i] ; // aggiorno la polyline splittata UpdateSplitLoop( plLoopSplit, nPtLoopSplit, vptInters.back()) ; } @@ -2347,16 +2352,16 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) } if ( nId == nFirstCell) vptInters.pop_back() ; - m_mTree[nId].m_vInters.back().vpt = vptInters ; + pCell->m_vInters.back().vpt = vptInters ; if ( bLoopInside) { // setto la categoria della cella - if ( m_mTree[nId].m_nFlag == -1) - m_mTree[nId].m_nFlag = 2 ; - else if ( m_mTree[nId].m_nFlag == 1) - m_mTree[nId].m_nFlag = 3 ; + if ( pCell->m_nFlag == -1) + pCell->m_nFlag = 2 ; + else if ( pCell->m_nFlag == 1) + pCell->m_nFlag = 3 ; // setto i lati di ingresso e uscita a -1 per indicare che ho un loop interno alla cella - m_mTree[nId].m_vInters.back().nIn = -1 ; - m_mTree[nId].m_vInters.back().nOut = -1 ; + pCell->m_vInters.back().nIn = -1 ; + pCell->m_vInters.back().nOut = -1 ; } // sono tornato alla cella di partenza, quindi devo fare il merge dei due vettori di intersezione che ho creato per questa cella // per lo stesso loop @@ -2364,7 +2369,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // verifico se sono effettivamente nella cella di partenza o in una cella adiacente if ( nId != nFirstCell) { Point3d ptFirst = m_mTree[nFirstCell].m_vInters[nPass].vpt[0] ; - Point3d ptLast = m_mTree[nId].m_vInters.back().vpt.back() ; + Point3d ptLast = pCell->m_vInters.back().vpt.back() ; //sistemo l'ingresso della prima cella int nEdge ; if ( ! OnWhichEdge( nFirstCell, ptFirst, nEdge)) @@ -2373,23 +2378,23 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // sistemo l'uscita dell'ultima cella if ( ! OnWhichEdge( nId, ptLast, nEdge)) return false ; - m_mTree[nId].m_vInters.back().nOut = nEdge ; + pCell->m_vInters.back().nOut = nEdge ; // sistemo il flag dell'ultima cella - if ( m_mTree[nId].m_nFlag == -1) - m_mTree[nId].m_nFlag = 1 ; - else if ( m_mTree[nId].m_nFlag == 2) - m_mTree[nId].m_nFlag = 3 ; + if ( pCell->m_nFlag == -1) + pCell->m_nFlag = 1 ; + else if ( pCell->m_nFlag == 2) + pCell->m_nFlag = 3 ; } // sono tornato nella cella iniziale, quindi giunto i due vettori intersezione else if ( nId == nFirstCell) { - int nOut = m_mTree[nId].m_vInters[nPass].nOut ; - m_mTree[nId].m_vInters.back().vpt.insert( m_mTree[nId].m_vInters.back().vpt.end(), - m_mTree[nId].m_vInters[nPass].vpt.begin(), - m_mTree[nId].m_vInters[nPass].vpt.end()) ; - m_mTree[nId].m_vInters[nPass] = m_mTree[nId].m_vInters.back() ; - m_mTree[nId].m_vInters.pop_back() ; + int nOut = pCell->m_vInters[nPass].nOut ; + pCell->m_vInters.back().vpt.insert( pCell->m_vInters.back().vpt.end(), + pCell->m_vInters[nPass].vpt.begin(), + pCell->m_vInters[nPass].vpt.end()) ; + pCell->m_vInters[nPass] = pCell->m_vInters.back() ; + pCell->m_vInters.pop_back() ; // sistemo il lato d'uscita - m_mTree[nId].m_vInters[nPass].nOut = nOut ; + pCell->m_vInters[nPass].nOut = nOut ; } } // salvo la polyline splittata @@ -2545,8 +2550,9 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) bool Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, PNTVECTOR& vptInters, bool bFirstInters) { - Point3d ptTR = m_mTree[nId].GetTopRight() ; - Point3d ptBL = m_mTree[nId].GetBottomLeft() ; + Cell* pCell = &m_mTree.at(nId) ; + Point3d ptTR = pCell->GetTopRight() ; + Point3d ptBL = pCell->GetBottomLeft() ; Point3d ptTl( ptBL.x , ptTR.y) ; Point3d ptBr( ptTR.x , ptBL.y) ; int nEdge ; // flag che indica il lato su cui ho l'intersezione a partire dal lato top in senso antiorario @@ -2586,7 +2592,7 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, // determino il lato/vertice di uscita if( ! OnWhichEdge( nId, ptInters, nEdge)) return false ; - m_mTree[nId].m_vInters.back().nOut = nEdge ; + pCell->m_vInters.back().nOut = nEdge ; // se è risultato che sono abbastanza vicino( di EPS_SMALL) ad un vertice allora il punto aggiunto sarà il vertice vero e proprio // se è abbastanza vicino ad un lato allora modifico le sue coordinate in modo che sia esattamente sul lato if ( nEdge == 0) @@ -2616,15 +2622,15 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, // salvo il vettore intersezione per la cella e capisco in quale altra cella passare if ( (int)vptInters.size() == 1) - m_mTree[nId].m_vInters.back().vpt.push_back( vptInters[0]) ; + pCell->m_vInters.back().vpt.push_back( vptInters[0]) ; else - m_mTree[nId].m_vInters.back().vpt = vptInters ; + pCell->m_vInters.back().vpt = vptInters ; vptInters.clear() ; // setto la categoria della cella - if ( m_mTree[nId].m_nFlag == -1) - m_mTree[nId].m_nFlag = 1 ; - else if ( m_mTree[nId].m_nFlag == 2) - m_mTree[nId].m_nFlag = 3 ; + if ( pCell->m_nFlag == -1) + pCell->m_nFlag = 1 ; + else if ( pCell->m_nFlag == 2) + pCell->m_nFlag = 3 ; // seleziono la cella successiva da analizzare // @@ -2640,16 +2646,18 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, break ; } } - m_mTree[nId].m_vInters.emplace_back() ; - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - if ( ptInters.x > m_mTree[nId].GetBottomLeft().x + EPS_SMALL && ptInters.x < m_mTree[nId].GetTopRight().x - EPS_SMALL) - m_mTree[nId].m_vInters.back().nIn = 2 ; - else if ( AreSamePointXYApprox( ptInters, m_mTree[nId].GetBottomLeft())) - m_mTree[nId].m_vInters.back().nIn = 5 ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; + Point3d ptBr( pCell->GetTopRight().x, pCell->GetBottomLeft().y) ; + if ( ptInters.x > pCell->GetBottomLeft().x + EPS_SMALL && ptInters.x < pCell->GetTopRight().x - EPS_SMALL) + pCell->m_vInters.back().nIn = 2 ; + else if ( AreSamePointXYApprox( ptInters, pCell->GetBottomLeft())) + pCell->m_vInters.back().nIn = 5 ; else if ( AreSamePointXYApprox( ptInters, ptBr)) - m_mTree[nId].m_vInters.back().nIn = 6 ; + pCell->m_vInters.back().nIn = 6 ; else - m_mTree[nId].m_vInters.back().nIn = 2 ; + pCell->m_vInters.back().nIn = 2 ; } else if ( nEdge == 1) { GetLeftNeigh( nId, vNeigh) ; @@ -2660,16 +2668,18 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, break ; } } - m_mTree[nId].m_vInters.emplace_back() ; - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - if ( ptInters.y > m_mTree[nId].GetBottomLeft().y + EPS_SMALL && ptInters.y < m_mTree[nId].GetTopRight().y - EPS_SMALL) - m_mTree[nId].m_vInters.back().nIn = 3 ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; + Point3d ptBr( pCell->GetTopRight().x, pCell->GetBottomLeft().y) ; + if ( ptInters.y > pCell->GetBottomLeft().y + EPS_SMALL && ptInters.y < pCell->GetTopRight().y - EPS_SMALL) + pCell->m_vInters.back().nIn = 3 ; else if ( AreSamePointXYApprox( ptInters, ptBr)) - m_mTree[nId].m_vInters.back().nIn = 6 ; - else if ( AreSamePointXYApprox( ptInters, m_mTree[nId].GetTopRight())) - m_mTree[nId].m_vInters.back().nIn = 7 ; + pCell->m_vInters.back().nIn = 6 ; + else if ( AreSamePointXYApprox( ptInters, pCell->GetTopRight())) + pCell->m_vInters.back().nIn = 7 ; else - m_mTree[nId].m_vInters.back().nIn = 3 ; + pCell->m_vInters.back().nIn = 3 ; } else if ( nEdge == 2) { GetBottomNeigh( nId, vNeigh) ; @@ -2679,16 +2689,18 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, break ; } } - m_mTree[nId].m_vInters.emplace_back() ; - Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - if ( ptInters.x > m_mTree[nId].GetBottomLeft().x + EPS_SMALL && ptInters.x < m_mTree[nId].GetTopRight().x - EPS_SMALL) - m_mTree[nId].m_vInters.back().nIn = 0 ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; + Point3d ptTl( pCell->GetBottomLeft().x, pCell->GetTopRight().y) ; + if ( ptInters.x > pCell->GetBottomLeft().x + EPS_SMALL && ptInters.x < pCell->GetTopRight().x - EPS_SMALL) + pCell->m_vInters.back().nIn = 0 ; else if ( AreSamePointXYApprox( ptInters, ptTl)) - m_mTree[nId].m_vInters.back().nIn = 4 ; - else if ( AreSamePointXYApprox( ptInters, m_mTree[nId].GetTopRight())) - m_mTree[nId].m_vInters.back().nIn = 7 ; + pCell->m_vInters.back().nIn = 4 ; + else if ( AreSamePointXYApprox( ptInters, pCell->GetTopRight())) + pCell->m_vInters.back().nIn = 7 ; else - m_mTree[nId].m_vInters.back().nIn = 0 ; + pCell->m_vInters.back().nIn = 0 ; } else if ( nEdge == 3) { GetRightNeigh( nId, vNeigh) ; @@ -2698,16 +2710,18 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, break ; } } - m_mTree[nId].m_vInters.emplace_back() ; - Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; - if ( ptInters.y > m_mTree[nId].GetBottomLeft().y + EPS_SMALL && ptInters.y < m_mTree[nId].GetTopRight().y - EPS_SMALL) - m_mTree[nId].m_vInters.back().nIn = 1 ; - else if ( AreSamePointXYApprox( ptInters, m_mTree[nId].GetBottomLeft())) - m_mTree[nId].m_vInters.back().nIn = 5 ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; + Point3d ptTl( pCell->GetBottomLeft().x, pCell->GetTopRight().y) ; + if ( ptInters.y > pCell->GetBottomLeft().y + EPS_SMALL && ptInters.y < pCell->GetTopRight().y - EPS_SMALL) + pCell->m_vInters.back().nIn = 1 ; + else if ( AreSamePointXYApprox( ptInters, pCell->GetBottomLeft())) + pCell->m_vInters.back().nIn = 5 ; else if ( AreSamePointXYApprox( ptInters, ptTl)) - m_mTree[nId].m_vInters.back().nIn = 4 ; + pCell->m_vInters.back().nIn = 4 ; else - m_mTree[nId].m_vInters.back().nIn = 1 ; + pCell->m_vInters.back().nIn = 1 ; } // esco da uno dei vertici else if ( nEdge == 4) { @@ -2719,28 +2733,32 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, // ingresso dal basso if ( ! nPossible.empty()) { nId = nPossible[0] ; - m_mTree[nId].m_vInters.emplace_back() ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + Point3d ptBr( pCell->GetTopRight().x, pCell->GetBottomLeft().y) ; if ( AreSamePointXYExact( ptInters, ptBr)) - m_mTree[nId].m_vInters.back().nIn = 6 ; - else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetBottomLeft())) - m_mTree[nId].m_vInters.back().nIn = 5 ; + pCell->m_vInters.back().nIn = 6 ; + else if ( AreSamePointXYExact( ptInters, pCell->GetBottomLeft())) + pCell->m_vInters.back().nIn = 5 ; else - m_mTree[nId].m_vInters.back().nIn = 2 ; + pCell->m_vInters.back().nIn = 2 ; } // ingresso da destra else if ( ! nPossible1.empty()) { nId = nPossible1.back() ; - m_mTree[nId].m_vInters.emplace_back() ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + Point3d ptBr( pCell->GetTopRight().x, pCell->GetBottomLeft().y) ; if ( AreSamePointXYExact( ptInters, ptBr)) - m_mTree[nId].m_vInters.back().nIn = 6 ; - else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetTopRight())) - m_mTree[nId].m_vInters.back().nIn = 7 ; + pCell->m_vInters.back().nIn = 6 ; + else if ( AreSamePointXYExact( ptInters, pCell->GetTopRight())) + pCell->m_vInters.back().nIn = 7 ; else - m_mTree[nId].m_vInters.back().nIn = 3 ; + pCell->m_vInters.back().nIn = 3 ; } // ingresso in diagonale else { @@ -2770,28 +2788,32 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, // ingresso dal destra if ( ! nPossible.empty()) { nId = nPossible[0] ; - m_mTree[nId].m_vInters.emplace_back() ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + Point3d ptBr( pCell->GetTopRight().x, pCell->GetBottomLeft().y) ; if ( AreSamePointXYExact( ptInters, ptBr)) - m_mTree[nId].m_vInters.back().nIn = 6 ; - else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetTopRight())) - m_mTree[nId].m_vInters.back().nIn = 7 ; + pCell->m_vInters.back().nIn = 6 ; + else if ( AreSamePointXYExact( ptInters, pCell->GetTopRight())) + pCell->m_vInters.back().nIn = 7 ; else - m_mTree[nId].m_vInters.back().nIn = 3 ; + pCell->m_vInters.back().nIn = 3 ; } // ingresso dall'alto else if ( ! nPossible1.empty()) { nId = nPossible1[0] ; - m_mTree[nId].m_vInters.emplace_back() ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato - Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; + Point3d ptTl( pCell->GetBottomLeft().x, pCell->GetTopRight().y) ; if ( AreSamePointXYExact( ptInters, ptTl)) - m_mTree[nId].m_vInters.back().nIn = 4 ; - else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetTopRight())) - m_mTree[nId].m_vInters.back().nIn = 7 ; + pCell->m_vInters.back().nIn = 4 ; + else if ( AreSamePointXYExact( ptInters, pCell->GetTopRight())) + pCell->m_vInters.back().nIn = 7 ; else - m_mTree[nId].m_vInters.back().nIn = 0 ; + pCell->m_vInters.back().nIn = 0 ; } // ingresso in diagonale else { @@ -2821,28 +2843,32 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, // ingresso dall'alto if ( ! nPossible.empty()) { nId = nPossible.back() ; - m_mTree[nId].m_vInters.emplace_back() ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato - Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; + Point3d ptTl( pCell->GetBottomLeft().x, pCell->GetTopRight().y) ; if ( AreSamePointXYExact( ptInters, ptTl)) - m_mTree[nId].m_vInters.back().nIn = 4 ; - else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetTopRight())) - m_mTree[nId].m_vInters.back().nIn = 7 ; + pCell->m_vInters.back().nIn = 4 ; + else if ( AreSamePointXYExact( ptInters, pCell->GetTopRight())) + pCell->m_vInters.back().nIn = 7 ; else - m_mTree[nId].m_vInters.back().nIn = 0 ; + pCell->m_vInters.back().nIn = 0 ; } // ingresso da sinistra else if ( ! nPossible1.empty()) { nId = nPossible1[0] ; - m_mTree[nId].m_vInters.emplace_back() ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato - Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; + Point3d ptTl( pCell->GetBottomLeft().x, pCell->GetTopRight().y) ; if ( AreSamePointXYExact( ptInters, ptTl)) - m_mTree[nId].m_vInters.back().nIn = 4 ; - else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetBottomLeft())) - m_mTree[nId].m_vInters.back().nIn = 5 ; + pCell->m_vInters.back().nIn = 4 ; + else if ( AreSamePointXYExact( ptInters, pCell->GetBottomLeft())) + pCell->m_vInters.back().nIn = 5 ; else - m_mTree[nId].m_vInters.back().nIn = 1 ; + pCell->m_vInters.back().nIn = 1 ; } // ingresso in diagonale else { @@ -2872,28 +2898,32 @@ Tree::FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, // ingresso da sinistra if ( ! nPossible.empty()) { nId = nPossible.back() ; - m_mTree[nId].m_vInters.emplace_back() ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato - Point3d ptTl( m_mTree[nId].GetBottomLeft().x, m_mTree[nId].GetTopRight().y) ; + Point3d ptTl( pCell->GetBottomLeft().x, pCell->GetTopRight().y) ; if ( AreSamePointXYExact( ptInters, ptTl)) - m_mTree[nId].m_vInters.back().nIn = 4 ; - else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetBottomLeft())) - m_mTree[nId].m_vInters.back().nIn = 5 ; + pCell->m_vInters.back().nIn = 4 ; + else if ( AreSamePointXYExact( ptInters, pCell->GetBottomLeft())) + pCell->m_vInters.back().nIn = 5 ; else - m_mTree[nId].m_vInters.back().nIn = 1 ; + pCell->m_vInters.back().nIn = 1 ; } // ingresso dal basso else if ( ! nPossible1.empty()) { nId = nPossible1.back() ; - m_mTree[nId].m_vInters.emplace_back() ; + // aggiorno il puntatore alla cella + pCell = &m_mTree.at(nId) ; + pCell->m_vInters.emplace_back() ; // controllo se entro in un vertice o a metà lato - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + Point3d ptBr( pCell->GetTopRight().x, pCell->GetBottomLeft().y) ; if ( AreSamePointXYExact( ptInters, ptBr)) - m_mTree[nId].m_vInters.back().nIn = 6 ; - else if ( AreSamePointXYExact( ptInters, m_mTree[nId].GetBottomLeft())) - m_mTree[nId].m_vInters.back().nIn = 5 ; + pCell->m_vInters.back().nIn = 6 ; + else if ( AreSamePointXYExact( ptInters, pCell->GetBottomLeft())) + pCell->m_vInters.back().nIn = 5 ; else - m_mTree[nId].m_vInters.back().nIn = 2 ; + pCell->m_vInters.back().nIn = 2 ; } // ingresso in diagonale else { @@ -2926,12 +2956,13 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX { // conto quanti vertici in più ho per lato e creo un vettore dei vertici per lato int nId = m_vnLeaves[nLeafId] ; + Cell& cCell = m_mTree[nId] ; PNTMATRIX vEdgeVertex(4) ; PNTMATRIX vEdgeVertex3d(4) ; - Point3d ptBL = m_mTree[nId].GetBottomLeft() ; - Point3d ptTR = m_mTree[nId].GetTopRight() ; - Point3d ptTl = m_mTree[nId].GetTopLeft() ; - Point3d ptBr = m_mTree[nId].GetBottomRight() ; + Point3d ptBL = cCell.GetBottomLeft() ; + Point3d ptTR = cCell.GetTopRight() ; + Point3d ptTl = cCell.GetTopLeft() ; + Point3d ptBr = cCell.GetBottomRight() ; int nVertToErase = m_mTree.at(nId).m_nVertToErase ; if( nVertToErase != 2) vEdgeVertex[0].push_back( ptTR) ; @@ -3011,12 +3042,12 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX INTVECTOR vAddedLoops ; Point3d ptLastAdded( -1, -1, 0) ; for ( int w = 0 ; w < (int)vToCheckNow.size() ; ++ w) { - if ( m_mTree[nId].m_vInters[w].vpt.size() < 2) { + if ( cCell.m_vInters[w].vpt.size() < 2) { continue ; } // indice del loop in m_vInters int j = vToCheckNow[w] ; - Inters inA = m_mTree[nId].m_vInters[j] ; + Inters inA = cCell.m_vInters[j] ; if ( inA.nIn != -1) { int nEdge ; if ( nEdgeIn == -1) { @@ -3109,10 +3140,10 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX int nNext ; // ciclo sui loop successivi per vedere se ne ho uno con un valid start for ( int t = w + 1 ; t < nPassToCheck ; ++ t) { - bValidNextStart = CheckIfBetween( m_mTree[nId].m_vInters[j], m_mTree[nId].m_vInters[vToCheckNow[t]]) ; + bValidNextStart = CheckIfBetween( cCell.m_vInters[j], cCell.m_vInters[vToCheckNow[t]]) ; if ( bValidNextStart) { nNext = t ; - bAtNextStart = AreSameEdge( m_mTree[nId].m_vInters[j].nOut, m_mTree[nId].m_vInters[vToCheckNow[t]].nIn) ; + bAtNextStart = AreSameEdge( cCell.m_vInters[j].nOut, cCell.m_vInters[vToCheckNow[t]].nIn) ; break ; } else { @@ -3142,7 +3173,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX // aggiorno le condizioni per il while if ( bValidNextStart) - bAtNextStart = AreSameEdge( nEdge, m_mTree[nId].m_vInters[vToCheckNow[nNext]].nIn) ; + bAtNextStart = AreSameEdge( nEdge, cCell.m_vInters[vToCheckNow[nNext]].nIn) ; bNotCameBack = ! ( AreSameEdge( nEdge, nEdgeIn) && CheckIfBefore( plTrimmedPoly, nEdge)) ; } @@ -3151,7 +3182,7 @@ Tree::CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX if ( bValidNextStart) { Point3d ptLast ; plTrimmedPoly.GetLastPoint( ptLast) ; for ( int p = nEdge == nEdgeWithVertexSkipped ? 0 : 1 ; p < (int) vEdgeVertex[nEdge].size() ; ++ p) { - if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], m_mTree[nId].m_vInters[vToCheckNow[nNext]].vpt[0]) && + if ( CheckIfBefore( nEdge, vEdgeVertex[nEdge][p], cCell.m_vInters[vToCheckNow[nNext]].vpt[0]) && CheckIfBefore( nEdge, ptLast, vEdgeVertex[nEdge][p])) { plTrimmedPoly.AddUPoint( c, vEdgeVertex[nEdge][p]) ; plTrimmedPoly3d.AddUPoint( c, vEdgeVertex3d[nEdge][p]) ; @@ -3260,29 +3291,30 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR POLYLINEVECTOR vCellPolygons3d ; // costruisco i poligoni partendo dal vettore delle intersezioni int nId = m_vnLeaves[nLeafId] ; + Cell& cCell = m_mTree[nId] ; //capisco se sono in modalità ForTriangulation // loop interni in una cella intersecata int nChunkBiggestCW = -1 ; - if ( m_mTree[nId].m_nFlag == 3 || m_mTree[nId].m_nFlag == 2) { + if ( cCell.m_nFlag == 3 || cCell.m_nFlag == 2) { PolyLine plInLoop ; PolyLine plInLoop3d ; Inters inA ; // se ho almeno un loop CW che non è contenuto in un altro poligono o in un loop interno CCW devo aggiungere il bordo bool bAllContained = true ; bool bContained = false ; - int nInters = (int) m_mTree[nId].m_vInters.size() ; + int nInters = (int) cCell.m_vInters.size() ; for ( int n = 0 ; n < nInters ; ++ n) { - inA = m_mTree[nId].m_vInters[n] ; + inA = cCell.m_vInters[n] ; if ( inA.nIn == -1) { // per ogni loop CW verifico che ci sia un loop CCW dello stesso chunk ( che quindi lo contiene) if ( ! inA.bCCW) { if ( nChunkBiggestCW == -1) nChunkBiggestCW = inA.nChunk ; bContained = false ; - Inters inB = m_mTree[nId].m_vInters[0] ; + Inters inB = cCell.m_vInters[0] ; for( int c = 0 ; c < nInters ; ++ c){ - inB = m_mTree[nId].m_vInters[c] ; + inB = cCell.m_vInters[c] ; if ( inB.nIn == -1) { if ( inB != inA && inB.nChunk == inA.nChunk && inB.bCCW) { bContained = true ; @@ -3299,15 +3331,15 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR break ; } - if ( m_mTree[nId].m_nFlag == 2 && ! bAllContained) { + if ( cCell.m_nFlag == 2 && ! bAllContained) { // i loop esterni sono CW, quindi prima dei loop di trim aggiungo il bordo cella - Point3d ptVert = m_mTree[nId].GetTopRight() ; + Point3d ptVert = cCell.GetTopRight() ; plInLoop.AddUPoint( 0, ptVert) ; - ptVert = m_mTree[nId].GetTopLeft() ; + ptVert = cCell.GetTopLeft() ; plInLoop.AddUPoint( 1, ptVert) ; - ptVert = m_mTree[nId].GetBottomLeft() ; + ptVert = cCell.GetBottomLeft() ; plInLoop.AddUPoint( 2, ptVert) ; - ptVert = m_mTree[nId].GetBottomRight() ; + ptVert = cCell.GetBottomRight() ; plInLoop.AddUPoint( 3, ptVert) ; plInLoop.Close() ; vCellPolygons.push_back( plInLoop) ; @@ -3330,7 +3362,7 @@ Tree::CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATR plInLoop.Clear() ; } for ( int nLoop = 0 ; nLoop < nInters ; ++ nLoop) { - inA = m_mTree[nId].m_vInters[nLoop] ; + inA = cCell.m_vInters[nLoop] ; if ( inA.nIn == -1) { // numero di vertici aggiunti al nuovo poligono int k = 0 ; @@ -3751,28 +3783,29 @@ Tree::AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVe bool Tree::SetRightEdgeIn( int nId) { + Cell& cCell = m_mTree[nId] ; // categorizzo la cella in base a quanta parte del lato destro è contenuta all'interno delle curve di trim // RightEdgeIn -> 0 non contenuto ; 1 contenuto ; 2 in parte contenuto - int nPass = (int) m_mTree[nId].m_vInters.size() ; + int nPass = (int) cCell.m_vInters.size() ; if ( nPass == 0) { - m_mTree[nId].m_nRightEdgeIn = 0 ; + cCell.m_nRightEdgeIn = 0 ; return true ; } bool bDone = false ; // se ho solo loop interni devo controllare se il più esterno è CCW ( lato destro esterno) o CW ( lato destro interno) - if ( m_mTree[nId].m_nFlag == 2) { + if ( cCell.m_nFlag == 2) { bool bAllContained = true ; bool bContained = false ; Inters inA ; - int nInters = (int) m_mTree[nId].m_vInters.size() ; + int nInters = (int) cCell.m_vInters.size() ; for ( int n = 0 ; n < nInters ; ++ n) { - inA = m_mTree[nId].m_vInters[n] ; + inA = cCell.m_vInters[n] ; if ( inA.nIn == -1) { if ( ! inA.bCCW) { bContained = false ; - Inters inB = m_mTree[nId].m_vInters[0] ; + Inters inB = cCell.m_vInters[0] ; for ( int c = 0 ; c < nInters ; ++ c) { - inB = m_mTree[nId].m_vInters[c] ; + inB = cCell.m_vInters[c] ; if ( inB.nIn == -1) { if ( inB != inA && inB.nChunk == inA.nChunk && inB.bCCW) { bContained = true ; @@ -3791,27 +3824,27 @@ Tree::SetRightEdgeIn( int nId) // se i loop CW interni sono tutti contenuti in un loop CW allora il right edge è esterno bool bRightEdgeIn = ! bAllContained ; if ( bRightEdgeIn) - m_mTree[nId].m_nRightEdgeIn = 1 ; + cCell.m_nRightEdgeIn = 1 ; else - m_mTree[nId].m_nRightEdgeIn = 0 ; + cCell.m_nRightEdgeIn = 0 ; return true ; } // se ho inters sul lato destro ( nEdge == 3) allora in parte è dentro for ( int k = 0 ; k < nPass ; ++ k) { - if ( m_mTree[nId].m_vInters[k].nIn == 3 || m_mTree[nId].m_vInters[k].nOut == 3) { - m_mTree[nId].m_nRightEdgeIn = 2 ; + if ( cCell.m_vInters[k].nIn == 3 || cCell.m_vInters[k].nOut == 3) { + cCell.m_nRightEdgeIn = 2 ; bDone = true ; break ; } // considero anche ingressi/ uscite dai vertici 6 e 7 // controllo nei vertici - else if ( m_mTree[nId].m_vInters[k].nOut == 6 && m_mTree[nId].m_vInters[k].nIn == 7) { - m_mTree[nId].m_nRightEdgeIn = 1 ; + else if ( cCell.m_vInters[k].nOut == 6 && cCell.m_vInters[k].nIn == 7) { + cCell.m_nRightEdgeIn = 1 ; bDone = true ; break ; } - else if ( m_mTree[nId].m_vInters[k].nOut == 7 && m_mTree[nId].m_vInters[k].nIn == 6) { - m_mTree[nId].m_nRightEdgeIn = 0 ; + else if ( cCell.m_vInters[k].nOut == 7 && cCell.m_vInters[k].nIn == 6) { + cCell.m_nRightEdgeIn = 0 ; bDone = true ; break ; } @@ -3822,27 +3855,27 @@ Tree::SetRightEdgeIn( int nId) bool bFound = false ; bool bRightMost = false ; int nEdgeUp = 6, nEdgeDown = 7, nLoop ; - Point3d ptDown( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; - Point3d ptUp = m_mTree[nId].GetTopRight() ; + Point3d ptDown( cCell.GetTopRight().x, cCell.GetBottomLeft().y) ; + Point3d ptUp = cCell.GetTopRight() ; for ( int k = 0 ; k < nPass ; ++ k) { - if ( m_mTree[nId].m_vInters[k].nIn != -1) { + if ( cCell.m_vInters[k].nIn != -1) { // trovo il loop che ha l'ingresso o l'uscita più a destra - if ( CheckIfBefore( m_mTree[nId].m_vInters[k].nIn, m_mTree[nId].m_vInters[k].vpt[0], nEdgeUp, ptUp) || - CheckIfBefore( m_mTree[nId].m_vInters[k].nOut, m_mTree[nId].m_vInters[k].vpt.back(), nEdgeUp, ptUp) || - CheckIfBefore( nEdgeDown, ptDown, m_mTree[nId].m_vInters[k].nIn, m_mTree[nId].m_vInters[k].vpt[0]) || - CheckIfBefore( nEdgeDown, ptDown, m_mTree[nId].m_vInters[k].nOut, m_mTree[nId].m_vInters[k].vpt.back())) { + if ( CheckIfBefore( cCell.m_vInters[k].nIn, cCell.m_vInters[k].vpt[0], nEdgeUp, ptUp) || + CheckIfBefore( cCell.m_vInters[k].nOut, cCell.m_vInters[k].vpt.back(), nEdgeUp, ptUp) || + CheckIfBefore( nEdgeDown, ptDown, cCell.m_vInters[k].nIn, cCell.m_vInters[k].vpt[0]) || + CheckIfBefore( nEdgeDown, ptDown, cCell.m_vInters[k].nOut, cCell.m_vInters[k].vpt.back())) { nLoop = k ; - if ( CheckIfBefore( m_mTree[nId].m_vInters[k])) { - ptUp = m_mTree[nId].m_vInters[k].vpt[0] ; - nEdgeUp = m_mTree[nId].m_vInters[k].nIn ; - ptDown = m_mTree[nId].m_vInters[k].vpt.back() ; - nEdgeDown = m_mTree[nId].m_vInters[k].nOut ; + if ( CheckIfBefore( cCell.m_vInters[k])) { + ptUp = cCell.m_vInters[k].vpt[0] ; + nEdgeUp = cCell.m_vInters[k].nIn ; + ptDown = cCell.m_vInters[k].vpt.back() ; + nEdgeDown = cCell.m_vInters[k].nOut ; } else { - ptUp = m_mTree[nId].m_vInters[k].vpt.back() ; - nEdgeUp = m_mTree[nId].m_vInters[k].nOut ; - ptDown = m_mTree[nId].m_vInters[k].vpt[0] ; - nEdgeDown = m_mTree[nId].m_vInters[k].nIn ; + ptUp = cCell.m_vInters[k].vpt.back() ; + nEdgeUp = cCell.m_vInters[k].nOut ; + ptDown = cCell.m_vInters[k].vpt[0] ; + nEdgeDown = cCell.m_vInters[k].nIn ; } bFound = true ; } @@ -3850,24 +3883,25 @@ Tree::SetRightEdgeIn( int nId) else continue ; } - if ( bFound && CheckIfBefore( m_mTree[nId].m_vInters[nLoop])) { + if ( bFound && CheckIfBefore( cCell.m_vInters[nLoop])) { bRightMost = true ; } // se il mio campione attraversa dall'alto al basso allora il lato destro è dentro!!! if ( bFound && bRightMost) - m_mTree[nId].m_nRightEdgeIn = 1 ; + cCell.m_nRightEdgeIn = 1 ; else - m_mTree[nId].m_nRightEdgeIn = 0 ; + cCell.m_nRightEdgeIn = 0 ; } - return ( m_mTree[nId].m_nRightEdgeIn != -1) ; + return ( cCell.m_nRightEdgeIn != -1) ; } //---------------------------------------------------------------------------- bool Tree::CategorizeCell( int nId) { - if ( m_mTree[nId].m_nFlag != -1) { + Cell& cCell = m_mTree[nId] ; + if ( cCell.m_nFlag != -1) { return true ; } INTVECTOR vNeigh, vNeigh1 ; @@ -3876,20 +3910,20 @@ Tree::CategorizeCell( int nId) // nRightEdgeIn // 0 right edge fuori, 1 right edge dentro, 2 metà e metà // nFlag // 0 fuori, 1 intersecata, 2 contiene loop, 3 = 1 & 2, 4 dentro if ( vNeigh.empty()) { - m_mTree[nId].m_nFlag = 0 ; + cCell.m_nFlag = 0 ; } else if ( vNeigh.size() == 1) { if ( m_mTree[vNeigh[0]].m_nRightEdgeIn == 1) - m_mTree[nId].m_nFlag = 4 ; + cCell.m_nFlag = 4 ; else if ( m_mTree[vNeigh[0]].m_nRightEdgeIn == 0) // devo verificare se la cella è intersecata if ( m_mTree[vNeigh[0]].m_nFlag == 1 || m_mTree[vNeigh[0]].m_nFlag == 3) - m_mTree[nId].m_nFlag = 0 ; + cCell.m_nFlag = 0 ; else { if ( m_mTree[vNeigh[0]].m_nFlag == 4) - m_mTree[nId].m_nFlag = 4 ; + cCell.m_nFlag = 4 ; else if ( m_mTree[vNeigh[0]].m_nFlag == 0) - m_mTree[nId].m_nFlag = 0 ; + cCell.m_nFlag = 0 ; } // se solo parte del right edge del vicino è compreso, allora devo verificare se la cella è contenuta o no // guardando nFlag del vicino bottom, che è già categorizzato! @@ -3898,16 +3932,16 @@ Tree::CategorizeCell( int nId) if ( ! vNeigh1.empty()) { int nNeigh = vNeigh1[0] ; if ( m_mTree[nNeigh].m_nFlag == 0 || m_mTree[nNeigh].m_nFlag == 2) { - m_mTree[nId].m_nFlag = 0 ; + cCell.m_nFlag = 0 ; } else if ( m_mTree[nNeigh].m_nFlag == 4) { - m_mTree[nId].m_nFlag = 4 ; + cCell.m_nFlag = 4 ; } else if ( m_mTree[nNeigh].m_nFlag == 1 || m_mTree[nNeigh].m_nFlag == 3) { if ( m_mTree[nNeigh].m_nRightEdgeIn == 0) - m_mTree[nId].m_nFlag = 0 ; + cCell.m_nFlag = 0 ; else if ( m_mTree[nNeigh].m_nRightEdgeIn == 1) - m_mTree[nId].m_nFlag = 4 ; + cCell.m_nFlag = 4 ; else if ( m_mTree[nNeigh].m_nRightEdgeIn == 2) { // in questo caso devo verificare le intersezioni sul lato destro del vicino bottom // scorro e cerco l'intersezione più alta, se è out la cella è dentro, se è in devo verificare l'out se è più a sinistra o a destra. @@ -3949,20 +3983,20 @@ Tree::CategorizeCell( int nId) if ( bFound && bTopMost) { if ( AreSameEdge( m_mTree[nNeigh].m_vInters[nLoop].nIn, 3) && AreSameEdge( m_mTree[nNeigh].m_vInters[nLoop].nOut, 3)) { if ( CheckIfBefore( m_mTree[nNeigh].m_vInters[nLoop])) - m_mTree[nId].m_nFlag = 4 ; + cCell.m_nFlag = 4 ; else - m_mTree[nId].m_nFlag = 0 ; + cCell.m_nFlag = 0 ; } else if ( AreSameEdge( m_mTree[nNeigh].m_vInters[nLoop].nOut, 3)) - m_mTree[nId].m_nFlag = 4 ; + cCell.m_nFlag = 4 ; else if ( AreSameEdge( m_mTree[nNeigh].m_vInters[nLoop].nIn, 3)) { // devo verificare se l'uscita è più a sinistra o più a destra della cella Point3d ptOut = m_mTree[nNeigh].m_vInters[nLoop].vpt.back() ; - Point3d ptBr( m_mTree[nId].GetTopRight().x, m_mTree[nId].GetBottomLeft().y) ; + Point3d ptBr( cCell.GetTopRight().x, cCell.GetBottomLeft().y) ; if ( ptOut.x >= ptBr.x) - m_mTree[nId].m_nFlag = 4 ; + cCell.m_nFlag = 4 ; else - m_mTree[nId].m_nFlag = 0 ; + cCell.m_nFlag = 0 ; } } } @@ -3988,25 +4022,25 @@ Tree::CategorizeCell( int nId) } } if ( bIntersIn) - m_mTree[nId].m_nFlag = 4 ; + cCell.m_nFlag = 4 ; else - m_mTree[nId].m_nFlag = 0 ; + cCell.m_nFlag = 0 ; } } } else { for ( int r = 0 ; r < (int)vNeigh.size() ; ++ r) { if ( m_mTree[vNeigh[r]].m_nRightEdgeIn == 1) { - m_mTree[nId].m_nFlag = 4 ; + cCell.m_nFlag = 4 ; break ; } else if ( m_mTree[vNeigh[r]].m_nRightEdgeIn == 0) { if ( m_mTree[vNeigh[r]].m_nFlag == 4) { - m_mTree[nId].m_nFlag = 4 ; + cCell.m_nFlag = 4 ; break ; } else if ( m_mTree[vNeigh[r]].m_nFlag == 0) { - m_mTree[nId].m_nFlag = 0 ; + cCell.m_nFlag = 0 ; break ; } } diff --git a/Tree.h b/Tree.h index e2d5adc..8b307b1 100644 --- a/Tree.h +++ b/Tree.h @@ -218,6 +218,7 @@ class Cell std::vector m_vInters ; // vettore delle intersezioni della cella con i loop di trim // ogni elemento del vettore è l'insieme dei punti che caratterizza un attraversamento della cella int m_nVertToErase ; // vertice da eliminare dal poligono della cella, in caso di lato sovrapposto ad un lato di polo + // contati in senso CCW a partire dal bottom left private : Point3d m_ptPbl ; // punto bottom left