From 11dd35af448c3c095aa9ea1d90ece32a14436279 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Tue, 9 Dec 2025 08:14:56 +0100 Subject: [PATCH] EgtGeomKernel : - aggiunta funzione di proiezione a minima distanza di curva su superfcie - migliorato LockAddErase per atomic_flag. --- GeomDB.cpp | 3 +- ProjectCurveSurf.cpp | 176 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 156 insertions(+), 23 deletions(-) diff --git a/GeomDB.cpp b/GeomDB.cpp index c2b7ef7..964cf4b 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -42,13 +42,14 @@ class LockAddErase : m_bAddEraseOn( bAddEraseOn), m_bUse( bUse) { if ( ! m_bUse) return ; while ( m_bAddEraseOn.test_and_set( memory_order_acquire)) { - this_thread::sleep_for( chrono::nanoseconds{ 1}) ; + m_bAddEraseOn.wait( true, memory_order_relaxed) ; } } ; ~LockAddErase( void) { if ( ! m_bUse) return ; m_bAddEraseOn.clear( memory_order_release) ; + m_bAddEraseOn.notify_one() ; } ; private : diff --git a/ProjectCurveSurf.cpp b/ProjectCurveSurf.cpp index 1c1dd66..2334d23 100644 --- a/ProjectCurveSurf.cpp +++ b/ProjectCurveSurf.cpp @@ -70,7 +70,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, double dCosAngLim = 1 - dSqTol / ( 2 * LENREF * LENREF) ; // Cerco gli angoli interni e marco opportunamente i punti nelle vicinanze fino ai limiti prima e dopo int nInd = 0 ; - while ( nInd < int( vPt5ax.size())) { + while ( nInd < ssize( vPt5ax)) { if ( vPt5ax[nInd].nFlag == P5AX_CONC) { // analizzo i punti appena precedenti int nIpv = nInd - 1 ; @@ -86,7 +86,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, } // analizzo i punti appena successivi int nInx = nInd + 1 ; - while ( nInx < int( vPt5ax.size())) { + while ( nInx < ssize( vPt5ax)) { double dSqLen = SqDist( vPt5ax[nInd].ptP, vPt5ax[nInx].ptP) ; if ( dSqLen < dSqMaxLen) vPt5ax[nInx].nFlag = P5AX_TO_DELETE ; @@ -104,7 +104,7 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, int nPrec = 0 ; int nCurr = 1 ; int nNext = 2 ; - while ( nNext < int( vPt5ax.size())) { + while ( nNext < ssize( vPt5ax)) { bool bRemove = false ; // lunghezza del segmento che unisce gli adiacenti double dSqLen = SqDist( vPt5ax[nPrec].ptP, vPt5ax[nNext].ptP) ; @@ -161,6 +161,138 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, return true ; } +//---------------------------------------------------------------------------- +static bool +ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar, Point5ax& Pt5ax) +{ + // punto sulle supefici a minima distanza + int nSurfMin = -1 ; + int nTriaMin ; + Point3d ptMin ; + double dMinDist ; + for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { + // punto sulla superficie a minima distanza + DistPointSurfTm dPS( ptP, *vpStm[i]) ; + double dDist ; + if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) { + nSurfMin = i ; + dPS.GetMinDistPoint( ptMin) ; + dPS.GetMinDistTriaIndex ( nTriaMin) ; + dMinDist = dDist ; + } + } + + // se trovato + if ( nSurfMin >= 0) { + // assegno il punto + Point3d ptInt = ptMin ; + // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) + Triangle3dEx trTria ; + if ( ! vpStm[nSurfMin]->GetTriangle( nTriaMin, trTria)) + return false ; + Vector3d vtN ; + if ( ! CalcNormal( ptMin, trTria, vtN)) + vtN = trTria.GetN() ; + // assegno valori al punto 5assi + Pt5ax.ptP = ptInt ; + Pt5ax.vtDir1 = vtN ; + Pt5ax.vtDir2 = vtN ; + Pt5ax.dPar = dPar ; + Pt5ax.nFlag = P5AX_STD ; + // ritorno con successo + return true ; + } + + return false ; +} + +//---------------------------------------------------------------------------- +bool +ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, + double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax) +{ + // sistemazioni per tipo di superficie + CISRFTMPVECTOR vpSurfTm ; + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { + const SurfTriMesh* pSurfTm = nullptr ; + switch ( vpSurf[i]->GetType()) { + case SRF_TRIMESH : + pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ; + break ; + case SRF_BEZIER : + { double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ; + SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ; + pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ; + SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ; + } break ; + case SRF_FLATRGN : + pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ; + break ; + default : + break ; + } + if ( pSurfTm == nullptr) + return false ; + vpSurfTm.emplace_back( pSurfTm) ; + } + + // controllo le tolleranze + dLinTol = max( dLinTol, LIN_TOL_MIN) ; + dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ; + + // approssimo la curva con una polilinea entro la metà della tolleranza + PolyLine PL ; + if ( ! crCrv.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) + return false ; + const double MAX_SEG_LEN = min( dMaxSegmLen, 0.977) ; + if ( ! PL.AdjustForMaxSegmentLen( MAX_SEG_LEN)) + return false ; + + // Pulisco e riservo spazio nel vettore dei punti risultanti + vPt5ax.clear() ; + vPt5ax.reserve( PL.GetPointNbr()) ; + + // proietto i punti della polilinea sulla superficie secondo la direzione di minima distanza + double dPar ; + Point3d ptP ; + bool bFound = PL.GetFirstUPoint( &dPar, &ptP) ; + while ( bFound) { + // se trovo proiezione, la salvo + Point5ax Pt5ax ; + if ( ProjectPointOnSurf( ptP, vpSurfTm, dPar, Pt5ax)) + vPt5ax.emplace_back( Pt5ax) ; + // passo al successivo + bFound = PL.GetNextUPoint( &dPar, &ptP) ; + } + + // se richiesto, inserimento punti intermedi in presenza di spigoli + if ( bSharpEdges) { + for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) { + // precedente + int j = i - 1 ; + // se normali tra corrente e precedente oltre limite e punti abbastanza lontani + if ( vPt5ax[i].vtDir1 * vPt5ax[j].vtDir1 < COS_ANG_MAX_CORNER && + SqDist( vPt5ax[i].ptP, vPt5ax[j].ptP) > 25 * SQ_EPS_SMALL) { + // punto medio + Point3d ptMid = Media( vPt5ax[i].ptP, vPt5ax[j].ptP) ; + double dMid = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; + // se trovo proiezione, la salvo + Point5ax Pt5ax ; + if ( ProjectPointOnSurf( ptMid, vpSurfTm, dMid, Pt5ax)) { + vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; + -- i ; + } + } + } + } + + // rimozione punti in eccesso rispetto alle tolleranze + RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ; + + return true ; +} + +//---------------------------------------------------------------------------- // --- vettore di oggetti intersezione massiva rette parallele SurfTM -------- typedef std::vector INTPARLINESTMPVECTOR ; @@ -173,11 +305,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame Point3d ptL = GetToLoc( ptP, frRefLine) ; int nInd = -1 ; IntLinStmInfo IntRes ; - for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) { ILSIVECTOR vIntRes ; if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) { // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; + int nI = ssize( vIntRes) - 1 ; while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) --nI ; // se trovata @@ -231,7 +363,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect { // sistemazioni per tipo di superficie CISRFTMPVECTOR vpSurfTm ; - for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { const SurfTriMesh* pSurfTm = nullptr ; switch ( vpSurf[i]->GetType()) { case SRF_TRIMESH : @@ -270,10 +402,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect if ( ! frRefLine.Set( ORIG, vtDir)) return false ; INTPARLINESTMPVECTOR vpIntPLSTM ; vpIntPLSTM.reserve( vpSurfTm.size()) ; - for ( int i = 0 ; i < int( vpSurfTm.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpSurfTm) ; ++ i) { IntersParLinesSurfTm* pIntPLSTM = new IntersParLinesSurfTm( frRefLine, *vpSurfTm[i]) ; if ( pIntPLSTM == nullptr) { - for ( int j = 0 ; j < int( vpIntPLSTM.size()) ; ++ j) + for ( int j = 0 ; j < ssize( vpIntPLSTM) ; ++ j) delete vpIntPLSTM[j] ; return false ; } @@ -298,12 +430,12 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect } // Libero oggetti per calcolo massivo - for ( int i = 0 ; i < int( vpIntPLSTM.size()) ; ++ i) + for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) delete vpIntPLSTM[i] ; // se richiesto, inserimento punti intermedi in presenza di spigoli if ( bSharpEdges) { - for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { + for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) { // precedente int j = i - 1 ; // se normali tra corrente e precedente oltre limite e punti abbastanza lontani @@ -385,11 +517,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP // conservo l'intersezione più alta int nInd = -1 ; IntLinStmInfo IntRes ; - for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { ILSIVECTOR vIntRes ; if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; + int nI = ssize( vIntRes) - 1 ; while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) --nI ; // se trovata @@ -444,7 +576,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo { // sistemazioni per tipo di superficie CISRFTMPVECTOR vpSurfTm ; - for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { const SurfTriMesh* pSurfTm = nullptr ; switch ( vpSurf[i]->GetType()) { case SRF_TRIMESH : @@ -498,7 +630,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo // se richiesto, inserimento punti intermedi in presenza di spigoli if ( bSharpEdges) { - for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { + for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) { // precedente int j = i - 1 ; // se normali tra corrente e precedente oltre limite e punti abbastanza lontani @@ -540,11 +672,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv // conservo l'intersezione più alta int nInd = -1 ; IntLinStmInfo IntRes ; - for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { ILSIVECTOR vIntRes ; if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; + int nI = ssize( vIntRes) - 1 ; while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) --nI ; // se trovata @@ -600,7 +732,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur { // Sistemazioni per tipo di superficie CISRFTMPVECTOR vpSurfTm ; - for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { const SurfTriMesh* pSurfTm = nullptr ; switch ( vpSurf[i]->GetType()) { case SRF_TRIMESH : @@ -654,7 +786,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur // se richiesto, inserimento punti intermedi in presenza di spigoli if ( bSharpEdges) { - for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { + for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) { // precedente int j = i - 1 ; // se normali tra corrente e precedente oltre limite e punti abbastanza lontani @@ -748,11 +880,11 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT // intersezione della retta con le superfici (conservo l'intersezione più alta) int nInd = -1 ; IntLinStmInfo IntRes ; - for ( int i = 0 ; i < int( vpStm.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { ILSIVECTOR vIntRes ; if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) { // cerco la prima intersezione valida a partire dall'ultima (è la più alta) - int nI = int( vIntRes.size()) - 1 ; + int nI = ssize( vIntRes) - 1 ; while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM) --nI ; // se trovata @@ -814,7 +946,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur { // sistemazioni per tipo di superficie CISRFTMPVECTOR vpSurfTm ; - for ( int i = 0 ; i < int( vpSurf.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { const SurfTriMesh* pSurfTm = nullptr ; switch ( vpSurf[i]->GetType()) { case SRF_TRIMESH : @@ -889,7 +1021,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur // se richiesto, inserimento punti intermedi in presenza di spigoli if ( bSharpEdges) { - for ( int i = 1 ; i < int( vPt5ax.size()) ; ++ i) { + for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) { // precedente int j = i - 1 ; // se normali tra corrente e precedente oltre limite e punti abbastanza lontani