From 1219e9bd804ce5773d507c44fc56b724bdfd715f Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 4 Nov 2025 14:37:34 +0100 Subject: [PATCH] EtgGeomKernel : - primo tentativo. --- SurfBezier.cpp | 480 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 313 insertions(+), 167 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index d0c66ed..61d93ab 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -42,6 +42,7 @@ #include "/EgtDev/Include/EGkIntervals.h" #define EIGEN_NO_IO #include "/EgtDev/Extern/Eigen/Dense" +#include "/EgtDev/Include/EGkGeoObjSave.h" using namespace std ; @@ -4380,6 +4381,55 @@ ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, I return true ; } +static bool +GetEdgeSplitByAngTol( const PolyLine& PL, double dAngTol, INTVECTOR& vEdgeSplit) +{ + int nPoints = PL.GetPointNbr() ; + vEdgeSplit.clear() ; + vEdgeSplit.resize( nPoints) ; + fill( vEdgeSplit.begin(), vEdgeSplit.end(), false) ; + bool bClosed = PL.IsClosed() ; + // Recupero l'insieme di punti associati alla PolyLine + PNTVECTOR vPoints ; vPoints.reserve( nPoints) ; + Point3d ptCurr = P_INVALID ; + // aggiungo come primo punto il penultimo punto della polyline in modo da analizzare direttamente anche la chiusura ( se è una polyline chiusa) + PL.GetLastPoint( ptCurr) ; + PL.GetPrevPoint( ptCurr) ; + vPoints.emplace_back( ptCurr) ; + bool bFound = PL.GetFirstPoint( ptCurr) ; + while ( bFound) { + vPoints.emplace_back( ptCurr) ; + bFound = PL.GetNextPoint( ptCurr) ; + } + Vector3d vtTanCurr = V_INVALID, vtTanNext = V_INVALID ; + // cos della tolleranza angolare massima + double dCosTol = cos( dAngTol * DEGTORAD) ; + for ( int nP = 0 ; nP < nPoints - 2 ; ++ nP) { + // Recupero il punto corrente e i due punti successivi + Point3d& ptCurr = vPoints[nP] ; + Point3d& ptNext = vPoints[nP + 1] ; + Point3d& ptNextNext = vPoints[nP + 2] ; + // Recupero i versori tangenti definiti dai tre punti ( ptCurr|ptNext e ptNext|ptNextNext) + if ( nP == 0) { + vtTanCurr = ptNext - ptCurr ; + vtTanCurr.Normalize() ; + } + else + vtTanCurr = vtTanNext ; + vtTanNext = ptNextNext - ptNext ; vtTanNext.Normalize() ; + // Calcolo il Coseno tra i due versori + double dCos = vtTanCurr * vtTanNext ; + // Se oltre la tolleranza allora ho incontrato un edge + if ( dCos < dCosTol) + vEdgeSplit[nP] = true ; + } + + if( ! bClosed) + vEdgeSplit[0] = false ; + + return true ; +} + //---------------------------------------------------------------------------- bool SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int nRuledType) @@ -4842,6 +4892,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int bool bIsClosed1 = plU1.IsClosed() ; Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ; vector> vMatch1 ; + PNTVECTOR vPnt1 ; vPnt1.emplace_back( ptP1) ; while ( plU1.GetNextPoint( ptP1, true)) { DistPointCurve dpc( ptP1, CrvU0, false) ; int nFlag = 0 ; @@ -4862,9 +4913,11 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } vMatch1.push_back( pair( ptJoint, dParam)) ; + vPnt1.emplace_back( ptP1) ; } Point3d ptP0 ; plU0.GetFirstPoint( ptP0) ; vector> vMatch0 ; + PNTVECTOR vPnt0 ; vPnt0.emplace_back( ptP0) ; while ( plU0.GetNextPoint( ptP0, true)) { DistPointCurve dpc( ptP0, CrvU1, false) ; int nFlag = 0 ; @@ -4884,163 +4937,247 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int dParam = round( dParam) ; } vMatch0.push_back( pair( ptJoint, dParam)) ; + vPnt0.emplace_back( ptP0) ; } + // verifico la presenza di eventuali "edge" lungo le polyline ( punti di passaggio di un edge e quindi cambi bruschi di direzione della polyline) + INTVECTOR vEdgeSplit0, vEdgeSplit1 ; + GetEdgeSplitByAngTol( plU0, 15, vEdgeSplit0) ; + GetEdgeSplitByAngTol( plU1, 15, vEdgeSplit1) ; + int nAtStart1 = 0 ; // match ripetuti dalla curva U0 allo start della curva U1 int nAtEnd1 = 0 ; - plU0.GetFirstPoint( ptP0) ; int c = 0 ; int nRep0 = 0 ; // match interni consecutivi uguali di punti della curva U0 con punti della curva U1 int nRep1 = 0 ; - double dLastParamMatch = 0 ; - Point3d ptLastPointMatch = ptP0 ; + double dLastParamMatch0 = 0 ; + plU0.GetFirstPoint( ptP0) ; + Point3d ptLastPointMatch0 = ptP0 ; BOOLVECTOR vbRep0( nSpanU0) ; INTVECTOR vnAddedOrNextIsRep0 ; // 0 non Rep, 1 Rep, 2 Next is Rep ; DBLVECTOR vdSplit0 ; fill( vbRep0.begin(), vbRep0.end(), false) ; - while ( plU0.GetNextPoint( ptP0, true)) { - // devo salvarmi se matcho più punti con lo start o l'end della curva totale - double dParam = vMatch0[c].second ; - Point3d ptJoint = vMatch0[c].first ; // nuovo punto che si vorrebbe aggiungere sulla curva U1 - if( bIsClosed1 && dParam > nSpanU1 - EPS_SMALL) - dParam = 0 ; - vMatch0[c].second = dParam ; - // ho match con lo start - if ( dParam < EPS_SMALL) { - ++nAtStart1 ; - vbRep0[c] = true ; - ++c ; - continue ; - } - // ho un match con l'end - else if ( dParam > nSpanU1 - EPS_SMALL ) { - vbRep0[c] = nAtEnd1 == 0 ? false : true ; - vbRep0.back() = true ; - ++ nAtEnd1 ; - ++c ; - continue ; - } - if ( dParam <= dLastParamMatch || AreSamePointApprox( ptJoint, ptLastPointMatch)) { - dParam = dLastParamMatch ; - vbRep0[c] = true ; - ++ nRep0 ; - ++c ; - continue ; - } - else { - dLastParamMatch = dParam ; - ptLastPointMatch = ptJoint ; - // ho un match con una joint esistente - if( dParam - int( dParam) < EPS_SMALL) { - ++c ; - continue ; - } - - vdSplit0.push_back( dParam) ; - // verifico se ho un match per questo punto - // in tal caso vuol dire che sto creando una ripetizione nRep1 - int nCase = 0 ; - for ( int j = 0 ; j < int( vMatch1.size()) ; ++j) { - if ( abs(vMatch1[j].second - (c + 1)) < EPS_SMALL) { - // devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione - bool bFoundMatch = false ; - for ( int z = int( round(vMatch1[j].second)) ; z < int( vMatch0.size()) ; ++z) { - if ( abs( vMatch0[z].second - ( j + 1 )) < EPS_SMALL ) { - bFoundMatch = true ; - break ; - } - } - - if ( ! bFoundMatch) { - ++nRep1 ; - // capisco se il punto è rep o se lo è il suo successivo - if( j + 1 < dParam) - nCase = 1 ; - else - nCase = 2 ; - } - break ; - } - } - vnAddedOrNextIsRep0.push_back( nCase) ; - } - ++c ; - } int nAtStart0 = 0 ; int nAtEnd0 = 0 ; + int j = 0 ; + double dLastParamMatch1 = 0 ; plU1.GetFirstPoint( ptP1) ; - c = 0 ; - dLastParamMatch = 0 ; - ptLastPointMatch = ptP1 ; + Point3d ptLastPointMatch1 = ptP1 ; INTVECTOR vnAddedOrNextIsRep1 ; // 0 non Rep, 1 Rep, 2 Next is Rep ; DBLVECTOR vdSplit1 ; BOOLVECTOR vbRep1( plU1.GetPointNbr() - 1) ; fill( vbRep1.begin(), vbRep1.end(), false) ; - while ( plU1.GetNextPoint( ptP1, true)) { - double dParam = vMatch1[c].second ; - Point3d ptJoint = vMatch1[c].first ; - if ( bIsClosed0 && dParam > nSpanU0 - EPS_SMALL) - dParam = 0 ; - // ho un match con lo start - if ( dParam < EPS_SMALL) { - ++nAtStart0 ; - vbRep1[c] = true ; - ++c ; - continue ; + bool bAdvance = true ; + // verifico i match effettivi tra le polyline + while( bAdvance) { + double dParam0 = vMatch0[c].second ; + Point3d ptJoint0 = vMatch0[c].first ; + double dParam1 = vMatch1[j].second ; + Point3d ptJoint1 = vMatch1[j].first ; + if( bIsClosed1 && dParam0 > nSpanU1 - EPS_SMALL) { + dParam0 = 0 ; + vMatch0[c].second = dParam0 ; } - // ho un match con l'end - else if ( dParam > nSpanU0 - EPS_SMALL ) { - vbRep1[c] = nAtEnd0 == 0 ? false : true ; - vbRep1.back() = true ; - ++ nAtEnd0 ; - ++c ; - continue ; + if( bIsClosed0 && dParam1 > nSpanU0 - EPS_SMALL) { + dParam1 = 0 ; + vMatch1[j].second = dParam1 ; } - if ( dParam <= dLastParamMatch || AreSamePointApprox( ptJoint, ptLastPointMatch)) { - dParam = dLastParamMatch ; - vbRep1[c] = true ; - ++ nRep1 ; - ++c ; - continue ; - } - else { - dLastParamMatch = dParam ; - ptLastPointMatch = ptJoint ; - // ho un match con una joint esistente - if( dParam - int( dParam) < EPS_SMALL) { + // capisco con quale delle due polyline avanzo + bool bAdvance0 = dParam0 < j + 1 + EPS_SMALL ; + bool bAdvance1 = dParam1 < c + 1 + EPS_SMALL ; + if ( bAdvance0) { + // ho match con lo start + if ( dParam0 < EPS_SMALL) { + ++nAtStart1 ; + vbRep0[c] = true ; ++c ; continue ; } - - vdSplit1.push_back( dParam) ; - // verifico se ho un match per questo punto - // in tal caso vuol dire che sto creando una ripetizione nRep0 - int nCase = 0 ; - for ( int j = 0 ; j < int( vMatch0.size()) ; ++j) { - if ( abs(vMatch0[j].second - (c + 1)) < EPS_SMALL) { - // devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione - bool bFoundMatch = false ; - for ( int z = int( round(vMatch0[j].second)) ; z < int( vMatch1.size()) ; ++z) { - if ( abs( vMatch1[z].second - ( j + 1 )) < EPS_SMALL ) { - bFoundMatch = true ; + // ho un match con l'end + else if ( dParam0 > nSpanU1 - EPS_SMALL ) { + vbRep0[c] = nAtEnd1 == 0 ? false : true ; + vbRep0.back() = true ; + ++ nAtEnd1 ; + ++c ; + continue ; + } + if ( dParam0 <= dLastParamMatch0 || AreSamePointApprox( ptJoint0, ptLastPointMatch0)) { + dParam0 = dLastParamMatch0 ; + vbRep0[c] = true ; + ++ nRep0 ; + ++c ; + continue ; + } + else { + dLastParamMatch0 = dParam0 ; + ptLastPointMatch0 = ptJoint0 ; + // ho un match con una joint esistente + if( dParam0 - int( dParam0) < EPS_SMALL) { + ; + } + // altrimenti lo aggiungo + else { + vdSplit0.push_back( dParam0) ; + // verifico se ho un match per questo punto + // in tal caso vuol dire che sto creando una ripetizione nRep1 + int nCase = 0 ; + for ( int k = 0 ; k < int( vMatch1.size()) ; ++k) { + if ( abs(vMatch1[k].second - (c + 1)) < EPS_SMALL) { + // devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione + bool bFoundMatch = false ; + for ( int z = int( round(vMatch1[k].second)) ; z < int( vMatch0.size()) ; ++z) { + if ( abs( vMatch0[z].second - ( k + 1 )) < EPS_SMALL ) { + bFoundMatch = true ; + break ; + } + } + + if ( ! bFoundMatch) { + ++nRep1 ; + // capisco se il punto è rep o se lo è il suo successivo + if( j + 1 < dParam0) + nCase = 1 ; + else + nCase = 2 ; + } break ; } } - - if ( ! bFoundMatch) { - ++nRep0 ; - // capisco se il punto è rep o se lo è il suo successivo - if( j + 1 < dParam) - nCase = 1 ; - else - nCase = 2 ; - } - break ; + vnAddedOrNextIsRep0.push_back( nCase) ; } } - vnAddedOrNextIsRep1.push_back( nCase) ; + ++c ; } - ++c ; + if ( bAdvance1) { + // ho un match con lo start + if ( dParam1 < EPS_SMALL) { + ++nAtStart0 ; + vbRep1[j] = true ; + ++j ; + continue ; + } + // ho un match con l'end + else if ( dParam1 > nSpanU0 - EPS_SMALL ) { + vbRep1[j] = nAtEnd0 == 0 ? false : true ; + vbRep1.back() = true ; + ++ nAtEnd0 ; + ++j ; + continue ; + } + if ( dParam1 <= dLastParamMatch1 || AreSamePointApprox( ptJoint1, ptLastPointMatch1)) { + dParam1 = dLastParamMatch1 ; + vbRep1[j] = true ; + ++ nRep1 ; + ++j ; + continue ; + } + else { + dLastParamMatch1 = dParam1 ; + ptLastPointMatch1 = ptJoint1 ; + // ho un match con una joint esistente + if( dParam1 - int( dParam1) < EPS_SMALL) { + ; + } + //altrimenti lo aggiungo + else { + vdSplit1.push_back( dParam1) ; + // verifico se ho un match per questo punto + // in tal caso vuol dire che sto creando una ripetizione nRep0 + int nCase = 0 ; + for ( int k = 0 ; k < int( vMatch0.size()) ; ++k) { + if ( abs(vMatch0[k].second - (j + 1)) < EPS_SMALL) { + // devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione + bool bFoundMatch = false ; + for ( int z = int( round(vMatch0[k].second)) ; z < int( vMatch1.size()) ; ++z) { + if ( abs( vMatch1[z].second - ( k + 1 )) < EPS_SMALL ) { + bFoundMatch = true ; + break ; + } + } + + if ( ! bFoundMatch) { + ++nRep0 ; + // capisco se il punto è rep o se lo è il suo successivo + if( k + 1 < dParam1) + nCase = 1 ; + else + nCase = 2 ; + } + break ; + } + } + vnAddedOrNextIsRep1.push_back( nCase) ; + } + } + ++j ; + } + if( ! bAdvance0 && ! bAdvance1) { + // sono arrivato ad un caso di incrocio!! + //1. verifico se sono vicino ad uno spigolo su entrambe le curve + //2. verifico se calcolando i punti bonus con i piani risolvo + //3. sennò aggiungo qualche rep + bool bEdgeFoundOnSecond = false ; + if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) { + // questo caso non è previsto !!!!! + ; + } + if( vEdgeSplit0[c+1]) { + //cerco se ho uno split anche su U1 entro una distanza che sia al massimo il doppio di quella che c'è col punto a mindist + double dDist = 0 ; + double dMaxDist = Dist( vPnt0[c+1], vMatch0[c].first) * 2 ; + int j_temp = j + 1 ; + while( dDist < dMaxDist) { + if ( vEdgeSplit1[j_temp]) { + bEdgeFoundOnSecond = true ; + break ; + } + ++j_temp ; + dDist = Dist( vPnt0[c+1], vPnt1[j_temp]) ; + } + if( bEdgeFoundOnSecond) { + // collego i due punti in cui ho il passaggio di un edge e tutti i punti che restano non accoppiati li metto come Rep + for( int i = j_temp ; i > j ; --i) + vbRep1[i] = true ; + j = j_temp ; + dLastParamMatch0 = j ; + ptLastPointMatch0 = vPnt1[j] ; + } + } + if( vEdgeSplit1[j+1]) { + //cerco se ho uno split anche su U1 entro una distanza che sia al massimo il doppio di quella che c'è col punto a mindist + double dDist = 0 ; + double dMaxDist = Dist( vPnt1[j+1], vMatch1[j].first) * 2 ; + int c_temp = c + 1 ; + while( dDist < dMaxDist) { + if ( vEdgeSplit0[c_temp]) { + bEdgeFoundOnSecond = true ; + break ; + } + ++c_temp ; + dDist = Dist( vPnt1[j+1], vPnt0[c_temp]) ; + } + if( bEdgeFoundOnSecond) { + // collego i due punti in cui ho il passaggio di un edge e tutti i punti che restano non accoppiati li metto come Rep + for( int i = c_temp ; i > c ; --i) + vbRep0[i] = true ; + c = c_temp ; + dLastParamMatch1 = c ; + ptLastPointMatch1 = vPnt0[c] ; + } + } + + bool bPlaneDist = false ; + if( ! bEdgeFoundOnSecond) { + // provo col piano b: cerco degli accoppiamenti usando i piani anziché il mindist + ; + } + + if( ! bPlaneDist) { + // cerco di capire come settare i punti Rep + ; + } + } + bAdvance = c < int(vMatch0.size()) - 1 || j < int(vMatch1.size()) - 1 ; } // applico effettivamente gli split e aggiungo gli elementi ai vettori vbRep @@ -5096,44 +5233,42 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int } } + //debug + INTVECTOR vCorresp0 ; + INTVECTOR vCorresp1 ; + vCorresp0.push_back( 0) ; + vCorresp1.push_back( 0) ; + plU0.GetFirstPoint(ptP0) ; + int cc = 0 ; + while( plU0.GetNextPoint(ptP0)) { + bool bFound = false ; + while( ! bFound) { + Point3d ptEnd ; CrvU0.GetCurve(cc)->GetEndPoint( ptEnd) ; + if( AreSamePointApprox( ptP0, ptEnd)) { + vCorresp0.push_back( cc + 1) ; + bFound = true ; + } + ++cc ; + } + } + plU1.GetFirstPoint(ptP1) ; + cc = 0 ; + while( plU1.GetNextPoint(ptP1)) { + bool bFound = false ; + while( ! bFound) { + Point3d ptEnd ; CrvU1.GetCurve(cc)->GetEndPoint( ptEnd) ; + if( AreSamePointApprox( ptP1, ptEnd)) { + vCorresp1.push_back( cc + 1) ; + bFound = true ; + } + ++cc ; + } + } + //debug + + nSpanU0 = CrvU0.GetCurveCount() ; nSpanU1 = CrvU1.GetCurveCount() ; - //aggiusto i vettori delle ripetizioni in modo in modo che non arrivino mai ad essere contemporaneamente true - int nAddedSpan = 0 ; - int nCrv0 = 0 ; - int nCrv1 = 0 ; - while ( nAddedSpan < nSpanU0 + nAtStart0 + nAtEnd0 + nRep1) { - if ( nCrv0 >= nSpanU0) - nCrv0 = nSpanU0 - 1; - if ( nCrv1 >= nSpanU1) - nCrv1 = nSpanU1 - 1; - bool bRep0 = vbRep0[nCrv0] ; - bool bRep1 = vbRep1[nCrv1] ; - if ( bRep0 && bRep1 ) { - vbRep0[nCrv0] = false ; - bRep0 = false ; - vbRep1[nCrv1] = false ; - bRep1 = false ; - -- nRep0 ; - -- nRep1 ; - } - if ( ! bRep0 || nCrv1 == nSpanU1 - 1) - ++ nCrv1 ; - if ( ! bRep1 || nCrv0 == nSpanU0 - 1) - ++ nCrv0 ; - ++nAddedSpan ; - } - // se non sono arrivato all'ultima curva su U0 o U1 vuol dire che ho creato delle ripetizioni che non ho contato prima - if( nCrv1 < nSpanU1) { - nRep1 += nSpanU1 - nCrv1 ; - for ( int z = int( vbRep1.size() - 1) ; z >= nCrv1 ; --z) - vbRep1[z] = true ; - } - if( nCrv0 < nSpanU0) { - nRep0 += nSpanU0 - nCrv0 ; - for ( int z = int( vbRep0.size() - 1) ; z >= nCrv0 ; --z) - vbRep0[z] = true ; - } // trovo il numero di span che dovrà avere la superficie // ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0) @@ -5147,9 +5282,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; // aggiungo i punti di controllo scorrendo in contemporanea le due curve - nAddedSpan = 0 ; - nCrv0 = 0 ; - nCrv1 = 0 ; + int nAddedSpan = 0 ; + int nCrv0 = 0 ; + int nCrv1 = 0 ; bool bLast0 = false ; bool bLast1 = false ; @@ -5194,6 +5329,17 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ++ nAddedSpan ; } + //debug + ICURVEPOVECTOR vCrv ; + GetAllPatchesIsocurves( false, vCrv) ; + vector vGeo ; + for( int i = 0 ; i < int(vCrv.size()); ++i) + vGeo.push_back( vCrv[i]) ; + vector vCol( vGeo.size()) ; + fill( vCol.begin(), vCol.end(), Color( 255, 0 ,128)) ; + SaveGeoObj( vGeo, vCol, "D:/Temp/bezier/ruled/isoCurves.nge") ; + //debug + return bOk ; } else if ( RLT_B_LENPAR ) {