From fb8bac86815f3f51abfcce79dc611f36756cc7dc Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 10 Apr 2025 15:34:57 +0200 Subject: [PATCH] EgtGeomKernel: - correzione di un errore di taglio con piani nelle surf Bezier. --- SurfBezier.cpp | 86 ++++++++++++++++++++++++++++++++++---------------- Tree.cpp | 4 +++ 2 files changed, 63 insertions(+), 27 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index e5977f7..664f1fb 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 ; @@ -1959,7 +1960,7 @@ SurfBezier::GetLeaves( vector>& vLeaves) const //Tree.BuildTree( 5 * LIN_TOL_FINE, 1) ; // per debug } else { - Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ; + Tree.BuildTree( 100 * LIN_TOL_FINE, 0.1) ; } vector vCells ; Tree.GetLeaves( vCells) ; @@ -2260,7 +2261,7 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE else pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; - // costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e i loop dei vari chunk della falr region + // costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e i loop dei vari chunk della flat region unordered_map mInters ; int nInters = 0 ; bool bStartFound = false ; @@ -2400,23 +2401,29 @@ SurfBezier::CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVE vbAdded[nNewToAdd] = true ; // di questo taglio mi salvo il chunk e loop di start e end TRINT tiStart, tiEnd ; + bool bStartFound = false ; + bool bEndFound = false ; for (const auto& pair : mInters) { if ( get<2>(pair.first) == nNewToAdd ) { for (int p = 0 ; p < int(pair.second.size()) ; ++p) { if ( pair.second[p].IciB->dU < EPS_SMALL) { tiStart = pair.first ; + bStartFound = true ; if ( bFirstCurveOfEdge){ // salvo l'inizio del taglio che è la prima curva di questa curva compo tiFirstInters = pair.first ; bFirstCurveOfEdge = false ; } } - else + else { tiEnd = pair.first ; + bEndFound = true ; + } } } } - + if ( ! bEndFound || ! bStartFound) + return nullptr ; // devo trovare fino a che punto seguire il loop che ho trovato come prosecuzione del taglio corrente // devo quindi trovare la prossima intersezione con un taglio int nInters = -1 ; @@ -2546,6 +2553,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) ICRVCOMPOPOVECTOR vpCCOpen ; ICRVCOMPOPOVECTOR vpCCClosed ; + ////debug + //static int a = 0 ; + //a += 1 ; + ////debug + while ( chainC.GetChainFromNear( ptNear, false, vId)) { // creo una curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; @@ -2595,8 +2607,18 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) vpCCClosed.back()->FromPolyLine( vPLTria[i]) ; } - // ora posso chiamare la costruzione dello spazio parametrico trimmato - + ////debug + //// ora posso chiamare la costruzione dello spazio parametrico trimmato + //if ( a == 4) { + // vector vObj ; + // for ( int i = 0 ; i < int(vpCCOpen.size()) ; ++i) + // vObj.push_back( vpCCOpen[i]->Clone()) ; + // vObj.push_back( m_pTrimReg->Clone()) ; + // vObj.push_back( this->Clone()) ; + // SaveGeoObj( vObj, "D:\\Temp\\bezier\\triangolazione\\doppiaSTM\\curveOPEN.nge", 2) ; + //} + ////debug + PtrOwner pSFR( CreateTrimRegionFromCuts( vpCCOpen, vpCCClosed)) ; if ( IsNull( pSFR) || ! pSFR->IsValid()) return false ; @@ -2798,13 +2820,16 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } // se la superficie è chiusa controllo se devo tenere conto della periodicità nel prendere le coordinate parametriche dei vertici - double dParamH, dParamL ; + double dParamH = 0, dParamL = 0 ; + INTVECTOR vOn(3) ; + fill( vOn.begin(), vOn.end(), -1) ; + bool bOneVertexOnClosureButNotPole = false ; if ( m_bClosedU || m_bClosedV) { dParamH = m_nSpanV * SBZ_TREG_COEFF ; dParamL = m_nSpanU * SBZ_TREG_COEFF ; // devo trovare il lato più lungo e confrontarlo con le dimensioni dello spazio parametrico Vector3d vtDir ; - double dDist ; + double dDist = 0 ; if ( DistXY( vPtPa[0], vPtPa[1]) > DistXY( vPtPa[1], vPtPa[2]) && DistXY( vPtPa[0], vPtPa[1]) > Dist( vPtPa[0], vPtPa[2])){ vtDir = vPtPa[1] - vPtPa[0] ; dDist = DistXY( vPtPa[0], vPtPa[1]) ; @@ -2823,8 +2848,6 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // do per scontato che se la superficie è chiusa lungo un parametro i lati di chiusura non siano dei poli if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.5 ) { // trovo se dei vertici del triangolo sono sul bordo dello spazio parametrico - INTVECTOR vOn(3) ; - fill( vOn.begin(), vOn.end(), -1) ; INTVECTOR vEdgesClosed = { 1, 3} ; // scorro sui vertici for ( int p = 0 ; p < 3; ++p ) { @@ -2839,12 +2862,12 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } // controllo che almeno un vertice sia su un edge e se è l'unico vertice, che non sia su un polo if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) { - // se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate - if ( vOn[0] * vOn[1] * vOn[2] < 0 || - (vOn[0] > 0 && 0 != nVertOnPole) || - (vOn[1] > 0 && 1 != nVertOnPole) || - (vOn[2] > 0 && 2 != nVertOnPole)) { - double dRightX ; + // se ho più di un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate + bOneVertexOnClosureButNotPole = (vOn[0] > 0 && 0 != nVertOnPole) || + (vOn[1] > 0 && 1 != nVertOnPole) || + (vOn[2] > 0 && 2 != nVertOnPole) ; + if ( vOn[0] * vOn[1] * vOn[2] < 0 || bOneVertexOnClosureButNotPole) { + double dRightX = 0 ; // tengo per buone le coordinate dei vertici che NON sono sul bordo dello spazio parametrico for ( int p = 0 ; p < 3; ++p) { if ( vOn[p] == -1) { @@ -2853,7 +2876,8 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } for ( int p = 0 ; p < 3; ++p) { - if ( abs(vPtPa[p].x - dRightX) > EPS_SMALL ) { + //if ( abs(vPtPa[p].x - dRightX) > EPS_SMALL ) { + if ( abs(vPtPa[p].x - dRightX) > SBZ_TREG_COEFF / 2) { if ( vPtPa[p].x < EPS_SMALL) vPtPa[p].x = dParamL ; else @@ -2864,8 +2888,6 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.5) { - INTVECTOR vOn(3) ; - fill( vOn.begin(), vOn.end(), -1) ; int nVertOnPole = -1 ; INTVECTOR vEdgesClosed = { 0, 2} ; // scorro sui vertici @@ -2882,10 +2904,10 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // controllo che almeno un vertice sia su un edge if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) { // se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate - if ( vOn[0] * vOn[1] * vOn[2] < 0 || - (vOn[0] > 0 && 0 != nVertOnPole) || - (vOn[1] > 0 && 1 != nVertOnPole) || - (vOn[2] > 0 && 2 != nVertOnPole)) { + bOneVertexOnClosureButNotPole = (vOn[0] > 0 && 0 != nVertOnPole) || + (vOn[1] > 0 && 1 != nVertOnPole) || + (vOn[2] > 0 && 2 != nVertOnPole) ; + if ( vOn[0] * vOn[1] * vOn[2] < 0 || bOneVertexOnClosureButNotPole) { double dRightY = 0 ; // tengo per buone le coordinate dei vertici che NON sono sul bordo dello spazio parametrico for ( int p = 0 ; p < 3; ++p) { @@ -2895,7 +2917,8 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } for ( int p = 0 ; p < 3; ++p) { - if ( abs(vPtPa[p].y - dRightY) > EPS_SMALL) { + //if ( abs(vPtPa[p].y - dRightY) > EPS_SMALL) { + if ( abs(vPtPa[p].y - dRightY) > SBZ_TREG_COEFF / 2) { if ( vPtPa[p].y < EPS_SMALL) vPtPa[p].y = dParamH ; else @@ -2912,16 +2935,25 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in if ( nEdge == -1) return false ; // trovo la coordinata giusta da tenere ( x o y a seconda dell'edge) - double dRightX, dRightY ; + double dRightX = 0, dRightY = 0 ; for ( int p = 0 ; p < 3; ++p) { if ( p != nVertOnPole) { if ( nEdge == 0 || nEdge == 2) { - dRightX = vPtPa[p].x ; + if ( vPtPa[p].x > dRightX ) + dRightX= vPtPa[p].x ; + // se un vertice è su un lato di chiusura, visto che sono vicino ad un polo, mi accerto che un lato del triangolo sia SUL lato di chiusura + if( m_bClosedU && bOneVertexOnClosureButNotPole) + dRightX = ( dParamL - vPtPa[p].x > vPtPa[p].x ? 0 : dParamL) ; dRightY = nEdge == 0 ? dParamH : 0 ; } else if ( nEdge == 1 || nEdge == 3) { + // se un vertice è su un lato di chiusura, visto che sono vicino ad un polo, mi accerto che un lato del triangolo sia SUL lato di chiusura + if( m_bClosedU && bOneVertexOnClosureButNotPole) + dRightY = ( dParamH - vPtPa[p].y > vPtPa[p].y ? 0 : dParamH) ; + dRightX = nEdge == 1 ? 0 : dParamL ; - dRightY = vPtPa[p].y ; + if ( vPtPa[p].y < dRightY ) + dRightY = vPtPa[p].y ; } } } diff --git a/Tree.cpp b/Tree.cpp index 1e8a251..364c0ba 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -2183,6 +2183,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) Point3d ptCurr ; auto iter = find( m_vnLeaves.begin(), m_vnLeaves.end(), nId) ; int nIdPolygon = distance( m_vnLeaves.begin(), iter) ; + if ( nIdPolygon > int( vplPolygons.size()) - 1) + return false ; bool bEraseNextPoint = false ; while ( plLoop.GetNextPoint( ptCurr)) { Point3d ptTStart, ptTEnd ; @@ -2218,6 +2220,8 @@ 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) ; + if ( nIdPolygon > int( vplPolygons.size()) - 1) + return false ; // aggiorno il puntatore alla cella pCell = &m_mTree[nId] ; // salvo il verso del loop