From 1d68a1ee8e4e15ced6f1716050221cd385fb5ec8 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 3 Feb 2026 17:18:46 +0100 Subject: [PATCH 01/22] EgtGeomKernel 3.1a5 : - in Trimming aggiunte le funzioni per ricerca di fori e asole - in Trimming migliorate e corrette le funzioni per la ricerca delle Patch dalle superfici - in Trimming corrette le tolleranze lineari per le approssimazioni dei bordi - in Trimming rimozione Memory Leaks e pulizia del codice. --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes Trimming.cpp | 1626 +++++++++++++++++++++++++++------------------- 2 files changed, 958 insertions(+), 668 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 5ff8fcbaacafb63d0892e3ed26b696523ac19e8c..c8b0b3fa0ba23636a1fd4024657496a3a24824ac 100644 GIT binary patch delta 81 zcmdlNy)SyhH#SDo&FAG5nSs COMPOVECTOR ; -typedef vector COMPOMATRIX ; -// Strutta per Patch semplici, Bordi e insieme di Bordi +typedef vector COMPOMATRIX ; + +// Strutta per Patch Semplici, Bordi e Insieme di Bordi struct SimplePatch { Point3d ptStart ; Point3d ptEnd ; @@ -91,37 +96,26 @@ struct SimplePatch { SimplePatch( const Point3d& ptS, const Point3d& ptE, int nB, bool bDelete) : ptStart( ptS), ptEnd( ptE), bErase( bDelete), nBorder( nB) {} ; } ; -typedef vector SimpleBorder ; -typedef vector SimpleBorderVector ; -typedef vector SimpleBorderMatrix ; +typedef vector SimpleBorder ; +typedef vector SimpleBorderVector ; +typedef vector SimpleBorderMatrix ; + // Struttura per superficie con relative Patch +typedef vector BOXMATRIX ; struct SurfPatches { - int nIndSurf ; const ISurf* pSurf ; - vector vPatches ; // non definiscono per forza un bordo, sono solo patch non ordinate - COMPOVECTOR CompoPathces ; + BBox3d BoxSurf ; + SimpleBorderVector vBorderPatches ; + COMPOVECTOR vCompoBorders ; + COMPOMATRIX matCompoPatches ; + BOXMATRIX matBox3dPatches ; + vector> vSetPatchPar ; } ; typedef vector SURFPATCHESVECTOR ; -// Struttura per Calcolo delle Normali su una superficie lungo il suo bordo ( per parallelismo ) -struct BorderInfo { - const ISurf* pSurf ; - const ICurveComposite* pCompo ; - int nInd ; - double dParam ; - Point3d ptCrv ; - Vector3d vtTan ; - Vector3d vtNorm ; - Point3d ptFinal ; - BorderInfo( const ISurf* pS, const ICurveComposite* pC, int nI, double dP) - : pSurf( pS), pCompo( pC), nInd( nI), dParam( dP) {} -} ; -typedef vector VBORDERINFO ; +// Classificazione tipologia di triangoli enum TriaClass { OK = 0, SMALL = 1, CAP = 2, HAT = 3, FLIPPED = 4} ; -//----------------------------------------------------------------------------- -static const string sCircle{ "circle"} ; - //----------------------------------------------------------------------------- //--------------------------- Approssimazione --------------------------------- //----------------------------------------------------------------------------- @@ -292,7 +286,7 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL) // Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante // Patches di curve di Bezier static bool -ApproxBorder( ICurveComposite& CrvCompo, double dLinTol, double dAngTol) +ApproxBorder( CurveComposite& CrvCompo, double dLinTol, double dAngTol) { // Controllo dei parametri if ( ! CrvCompo.IsValid()) @@ -324,6 +318,11 @@ ApproxBorder( ICurveComposite& CrvCompo, double dLinTol, double dAngTol) SaveGeoObj( VT, VC, "C:\\Temp\\RawEdge.nge") ; #endif + // NB. L'approssimazione avviene prima mediante Archi e Rette e successivamente mediante + // Curve di Bezier. Entrambe vengono eseguite con un tolleranza lineare dimezzata in modo + // da rispettare la tolleranza lineare per la curva complessiva. + double dHalfLinTol = max( EPS_SMALL, dLinTol / 2.) ; + // Approssimo le Patch mediante Archi CurveComposite CCApprox ; for ( const PolyLine& PL : vPL) { @@ -331,18 +330,18 @@ ApproxBorder( ICurveComposite& CrvCompo, double dLinTol, double dAngTol) CurveComposite CCPatch ; CCPatch.FromPolyLine( PL) ; // Creo la Patch Approssimata con Archi PolyArc PA ; - CCPatch.ApproxWithArcs( dLinTol, dAngTol, PA) ; + CCPatch.ApproxWithArcs( dHalfLinTol, dAngTol, PA) ; CurveComposite CCPatchApprox ; CCPatchApprox.FromPolyArc( PA) ; - // Rimozione delle Imperfezioni - CCPatchApprox.RemoveSmallDefects( dLinTol, dAngTol) ; - // Merge complessivo - CCPatchApprox.MergeCurves( dLinTol, dAngTol) ; + // Rimozione delle Imperfezioni ( metà della tolleranza lineare) + CCPatchApprox.RemoveSmallDefects( dHalfLinTol / 2., dAngTol) ; + // Merge complessivo ( metà della tolleranza lineare) + CCPatchApprox.MergeCurves( dHalfLinTol / 2., dAngTol) ; #if DEBUG_BEZIER_INTERP VT.emplace_back( CCPatchApprox.Clone()) ; VC.emplace_back( vColor[ ++ nIndCol]) ; #endif // Approssimo tale curva con una Bezier - PtrOwner pCrvPatchBZ( ApproxCurveWithBezier( &CCPatchApprox, dLinTol, 123456)) ; + PtrOwner pCrvPatchBZ( ApproxCurveWithBezier( &CCPatchApprox, dHalfLinTol, 123456)) ; if ( IsNull( pCrvPatchBZ) || ! pCrvPatchBZ->IsValid()) { LOG_ERROR( GetEGkLogger(), "Error : Interpolating points to bezier curve failed") ; return false ; @@ -360,6 +359,7 @@ ApproxBorder( ICurveComposite& CrvCompo, double dLinTol, double dAngTol) VC.emplace_back( RED) ; SaveGeoObj( VT, VC, "C:\\Temp\\RawEdge.nge") ; #endif + if ( CCApprox.IsValid()) CrvCompo.CopyFrom( CCApprox.Clone()) ; @@ -509,98 +509,6 @@ GetNormalAtPoint( const ISurf* pSurf, const Point3d& pt, Vector3d& vtN) return true ; } -// ---------------------------------------------------------------------------- -// Funzione per Splittare una Patch con un'altra -static bool -SplitPatchWithPatch( SurfPatches& SurfPatchA, SurfPatches& SurfPatchB, double dLinTol) -{ - // Definisco la tolleranza di parametro - const double TOL_LINE_PARAM = 10. * EPS_SMALL ; // <-- euristica, modificabile - - // Scorro le Patch della superficie A - for ( int nPatchA = 0 ; nPatchA < int( SurfPatchA.CompoPathces.size()) ; ++ nPatchA) { - // Recupero la PatchA - CurveComposite& PatchA = SurfPatchA.CompoPathces[nPatchA] ; - Point3d& ptStartA = SurfPatchA.vPatches[nPatchA].ptStart ; - Point3d& ptEndA = SurfPatchA.vPatches[nPatchA].ptEnd ; - // Scorro le Patch della supericie B - for ( int nPatchB = 0 ; nPatchB < int( SurfPatchB.CompoPathces.size()) ; ++ nPatchB) { - // Recupero la PatchB - CurveComposite& PatchB = SurfPatchB.CompoPathces[nPatchB] ; - Point3d& ptStartB = SurfPatchB.vPatches[nPatchB].ptStart ; - Point3d& ptEndB = SurfPatchB.vPatches[nPatchB].ptEnd ; - - // Verifico se gli estremi giaciono sulle linee - double dDist = 0. ; - double dPar = 0., dParS = 0., dParE = 0. ; - int nFlag = 0 ; - bool bSplit = false ; - Point3d ptInters ; - - // Estremi B su PatchA ( sono tutti tratti lineari, quindi nel 3d va bene) - DistPointCurve DLL0( ptStartB, PatchA) ; - bSplit = ( DLL0.GetDist( dDist) && dDist < dLinTol && - DLL0.GetParamAtMinDistPoint( 0., dPar, nFlag) && - PatchA.GetDomain( dParS, dParE) && - dParS + TOL_LINE_PARAM < dPar && dPar < dParE - TOL_LINE_PARAM) ; - if ( ! bSplit) { - DistPointCurve DLL1( ptEndB, PatchA) ; - bSplit = ( DLL1.GetDist( dDist) && dDist < dLinTol && - DLL1.GetParamAtMinDistPoint( 0., dPar, nFlag) && - PatchA.GetDomain( dParS, dParE) && - dParS + TOL_LINE_PARAM < dPar && dPar < dParE - TOL_LINE_PARAM) ; - } - // Se Split della PatchA richiesto - if ( bSplit) { - // Split della Patch - PatchA.GetPointD1D2( dPar, ICurve::FROM_MINUS, ptInters) ; - SimplePatch NextPatch( ptInters, ptEndA, 0, false) ; - SurfPatchA.vPatches.insert( SurfPatchA.vPatches.begin() + nPatchA + 1, NextPatch) ; - ptEndA = ptInters ; - // Split della curva composita associata - CurveComposite* pCompoAfter( PatchA.Clone()) ; - PatchA.TrimEndAtParam( dPar) ; - pCompoAfter->TrimStartAtParam( dPar) ; - SurfPatchA.CompoPathces.insert( SurfPatchA.CompoPathces.begin() + nPatchA + 1, *pCompoAfter) ; - // Aggiorno i contatori - -- nPatchA ; - break ; - } - - // Estremi Curr su LineNext ( sono tutti tratti lineari, quindi nel 3d va bene) - DistPointCurve DLL2( ptStartA, PatchB) ; - bSplit = ( DLL2.GetDist( dDist) && dDist < dLinTol && - DLL2.GetParamAtMinDistPoint( 0., dPar, nFlag) && - PatchB.GetDomain( dParS, dParE) && - dParS + TOL_LINE_PARAM < dPar && dPar < dParE - TOL_LINE_PARAM) ; - if ( ! bSplit) { - DistPointCurve DLL3( ptEndA, PatchB) ; - bSplit = ( DLL3.GetDist( dDist) && dDist < dLinTol && - DLL3.GetParamAtMinDistPoint( 0., dPar, nFlag) && - PatchB.GetDomain( dParS, dParE) && - dParS + TOL_LINE_PARAM < dPar && dPar < dParE - TOL_LINE_PARAM) ; - } - // Se Split della PatchB richiesto - if ( bSplit) { - // Split della Patch - PatchB.GetPointD1D2( dPar, ICurve::FROM_MINUS, ptInters) ; - SimplePatch NextPatch( ptInters, ptEndB, 0, false) ; - SurfPatchB.vPatches.insert( SurfPatchB.vPatches.begin() + nPatchB + 1, NextPatch) ; - ptEndB = ptInters ; - // Split della curva composita associata - CurveComposite* pCompoAfter( PatchB.Clone()) ; - PatchB.TrimEndAtParam( dPar) ; - pCompoAfter->TrimStartAtParam( dPar) ; - SurfPatchB.CompoPathces.insert( SurfPatchB.CompoPathces.begin() + nPatchB + 1, *pCompoAfter) ; - // Aggiorno i contatori - -- nPatchB ; - } - } - } - - return true ; -} - // ---------------------------------------------------------------------------- // Funzione per ottenere le Patch dei bordi di una superficie static bool @@ -648,32 +556,59 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, matCompoPatches.back().back().FromPolyLine( PLPatch) ; } } + // Dalle PolyLine ricevute tengo il vettore di Curve Composite. Il punto iniziale coicide con + // Quello della prima Patch trovata + COMPOVECTOR vCompoBorders ; vCompoBorders.reserve( vPLBorders.size()) ; + for ( int i = 0 ; i < ssize( vPLBorders) ; ++ i) { + vCompoBorders.emplace_back( CurveComposite()) ; + vCompoBorders.back().FromPolyLine( vPLBorders[i]) ; + if ( ! vCompoBorders.back().IsValid()) + return false ; + const PolyLine& PLFirstPatch = matPLPatches[i].front() ; + Point3d ptStart ; + if ( ! PLFirstPatch.GetFirstPoint( ptStart)) + return false ; + double dUS = 0. ; + vCompoBorders.back().GetParamAtPoint( ptStart, dUS) ; + vCompoBorders.back().ChangeStartPoint( dUS) ; + } // Ogni curva Patch diventa un insieme di tratti attivi definiti dagli estremi calcolati // NB. In questo modo si salvano solo gli estremi della curva Patch, mentre la sua geometria // è rimasta memorizzata in precedenza [*] // Ogni bordo viene quindi visto come un insieme di Patch semplici ( per adesso tutte attive) - SimpleBorderVector vvSimpleBorder ; vvSimpleBorder.reserve( matPLPatches.size()) ; + // Le Patch più corte della tolleranza vengono considerate invalide + SimpleBorderVector vSimpleBorder ; vSimpleBorder.reserve( matPLPatches.size()) ; + vector> matPatchPar ; matPatchPar.reserve( matPLPatches.size()) ; for ( int i = 0 ; i < int( matPLPatches.size()) ; ++ i) { - vvSimpleBorder.emplace_back( SimpleBorder()) ; - for ( int j = 0 ; j < int( matPLPatches[i].size()) ; ++ j) { + vSimpleBorder.emplace_back( SimpleBorder()) ; + matPatchPar.emplace_back( set()) ; + for ( int j = 0 ; j < ssize( matPLPatches[i]) ; ++ j) { Point3d ptS ; matPLPatches[i][j].GetFirstPoint( ptS) ; Point3d ptE ; matPLPatches[i][j].GetLastPoint( ptE) ; - vvSimpleBorder.back().emplace_back( ptS, ptE, i, false) ; + vSimpleBorder.back().emplace_back( ptS, ptE, i, false) ; + double dPar = -1. ; + if ( j != ssize( matPLPatches[i]) - 1) + vCompoBorders[i].GetParamAtPoint( ptE, dPar, dLinTol) ; + else { + double dParS = 0. ; + vCompoBorders[i].GetDomain( dParS, dPar) ; + } + matPatchPar.back().insert( int( round( dPar))) ; } } #if DEBUG_CHAIN_CURVES VC.clear() ; VT.clear() ; - for ( int i = 0 ; i < int( vvSimpleBorder.size()) ; ++ i) { - for ( int j = 0 ; j < int( vvSimpleBorder[i].size()) ; ++ j) { + for ( int i = 0 ; i < int( vSimpleBorder.size()) ; ++ i) { + for ( int j = 0 ; j < int( vSimpleBorder[i].size()) ; ++ j) { VT.emplace_back( matCompoPatches[i][j].Clone()) ; VC.emplace_back( RED) ; IGeoPoint3d* ptS = CreateGeoPoint3d() ; - ptS->Set( vvSimpleBorder[i][j].ptStart) ; + ptS->Set( vSimpleBorder[i][j].ptStart) ; VT.emplace_back( ptS) ; VC.emplace_back( AQUA) ; IGeoPoint3d* ptE = CreateGeoPoint3d() ; - ptE->Set( vvSimpleBorder[i][j].ptEnd) ; + ptE->Set( vSimpleBorder[i][j].ptEnd) ; VT.emplace_back( ptE) ; VC.emplace_back( AQUA) ; } @@ -686,138 +621,108 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, // una Patch cada ad esempio a metà di un'altra Patch e non nei suoi estremi ) // Soluzione : si spezzano le Patch ulteriormente in modo che ogni estremo di patch sia o nell'intorno // di un altro estremo di patch o isolato ( ad esempio nei bordi più esterni ) - const double TOL_LINE_PARAM = 10. * EPS_SMALL ; // <-- eursitica, modificabile - for ( int nCurrCrv = 0 ; nCurrCrv < int( vvSimpleBorder.size()) - 1 ; ++ nCurrCrv) { - // Recupero la curva corrente - SimpleBorder& CurrCurve = vvSimpleBorder[nCurrCrv] ; - // Scorro i suoi Edges - for ( int nCurrEdge = 0 ; nCurrEdge < int( CurrCurve.size()) ; ++ nCurrEdge) { - // Recupero il tratto di curva corrente - CurveComposite& CurrCompo = matCompoPatches[nCurrCrv][nCurrEdge] ; - // Scorro le curve successive - for ( int nNextCrv = nCurrCrv + 1 ; nNextCrv < int( vvSimpleBorder.size()) ; ++ nNextCrv) { - // Recupero la curva successiva - SimpleBorder& NextCurve = vvSimpleBorder[nNextCrv] ; - // Scorro i suoi Edges - for ( int nNextEdge = 0 ; nNextEdge < int( NextCurve.size()) ; ++ nNextEdge) { - // Se appartiene allo stesso bordo, passo alla seguente - if ( NextCurve[nNextEdge].nBorder == CurrCurve[nCurrEdge].nBorder) - continue ; - // Recupero il tratto di curva corrente - CurveComposite& NextCompo = matCompoPatches[nNextCrv][nNextEdge] ; - // Verifico se gli estremi giaciono sulle linee - double dDist = 0. ; - double dPar = 0., dParS = 0., dParE = 0. ; + BOOLVECTOR vBorderModif( vSimpleBorder.size(), false) ; + for ( int nCurrBorder = 0 ; nCurrBorder < ssize( vSimpleBorder) ; ++ nCurrBorder) { + // Recupero la Composita associata al Bordo Corrente + CurveComposite& CurrCompoBorder = vCompoBorders[nCurrBorder] ; + // Recupero le Patch associate + SimpleBorder& vPatchCurrBorder = vSimpleBorder[nCurrBorder] ; + // Recupero il vettore dei Parametri di Split + set& setSplitPar = matPatchPar[nCurrBorder] ; + #if DEBUG_CHAIN_CURVES + VC.clear() ; VT.clear() ; + VT.emplace_back( CurrCompoBorder.Clone()) ; + VC.emplace_back( RED) ; + for ( auto Iter = setSplitPar.begin() ; Iter != setSplitPar.end() ; ++ Iter) { + Point3d ptCurr ; + CurrCompoBorder.GetPointD1D2( *Iter, ICurve::FROM_MINUS, ptCurr) ; + PtrOwner ptGeoCurr( CreateGeoPoint3d()) ; ptGeoCurr->Set( ptCurr) ; + VT.emplace_back( ptGeoCurr->Clone()) ; + VC.emplace_back( ORANGE) ; + } + #endif + + // Scorro gli altri Bordi + for ( int nOtherBorder = 0 ; nOtherBorder < ssize( vSimpleBorder) ; ++ nOtherBorder) { + if ( nOtherBorder == nCurrBorder) + continue ; + #if DEBUG_CHAIN_CURVES + CurveComposite& OtherCompoBorder = vCompoBorders[nOtherBorder] ; + VT.emplace_back( OtherCompoBorder.Clone()) ; + VC.emplace_back( BLACK) ; + #endif + // Recupero l'altro bordo + SimpleBorder& OtherBorder = vSimpleBorder[nOtherBorder] ; + // Scorro le sue Patch + for ( int nOtherPatch = 0 ; nOtherPatch < ssize( OtherBorder) ; ++ nOtherPatch) { + // Recupero gli estremi della Path attuale + DistPointCurve DPTCRV( OtherBorder[nOtherPatch].ptStart, CurrCompoBorder) ; + double dDist = INFINITO ; + if ( DPTCRV.GetDist( dDist) && dDist < dLinTol) { + Point3d ptMinDist ; int nFlag = 0 ; - bool bSplit = false ; - Point3d ptInters ; - - // Estremi Next su LineCurr ( sono tutti tratti lineari, quindi nel 3d va bene) - DistPointCurve DLL0( NextCurve[nNextEdge].ptStart, CurrCompo) ; - bSplit = ( DLL0.GetDist( dDist) && dDist < dLinTol && - DLL0.GetParamAtMinDistPoint( 0., dPar, nFlag) && - CurrCompo.GetDomain( dParS, dParE) && - dParS + TOL_LINE_PARAM < dPar && dPar < dParE - TOL_LINE_PARAM) ; - if ( ! bSplit) { - DistPointCurve DLL1( NextCurve[nNextEdge].ptEnd, CurrCompo) ; - bSplit = ( DLL1.GetDist( dDist) && dDist < dLinTol && - DLL1.GetParamAtMinDistPoint( 0., dPar, nFlag) && - CurrCompo.GetDomain( dParS, dParE) && - dParS + TOL_LINE_PARAM < dPar && dPar < dParE - TOL_LINE_PARAM) ; - } - // Split dell'Edge se richiesto - if ( bSplit) { - #if DEBUG_CHAIN_CURVES - VT.clear() ; VC.clear() ; - VT.emplace_back( NextCompo.Clone()) ; - VC.emplace_back( ORANGE) ; - VT.emplace_back( CurrCompo.Clone()) ; - VC.emplace_back( LIME) ; - SaveGeoObj( VT, VC, "C:\\Temp\\LineIntersection.nge") ; - #endif - // Aggiorno gli Edges - CurrCompo.GetPointD1D2( dPar, ICurve::FROM_MINUS, ptInters) ; - SimplePatch NextEdge( ptInters, CurrCurve[nCurrEdge].ptEnd, - CurrCurve[nCurrEdge].nBorder, false) ; - CurrCurve.insert( CurrCurve.begin() + nCurrEdge + 1, NextEdge) ; - CurrCurve[nCurrEdge].ptEnd = ptInters ; - // Aggiorno le Curve - CurveComposite* pCompoAfter( CurrCompo.Clone()) ; - CurrCompo.TrimEndAtParam( dPar) ; - pCompoAfter->TrimStartAtParam( dPar) ; - matCompoPatches[nCurrCrv].insert( matCompoPatches[nCurrCrv].begin() + nCurrEdge + 1, *pCompoAfter) ; - // Aggiorno i contatori - -- nCurrEdge ; - nNextCrv = int( vvSimpleBorder.size()) ; - break ; - } - - // Estremi Curr su LineNext ( sono tutti tratti lineari, quindi nel 3d va bene) - DistPointCurve DLL2( CurrCurve[nCurrEdge].ptStart, NextCompo) ; - bSplit = ( DLL2.GetDist( dDist) && dDist < dLinTol && - DLL2.GetParamAtMinDistPoint( 0., dPar, nFlag) && - NextCompo.GetDomain( dParS, dParE) && - dParS + TOL_LINE_PARAM < dPar && dPar < dParE - TOL_LINE_PARAM) ; - if ( ! bSplit) { - DistPointCurve DLL3( CurrCurve[nCurrEdge].ptEnd, NextCompo) ; - bSplit = ( DLL3.GetDist( dDist) && dDist < dLinTol && - DLL3.GetParamAtMinDistPoint( 0., dPar, nFlag) && - NextCompo.GetDomain( dParS, dParE) && - dParS + TOL_LINE_PARAM < dPar && dPar < dParE - TOL_LINE_PARAM) ; - } - // Split dell'Edge se richiesto - if ( bSplit) { - #if DEBUG_CHAIN_CURVES - VT.clear() ; VC.clear() ; - VT.emplace_back( NextCompo.Clone()) ; - VC.emplace_back( ORANGE) ; - VT.emplace_back( CurrCompo.Clone()) ; - VC.emplace_back( LIME) ; - SaveGeoObj( VT, VC, "C:\\Temp\\LineIntersection.nge") ; - #endif - // Aggiorno gli Edges - NextCompo.GetPointD1D2( dPar, ICurve::FROM_MINUS, ptInters) ; - SimplePatch NextEdge( ptInters, NextCurve[nNextEdge].ptEnd, - NextCurve[nNextEdge].nBorder, false) ; - NextCurve.insert( NextCurve.begin() + nNextEdge + 1, NextEdge) ; - NextCurve[nNextEdge].ptEnd = ptInters ; - // Aggiorno le curve - CurveComposite* pCompoAfter( NextCompo.Clone()) ; - NextCompo.TrimEndAtParam( dPar) ; - pCompoAfter->TrimStartAtParam( dPar) ; - matCompoPatches[nNextCrv].insert( matCompoPatches[nNextCrv].begin() + nNextEdge + 1, *pCompoAfter) ; - // Aggiorno i contatori - -- nNextEdge ; + if ( DPTCRV.GetMinDistPoint( 0., ptMinDist, nFlag)) { + bool bInsert = true ; + for ( int nCurrPatch = 0 ; bInsert && nCurrPatch < ssize( vPatchCurrBorder) ; ++ nCurrPatch) { + const SimplePatch& Patch = vPatchCurrBorder[nCurrPatch] ; + bInsert = ( ! AreSamePointEpsilon( Patch.ptStart, ptMinDist, dLinTol) && + ! AreSamePointEpsilon( Patch.ptEnd, ptMinDist, dLinTol)) ; + } + if ( bInsert) { + double dPar = -1. ; + if ( DPTCRV.GetParamAtMinDistPoint( 0., dPar, nFlag)) { + setSplitPar.insert( dPar) ; + vBorderModif[nCurrBorder] = true ; + #if DEBUG_CHAIN_CURVES + PtrOwner ptGeoCurr( CreateGeoPoint3d()) ; + ptGeoCurr->Set( ptMinDist) ; + VT.emplace_back( ptGeoCurr->Clone()) ; + VC.emplace_back( AQUA) ; + #endif + } + } } } } } + #if DEBUG_CHAIN_CURVES + SaveGeoObj( VT, VC, "C:\\Temp\\SplitPathces.nge") ; + #endif } - #if DEBUG_CHAIN_CURVES - VC.clear() ; VT.clear() ; - for ( int i = 0 ; i < int( vvSimpleBorder.size()) ; ++ i) { - for ( int j = 0 ; j < int( vvSimpleBorder[i].size()) ; ++ j) { - VT.emplace_back( matCompoPatches[i][j].Clone()) ; - VC.emplace_back( RED) ; - IGeoPoint3d* pt = CreateGeoPoint3d() ; - pt->Set( vvSimpleBorder[i][j].ptStart) ; - VT.emplace_back( pt) ; - VC.emplace_back( AQUA) ; - pt = CreateGeoPoint3d() ; - pt->Set( vvSimpleBorder[i][j].ptEnd) ; - VT.emplace_back( pt) ; - VC.emplace_back( AQUA) ; + for ( int nCurrBorder = 0 ; nCurrBorder < ssize( vSimpleBorder) ; ++ nCurrBorder) { + // Se il bordo corrente non ha subito Split, passo al successivo + if ( ! vBorderModif[nCurrBorder]) + continue ; + // Pulisco le Composite associate associate a tale Bordo + COMPOVECTOR& vCompoPatches = matCompoPatches[nCurrBorder] ; + vCompoPatches.clear() ; + // Recupero la Curva Composita corrente + CurveComposite& CurrCompo = vCompoBorders[nCurrBorder] ; + // Inizializzo il nuovo Bordo semplice formato dalle Patch + SimpleBorder newSimpleBorder ; + // Recupero il vettore dei Parametri di Split + set& setSplitPar = matPatchPar[nCurrBorder] ; + double dLastPar = 0 ; + for ( auto Iter = setSplitPar.begin() ; Iter != setSplitPar.end() ; ++ Iter) { + PtrOwner pCrvPatch( CurrCompo.CopyParamRange( dLastPar, *Iter)) ; + if ( ! IsNull( pCrvPatch) && pCrvPatch->IsValid()) { // ad esempio per punti coincidenti + vCompoPatches.emplace_back( *ConvertCurveToBasicComposite( Release( pCrvPatch))) ; + Point3d ptStart ; vCompoPatches.back().GetStartPoint( ptStart) ; + Point3d ptEnd ; vCompoPatches.back().GetEndPoint( ptEnd) ; + newSimpleBorder.emplace_back( ptStart, ptEnd, nCurrBorder, false) ; + dLastPar = *Iter ; } } - SaveGeoObj( VT, VC, "C:\\Temp\\BordersWithOverlaps.nge") ; - #endif + vSimpleBorder[nCurrBorder] = newSimpleBorder ; + } + // Si eliminano ora tutte le Patch che si sovrappongono, in modo da ottenere solo un // le Patch che rappresentano il bordo esterno const double MAXPOINT = 10 ; - for ( int nCurrCrv = 0 ; nCurrCrv < int( vvSimpleBorder.size()) - 1 ; ++ nCurrCrv) { + for ( int nCurrCrv = 0 ; nCurrCrv < int( vSimpleBorder.size()) - 1 ; ++ nCurrCrv) { // Recupero la curva corrente - SimpleBorder& CurrCurve = vvSimpleBorder[nCurrCrv] ; + SimpleBorder& CurrCurve = vSimpleBorder[nCurrCrv] ; // Scorro i suoi Edges for ( int nCurrEdge = 0 ; nCurrEdge < int( CurrCurve.size()) ; ++ nCurrEdge) { // Se Edge cancellato, passo al successivo @@ -827,9 +732,9 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, Point3d& ptCurrStart = CurrCurve[nCurrEdge].ptStart ; Point3d& ptCurrEnd = CurrCurve[nCurrEdge].ptEnd ; // Scorro le curve successive - for ( int nNextCrv = nCurrCrv + 1 ; nNextCrv < int( vvSimpleBorder.size()) ; ++ nNextCrv) { + for ( int nNextCrv = nCurrCrv + 1 ; nNextCrv < int( vSimpleBorder.size()) ; ++ nNextCrv) { // Recupero la curva successiva - SimpleBorder& NextCurve = vvSimpleBorder[nNextCrv] ; + SimpleBorder& NextCurve = vSimpleBorder[nNextCrv] ; // Scorro i suoi Edges for ( int nNextEdge = 0 ; nNextEdge < int( NextCurve.size()) ; ++ nNextEdge) { // Se Edge cancellato, passo al successivo @@ -876,7 +781,7 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, } // Dalle PolyLine recupero delle curve composite ( quindi anch'esse come insieme di tratti linari) - ICRVCOMPOPOVECTOR vCompoPatches ; vCompoPatches.reserve( vvSimpleBorder.size()) ; + ICRVCOMPOPOVECTOR vCompoPatches ; vCompoPatches.reserve( vSimpleBorder.size()) ; for ( const PolyLine& PL : vPLBorders) { if ( ! vCompoPatches.emplace_back( CreateCurveComposite()) || ! vCompoPatches.back()->FromPolyLine( PL)) @@ -885,9 +790,9 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, } // Recupero solo i sottotratti di curva validi ( quindi che non fanno overlap tra loro) - for ( int nCrv = 0 ; nCrv < int( vvSimpleBorder.size()) ; ++ nCrv) { + for ( int nCrv = 0 ; nCrv < int( vSimpleBorder.size()) ; ++ nCrv) { // Recupero la curva - SimpleBorder& CrvEdge = vvSimpleBorder[nCrv] ; + SimpleBorder& CrvEdge = vSimpleBorder[nCrv] ; // Scorro i suoi edges for ( int nEdge = 0 ; nEdge < int( CrvEdge.size()) ; ++ nEdge) { // Se edge non attivo, passo al successivo @@ -1007,6 +912,14 @@ ChainCompoPatches( ICRVCOMPOPOVECTOR& vCompoPatches, double dChainTol, // Trasferisco le TempProps alle sottocurve for ( int nU = 0 ; nU < pCrv->GetCurveCount() ; ++ nU) pCrv->SetCurveTempProp( nU, pCrv->GetTempProp( 0), 0) ; + // Se estremi più distanti della tolleranza, li cambio nel punto medio tra essi + Point3d ptEndCurr ; vCompoChained.back()->GetEndPoint( ptEndCurr) ; + Point3d ptStartNext ; pCrv->GetStartPoint( ptStartNext) ; + if ( SqDist( ptEndCurr, ptStartNext) > dChainTol * dChainTol) { + Point3d ptMid = Media( ptEndCurr, ptStartNext) ; + vCompoChained.back()->ModifyEnd( ptMid) ; + pCrv->ModifyStart( ptMid) ; + } // Concateno if ( ! vCompoChained.back()->AddCurve( pCrv->Clone(), true, dChainTol)) return false ; @@ -1072,7 +985,7 @@ GetRawEdges( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, Point3d ptS ; vCompoChained[i]->GetStartPoint( ptS) ; Point3d ptE ; vCompoChained[i]->GetEndPoint( ptE) ; if ( AreSamePointEpsilon( ptS, ptE, dLinTol)) { - vCompoChained[i]->Close() ; + vCompoChained[i]->Close() ; // utilizza il punto medio // Riporto la Temp Prop int nTmpProp0 = vCompoChained[i]->GetFirstCurve()->GetTempProp( 0) ; vCompoChained[i]->SetCurveTempProp( vCompoChained[i]->GetCurveCount() - 1, nTmpProp0, 0) ; @@ -1670,6 +1583,97 @@ GetBorderByExtrusion( const SurfTriMesh* pStm, double dThick, double dLinTol, do // ---------------------------------- Analisi Adiacenze ----------------------- // ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- +// Funzione per calcolare le Patch di una Superficie TriMesh +static bool +CalcSurfPatch( const ISurf* pSurf, double dLinTol, double dAngTol, SurfPatches& SrfPatches) +{ + // Verifico che la Superficie sia valida + if ( pSurf == nullptr || ! pSurf->IsValid()) + return false ; + + // Recupero il Box della superficie ( ingrandito della tolleranza lineare) + if ( ! pSurf->GetLocalBBox( SrfPatches.BoxSurf)) + return false ; + SrfPatches.BoxSurf.Expand( 2. * dLinTol + 10. * EPS_SMALL) ; + + // Recupero i suoi Loops come PolyLines + POLYLINEVECTOR vPLBorders ; + if ( ! InsertLoopsOfSurf( pSurf, vPLBorders)) + return false ; + + // Dai Bordi, recupero le Patches + POLYLINEMATRIX matPLPatchBorders ; + if ( ! CalcPatches( vPLBorders, dAngTol, matPLPatchBorders)) + return false ; + + #if DEBUG_SURF_PATCHES + VT.clear() ; VC.clear() ; + VT.emplace_back( pSurf->Clone()) ; + VC.emplace_back( BLACK) ; + for ( int i = 0 ; i < ssize( matPLPatchBorders) ; ++ i) { + for ( int j = 0 ; j < ssize( matPLPatchBorders[i]) ; ++ j) { + CurveComposite CompoPatch ; CompoPatch.FromPolyLine( matPLPatchBorders[i][j]) ; + VT.emplace_back( CompoPatch.Clone()) ; + VC.emplace_back( Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.)) ; + } + } + //SaveGeoObj( VT, VC, "C:\\Temp\\Patches.nge") ; + #endif + + // Definisco le Patches + // Recupero la Curva Composita associata per la Patch + // Memerizzo il Box3d della Patch + // Memorizzo i Parametri delle Patch sulle Curve Composite + SrfPatches.vCompoBorders.reserve( vPLBorders.size()) ; + SrfPatches.matCompoPatches.reserve( vPLBorders.size()) ; + SrfPatches.vBorderPatches.reserve( matPLPatchBorders.size()) ; + SrfPatches.matBox3dPatches.reserve( matPLPatchBorders.size()) ; + SrfPatches.vSetPatchPar.reserve( matPLPatchBorders.size()) ; + for ( int i = 0 ; i < ssize( matPLPatchBorders) ; ++ i) { + // Recupero il Bordo Corrente + const POLYLINEVECTOR& PLBorder = matPLPatchBorders[i] ; + // Recupero la Curva Composita di Bordo + SrfPatches.vCompoBorders.emplace_back( CurveComposite()) ; + SrfPatches.vCompoBorders.back().FromPolyLine( vPLBorders[i]) ; + // Inizializzo i Parametri + SrfPatches.vBorderPatches.emplace_back( SimpleBorder()) ; + SrfPatches.matBox3dPatches.emplace_back( BOXVECTOR{}) ; + SrfPatches.vSetPatchPar.emplace_back( set()) ; + SrfPatches.matCompoPatches.emplace_back( COMPOVECTOR{}) ; + for ( int j = 0 ; j < ssize( PLBorder) ; ++ j) { + // Recupero la PolyLine associata alla Patch corrente + const PolyLine& PLPatch = PLBorder[j] ; + // Definizione della Patch Semplice + Point3d ptStart ; PLPatch.GetFirstPoint( ptStart) ; + if ( j == 0) { + double dUStart = 0. ; + SrfPatches.vCompoBorders.back().GetParamAtPoint( ptStart, dUStart) ; + SrfPatches.vCompoBorders.back().ChangeStartPoint( dUStart) ; + } + Point3d ptEnd ; PLPatch.GetLastPoint( ptEnd) ; + SrfPatches.vBorderPatches.back().emplace_back( ptStart, ptEnd, i, false) ; + SrfPatches.matCompoPatches.back().emplace_back( CurveComposite()) ; + SrfPatches.matCompoPatches.back().back().FromPolyLine( PLPatch) ; + // Box Della Patch + SrfPatches.matBox3dPatches.back().emplace_back( BBox3d()) ; + PLPatch.GetLocalBBox( SrfPatches.matBox3dPatches.back().back()) ; + SrfPatches.matBox3dPatches.back().back().Expand( 2. * dLinTol + 10. * EPS_SMALL) ; + // Parametri dU associati + double dPar = -1. ; + if ( j != ssize( matPLPatchBorders[i]) - 1) + SrfPatches.vCompoBorders.back().GetParamAtPoint( ptEnd, dPar, dLinTol) ; + else { + double dParS = 0. ; + SrfPatches.vCompoBorders.back().GetDomain( dParS, dPar) ; + } + SrfPatches.vSetPatchPar.back().insert( int( round( dPar))) ; + } + } + + return true ; +} + // ---------------------------------------------------------------------------- // Funzione per individuare se un triangolo piccolo è trascurabile static bool @@ -1681,7 +1685,7 @@ CheckUnrelevantTriangle( const SurfTriMesh& Stm, int nCurrTria, int nTriaAdj, in if ( ! Stm.IsValid()) return false ; - // Verifico che il triangoli appartengano alla TriMesh + // Verifico che il triangolo appartenga alla TriMesh Triangle3d Tria, TriaAdj ; if ( ! Stm.GetTriangle( nCurrTria, Tria) || ! Stm.GetTriangle( nTriaAdj, TriaAdj)) return false ; @@ -1742,7 +1746,7 @@ AnalyzeTriangle( const Triangle3d& Tria, const Triangle3d& TriaAdj, double dAngT // Verifico caso Small double dArea = TriaAdj.GetArea() ; - if ( dArea < ( 70 * EPS_SMALL) * ( 70. * EPS_SMALL)) { // ~ 0.005 + if ( dArea < ( 70. * EPS_SMALL) * ( 70. * EPS_SMALL)) { // ~ 0.005 nTriaClass = TriaClass::SMALL ; return true ; } @@ -2530,8 +2534,10 @@ CheckCurvesInBox( const SurfTriMesh& Stm, const COMPOVECTOR& vCompoChain, const ! CompoBTmp.GetParamAtLength( dLenMinB, dUBS) || ! CompoBTmp.GetParamAtLength( dLenMaxB, dUBE)) return false ; - CompoA.CopyFrom( ConvertCurveToBasicComposite( CompoATmp.CopyParamRange( dUAS, dUAE))) ; - CompoB.CopyFrom( ConvertCurveToBasicComposite( CompoBTmp.CopyParamRange( dUBS, dUBE))) ; + PtrOwner pCrvATmp( CompoATmp.CopyParamRange( dUAS, dUAE)) ; + PtrOwner pCrvBTmp( CompoBTmp.CopyParamRange( dUBS, dUBE)) ; + CompoA.CopyFrom( pCrvATmp) ; + CompoB.CopyFrom( pCrvBTmp) ; #if DEBUG_FACE_SEARCH VT.emplace_back( CompoA.Clone()) ; @@ -2619,11 +2625,14 @@ UpdateBorderByTriaAdj( CurveComposite& Compo, double dLinTol, const COMPOVECTOR& return false ; CurveComposite CompoPrev ; if ( Compo.IsPointOn( ptS) && ! Compo.IsPointOn( ptE)) { - CompoPrev.CopyFrom( ConvertCurveToBasicComposite( CompoChain.CopyParamRange( dUBreak, dUE))) ; + PtrOwner pCrv( CompoChain.CopyParamRange( dUBreak, dUE)) ; + CompoPrev.CopyFrom( pCrv) ; CompoPrev.Invert() ; } - else if ( Compo.IsPointOn( ptE) && ! Compo.IsPointOn( ptS)) - CompoPrev.CopyFrom( ConvertCurveToBasicComposite( CompoChain.CopyParamRange( dUS, dUBreak))) ; + else if ( Compo.IsPointOn( ptE) && ! Compo.IsPointOn( ptS)) { + PtrOwner pCrv( CompoChain.CopyParamRange( dUS, dUBreak)) ; + CompoPrev.CopyFrom( pCrv) ; + } #if DEBUG_FACE_SEARCH VT.emplace_back( CompoPrev.Clone()) ; VC.emplace_back( LIME) ; @@ -2636,10 +2645,13 @@ UpdateBorderByTriaAdj( CurveComposite& Compo, double dLinTol, const COMPOVECTOR& if ( ! CompoChain.GetParamAtPoint( ptEnd, dUBreak, dLinTol)) return false ; CurveComposite CompoAft ; - if ( Compo.IsPointOn( ptS) && ! Compo.IsPointOn( ptE)) - CompoAft.CopyFrom( ConvertCurveToBasicComposite( CompoChain.CopyParamRange( dUBreak, dUE))) ; + if ( Compo.IsPointOn( ptS) && ! Compo.IsPointOn( ptE)) { + PtrOwner pCrv( CompoChain.CopyParamRange( dUBreak, dUE)) ; + CompoAft.CopyFrom( pCrv) ; + } else if ( Compo.IsPointOn( ptE) && ! Compo.IsPointOn( ptS)) { - CompoAft.CopyFrom( ConvertCurveToBasicComposite( CompoChain.CopyParamRange( dUS, dUBreak))) ; + PtrOwner pCrv( CompoChain.CopyParamRange( dUS, dUBreak)) ; + CompoAft.CopyFrom( pCrv) ; CompoAft.Invert() ; } #if DEBUG_FACE_SEARCH @@ -2658,13 +2670,17 @@ UpdateBorderByTriaAdj( CurveComposite& Compo, double dLinTol, const COMPOVECTOR& CurveComposite CompoPrev ; CurveComposite CompoAft ; if ( dUBreak < dUBreak1) { - CompoPrev.CopyFrom( ConvertCurveToBasicComposite( CompoChain.CopyParamRange( dUS, dUBreak))) ; - CompoAft.CopyFrom( ConvertCurveToBasicComposite( CompoChain.CopyParamRange( dUBreak1, dUE))) ; + PtrOwner pCrvPrev( CompoChain.CopyParamRange( dUS, dUBreak)) ; + PtrOwner pCrvAft( CompoChain.CopyParamRange( dUBreak1, dUE)) ; + CompoPrev.CopyFrom( pCrvPrev) ; + CompoAft.CopyFrom( pCrvAft) ; } else { - CompoPrev.CopyFrom( ConvertCurveToBasicComposite( CompoChain.CopyParamRange( dUBreak, dUE))) ; + PtrOwner pCrvPrev( CompoChain.CopyParamRange( dUBreak, dUE)) ; + CompoPrev.CopyFrom( pCrvPrev) ; CompoPrev.Invert() ; - CompoAft.CopyFrom( ConvertCurveToBasicComposite( CompoChain.CopyParamRange( dUS, dUBreak1))) ; + PtrOwner pCrvAft( CompoChain.CopyParamRange( dUS, dUBreak1)) ; + CompoAft.CopyFrom( pCrvAft) ; CompoAft.Invert() ; } #if DEBUG_FACE_SEARCH @@ -2679,7 +2695,8 @@ UpdateBorderByTriaAdj( CurveComposite& Compo, double dLinTol, const COMPOVECTOR& else if ( Compo.IsPointOn( ptS) && Compo.IsPointOn( ptE)) { CurveComposite CompoSingle ; if ( dUBreak < dUBreak1) { - CompoSingle.CopyFrom( ConvertCurveToBasicComposite( CompoChain.CopyParamRange( dUBreak, dUBreak1))) ; + PtrOwner pCrv( CompoChain.CopyParamRange( dUBreak, dUBreak1)) ; + CompoSingle.CopyFrom( pCrv) ; CompoSingle.Invert() ; #if DEBUG_FACE_SEARCH VT.emplace_back( CompoSingle.Clone()) ; @@ -2691,7 +2708,8 @@ UpdateBorderByTriaAdj( CurveComposite& Compo, double dLinTol, const COMPOVECTOR& } } else { - CompoSingle.CopyFrom( ConvertCurveToBasicComposite( CompoChain.CopyParamRange( dUBreak1, dUBreak))) ; + PtrOwner pCrv( CompoChain.CopyParamRange( dUBreak1, dUBreak)) ; + CompoSingle.CopyFrom( pCrv) ; #if DEBUG_FACE_SEARCH VT.emplace_back( CompoSingle.Clone()) ; VC.emplace_back( LIME) ; @@ -2707,7 +2725,7 @@ UpdateBorderByTriaAdj( CurveComposite& Compo, double dLinTol, const COMPOVECTOR& } #if DEBUG_FACE_SEARCH - //SaveGeoObj( VT, VC, "C:\\Temp\\6.nge") ; + //SaveGeoObj( VT, VC, "C:\\Temp\\6.nge") ; #endif bUpdate = ( bUpdateStart || bUpdateEnd) ; return true ; @@ -2768,8 +2786,9 @@ CheckBordersInBox( CurveComposite& CompoA, CurveComposite& CompoB, ! CompoX.GetParamAtLength( dSize + dSizeTol + 2. * EPS_SMALL, dUEndB)) return false ; // Per sicurezza [ migliorabile se stabile] - if ( ! myCompoA.CopyFrom( CompoX.CopyParamRange( dUStartA, dUE)) || - ! myCompoB.CopyFrom( CompoX.CopyParamRange( dUS, dUEndB))) + PtrOwner pCrvA( CompoX.CopyParamRange( dUStartA, dUE)) ; + PtrOwner pCrvB( CompoX.CopyParamRange( dUS, dUEndB)) ; + if ( ! myCompoA.CopyFrom( pCrvA) || ! myCompoB.CopyFrom( pCrvB)) return false ; dLenStartA = 0. ; dLenStartB = 0. ; @@ -3221,13 +3240,20 @@ MarchAlongPath( const BBox3d& BBoxCurr, const SurfTriMesh& Stm, } // ---------------------------------------------------------------------------- -// Funzione per definire se il bordo di una TriMesh è una circonferenza +// Funzione per definire se un bordo è una circonferenza +// ( Restituisce true nel caso lo sia e la circonferenza perfetta come ultimo parametro) static bool -IsBorderACircle( const PolyLine& PL, double dShapeLinTol, Point3d& ptC, Vector3d& vtN, double& dRad) +IsBorderACircle( const PolyLine& PL, double dLinTol, double dAngTol, Frame3d& frCircle, double& dRad, + CurveArc& CrvCircle) { // Se PolyLine aperta o non piana, non è un cerchio Plane3d PlanePL ; - if ( ! PL.IsClosed() || ! PL.IsFlat( PlanePL, dShapeLinTol)) + if ( ! PL.IsClosed() || ! PL.IsFlat( PlanePL, dLinTol)) + return false ; + + // Verifico che tutti i punti rispettino la tolleranza angolare + POLYLINEVECTOR vPL ; + if ( ! GetPointSetByAngTol( PL, dAngTol, vPL) || ssize( vPL) != 1) return false ; // Creo un sistema di riferimento centrato nella PolyLine @@ -3242,6 +3268,7 @@ IsBorderACircle( const PolyLine& PL, double dShapeLinTol, Point3d& ptC, Vector3d PolyLine PLLoc = PL ; PLLoc.ToLoc( frCurr) ; // Per ogni tratto salvo i suoi estremi e il punto medio in successione ( senza ripetizioni) + // ( I punti vengono proeittati nel piano per una maggiore precisione) PNTVECTOR vPts ; Point3d ptNext ; PLLoc.GetFirstPoint( ptNext) ; @@ -3250,6 +3277,27 @@ IsBorderACircle( const PolyLine& PL, double dShapeLinTol, Point3d& ptC, Vector3d vPts.push_back( Media( vPts.back(), ptNext)) ; vPts.push_back( ptNext) ; } + for ( POINTU& ptU : PLLoc.GetUPointList()) + ptU.first.z = 0. ; + + #if DEBUG_HOLES + vector VTCircle ; + vector VCCirle ; + CurveComposite CompoPL ; CompoPL.FromPolyLine( PLLoc) ; + VTCircle.emplace_back( CompoPL.Clone()) ; + VCCirle.emplace_back( RED) ; + IGeoPoint3d* ptCenter = CreateGeoPoint3d() ; ptCenter->Set( ptCentroid) ; + ptCenter->ToLoc( frCurr) ; + VTCircle.emplace_back( ptCenter) ; + VCCirle.emplace_back( BLUE) ; + for ( int i = 0 ; i < ssize( vPts) ; ++ i) { + IGeoPoint3d* ptOnCirle = CreateGeoPoint3d() ; ptOnCirle->Set( vPts[i]) ; + VTCircle.emplace_back( ptOnCirle) ; + VCCirle.emplace_back( GREEN) ; + } + SaveGeoObj( VTCircle, VCCirle, "C:\\Temp\\CircleDebug.nge") ; + Point3d ptIMin, ptEMin, ptMaxDist ; + #endif // Per ogni coppia di punti calcolo la Distanza Massima e Minima dal centro del cerchio locale ( ORIG) double dSqMaxDist = 0. ; @@ -3257,221 +3305,180 @@ IsBorderACircle( const PolyLine& PL, double dShapeLinTol, Point3d& ptC, Vector3d for ( int i = 0 ; i < int( floor( 0.5 * int( vPts.size()))) ; i = i + 2) { double dSqLineDist = INFINITO ; DistPointLine( ORIG, vPts[i], vPts[i + 1]).GetSqDist( dSqLineDist) ; - if ( dSqLineDist < dSqMinDist) + if ( dSqLineDist < dSqMinDist) { dSqMinDist = dSqLineDist ; + #if DEBUG_HOLES + ptIMin = vPts[i] ; ptEMin = vPts[i + 1] ; + #endif + } double dSqPtDist = SqDist( ORIG, vPts[i]) ; - if ( dSqPtDist > dSqMaxDist) + if ( dSqPtDist > dSqMaxDist) { dSqMaxDist = dSqPtDist ; + #if DEBUG_HOLES + ptMaxDist = vPts[i] ; + #endif + } } + #if DEBUG_HOLES + CurveLine LineMinDist ; LineMinDist.Set( ptIMin, ptEMin) ; + VTCircle.emplace_back( LineMinDist.Clone()) ; + VCCirle.emplace_back( YELLOW) ; + IGeoPoint3d* myPtMaxDist = CreateGeoPoint3d() ; myPtMaxDist->Set( ptMaxDist) ; + VTCircle.emplace_back( myPtMaxDist) ; + VCCirle.emplace_back( YELLOW) ; + SaveGeoObj( VTCircle, VCCirle, "C:\\Temp\\CircleDebug.nge") ; + #endif // Se distanza minima e massima entro tolleranza, allora è una circonferenza - if ( abs( dSqMaxDist - dSqMinDist) < dShapeLinTol * dShapeLinTol) { - ptC = ptCentroid ; - vtN = PlanePL.GetVersN() ; - dRad = 0.5 * ( sqrt( dSqMaxDist) + sqrt( dSqMinDist)) ; - return true ; + double dMinDist = sqrt( dSqMinDist) ; + double dMaxDist = sqrt( dSqMaxDist) ; + if ( abs( dMaxDist - dMinDist) < dLinTol) { + frCircle.Set( ptCentroid, PlanePL.GetVersN()) ; + dRad = ( dMinDist + dMaxDist) / 2. ; + return ( CrvCircle.Set( frCircle.Orig(), frCircle.VersZ(), dRad)) ; } return false ; } // ---------------------------------------------------------------------------- -// Funzione per estrarre Geometrie note da una sola TriMesh +// Funzione per definire se il bordo di una TriMesh è un'asola static bool -GetShapesFromSurf( const ISurf* pSurf, double dShapeLinTol, double dShapeAngTol, double dLinTol, - double dEdgeLinTol, double dAngTol, double dFaceAngTol, const STRVECTOR& vsShapes, - ISURFPOVECTOR& vSurfSel, ICRVCOMPOPOMATRIX& matCompoBorders) +IsBorderAButtonHole( const PolyLine& PL, double dLinTol, double dAngTol, Frame3d& frBtHole, + double& dRectLen, double& dRad, CurveComposite& CompoBthole) { - vSurfSel.clear() ; - matCompoBorders.clear() ; - // Verifico la validità della superficie - if ( pSurf == nullptr || ! pSurf->IsValid()) + // Se PolyLine aperta o non piana, non è un'asola + Plane3d PlanePL ; + if ( ! PL.IsClosed() || ! PL.IsFlat( PlanePL, dLinTol)) return false ; - // Recupero il Tipo - int nType = pSurf->GetType() ; + // Verifico che tutti i punti rispettino la tolleranza angolare + POLYLINEVECTOR vPL ; + if ( ! GetPointSetByAngTol( PL, dAngTol, vPL) || ssize( vPL) != 1) + return false ; - ISURFTMPOVECTOR vSurfTmSelTmp ; - // Se superficie di Besier, non faccio nulla (?) - if ( nType == SRF_BEZIER) - return true ; - // Se superficie TriMesh - else if ( nType == SRF_TRIMESH) { - // Recupero la TriMesh - const SurfTriMesh* pStmBasic = GetBasicSurfTriMesh( pSurf) ; - if ( pStmBasic == nullptr || ! pStmBasic->IsValid()) - return false ; - // Ciclo di Analisi Triangoli - const int MAXTRY = 1000 ; - int nCount = 0 ; - int nTriaCheck = 0 ; - BOOLVECTOR vbTria( pStmBasic->GetTriangleCount(), false) ; - while ( nCount < MAXTRY && nTriaCheck < pStmBasic->GetTriangleCount()) { - // Recupero il primo triangolo valido disponibile non ancora analizzato - int nFirstTria = 0 ; - for ( int nT = 0 ; nT < ssize( vbTria) ; ++ nT) { - if ( ! vbTria[nT]) { - nFirstTria = nT ; - break ; - } - } - unordered_set setNewTria ; setNewTria.reserve( pStmBasic->GetTriangleCount()) ; - unordered_set setAvoidTria ; setAvoidTria.reserve( pStmBasic->GetTriangleCount()) ; - // Collezioni di triangoli da analizzare - INTVECTOR vTria ; vTria.reserve( pStmBasic->GetTriangleCount()) ; - vTria.push_back( nFirstTria) ; - // Finchè ho triangoli da visitare - while ( ! vTria.empty()) { - // Recupero il triangolo corrente - int nCurrTria = vTria.back() ; - // Elimino il triangolo corente - vTria.pop_back() ; + #if DEBUG_HOLES + vector VTCircle ; + vector VCCirle ; + CurveComposite CompoPL ; CompoPL.FromPolyLine( PL) ; + VTCircle.emplace_back( CompoPL.Clone()) ; + VCCirle.emplace_back( RED) ; + SaveGeoObj( VTCircle, VCCirle, "C:\\Temp\\ButtonHoleDebug.nge") ; + #endif - // Se triangolo da evitare, passo al successivo - if ( setAvoidTria.find( nCurrTria) != setAvoidTria.end()) - continue ; - // Se triangolo mai visitato lo aggiungo tra quelli visitati, altrimenti passo al successivo - if ( vbTria[nCurrTria]) - continue ; - vbTria[nCurrTria] = true ; - ++ nTriaCheck ; + // Creo un sistema di riferimento centrato nella PolyLine e porto una sua copia in esso + Frame3d frXY ; + if ( ! frXY.Set( PlanePL.GetPoint(), PlanePL.GetVersN())) + return false ; + PolyLine PLXY = PL ; PLXY.ToLoc( frXY) ; + for ( POINTU& ptU : PLXY.GetUPointList()) + ptU.first.z = 0. ; - // Inserisco il triangolo corrente - setNewTria.insert( nCurrTria) ; + #if DEBUG_HOLES + CurveComposite CompoXY ; CompoXY.FromPolyLine( PLXY) ; + VTCircle.emplace_back( CompoXY.Clone()) ; + VCCirle.emplace_back( BLUE) ; + SaveGeoObj( VTCircle, VCCirle, "C:\\Temp\\ButtonHoleDebug.nge") ; + #endif - // Recupero il triangolo corrente e le sue adiacenze - int nTriaVertices[3] ; - if ( ! pStmBasic->GetTriangle( nCurrTria, nTriaVertices)) - return false ; - Triangle3d Tria ; - if ( ! pStmBasic->GetTriangle( nCurrTria, Tria)) - return false ; - int nIdAdjTriaId[3] ; - if ( ! pStmBasic->GetTriangleAdjacencies( nCurrTria, nIdAdjTriaId)) - return false ; + // Recupero il rettangolo ad area minima + Point3d ptCen ; + Vector3d vtRectAx ; + double dLen, dHeight ; + if ( ! PLXY.GetMinAreaRectangleXY( ptCen, vtRectAx, dLen, dHeight)) + return false ; - // Scorro le adiacenze - for ( int nAdj = 0 ; nAdj < 3 ; ++ nAdj) { - // Recupero l'indice del triangolo corrente - int nTriaAdj = nIdAdjTriaId[nAdj] ; - // Se non ho adiacenza, non faccio nulla - if ( nTriaAdj == SVT_NULL) - continue ; - // Recupero il triangolo adiacente - Triangle3d TriaAdj ; - if ( ! pStmBasic->GetTriangle( nTriaAdj, TriaAdj)) - return false ; - // Se la normale è fuori dalla tolleranza, memorizzo il triangolo tra quelli da scartare - if ( Tria.GetN() * TriaAdj.GetN() < cos( ( dFaceAngTol + EPS_ANG_SMALL) * DEGTORAD)) { - setAvoidTria.insert( nTriaAdj) ; - continue ; - } - // Inserisco il triangolo per la ricerca futura - vTria.push_back( nTriaAdj) ; - } - } - ++ nCount ; - // Se ho nuovi triangoli, definisco una superficie da essi - if ( ! setNewTria.empty()) { + // Verifico che non sia un rettangolo ben definito, non un quadrato + if ( dLen - dHeight < 1001. * EPS_SMALL) + return false ; // potrebbe essere una circonferenza - #if DEBUG_SHAPE_STM - VT.clear() ; VC.clear() ; - VT.emplace_back( pStmBasic->Clone()) ; - VC.emplace_back( BLACK) ; - StmFromTriangleSoup _TriaSoup ; _TriaSoup.Start() ; - for ( auto _Iter = setNewTria.begin() ; _Iter != setNewTria.end() ; ++ _Iter) { - Triangle3d _Tria ; - if ( ! pStmBasic->GetTriangle( *_Iter, _Tria)) - return false ; - _TriaSoup.AddTriangle( _Tria) ; - } - _TriaSoup.End() ; - VT.emplace_back( _TriaSoup.GetSurf()) ; - VC.emplace_back( LIME) ; - //SaveGeoObj( VT, VC, "C:\\Temp\\MyShape.nge") ; - VT.clear() ; VC.clear() ; - #endif + // Cambio il sistema di riferimento in quello definito dal rettangolo + Frame3d frRect ; + if ( ! frRect.Set( ptCen, Z_AX, vtRectAx)) + return false ; + PLXY.ToLoc( frRect) ; - StmFromTriangleSoup TriaSoup ; TriaSoup.Start() ; - for ( auto Iter = setNewTria.begin() ; Iter != setNewTria.end() ; ++ Iter) { - Triangle3d Tria ; - if ( ! pStmBasic->GetTriangle( *Iter, Tria)) - return false ; - TriaSoup.AddTriangle( Tria) ; - } - TriaSoup.End() ; - PtrOwner pStmTmp( TriaSoup.GetSurf()) ; - if ( ! IsNull( pStmTmp) && pStmTmp->IsValid() && pStmTmp->GetTriangleCount() > 0) { - if ( ! vSurfTmSelTmp.emplace_back( Release( pStmTmp))) - return false ; - } - } + #if DEBUG_HOLES + CompoXY.Clear() ; CompoXY.FromPolyLine( PLXY) ; + VTCircle.emplace_back( CompoXY.Clone()) ; + VCCirle.emplace_back( AQUA) ; + SaveGeoObj( VTCircle, VCCirle, "C:\\Temp\\ButtonHoleDebug.nge") ; + #endif + + // Individuo il punto in basso a sinistra del rettangolo + Point3d ptLeftBotton = ORIG - ( dLen / 2.) * X_AX - ( dHeight / 2.) * Y_AX ; + + // Semicirconferenza a sinistra + Point3d ptArcLeftCenter = ptLeftBotton + X_AX * dHeight / 2. + Y_AX * dHeight / 2. ; + CurveArc ArcLeft ; + ArcLeft.Set( ptArcLeftCenter, Z_AX, dHeight / 2., Y_AX, ANG_STRAIGHT, 0.) ; + + // Semicirconferenza a destra + Point3d ptArcRightCenter = ptLeftBotton + ( dLen - dHeight / 2.) * X_AX + Y_AX * dHeight / 2. ; + CurveArc ArcRight ; + ArcRight.Set( ptArcRightCenter, Z_AX, dHeight / 2., - Y_AX, ANG_STRAIGHT, 0.) ; + + // Tratto Lineare Top + CurveLine LineTop ; + LineTop.Set( ptArcRightCenter + Y_AX * dHeight / 2., ptArcLeftCenter + Y_AX * dHeight / 2.) ; + + // Tratto Lineare Botton + CurveLine LineBottom ; + LineBottom.Set( ptArcLeftCenter - Y_AX * dHeight / 2., ptArcRightCenter - Y_AX * dHeight / 2.) ; + + // Curva Composita complessiva dell'asola + CurveComposite CompoButtonHolePerfect ; + CompoButtonHolePerfect.AddCurve( LineTop) ; + CompoButtonHolePerfect.AddCurve( ArcLeft) ; + CompoButtonHolePerfect.AddCurve( LineBottom) ; + CompoButtonHolePerfect.AddCurve( ArcRight) ; + + #if DEBUG_HOLES + VTCircle.emplace_back( CompoButtonHolePerfect.Clone()) ; + VCCirle.emplace_back( WHITE) ; + SaveGeoObj( VTCircle, VCCirle, "C:\\Temp\\ButtonHoleDebug.nge") ; + #endif + + // Verifico che tutti i punti dell PolyLine siano abbastanza vicini a tale curva + // Campiono usando i punti medi, altrimenti qualsiasi poligono iscritto nell'asola ideale + // sarebbe valido + PNTVECTOR vPts ; + Point3d ptNext ; + PLXY.GetFirstPoint( ptNext) ; + vPts.push_back( ptNext) ; + while ( PLXY.GetNextPoint( ptNext)) { + vPts.push_back( Media( vPts.back(), ptNext)) ; + vPts.push_back( ptNext) ; + } + #if DEBUG_HOLES + for ( int i = 0 ; i < ssize( vPts) ; ++ i) { + IGeoPoint3d* ptOnCirle = CreateGeoPoint3d() ; ptOnCirle->Set( vPts[i]) ; + VTCircle.emplace_back( ptOnCirle) ; + VCCirle.emplace_back( GREEN) ; } + SaveGeoObj( VTCircle, VCCirle, "C:\\Temp\\ButtonHoleDebug.nge") ; + #endif + bool bButtonHole = true ; + for ( int i = 0 ; bButtonHole && i < ssize( vPts) ; ++ i) { + double dSqDist = INFINITO ; + bButtonHole = ( DistPointCurve( vPts[i], CompoButtonHolePerfect).GetSqDist( dSqDist) && + dSqDist < dLinTol * dLinTol) ; } - // Se non ho ricavato superfici, esco - if ( vSurfTmSelTmp.empty()) + // Se Asola, restituisco i parametri + if ( bButtonHole) { + frBtHole.Set( GetToGlob( GetToGlob( ORIG, frRect), frXY), + PlanePL.GetVersN(), + GetToGlob( GetToGlob( X_AX, frRect), frXY)) ; + dRectLen = dLen - 2. * dHeight ; + dRad = dHeight / 2. ; + CompoBthole.CopyFrom( &CompoButtonHolePerfect) ; + CompoBthole.ToGlob( frRect) ; + CompoBthole.ToGlob( frXY) ; return true ; - - // Per ognuna di esse ricerco le geometrie compatibili - for ( int i = 0 ; i < ssize( vSurfTmSelTmp) ; ++ i) { - // Recupero i Loops - POLYLINEVECTOR vPL ; - vSurfTmSelTmp[i]->GetLoops( vPL) ; - // Elimino i Loop che non sono chiusi - vPL.erase( - remove_if( vPL.begin(), vPL.end(), []( const PolyLine& PL) { - return ( ! PL.IsClosed()) ; - }), - vPL.end() - ) ; - // Se non ho esattamente due Loops, passo alla superficie successiva - if ( ssize( vPL) != 2) - continue ; - // Se devo ricercare Circonferenze - if ( find_if( vsShapes.begin(), vsShapes.end(), [&]( const string& sStr) { - return ( sStr.compare( sCircle) == 0) ; - }) != vsShapes.end()) { - // Verifico che le due PolyLine siano circonferenze - Point3d ptCA, ptCB ; Vector3d vtNA, vtNB ; double dRadA, dRadB ; - if ( IsBorderACircle( vPL[0], dShapeLinTol, ptCA, vtNA, dRadA) && - IsBorderACircle( vPL[1], dShapeAngTol, ptCB, vtNB, dRadB)) { - // Definisco le due circonferenze - PtrOwner pCirA( CreateCurveArc()) ; - PtrOwner pCirB( CreateCurveArc()) ; - if ( ! IsNull( pCirA) && ! IsNull( pCirB) && - pCirA->Set( ptCA, vtNA, dRadA) && - pCirB->Set( ptCB, vtNB, dRadB)) { - vSurfSel.emplace_back( GetSurf( Release( vSurfTmSelTmp[i]))) ; - matCompoBorders.emplace_back( ICRVCOMPOPOVECTOR{}) ; - matCompoBorders.back().resize( 2) ; - matCompoBorders.back()[0].Set( ConvertCurveToComposite( Release( pCirA))) ; - matCompoBorders.back()[1].Set( ConvertCurveToComposite( Release( pCirB))) ; - // l'Approssimazione delle curve prevede che io usi sempre tratti lineari, quindi approssimo - PolyLine PLA ; matCompoBorders.back()[0]->ApproxWithLines( dLinTol, dAngTol, ICurve::APL_SPECIAL, PLA) ; - PolyLine PLB ; matCompoBorders.back()[0]->ApproxWithLines( dLinTol, dAngTol, ICurve::APL_SPECIAL, PLB) ; - matCompoBorders.back()[0]->Clear() ; matCompoBorders.back()[0]->FromPolyLine( PLA) ; - matCompoBorders.back()[1]->Clear() ; matCompoBorders.back()[1]->FromPolyLine( PLB) ; - } - } - - #if DEBUG_SHAPE_STM - CurveComposite _CompoA ; _CompoA.FromPolyLine( vPL[0]) ; - CurveComposite _CompoB ; _CompoB.FromPolyLine( vPL[1]) ; - VT.emplace_back( _CompoA.Clone()) ; - VT.emplace_back( _CompoB.Clone()) ; - Color _cCol = Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ; - VC.emplace_back( _cCol) ; - VC.emplace_back( _cCol) ; - #endif - } } - // #if DEBUG_SHAPE_STM - // SaveGeoObj( VT, VC, "C:\\Temp\\myAutoBorders.nge") ; - // #endif - - return true ; + return false ; } //----------------------------------------------------------------------------- @@ -3515,6 +3522,19 @@ GetTrimmingRawEdges( const CISURFPVECTOR& vSurf, const SELVECTOR& vSurfFace, return false ; } + #if DEBUG_RAW_EDGES + VT.clear() ; VC.clear() ; + for ( int i = 0 ; i < ssize( vSurf) ; ++ i) { + VT.emplace_back( vSurf[i]->Clone()) ; + VC.emplace_back( BLACK) ; + } + for ( int i = 0 ; i < ssize( vCompoRawEdges) ; ++ i) { + VT.emplace_back( vCompoRawEdges[i]) ; + VC.emplace_back( RED) ; + } + SaveGeoObj( VT, VC, "C:\\Temp\\RawEdges.nge") ; + #endif + return true ; } @@ -3650,10 +3670,10 @@ GetTrimmingFinalBorders( CISURFPVECTOR& vpSurf, const SELVECTOR& vSurfFaces, dou if ( IsNull( pCompoLoopExtr) || ! pCompoLoopExtr->FromPolyLine( PLLoopExtr)) continue ; vCompoBezierEdges.emplace_back( Release( pCompoLoop)) ; - if ( ! ApproxBorder( *vCompoBezierEdges.back(), dMyLinTol, dMyAngTol)) + if ( ! ApproxBorder( *GetBasicCurveComposite( vCompoBezierEdges.back()), dMyLinTol, dMyAngTol)) return false ; vCompoBezierEdges.emplace_back( Release( pCompoLoopExtr)) ; - if ( ! ApproxBorder( *vCompoBezierEdges.back(), dMyLinTol, dMyAngTol)) + if ( ! ApproxBorder( *GetBasicCurveComposite( vCompoBezierEdges.back()), dMyLinTol, dMyAngTol)) return false ; } @@ -3698,7 +3718,7 @@ GetTrimmingBezierEdges( ICRVCOMPOPOVECTOR& vCompoRawEdges, double dLinTol, doubl for ( int i = 0 ; i < int( vCompoRawEdges.size()) ; ++ i) { PtrOwner pCompoTmp( CloneCurveComposite( vCompoRawEdges[i])) ; if ( IsNull( pCompoTmp) || - ! ApproxBorder( *pCompoTmp, dMyLinTol, dMyAngTol) || + ! ApproxBorder( *GetBasicCurveComposite( pCompoTmp), dMyLinTol, dMyAngTol) || ! vBezierEdges.emplace_back( Release( pCompoTmp))) { LOG_ERROR( GetEGkLogger(), "Error in Trimming : Approxing edge failed") ; return false ; @@ -3905,15 +3925,15 @@ GetTrimmingRuledBezier( const CISURFPVECTOR& vSurf, const ICurve* pCrvEdge1, // quella faccia viene memorizzata e considerata come nuovo punto di partenza per la ricerca // di ulteriori adiacenze. bool -GetTrimmingStmAdjTria( const ISurfTriMesh* pStm, const INTVECTOR& vTria, const PNTVECTOR& vPts, +GetTrimmingStmAdjTria( const ISurfTriMesh* pStm, int nStartTria, const Point3d& ptStartTria, double dAngTol, double dSize, double dSizeTol, ISurfTriMesh* pStmAdjTria) { // La superfcicie deve essere inizializzata if ( pStmAdjTria == nullptr) return false ; - // Verifico la validità della superficie TriMesh e l'esistenza di triangoli di riferimento - if ( ! pStm->IsValid() || vTria.empty()) + // Verifico la validità della superficie TriMesh + if ( ! pStm->IsValid()) return false ; // Recupero la superficie di base @@ -3924,10 +3944,10 @@ GetTrimmingStmAdjTria( const ISurfTriMesh* pStm, const INTVECTOR& vTria, const P // Definisco un Box3d nel punto di Selezione di dimensioni pari al doppio della dimensione della // striscia di ricerca considerando la tolleranza Triangle3d firstTria ; - if ( ! pStmBasic->GetTriangle( vTria[0], firstTria)) + if ( ! pStmBasic->GetTriangle( nStartTria, firstTria)) return false ; BBox3d BBoxCurr ; - BBoxCurr.Add( vPts[0]) ; + BBoxCurr.Add( ptStartTria) ; const double EXPAND_EXTRA_TOL = 10. * EPS_SMALL ; BBoxCurr.Expand( ( dSize + dSizeTol + EXPAND_EXTRA_TOL)) ; @@ -3942,7 +3962,7 @@ GetTrimmingStmAdjTria( const ISurfTriMesh* pStm, const INTVECTOR& vTria, const P Point3d ptMid, ptMid1 ; int nTria = 0, nTria1 = 0 ; CurveComposite CompoA, CompoB ; - if ( ! GetBordersInBox( *pStmBasic, BBoxCurr, vTria[0], vPts[0], dSize, dSizeTol, true, true, + if ( ! GetBordersInBox( *pStmBasic, BBoxCurr, nStartTria, ptStartTria, dSize, dSizeTol, true, true, dAngTol, 2. * EPS_SMALL, setAvoidTria, setNewTria, mapTriaClass, CompoA, CompoB, ptMid, ptMid1, nTria, nTria1, bBreak, bStop)) return false ; @@ -3993,10 +4013,7 @@ GetTrimmingStmAdjTria( const ISurfTriMesh* pStm, const INTVECTOR& vTria, const P if ( IsNull( pStmTria) || ! pStmTria->IsValid() || pStmTria->GetTriangleCount() == 0) return false ; - else - return ( pStmAdjTria->CopyFrom( pStmTria)) ; - - return true ; + return ( pStmAdjTria->CopyFrom( pStmTria)) ; } //------------------------------------------------------------------------------ @@ -4015,87 +4032,197 @@ GetTrimmingAdjSurfs( const CISURFPVECTOR& vSurf, const CISURFPVECTOR& vOtherSurf return false ; } - // creo l'insieme delle curve di bordo in continuità + // Recupero le Patch delle superfici SURFPATCHESVECTOR vSurfPatches ; vSurfPatches.reserve( vSurf.size() + vOtherSurf.size()) ; - BOXVECTOR vBBox3d ; vBBox3d.reserve( vSurf.size() + vOtherSurf.size()) ; + // --- Superfici Selezionate for ( int nS = 0 ; nS < int( vSurf.size()) ; ++ nS) { vSurfPatches.emplace_back( SurfPatches()) ; vSurfPatches.back().pSurf = vSurf[nS] ; - vSurfPatches.back().nIndSurf = nS ; - vBBox3d.emplace_back( BBox3d()) ; - POLYLINEVECTOR vPLBorders ; - if ( ! InsertLoopsOfSurf( vSurf[nS], vPLBorders)) + if ( ! CalcSurfPatch( vSurf[nS], dLinTol, dAngTol, vSurfPatches.back())) return false ; - for ( int nPL = 0 ; nPL < int( vPLBorders.size()) ; ++ nPL) - vPLBorders[nPL].GetLocalBBox( vBBox3d.back()) ; - vBBox3d.back().Expand( 2. * dLinTol) ; - POLYLINEMATRIX matPLPatchBorders ; - if ( ! CalcPatches( vPLBorders, dAngTol, matPLPatchBorders)) - return false ; - for ( int i = 0 ; i < int( matPLPatchBorders.size()) ; ++ i) { - for ( int j = 0 ; j < int( matPLPatchBorders[i].size()) ; ++ j) { - Point3d ptS ; matPLPatchBorders[i][j].GetFirstPoint( ptS) ; - Point3d ptE ; matPLPatchBorders[i][j].GetLastPoint( ptE) ; - vSurfPatches.back().vPatches.emplace_back( ptS, ptE, i, false) ; - vSurfPatches.back().CompoPathces.emplace_back( CurveComposite()) ; - vSurfPatches.back().CompoPathces.back().FromPolyLine( matPLPatchBorders[i][j]) ; - } - } } + // --- Altre Superfici for ( int nS = 0 ; nS < int( vOtherSurf.size()) ; ++ nS) { vSurfPatches.emplace_back( SurfPatches()) ; vSurfPatches.back().pSurf = vOtherSurf[nS] ; - vSurfPatches.back().nIndSurf = int( vSurf.size()) + nS ; - vBBox3d.emplace_back( BBox3d()) ; - POLYLINEVECTOR vPLBorders ; - if ( ! InsertLoopsOfSurf( vOtherSurf[nS], vPLBorders)) - continue ; - for ( int nPL = 0 ; nPL < int( vPLBorders.size()) ; ++ nPL) - vPLBorders[nPL].GetLocalBBox( vBBox3d.back()) ; - vBBox3d.back().Expand( 2. * dLinTol) ; - POLYLINEMATRIX matPLPatchBorders ; - if ( ! CalcPatches( vPLBorders, dAngTol, matPLPatchBorders)) + if ( ! CalcSurfPatch( vOtherSurf[nS], dLinTol, dAngTol, vSurfPatches.back())) return false ; - for ( int i = 0 ; i < int( matPLPatchBorders.size()) ; ++ i) { - for ( int j = 0 ; j < int( matPLPatchBorders[i].size()) ; ++ j) { - Point3d ptS ; matPLPatchBorders[i][j].GetFirstPoint( ptS) ; - Point3d ptE ; matPLPatchBorders[i][j].GetLastPoint( ptE) ; - vSurfPatches.back().vPatches.emplace_back( ptS, ptE, i, false) ; - vSurfPatches.back().CompoPathces.emplace_back( CurveComposite()) ; - vSurfPatches.back().CompoPathces.back().FromPolyLine( matPLPatchBorders[i][j]) ; - } - } } - // Se necessario, Splitto le Patch per far combiaciare gli estremi - for ( int i = 0 ; i < int( vSurfPatches.size()) - 1 ; ++ i) { - for ( int j = i + 1 ; j < int( vSurfPatches.size()) ; ++ j) { - if ( vBBox3d[i].Overlaps( vBBox3d[j])) { - if ( ! SplitPatchWithPatch( vSurfPatches[i], vSurfPatches[j], dLinTol)) - return false ; - } - } - } - - #if DEBUG_SIMPLE_PATCHES + #if DEBUG_SURF_PATCHES VT.clear() ; VC.clear() ; - for ( int i = 0 ; i < int( vSurfPatches.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vSurfPatches) ; ++ i) { Color myCol = Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ; - for ( int j = 0 ; j < int( vSurfPatches[i].CompoPathces.size()) ; ++ j) { - VT.emplace_back( vSurfPatches[i].CompoPathces[j].Clone()) ; + for ( int j = 0 ; j < ssize( vSurfPatches[i].vCompoBorders) ; ++ j) { + VT.emplace_back( vSurfPatches[i].vCompoBorders[j].Clone()) ; VC.emplace_back( myCol) ; - IGeoPoint3d* _pt = CreateGeoPoint3d() ; _pt->Set( vSurfPatches[i].vPatches[j].ptStart) ; - VT.emplace_back( _pt) ; - VC.emplace_back( AQUA) ; - IGeoPoint3d* _pt1 = CreateGeoPoint3d() ; _pt1->Set( vSurfPatches[i].vPatches[j].ptEnd) ; - VT.emplace_back( _pt1) ; - VC.emplace_back( AQUA) ; + set& setPar = vSurfPatches[i].vSetPatchPar[j] ; + for ( auto Iter = setPar.begin() ; Iter != setPar.end() ; ++ Iter) { + Point3d ptCurr ; + vSurfPatches[i].vCompoBorders[j].GetPointD1D2( *Iter, ICurve::FROM_MINUS, ptCurr) ; + PtrOwner ptGeoCurr( CreateGeoPoint3d()) ; ptGeoCurr->Set( ptCurr) ; + VT.emplace_back( ptGeoCurr->Clone()) ; + VC.emplace_back( ORANGE) ; + } } } - SaveGeoObj( VT, VC, "C:\\Temp\\SimplePatch.nge") ; + SaveGeoObj( VT, VC, "C:\\Temp\\SurfPatches.nge") ; #endif - // Verifico ora se le tangenze nei punti di giunzione sono al di sotto della tolleranza angolare + // Se necessario, Splitto le Patch per far combiaciare gli estremi + vector matBorderModif( vSurfPatches.size()) ; + for ( int i = 0 ; i < ssize( vSurfPatches) ; ++ i) { + // Recupero la SurfPatch corrente + SurfPatches& CurrSurfPatch = vSurfPatches[i] ; + // Recupero i Suoi Bordi e i Parametri associati + const SimpleBorderVector& vSimpleBorder = CurrSurfPatch.vBorderPatches ; + matBorderModif[i].resize( vSimpleBorder.size(), false) ; + const COMPOVECTOR& vCompoBorders = CurrSurfPatch.vCompoBorders ; + vector>& vSetSplitPar = CurrSurfPatch.vSetPatchPar ; + // Scorro i Bordi della Superficie + for ( int nCurrBorder = 0 ; nCurrBorder < ssize( vSimpleBorder) ; ++ nCurrBorder) { + // Recupero la Composita associata al Bordo Corrente e il suo Box + const CurveComposite& CurrCompoBorder = vCompoBorders[nCurrBorder] ; + BBox3d BBoxCurrCompoBorder ; CurrCompoBorder.GetLocalBBox( BBoxCurrCompoBorder) ; + // Recupero le Patch associate + const SimpleBorder& vPatchCurrBorder = vSimpleBorder[nCurrBorder] ; + // Recupero il vettore dei Parametri di Split + set& setSplitPar = vSetSplitPar[nCurrBorder] ; + #if DEBUG_SURF_PATCHES + VC.clear() ; VT.clear() ; + VT.emplace_back( CurrCompoBorder.Clone()) ; + VC.emplace_back( RED) ; + for ( auto Iter = setSplitPar.begin() ; Iter != setSplitPar.end() ; ++ Iter) { + Point3d ptCurr ; + CurrCompoBorder.GetPointD1D2( *Iter, ICurve::FROM_MINUS, ptCurr) ; + PtrOwner ptGeoCurr( CreateGeoPoint3d()) ; ptGeoCurr->Set( ptCurr) ; + VT.emplace_back( ptGeoCurr->Clone()) ; + VC.emplace_back( ORANGE) ; + } + #endif + // Scorro le altre SurfPatches + for ( int j = 0 ; j < ssize( vSurfPatches) ; ++ j) { + // Se stessa SurfPath, passo alla successiva + if ( i == j) + continue ; + // Recupero l'altra SurfPatch + SurfPatches& OtherSurfPatch = vSurfPatches[j] ; + // Recupero i Suoi Bordi e i Parametri associati + const SimpleBorderVector& vSimpleOtherBorder = OtherSurfPatch.vBorderPatches ; + const COMPOVECTOR& vCompoBorders = OtherSurfPatch.vCompoBorders ; + // Scorro i suoi bordi + for ( int nOtherBorder = 0 ; nOtherBorder < ssize( vSimpleOtherBorder) ; ++ nOtherBorder) { + // Recupero le Patch associate + const SimpleBorder& vPatchOtherBorder = vSimpleOtherBorder[nOtherBorder] ; + // Recupero la Composita associata al Bordo + const CurveComposite& OtherCompoBorder = vCompoBorders[nOtherBorder] ; + #if DEBUG_SURF_PATCHES + VT.emplace_back( OtherCompoBorder.Clone()) ; + VC.emplace_back( BLACK) ; + #endif + // Scorro le sue Patches + for ( int nOtherPatch = 0 ; nOtherPatch < ssize( vPatchOtherBorder) ; ++ nOtherPatch) { + // Recupero il Box della patch + BBox3d BBoxOtherPath = OtherSurfPatch.matBox3dPatches[nOtherBorder][nOtherPatch] ; + // Se Tali Box ( espansi già della tolleranza lineare) non interferiscono, allora passo + // alla Patch successiva + if ( ! BBoxCurrCompoBorder.Overlaps( BBoxOtherPath)) + continue ; + // Recupero gli estremi della Path attuale + DistPointCurve DPTCRV( vPatchOtherBorder[nOtherPatch].ptStart, CurrCompoBorder) ; + double dDist = INFINITO ; + if ( DPTCRV.GetDist( dDist) && dDist < dLinTol) { + Point3d ptMinDist ; + int nFlag = 0 ; + if ( DPTCRV.GetMinDistPoint( 0., ptMinDist, nFlag)) { + bool bInsert = true ; + for ( int nCurrPatch = 0 ; bInsert && nCurrPatch < ssize( vPatchCurrBorder) ; ++ nCurrPatch) { + const SimplePatch& Patch = vPatchCurrBorder[nCurrPatch] ; + bInsert = ( ! AreSamePointEpsilon( Patch.ptStart, ptMinDist, dLinTol) && + ! AreSamePointEpsilon( Patch.ptEnd, ptMinDist, dLinTol)) ; + } + if ( bInsert) { + double dPar = -1. ; + if ( DPTCRV.GetParamAtMinDistPoint( 0., dPar, nFlag)) { + setSplitPar.insert( dPar) ; + matBorderModif[i][nCurrBorder] = true ; + #if DEBUG_SURF_PATCHES + PtrOwner ptGeoCurr( CreateGeoPoint3d()) ; + ptGeoCurr->Set( ptMinDist) ; + VT.emplace_back( ptGeoCurr->Clone()) ; + VC.emplace_back( AQUA) ; + #endif + } + } + } + } + } + } + } + } + #if DEBUG_SURF_PATCHES + SaveGeoObj( VT, VC, "C:\\Temp\\SplitPathces.nge") ; + #endif + } + // Scorro tutte le Surf Patches + for ( int i = 0 ; i < ssize( vSurfPatches) ; ++ i) { + // Recupero la SurfPatch corrente + SurfPatches& CurrSurfPatch = vSurfPatches[i] ; + // Recupero i Suoi Bordi e i Parametri associati + SimpleBorderVector& vSimpleBorder = CurrSurfPatch.vBorderPatches ; + COMPOMATRIX& matCompoPatches = CurrSurfPatch.matCompoPatches ; + COMPOVECTOR& vCompoBorders = CurrSurfPatch.vCompoBorders ; + const vector>& vSetSplitPar = CurrSurfPatch.vSetPatchPar ; + // Scorro i Bordi + for ( int nCurrBorder = 0 ; nCurrBorder < ssize( vSimpleBorder) ; ++ nCurrBorder) { + // Se il bordo corrente non ha subito Split, passo al successivo + if ( ! matBorderModif[i][nCurrBorder]) + continue ; + // Pulisco la Composita associata a tale Bordo + COMPOVECTOR& vCompoPatches = matCompoPatches[nCurrBorder] ; + vCompoPatches.clear() ; + // Recupero la Curva Composita corrente + CurveComposite& CurrCompo = vCompoBorders[nCurrBorder] ; + // Inizializzo il nuovo Bordo semplice formato dalle Patch + SimpleBorder newSimpleBorder ; + // Recupero il vettore dei Parametri di Split + const set& setSplitPar = vSetSplitPar[nCurrBorder] ; + double dLastPar = 0 ; + for ( auto Iter = setSplitPar.begin() ; Iter != setSplitPar.end() ; ++ Iter) { + PtrOwner pCrvPatch( CurrCompo.CopyParamRange( dLastPar, *Iter)) ; + if ( ! IsNull( pCrvPatch) && pCrvPatch->IsValid()) { + vCompoPatches.emplace_back( *ConvertCurveToBasicComposite( Release( pCrvPatch))) ; + Point3d ptStart ; vCompoPatches.back().GetStartPoint( ptStart) ; + Point3d ptEnd ; vCompoPatches.back().GetEndPoint( ptEnd) ; + newSimpleBorder.emplace_back( ptStart, ptEnd, nCurrBorder, false) ; + dLastPar = *Iter ; + } + } + vSimpleBorder[nCurrBorder] = newSimpleBorder ; + } + } + #if DEBUG_SURF_PATCHES + VT.clear() ; VC.clear() ; + for ( int i = 0 ; i < ssize( vSurfPatches) ; ++ i) { + Color myCol = Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ; + for ( int j = 0 ; j < ssize( vSurfPatches[i].matCompoPatches) ; ++ j) { + for ( int k = 0 ; k < ssize( vSurfPatches[i].matCompoPatches[j]) ; ++ k) { + VT.emplace_back( vSurfPatches[i].matCompoPatches[j][k].Clone()) ; + VC.emplace_back( myCol) ; + IGeoPoint3d* _pt = CreateGeoPoint3d() ; _pt->Set( vSurfPatches[i].vBorderPatches[j][k].ptStart) ; + VT.emplace_back( _pt) ; + VC.emplace_back( AQUA) ; + IGeoPoint3d* _pt1 = CreateGeoPoint3d() ; _pt1->Set( vSurfPatches[i].vBorderPatches[j][k].ptEnd) ; + VT.emplace_back( _pt1) ; + VC.emplace_back( AQUA) ; + } + } + } + SaveGeoObj( VT, VC, "C:\\Temp\\SplitPatch.nge") ; + #endif + + // Verifico ora se le Normali nei Tratti di giunzione tra Patches sono al di sotto + // della tolleranza angolare INTVECTOR vSurfToCheck ; INTSET setSurf ; for ( int i = 0 ; i < int( vSurf.size()) ; ++ i) @@ -4115,93 +4242,116 @@ GetTrimmingAdjSurfs( const CISURFPVECTOR& vSurf, const CISURFPVECTOR& vOtherSurf else continue ; - // Recupero la superficie corrente - const ISurf* pCurrSurf = vSurfPatches[nSurf].pSurf ; + // Recupero la Surf Patch Corrente + SurfPatches& currSurfPatch = vSurfPatches[nSurf] ; + // Recupero la Superficie corrente + const ISurf* pCurrSurf = currSurfPatch.pSurf ; + // Recupero il Box Corrente della Superficie + const BBox3d& BBoxCurrSurf = currSurfPatch.BoxSurf ; - // Scorro le sua Patches - for ( int nCurrPatch = 0 ; nCurrPatch < int( vSurfPatches[nSurf].vPatches.size()) ; ++ nCurrPatch) { - // Recupero la Patch attuale - SimplePatch& currPatch = vSurfPatches[nSurf].vPatches[nCurrPatch] ; - // Se Patch già analizzata, passo alla successiva - if ( currPatch.bErase) - continue ; - currPatch.bErase = true ; - // Scorro le altre Patches - for ( int nOtherSurf = 0 ; nOtherSurf < int( vSurfPatches.size()) ; ++ nOtherSurf) { - // Se stessa superficie, passo alla successiva - if ( nOtherSurf == nSurf) + // Scorro i suoi Bordi semplici + for ( int nCurrBorder = 0 ; nCurrBorder < ssize( currSurfPatch.vBorderPatches) ; ++ nCurrBorder) { + // Recupero il Bordo Corrente + SimpleBorder& CurrSimpleBorder = currSurfPatch.vBorderPatches[nCurrBorder] ; + // Scorro le sua Patches + for ( int nCurrPatch = 0 ; nCurrPatch < ssize( CurrSimpleBorder) ; ++ nCurrPatch) { + // Recupero la Patch attuale + SimplePatch& currPatch = CurrSimpleBorder[nCurrPatch] ; + // Se Patch già analizzata, passo alla successiva + if ( currPatch.bErase) continue ; - // Se superficie già analizzata, passo alla successiva - if ( setSurf.find( nOtherSurf) != setSurf.end()) - continue ; - // Recupero la superficie di confronto - const ISurf* pOtherSurf = vSurfPatches[nOtherSurf].pSurf ; - // Scorro le sua Patches - for ( int nOtherPatch = 0 ; nOtherPatch < int( vSurfPatches[nOtherSurf].vPatches.size()) ; ++ nOtherPatch) { - // Recupero la Patch di confronto - SimplePatch& nextPatch = vSurfPatches[nOtherSurf].vPatches[nOtherPatch] ; - // Se Patch già analizzata, passo alla successiva - if ( nextPatch.bErase) + currPatch.bErase = true ; + + // Scorro le altre Superfici + for ( int nOtherSurf = 0 ; nOtherSurf < ssize( vSurfPatches) ; ++ nOtherSurf) { + // Se stessa superficie, passo alla successiva + if ( nOtherSurf == nSurf) continue ; - // Se gli estremi coincidono - if ( ( AreSamePointEpsilon( currPatch.ptStart, nextPatch.ptStart, dLinTol) && - AreSamePointEpsilon( currPatch.ptEnd, nextPatch.ptEnd, dLinTol)) || - ( AreSamePointEpsilon( currPatch.ptStart, nextPatch.ptEnd, dLinTol) && - AreSamePointEpsilon( currPatch.ptEnd, nextPatch.ptStart, dLinTol))) { - // Controllo se le tangenze rimangono nella tolleranza - bool bTangent = true ; - // Campiono la Patch corrente - const int MAX_POINTS = 5 ; - BIPNTVECTOR vPtAPtB ; vPtAPtB.reserve( MAX_POINTS + 1) ; - CurveComposite& currCompoPatch = vSurfPatches[nSurf].CompoPathces[nCurrPatch] ; - CurveComposite& otherCompoPatch = vSurfPatches[nOtherSurf].CompoPathces[nOtherPatch] ; - bTangent = ( currCompoPatch.IsValid() && otherCompoPatch.IsValid()) ; - if ( bTangent) { - double dLen = 0.; - currCompoPatch.GetLength( dLen) ; - for ( int i = 0 ; bTangent && i <= MAX_POINTS ; ++ i) { - double dU = 0. ; - currCompoPatch.GetParamAtLength( ( dLen / MAX_POINTS) * i, dU) ; - Point3d ptCurr ; - currCompoPatch.GetPointD1D2( dU, ICurve::FROM_MINUS, ptCurr) ; - Point3d ptOther ; - int nFlag = 0 ; - if ( ! DistPointCurve( ptCurr, otherCompoPatch).GetMinDistPoint( 0., ptOther, nFlag)) - bTangent = false ; - // Recupero le due normali sulle curva patch campionate - Vector3d vtNCurr = V_INVALID, vtNOther = V_INVALID ; - if ( ! GetNormalAtPoint( pCurrSurf, ptCurr, vtNCurr) || - ! GetNormalAtPoint( pOtherSurf, ptOther, vtNOther)) - return false ; - bTangent = ( vtNCurr * vtNOther > cos( ( dFaceAngTol - EPS_ANG_SMALL) * DEGTORAD)) ; + // Se superficie già analizzata, passo alla successiva + if ( setSurf.find( nOtherSurf) != setSurf.end()) + continue ; + + // Recupero la Surf Patch + SurfPatches OtherSurfPatch = vSurfPatches[nOtherSurf] ; + // Recupero la Superficie + const ISurf* pOtherSurf = OtherSurfPatch.pSurf ; + // Recupero il Box della Superficie + const BBox3d& BBoxOtherSurf = OtherSurfPatch.BoxSurf ; + // Se non c'è Intersezione dei Box ( opportunamente estesi), passo alla SurfPatch successiva + if ( ! BBoxCurrSurf.Overlaps( BBoxOtherSurf)) + continue ; + + // Scorro i suoi Bordi semplici + for ( int nOtherBorder = 0 ; nOtherBorder < ssize( OtherSurfPatch.vBorderPatches) ; ++ nOtherBorder) { + // Recupero il Bordo + SimpleBorder& OtherSimpleBorder = OtherSurfPatch.vBorderPatches[nOtherBorder] ; + // Scorro le sue Patches + for ( int nOtherPatch = 0 ; nOtherPatch < ssize( OtherSimpleBorder) ; ++ nOtherPatch) { + // Recupero la Patch di confronto + SimplePatch& OtherPatch = OtherSimpleBorder[nOtherPatch] ; + // Se Patch già analizzata, passo alla successiva + if ( OtherPatch.bErase) + continue ; + // Se gli estremi coincidono + if ( ( AreSamePointEpsilon( currPatch.ptStart, OtherPatch.ptStart, dLinTol) && + AreSamePointEpsilon( currPatch.ptEnd, OtherPatch.ptEnd, dLinTol)) || + ( AreSamePointEpsilon( currPatch.ptStart, OtherPatch.ptEnd, dLinTol) && + AreSamePointEpsilon( currPatch.ptEnd, OtherPatch.ptStart, dLinTol))) { + // Controllo se le tangenze rimangono nella tolleranza + bool bTangent = true ; + // Campiono la Patch corrente ( passando per la Composita associata) + const int MAX_POINTS = 5 ; + BIPNTVECTOR vPtAPtB ; vPtAPtB.reserve( MAX_POINTS + 1) ; + CurveComposite& currCompoPatch = currSurfPatch.matCompoPatches[nCurrBorder][nCurrPatch] ; + CurveComposite& otherCompoPatch = OtherSurfPatch.matCompoPatches[nOtherBorder][nOtherPatch] ; + bTangent = ( currCompoPatch.IsValid() && otherCompoPatch.IsValid()) ; + if ( bTangent) { + double dLen = 0.; + currCompoPatch.GetLength( dLen) ; + for ( int i = 0 ; bTangent && i <= MAX_POINTS ; ++ i) { + double dU = 0. ; + currCompoPatch.GetParamAtLength( ( dLen / MAX_POINTS) * i, dU) ; + Point3d ptCurr ; + currCompoPatch.GetPointD1D2( dU, ICurve::FROM_MINUS, ptCurr) ; + Point3d ptOther ; + int nFlag = 0 ; + if ( ! DistPointCurve( ptCurr, otherCompoPatch).GetMinDistPoint( 0., ptOther, nFlag)) + bTangent = false ; + // Recupero le due normali sulle curva patch campionate + Vector3d vtNCurr = V_INVALID, vtNOther = V_INVALID ; + if ( ! GetNormalAtPoint( pCurrSurf, ptCurr, vtNCurr) || + ! GetNormalAtPoint( pOtherSurf, ptOther, vtNOther)) + return false ; + bTangent = ( vtNCurr * vtNOther > cos( ( dFaceAngTol - EPS_ANG_SMALL) * DEGTORAD)) ; + } + } + // Se superficie in tangenza, aggiorno i parametri + if ( bTangent) { + #if DEBUG_SURF_PATCHES + VC.clear() ; VT.clear() ; + VT.emplace_back( pCurrSurf->Clone()) ; + VC.emplace_back( LIME) ; + VT.emplace_back( pOtherSurf->Clone()) ; + VC.emplace_back( GREEN) ; + VT.emplace_back( currCompoPatch.Clone()) ; + VC.emplace_back( RED) ; + VT.emplace_back( otherCompoPatch.Clone()) ; + VC.emplace_back( BLUE) ; + SaveGeoObj( VT, VC, "C:\\Temp\\Test.nge") ; + #endif + vSurfToCheck.emplace_back( nOtherSurf) ; + OtherPatch.bErase = true ; + if ( nOtherSurf >= int( vSurf.size()) && + find( vIndOtherSurf.begin(), vIndOtherSurf.end(), nOtherSurf - ssize( vSurf)) == vIndOtherSurf.end()) + vIndOtherSurf.push_back( nOtherSurf - ssize( vSurf)) ; + } } } - // Se superficie in tangenza, aggiorno i parametri - if ( bTangent) { - #if DEBUG_SIMPLE_PATCHES - VC.clear() ; VT.clear() ; - VT.emplace_back( pCurrSurf->Clone()) ; - VC.emplace_back( LIME) ; - VT.emplace_back( pOtherSurf->Clone()) ; - VC.emplace_back( GREEN) ; - VT.emplace_back( currCompoPatch.Clone()) ; - VC.emplace_back( RED) ; - VT.emplace_back( otherCompoPatch.Clone()) ; - VC.emplace_back( BLUE) ; - SaveGeoObj( VT, VC, "C:\\Temp\\Test.nge") ; - #endif - vSurfToCheck.emplace_back( nOtherSurf) ; - nextPatch.bErase = true ; - if ( nOtherSurf >= int( vSurf.size()) && - find( vIndOtherSurf.begin(), vIndOtherSurf.end(), nOtherSurf - int( vSurf.size())) == vIndOtherSurf.end()) - vIndOtherSurf.push_back( nOtherSurf - int( vSurf.size())) ; - } } } } } } - #if DEBUG_SURF_PATCHES VT.clear() ; VC.clear() ; for ( const int& nInd : vIndOtherSurf) { @@ -4219,64 +4369,204 @@ GetTrimmingAdjSurfs( const CISURFPVECTOR& vSurf, const CISURFPVECTOR& vOtherSurf } //------------------------------------------------------------------------------ -// Funzione per la ricerca automatica delle Geometrie di Trimming +// Funzione per l'estrazione dei Bordi di Fori e Asole dato un vettore di Superfici bool -GetTrimmingAutoEntities( const CISURFPVECTOR& vSurf, double dShapeLinTol, double dShapeAngTol, - double dLinTol, double dEdgeLinTol, double dAngTol, double dAngFaceTol, - const STRVECTOR& vsShapes, ISURFPOMATRIX& matSelSurf, - ICRVCOMPOPOMATRIX& matCompoBorders, ISURFBEZPOVECTOR& vSurfBz) +GetTrimmingHoleBorders( const CISURFPVECTOR& vpSurf, const Point3d& ptRef, double dSurfLinTol, double dSurfAngTol, + double dEdgeLinTol, double dEdgeAngTol, double dEdgeThick, + ICRVCOMPOPOVECTOR& vHoleBorders) { - // Pulizia dei parametri di ingresso - matSelSurf.clear() ; - matCompoBorders.clear() ; - vSurfBz.clear() ; - - // Se non ho superfici non devo fare nulla - if ( vSurf.empty()) + vHoleBorders.clear() ; + // Se non ho superfici, non faccio nulla + if ( vpSurf.empty()) return true ; - // Verifico che le superfici presenti siano ben definite - for ( const ISurf* pSurf : vSurf) { + // Verifico che tutte le superfici siano valide + for ( const ISurf* pSurf : vpSurf) { if ( pSurf == nullptr || ! pSurf->IsValid()) return false ; } - // Controllo sulla tolleranza lineare - double dMyShapeLinTol = Clamp( dShapeLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; - double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; - double dMyEdgeLinTol = Clamp( dEdgeLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; - // Controllo sulla tolleranza angolare - double dMyShapeAngTol = Clamp( dShapeAngTol, 1., 60.) ; - double dMyAngTol = Clamp( dAngTol, 1., 45.) ; - double dMyFaceAngTol = Clamp( dAngFaceTol, 1., 60.) ; - - ICRVCOMPOPOMATRIX matCompoBordersTmp ; - // Se una sola superficie, effettuo la ricerca per triangoli - if ( ssize( vSurf) == 1) { - ISURFPOVECTOR vSurfTmp ; - if ( ! GetShapesFromSurf( vSurf[0], dMyShapeLinTol, dMyShapeAngTol, dMyLinTol, dMyEdgeLinTol, - dMyAngTol, dMyFaceAngTol, vsShapes, vSurfTmp, matCompoBordersTmp)) - return false ; - for ( int i = 0 ; i < ssize( vSurfTmp) ; ++ i) { - matSelSurf.emplace_back( ISURFPOVECTOR{}) ; - matSelSurf.back().emplace_back( Release( vSurfTmp[i])) ; + #if DEBUG_HOLES + VT.clear() ; VC.clear() ; + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) { + VT.emplace_back( vpSurf[i]->Clone()) ; + VC.emplace_back( Color( 0., 0., 0., 0.25)) ; } - } - // Se più superfici eseguo la ricerca per Patches - else { - - } + SaveGeoObj( VT, VC, "C:\\Temp\\HoleBorders.nge") ; + #endif - // Se non ho alcuna Geometria voluta, esco - if ( matSelSurf.empty()) + // Aggiusto le tolleranze + double dMySurfLinTol = Clamp( dSurfLinTol, EPS_SMALL, 1e5) ; + double dMySurfAngTol = Clamp( dSurfAngTol, EPS_ANG_SMALL, 60.) ; + double dMyEdgeLinTol = Clamp( dEdgeLinTol, EPS_SMALL, 1e5) ; + double dMyEdgeAngTol = Clamp( dEdgeAngTol, EPS_ANG_SMALL, 60.) ; + double dMyEdgeThick = max( 10. * EPS_SMALL, dEdgeThick) ; // coerente con Offset + + // Dalle superfici ricavo i bordi Grezzi + SELVECTOR vSelIds ; vSelIds.resize( vpSurf.size()) ; + for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) + vSelIds.emplace_back( SelData( i, SEL_SUB_ALL)) ; + ICRVCOMPOPOVECTOR vRawEdges ; + if ( ! GetTrimmingRawEdges( vpSurf, vSelIds, dMySurfLinTol, dMySurfAngTol, vRawEdges)) + return false ; + if ( vRawEdges.empty()) return true ; - // Per ogni Geometria, approssimo le Curve mediante delle Bezier e calolo la Rigata - for ( int i = 0 ; i < ssize( matSelSurf) ; ++ i) { - matCompoBorders.emplace_back( ICRVCOMPOPOVECTOR{}) ; matCompoBorders.back().reserve( 2) ; - if ( ! GetTrimmingBezierEdges( matCompoBordersTmp[i], dLinTol, dAngTol, matCompoBorders.back())) + #if DEBUG_HOLES + for ( int i = 0 ; i < ssize( vRawEdges) ; ++ i) { + VT.emplace_back( CloneCurveComposite( vRawEdges[i])) ; + VC.emplace_back( RED) ; + } + SaveGeoObj( VT, VC, "C:\\Temp\\HoleBorders.nge") ; + #endif + + // Tra le curve ricavate, tengo in considerazione solo Fori e Asole + enum HoleType { CIRCLE = 0, BUTTONHOLE = 1 } ; + struct Hole { + PtrOwner pCompoHole ; + int nType ; + Frame3d frCompo ; + double dRad ; + double dLen ; + Hole( ICurveComposite* pHole, int nT, const Frame3d& frC, double dR, double dL) + : nType( nT), frCompo( frC), dRad( dR), dLen( dL) { + pCompoHole.Set( pHole) ; + } + } ; + vector vHoles ; vHoles.reserve( vRawEdges.size()) ; + for ( int i = 0 ; i < ssize( vRawEdges) ; ++ i) { + // Verifico che la curva sia valida + if ( IsNull( vRawEdges[i]) || ! vRawEdges[i]->IsValid()) + continue ; + // Recupero la PolyLine associata + PolyLine PL ; + if ( ! vRawEdges[i]->ApproxWithLines( EPS_SMALL, EPS_ANG_SMALL, ICurve::APL_SPECIAL, PL)) return false ; - vSurfBz.emplace_back( GetTrimmingRuledBezier( vSurf, matCompoBorders.back()[0], matCompoBorders.back()[1], - dMyLinTol, BIPNTVECTOR{})) ; + // Verifico che -- CIRCONFERENZA -- + Frame3d frCompo ; + double dRad = 0. ; + CurveArc CrvCircle ; + if ( IsBorderACircle( PL, dMyEdgeLinTol, dMyEdgeAngTol, frCompo, dRad, CrvCircle)) { + PtrOwner pCompoCircle( CreateCurveComposite()) ; + if ( IsNull( pCompoCircle) || ! pCompoCircle->AddCurve( CrvCircle)) + return false ; + vHoles.emplace_back( Release( pCompoCircle), 0, frCompo, dRad, -1.) ; + continue ; + } + // Verifico se -- ASOLA -- + double dLen = 0. ; + CurveComposite CompoBtHole ; + if ( IsBorderAButtonHole( PL, dMyEdgeLinTol, dMyEdgeAngTol, frCompo, dLen, dRad, CompoBtHole)) { + PtrOwner pCompoBtHole( CreateCurveComposite()) ; + if ( IsNull( pCompoBtHole) || ! pCompoBtHole->AddCurve( CompoBtHole)) + return false ; + vHoles.emplace_back( Release( pCompoBtHole), HoleType::BUTTONHOLE, frCompo, dRad, dLen) ; + continue ; + } + } + + // Vedo se ci sono curve da accoppiare tra di loro + vHoleBorders.reserve( vHoles.size()) ; + if ( ssize( vHoles) > 1) { + for ( int i = 0 ; i < ssize( vHoles) - 1 ; ++ i) { + // Recupero la curva corrente, se non presente allora passo alla successiva + if ( IsNull( vHoles[i].pCompoHole)) + continue ; + int nIndJ = -1 ; + // Scorro le curve successive + for ( int j = i + 1 ; nIndJ == -1 && j < ssize( vHoles) ; ++ j) { + // Recupero la curva corrente, se non presente allora passo alla successiva + if ( IsNull( vHoles[i].pCompoHole)) + continue ; + // Se il tipo è differente non possono essere in coppia + if ( vHoles[i].nType != vHoles[j].nType) + continue ; + // Essendo della stessa topologia, verifico i parametri + bool bCouple = false ; + Vector3d vtCenCen ; + if ( vHoles[i].nType == HoleType::CIRCLE) { + bCouple = ( abs( vHoles[i].dRad - vHoles[j].dRad) < dMyEdgeLinTol && + AreSameOrOppositeVectorEpsilon( vHoles[i].frCompo.VersZ(), vHoles[j].frCompo.VersZ(), dMyEdgeLinTol)) ; + if ( bCouple) { + vtCenCen = ( vHoles[i].frCompo.Orig() - vHoles[j].frCompo.Orig()) ; + bCouple = ( vtCenCen.SqLen() > dMyEdgeLinTol * dMyEdgeLinTol) ; + if ( bCouple) { + bCouple = ( vtCenCen.Normalize() && + AreSameOrOppositeVectorEpsilon( vtCenCen, vHoles[i].frCompo.VersZ(), dMyEdgeLinTol)) ; + } + } + } + else if ( vHoles[i].nType == HoleType::BUTTONHOLE) { + bCouple = ( abs( vHoles[i].dRad - vHoles[j].dRad) < dMyEdgeLinTol && + abs( vHoles[i].dLen - vHoles[j].dLen) < dMyEdgeLinTol && + AreSameOrOppositeVectorEpsilon( vHoles[i].frCompo.VersZ(), vHoles[j].frCompo.VersZ(), dMyEdgeLinTol)) ; + if ( bCouple) { + vtCenCen = ( vHoles[i].frCompo.Orig() - vHoles[j].frCompo.Orig()) ; + bCouple = ( vtCenCen.SqLen() > dMyEdgeLinTol * dMyEdgeLinTol) ; + if ( bCouple) { + bCouple = ( vtCenCen.Normalize() && + AreSameOrOppositeVectorEpsilon( vtCenCen, vHoles[i].frCompo.VersZ(), dMyEdgeLinTol)) ; + } + } + } + if ( bCouple) + nIndJ = j ; + } + + // Determino l'indice della curva da conservare + int nInd = i ; + // Se curva non in coppia, allora ho finito, altrimenti devo sceglierne una + if ( nIndJ != -1) { + int nIndToErase = nIndJ ; + // Recupero i due Box + BBox3d BBoxI ; vHoles[i].pCompoHole->GetLocalBBox( BBoxI) ; + BBox3d BBoxJ ; vHoles[nIndJ].pCompoHole->GetLocalBBox( BBoxJ) ; + // Recupero le Coordinate massime di ZGlob + double dZI = BBoxI.GetMax().z ; + double dZJ = BBoxJ.GetMax().z ; + // Se le 2 curve hanno ZGlob massime differente tra loro + if ( abs( dZI - dZJ) > 5. * EPS_SMALL) { + // Tengo la Curva con ZGlob massima + if ( dZJ > dZI) + swap( nInd, nIndToErase) ; + } + // Se invece le ZGlob sono circa uguali + else { + // Tengo la Curva più distante dal punto di Riferimento ( se Valido) + if ( ptRef.IsValid()) { + double dSqDistI = INFINITO, dSqDistJ = INFINITO ; + DistPointCurve( ptRef, *vHoles[i].pCompoHole).GetSqDist( dSqDistI) ; + DistPointCurve( ptRef, *vHoles[nIndJ].pCompoHole).GetSqDist( dSqDistJ) ; + if ( dSqDistJ > dSqDistI) + swap( nInd, nIndToErase) ; + } + } + // Elimino la curva non significativa delle 2 + vHoles[nIndToErase].pCompoHole.Reset() ; + } + + // Imposto Estrusione alla curva nInd-esima + Vector3d vtExtr = vHoles[nInd].frCompo.VersZ() ; + // Se Estrusione perpendicolare a Z_AX + if ( OrthoCompo( Z_AX, vtExtr).Len() > 1 - 5. * EPS_SMALL) { + // Se punto di Riferimento valido + if ( ptRef.IsValid()) { + Vector3d vtCenCen = vHoles[nInd].frCompo.Orig() - ptRef ; + vtCenCen.Normalize() ; + vHoles[nInd].pCompoHole->SetExtrusion( ( vtExtr * vtCenCen > 0.) ? vtExtr : - vtExtr) ; + } + else + vHoles[nInd].pCompoHole->SetExtrusion( vtExtr) ; + } + // Se estrusione non perpendicolare a Z_AX + else + vHoles[nInd].pCompoHole->SetExtrusion( ( vtExtr * Z_AX > 0.) ? vtExtr : - vtExtr) ; + + // Imposso Spessore alla curva nInd-esima + vHoles[nInd].pCompoHole->SetThickness( - dMyEdgeThick) ; + + // Memorizzo la curva nInd-esima + vHoleBorders.emplace_back( Release( vHoles[nInd].pCompoHole)) ; + } } return true ; From 7cdc1ba5a3411ff18208fdb65db3c9a9ac1b20ab Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 5 Feb 2026 16:54:09 +0100 Subject: [PATCH 02/22] EgtGeomKernel : - implementazione dell'approsimazione tramite curve di bezier. --- CalcDerivate.cpp | 233 +++++++++++++++++++++++++++++ CalcDerivate.h | 5 + CurveAux.cpp | 262 ++++++++++++++++++++++++++++---- CurveByApprox.cpp | 203 +------------------------ CurveByInterp.cpp | 271 +++++----------------------------- EgtGeomKernel.vcxproj | 1 + EgtGeomKernel.vcxproj.filters | 3 + 7 files changed, 513 insertions(+), 465 deletions(-) create mode 100644 CalcDerivate.cpp diff --git a/CalcDerivate.cpp b/CalcDerivate.cpp new file mode 100644 index 0000000..60f3582 --- /dev/null +++ b/CalcDerivate.cpp @@ -0,0 +1,233 @@ +//---------------------------------------------------------------------------- +// EgalTech 2026 +//---------------------------------------------------------------------------- +// File : CalcDerivate.cpp Data : 03.02.26 Versione : 1.5h1 +// Contenuto : Funzioni per calcolo derivate secondo Bessel e Akima. +// +// +// +// Modifiche : 03.02.26 DB Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "stdafx.h" +#include "CalcDerivate.h" +#include "/EgtDev/Include/EGkPoint3d.h" +#include "/EgtDev/Include/EgtNumCollection.h" +#include "/EgtDev/Include/EGkGeoCollection.h" + +//---------------------------------------------------------------------------- +bool +ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) +{ + // pulisco i vettori dei parametri e delle tangenti + vPrevDer.clear() ; + vNextDer.clear() ; + + // numero di punti + int nSize = int( vPnt.size()) ; + + // sono necessari almeno due punti + if ( nSize < 2) + return false ; + + // calcolo le derivate + vPrevDer.reserve( nSize) ; + vNextDer.reserve( nSize) ; + // se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce + if ( nSize == 2) { + // non esiste derivata prima del primo punto + vPrevDer.emplace_back( 0, 0, 0) ; + vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ; + vPrevDer.push_back( vNextDer[0]) ; + // non esiste derivata dopo il secondo e ultimo punto + vNextDer.emplace_back( 0, 0, 0) ; + return true ; + } + // verifico se curva chiusa (primo e ultimo punto coincidono) + bool bClosed = AreSamePointApprox( vPnt.front(), vPnt.back()) ; + // calcolo le derivate + for ( int i = 0 ; i < nSize ; ++ i) { + Vector3d vtPrevDer ; + Vector3d vtNextDer ; + // primo punto + if ( i == 0) { + // se curva chiusa, come precedente uso il penultimo punto + if ( bClosed) { + // se non ci sono almeno 5 punti + if ( nSize < 5) { + if ( ! CalcCircleMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i], + vPar[i+1], vPnt[i+1], vtNextDer)) + return false ; + vtPrevDer = vtNextDer ; + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( vPar[nSize-3] - vPar[nSize-1], vPnt[nSize-3], vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], + vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], + vPar[i+2], vPnt[i+2], bDetectCorner, + vtPrevDer, vtNextDer)) + return false ; + } + } + // altrimenti, uso arco sui primi tre punti + else { + if ( ! CalcCircleStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], + vPar[i+2], vPnt[i+2], vtNextDer)) + return false ; + vtPrevDer = Vector3d( 0, 0, 0) ; + } + } + // ultimo punto + else if ( i == nSize - 1) { + // se curva chiusa, le tg devono coincidere con quelle del primo + if ( bClosed) { + vtPrevDer = vPrevDer[0] ; + vtNextDer = vNextDer[0] ; + } + // altrimenti, uso arco sugli ultimi tre punti + else { + if ( ! CalcCircleEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1], + vPar[i], vPnt[i], vtPrevDer)) + return false ; + vtNextDer = Vector3d( 0, 0, 0) ; + } + } + // punti intermedi + else { + // se secondo punto + if ( i == 1) { + // se curva aperta o non ci sono almeno 5 punti + if ( ! bClosed || nSize < 5) { + if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], + vPar[i+1], vPnt[i+1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i-1], vPnt[i-1], + vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], + vPar[i+2], vPnt[i+2], bDetectCorner, + vtPrevDer, vtNextDer)) + return false ; + } + } + // se penultimo punto + else if ( i == nSize - 2) { + // se curva aperta o non ci sono almeno 5 punti + if ( ! bClosed || nSize < 5) { + if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], + vPar[i+1], vPnt[i+1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1], + vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], + vPar[1] + vPar[i+1], vPnt[1], bDetectCorner, + vtPrevDer, vtNextDer)) + return false ; + } + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1], + vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], + vPar[i+2], vPnt[i+2], bDetectCorner, + vtPrevDer, vtNextDer)) + return false ; + } + } + // salvo la derivata + vPrevDer.push_back( vtPrevDer) ; + vNextDer.push_back( vtNextDer) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) +{ + // pulisco i vettori dei parametri e delle tangenti + vPrevDer.clear() ; + vNextDer.clear() ; + + // numero di punti + int nSize = int( vPnt.size()) ; + + // sono necessari almeno due punti + if ( nSize < 2) + return false ; + + // calcolo le derivate + vPrevDer.reserve( nSize) ; + vNextDer.reserve( nSize) ; + // se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce + if ( nSize == 2) { + // non esiste derivata prima del primo punto + vPrevDer.emplace_back( 0, 0, 0) ; + vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ; + vPrevDer.push_back( vNextDer[0]) ; + // non esiste derivata dopo il secondo e ultimo punto + vNextDer.emplace_back( 0, 0, 0) ; + return true ; + } + // verifico se curva chiusa (primo e ultimo punto coincidono) + bool bClosed = AreSamePointApprox( vPnt.front(), vPnt.back()) ; + // calcolo le derivate + for ( int i = 0 ; i < nSize ; ++ i) { + Vector3d vtPrevDer ; + Vector3d vtNextDer ; + // primo punto + if ( i == 0) { + // se curva chiusa, come precedente uso il penultimo punto + if ( bClosed) { + if ( ! CalcBesselMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i], + vPar[i+1], vPnt[i+1], vtNextDer)) + return false ; + vtPrevDer = vtNextDer ; + } + // altrimenti, uso i primi tre punti + else { + if ( ! CalcBesselStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], + vPar[i+2], vPnt[i+2], vtNextDer)) + return false ; + vtPrevDer = Vector3d( 0, 0, 0) ; + } + } + // ultimo punto + else if ( i == nSize - 1) { + // se curva chiusa, le tg devono coincidere con quelle del primo + if ( bClosed) { + vtPrevDer = vPrevDer[0] ; + vtNextDer = vNextDer[0] ; + } + // altrimenti, uso gli ultimi tre punti + else { + if ( ! CalcBesselEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1], + vPar[i], vPnt[i], vtPrevDer)) + return false ; + vtNextDer = Vector3d( 0, 0, 0) ; + } + } + // punti intermedi + else { + if ( ! CalcBesselMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], + vPar[i+1], vPnt[i+1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // salvo la derivata + vPrevDer.push_back( vtPrevDer) ; + vNextDer.push_back( vtNextDer) ; + } + + return true ; +} \ No newline at end of file diff --git a/CalcDerivate.h b/CalcDerivate.h index 1ba6904..d6a1bbd 100644 --- a/CalcDerivate.h +++ b/CalcDerivate.h @@ -14,6 +14,8 @@ #pragma once #include "/EgtDev/Include/EGkPoint3d.h" +#include "/EgtDev/Include/EgtNumCollection.h" +#include "/EgtDev/Include/EGkGeoCollection.h" //---------------------------------------------------------------------------- @@ -179,3 +181,6 @@ CalcAkimaMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP } return ( ! vtPrevDer.IsZero() && ! vtNextDer.IsZero()) ; } + +bool ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) ; +bool ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) ; \ No newline at end of file diff --git a/CurveAux.cpp b/CurveAux.cpp index 5f4c1c3..ede91d4 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -13,6 +13,8 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" +#include "CalcDerivate.h" +#include "Bernstein.h" #include "CurveAux.h" #include "GeoConst.h" #include "CurveLine.h" @@ -23,6 +25,7 @@ #include "IntersLineLine.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkStringUtils3d.h" +#include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EGkCurveByInterp.h" @@ -30,6 +33,11 @@ #define EIGEN_NO_IO #include "/EgtDev/Extern/Eigen/Dense" +#define SAVEAPPROX 0 +#if SAVEAPPROX + #include "/EgtDev/Include/EGkGeoObjSave.h" +#endif + using namespace std ; static bool FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan) ; @@ -1187,7 +1195,8 @@ CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTO //---------------------------------------------------------------------------- ICurve* -InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, int nEnd, int nDeg, const DBLVECTOR& vLen, double dLenTot) +InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, int nEnd, int nDeg, const DBLVECTOR& vLen, double dLenTot, + const Vector3d& vtStartDir = V_NULL, const Vector3d& vtEndDir = V_NULL) { PtrOwner pCrvInt ; @@ -1216,6 +1225,8 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, return nullptr ; } + bool bUseStartEndDir = vtStartDir.IsValid() && vtEndDir.IsValid() ; + DBLVECTOR vPntParam ; vPntParam.resize( nPoints) ; vPntParam[0] = 0 ; @@ -1224,13 +1235,15 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, vPntParam[i] = vPntParam[i-1] + vLen[i-1] / dLenTot ; DBLVECTOR vKnots ; - vKnots.resize( nPoints + nDeg - 1) ; + int nKnots = bUseStartEndDir ? nPoints + nDeg - 1 + 2 : nPoints + nDeg - 1 ; + vKnots.resize( nKnots) ; for ( int i = 0 ; i < nDeg ; ++i) { vKnots[i] = 0 ; vKnots.end()[-i-1] = 1 ; } - for ( int i = nDeg ; i < nPoints - 1 ; ++i) { + int nKnotsToEdit = bUseStartEndDir ? nPoints + 1 : nPoints - 1 ; + for ( int i = nDeg ; i < nKnotsToEdit ; ++i) { double dKnot = 0 ; for ( int j = i + 1 ; j < i + nDeg + 1 ; ++j) dKnot += vPntParam[j - nDeg] ; @@ -1238,13 +1251,14 @@ InterpolatePointSetWithBezierNoIntermedLines( const PNTVECTOR& vPnt, int nStart, vKnots[i] = dKnot ; } - Eigen::MatrixXd mA( nPoints, nPoints) ; + int nEq = bUseStartEndDir ? nPoints + 2 : nPoints ; + Eigen::MatrixXd mA( nEq, nEq) ; mA.fill( 0) ; - for ( int i = 0 ; i < nPoints ; ++i) { + for ( int i = 0 ; i < nEq ; ++i) { if ( i == 0) mA.row(0).col(0) << 1 ; - else if ( i == nPoints - 1) - mA.row(i).col(nPoints - 1) << 1 ; + else if ( i == nEq - 1) + mA.row(i).col( nEq - 1) << 1 ; else { int nSpan = 0 ; FindSpan( vPntParam[i], nDeg, vKnots, nSpan) ; DBLVECTOR vBasis ; vBasis.resize( nDeg + 1) ; @@ -1346,7 +1360,13 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa if ( vLen.size() != 0) { if ( nEnd == 0) nEnd = nPoints - 1 ; - pCrvInt->AddCurve( InterpolatePointSetWithBezierNoIntermedLines( vPnt, nStart, nEnd, nDeg, vLen, dLenTot)) ; + Vector3d vtStartDir = V_INVALID ; + Vector3d vtEndDir = V_INVALID ; + //if ( nStart != 0 && nEnd != nPoints - 1) { + // pCrvInt->GetEndDir( vtStartDir) ; + // vtEndDir = + //} + pCrvInt->AddCurve( InterpolatePointSetWithBezierNoIntermedLines( vPnt, nStart, nEnd, nDeg, vLen, dLenTot, vtStartDir, vtEndDir)) ; } if ( bFoundLine) { @@ -1358,6 +1378,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa nStart = nEnd ; } + //dErr = 0 ; CalcApproxError( pCrvOri, pCrvInt, dErr) ; if ( dErr > dLinTol && dMaxLen > 200 * EPS_SMALL) dMaxLen /= 2 ; @@ -1372,42 +1393,227 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa } //---------------------------------------------------------------------------- -ICurve* -ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) +static bool +ParamByLen( const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast) { - PolyLine plApprox ; - double dAngTolFine = 2 ; - pCrv->ApproxWithLines( dTol, dAngTolFine, ICurve::APL_STD, plApprox) ; + int nPoints = nLast - nFirst + 1 ; + if ( nPoints < 2) + return false ; + if( ssize(vParam) == 0) + vParam.resize( nPoints) ; + if( vParam[nFirst] == 0 && vParam[nLast] == 1) + return true ; + vParam[nFirst] = 0 ; + for ( int i = nFirst + 1 ; i <= nLast ; ++i) { + double dDist = Dist( vPnt[i], vPnt[i-1]) ; + vParam[i] = vParam[i- 1] + dDist ; + } + for ( int i = nFirst + 1 ; i < nLast ; ++i) + vParam[i] /= vParam[nLast] ; + vParam[nLast] = 1 ; - PNTVECTOR vPnt ; - Point3d pt ; plApprox.GetFirstPoint( pt) ; - do { - vPnt.push_back( pt) ; - } while ( plApprox.GetNextPoint( pt)) ; + return true ; +} - // campiono punti lungo la curva e poi li interpolo +//---------------------------------------------------------------------------- +ICurveBezier* +ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, const Vector3d& vtStartDir, const Vector3d& vtEndDir, + const DBLVECTOR& vParam) +{ + // cerco di approssimare un set di punti con una sola bezier cubica non razionale + int nPoints = nLast - nFirst + 1 ; + // se ho solo quattro punti allora costruisco direttamente la curva + PtrOwner pCrvBez( CreateCurveBezier()) ; + int nDeg = 3 ; + bool bRat = false ; + pCrvBez->Init( nDeg, bRat) ; + const Point3d& pt0 = vPnt[nFirst] ; + const Point3d& pt3 = vPnt[nLast] ; + pCrvBez->SetControlPoint( 0, pt0) ; + pCrvBez->SetControlPoint( 3, pt3) ; + Eigen::Vector2d mA ; + if( nPoints > 4) { + // risoluzione sistema + Eigen::Matrix2d mC ; mC.setZero() ; + Eigen::Vector2d mX ; mX.setZero() ; + for ( int i = nFirst ; i <= nLast ; ++i) { + double dU = vParam[i] ; + DBLVECTOR vBern(4) ; + GetAllBernstein( dU, 3, vBern) ; - PtrOwner pCC( InterpolatePointSetWithBezier( vPnt, dTol, 100)) ; - if ( ! IsNull( pCC) && pCC->IsValid()) - return Release( pCC) ; - else - return nullptr ; + Vector3d A1 = vtStartDir * vBern[1] ; + Vector3d A2 = vtEndDir * vBern[2] ; + + Vector3d tmp = vPnt[i] - ( pt0 * ( vBern[0] + vBern[1])) - (( pt3 * ( vBern[2] + vBern[3])) - ORIG) ; // ORIG serve solo per trasformare l'ultimo termine in un vettore + + mC(0,0) += A1 * A1 ; + mC(0,1) += A1 * A2 ; + mC(1,0) += A1 * A2 ; + mC(1,1) += A2 * A2 ; + + mX(0) += A1 * tmp ; + mX(1) += A2 * tmp ; + } + mA = mC.fullPivLu().solve(mX) ; + + double C00 = mC(0,0) ; + double C01 = mC(0,1) ; + double C10 = mC(1,0) ; + double C11 = mC(1,1) ; + + double X0 = mX(0) ; + double X1 = mX(1) ; + } + // l'algoritmo è fatto in modo che alpha1 e alpha2 siano positivi ( se tutto va bene) + // io invece ho tenuto le tangenti con la direzione originale, quindi il primo dovrebbe essere positivo e il secondo negativo + if ( mA(0) < 0 || mA(1) > 0 || nPoints < 4) { + LOG_DBG_ERR( GetEGkLogger(), "valori di alfa sballati, potrebbe essere la spaziatura dismogenea tra punti, oppure solo la curva da spezzare") + double dDistCorr = Dist( pt3, pt0) / 3 ; + mA(0) = dDistCorr ; + mA(1) = - dDistCorr ; + } + + double alpah1 = mA(0) ; + double alpha2 = mA(1) ; + Point3d pt1 = pt0 + vtStartDir * mA(0) ; + Point3d pt2 = pt3 + vtEndDir * mA(1) ; + pCrvBez->SetControlPoint( 1, pt1) ; + pCrvBez->SetControlPoint( 2, pt2) ; + return Release( pCrvBez) ; +} + +//---------------------------------------------------------------------------- +bool +CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam, int nFirst, int nLast, const ICurve* pCrvNew, double& dErr, int& nPointMaxErr) +{ + dErr = 0 ; + // calcolo l'errore di approssimazione + for ( int i = nFirst ; i <= nLast ; ++i) { + Point3d ptBez ; pCrvNew->GetPointD1D2( vParam[i], ICurve::Side::FROM_MINUS, ptBez) ; + double dErrTemp = Dist( vPntOrig[i], ptBez) ; + if( dErrTemp > dErr) { + dErr = dErrTemp ; + nPointMaxErr = i ; + } + } + + return true ; } //---------------------------------------------------------------------------- ICurve* -ApproxPointSetWithBezier( const ICurve* pCrv, double dTol) +FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, double dTol) { - // campiono punti lungo la curva e poi li interpolo + ParamByLen(vPnt, vParam, nFirst, nLast) ; + PtrOwner pCrvFit( CreateCurveComposite()) ; + PtrOwner pCrvBez( CreateCurveBezier()) ; + double dErr = INFINITO ; + double dErrSplit = dTol * 25 ; + int nIter = 0 ; + while ( dErr > dTol && nIter < 10) { + if( dErr < INFINITO) { + // riparametrizzo i punti + for ( int i = nFirst + 1 ; i < nLast ; ++i) { + //questo potrebbe diventare un while appena capisco di quanto si aggiusta il parametro ad ogni iterazione + double dCorr = 1 ; + do { + Vector3d vtDer1, vtDer2 ; + Point3d ptBez ; pCrvBez->GetPointD1D2( vParam[i], ICurve::Side::FROM_MINUS, ptBez, &vtDer1, &vtDer2) ; + Vector3d vtLink = ptBez - vPnt[i] ; + double dNum = vtLink * vtDer1 ; + double dDen = vtLink * vtDer2 + vtDer1 * vtDer1 ; + dCorr = dDen > EPS_ZERO ? dNum / dDen : 0 ; + vParam[i] = vParam[i] - dCorr ; + } while ( abs( dCorr) > EPS_ZERO) ; + Clamp( vParam[i], 0., 1.) ; + } + } - PtrOwner pCC( CreateBasicCurveComposite()) ; - return Release( pCC) ; + // fit della curva + pCrvBez.Set( ApproxPointSetWithSingleBezier( vPnt, nFirst, nLast, vNextDer[nFirst], vPrevDer[nLast], vParam)) ; + if( IsNull( pCrvBez) || ! pCrvBez->IsValid()) + return nullptr ; +#if SAVEAPPROX + SaveGeoObj( pCrvBez->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\first_approx.nge") ; +#endif + + int nPointMaxErr = 0 ; + CalcPointSetApproxError( vPnt, vParam, nFirst, nLast, pCrvBez, dErr, nPointMaxErr) ; + if ( dErr < dTol) { + // verifico anche più finemente + int nCheckPoints = (nLast - nFirst) * 2 ; + CalcApproxError( pCrvOrig->CopyParamRange( nFirst, nLast), pCrvBez, dErr, nCheckPoints) ; + } + ++nIter ; + bool bSplit = false ; + if( nIter == 10 && dErr > dTol) + bSplit = true ; + // se la curva di approssimazione è ancora molto lontana dalla curva originale allora divido il set di punti in due + if ( dErr > dErrSplit || bSplit) { + if( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol)) || + ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol))) + return nullptr ; + break ; + } + } + + if ( pCrvFit->GetCurveCount() > 0) + return Release( pCrvFit) ; + else if ( dErr < dTol) + return Release( pCrvBez) ; + else + return nullptr ; +} + +//---------------------------------------------------------------------------- +ICurve* +ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) +{ + //// uso l'algoritmo di Schneider in Grafic Gems I + // mi aspetto che non ci siano angoli ( discontinuità della derivata prima) nel risultato desiderato + PolyLine plApprox ; + double dAngTolFine = 2 ; + pCrv->ApproxWithLines( dTol, dAngTolFine, ICurve::APL_STD, plApprox) ; + + CurveByInterp cbi ; + PNTVECTOR vPnt ; + Point3d pt ; plApprox.GetFirstPoint( pt) ; + do { + vPnt.push_back( pt) ; + cbi.AddPoint( pt) ; + } while ( plApprox.GetNextPoint( pt)) ; + + int nPoints = ssize( vPnt) ; + DBLVECTOR vParam( nPoints) ; + int nFirst = 0 ; + int nLast = ssize( vPnt) - 1 ; + ParamByLen( vPnt, vParam, nFirst, nLast) ; + + VCT3DVECTOR vPrevDer ; + VCT3DVECTOR vNextDer ; + ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ; + //normalizzo tutte le derivate + for( int i = 0 ; i < ssize( vPrevDer) ; ++i) { + vPrevDer[i].Normalize() ; + vNextDer[i].Normalize() ; + } + + //definisco la bezier che vado a raffinare iterativamente + PtrOwner pCApprox( FitWithBezier( pCrv, vPnt, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol)) ; + if( IsNull( pCApprox) || ! pCApprox->IsValid()) + return nullptr ; + + return Release( pCApprox) ; } //---------------------------------------------------------------------------- bool CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int nPoints) { + if( pCrvOri == nullptr || ! pCrvOri->IsValid() || pCrvNew == nullptr || ! pCrvNew->IsValid()){ + dErr = INFINITO ; + return false ; + } // controllo l'errore effettivo campionando più finemente double dLenOri = 0 ; pCrvOri->GetLength( dLenOri) ; double dLenNew = 0 ; pCrvNew->GetLength( dLenNew) ; diff --git a/CurveByApprox.cpp b/CurveByApprox.cpp index 836ccfe..2e3307c 100644 --- a/CurveByApprox.cpp +++ b/CurveByApprox.cpp @@ -202,213 +202,14 @@ CurveByApprox::CalcParameterization( void) bool CurveByApprox::CalcAkimaTangents( bool bDetectCorner) { - // pulisco i vettori delle tangenti - m_vPrevDer.clear() ; - m_vNextDer.clear() ; - - // numero di punti - int nSize = int( m_vPnt.size()) ; - - // sono necessari almeno due punti - if ( nSize < 2) - return false ; - - // calcolo le derivate - m_vPrevDer.reserve( nSize) ; - m_vNextDer.reserve( nSize) ; - // se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce - if ( nSize == 2) { - // non esiste derivata prima del primo punto - m_vPrevDer.emplace_back( 0, 0, 0) ; - m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ; - m_vPrevDer.push_back( m_vNextDer[0]) ; - // non esiste derivata dopo il secondo e ultimo punto - m_vNextDer.emplace_back( 0, 0, 0) ; - return true ; - } - // verifico se curva chiusa (primo e ultimo punto coincidono) - bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ; - // calcolo le derivate - for ( int i = 0 ; i < nSize ; ++ i) { - Vector3d vtPrevDer ; - Vector3d vtNextDer ; - // primo punto - if ( i == 0) { - // se curva chiusa, come precedente uso il penultimo punto - if ( bClosed) { - // se non ci sono almeno 5 punti - if ( nSize < 5) { - if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtNextDer)) - return false ; - vtPrevDer = vtNextDer ; - } - // altrimenti - else { - if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], - m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], bDetectCorner, - vtPrevDer, vtNextDer)) - return false ; - } - } - // altrimenti, uso arco sui primi tre punti - else { - if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], vtNextDer)) - return false ; - vtPrevDer = Vector3d( 0, 0, 0) ; - } - } - // ultimo punto - else if ( i == nSize - 1) { - // se curva chiusa, le tg devono coincidere con quelle del primo - if ( bClosed) { - vtPrevDer = m_vPrevDer[0] ; - vtNextDer = m_vNextDer[0] ; - } - // altrimenti, uso arco sugli ultimi tre punti - else { - if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], vtPrevDer)) - return false ; - vtNextDer = Vector3d( 0, 0, 0) ; - } - } - // punti intermedi - else { - // se secondo punto - if ( i == 1) { - // se curva aperta o non ci sono almeno 5 punti - if ( ! bClosed || nSize < 5) { - if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) - return false ; - vtNextDer = vtPrevDer ; - } - // altrimenti - else { - if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], bDetectCorner, - vtPrevDer, vtNextDer)) - return false ; - } - } - // se penultimo punto - else if ( i == nSize - 2) { - // se curva aperta o non ci sono almeno 5 punti - if ( ! bClosed || nSize < 5) { - if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) - return false ; - vtNextDer = vtPrevDer ; - } - // altrimenti - else { - if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner, - vtPrevDer, vtNextDer)) - return false ; - } - } - // altrimenti - else { - if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], bDetectCorner, - vtPrevDer, vtNextDer)) - return false ; - } - } - // salvo la derivata - m_vPrevDer.push_back( vtPrevDer) ; - m_vNextDer.push_back( vtNextDer) ; - } - - return true ; + return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ; } //---------------------------------------------------------------------------- bool CurveByApprox::CalcBesselTangents( void) { - // pulisco i vettori delle tangenti - m_vPrevDer.clear() ; - m_vNextDer.clear() ; - - // numero di punti - int nSize = int( m_vPnt.size()) ; - - // sono necessari almeno due punti - if ( nSize < 2) - return false ; - - // calcolo le derivate - m_vPrevDer.reserve( nSize) ; - m_vNextDer.reserve( nSize) ; - // se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce - if ( nSize == 2) { - // non esiste derivata prima del primo punto - m_vPrevDer.emplace_back( 0, 0, 0) ; - m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ; - m_vPrevDer.push_back( m_vNextDer[0]) ; - // non esiste derivata dopo il secondo e ultimo punto - m_vNextDer.emplace_back( 0, 0, 0) ; - return true ; - } - // verifico se curva chiusa (primo e ultimo punto coincidono) - bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ; - // calcolo le derivate - for ( int i = 0 ; i < nSize ; ++ i) { - Vector3d vtPrevDer ; - Vector3d vtNextDer ; - // primo punto - if ( i == 0) { - // se curva chiusa, come precedente uso il penultimo punto - if ( bClosed) { - if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtNextDer)) - return false ; - vtPrevDer = vtNextDer ; - } - // altrimenti, uso i primi tre punti - else { - if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], vtNextDer)) - return false ; - vtPrevDer = Vector3d( 0, 0, 0) ; - } - } - // ultimo punto - else if ( i == nSize - 1) { - // se curva chiusa, le tg devono coincidere con quelle del primo - if ( bClosed) { - vtPrevDer = m_vPrevDer[0] ; - vtNextDer = m_vNextDer[0] ; - } - // altrimenti, uso gli ultimi tre punti - else { - if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], vtPrevDer)) - return false ; - vtNextDer = Vector3d( 0, 0, 0) ; - } - } - // punti intermedi - else { - if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) - return false ; - vtNextDer = vtPrevDer ; - } - // salvo la derivata - m_vPrevDer.push_back( vtPrevDer) ; - m_vNextDer.push_back( vtNextDer) ; - } - - return true ; + return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ; } //---------------------------------------------------------------------------- diff --git a/CurveByInterp.cpp b/CurveByInterp.cpp index 0c7003c..6ba70b6 100644 --- a/CurveByInterp.cpp +++ b/CurveByInterp.cpp @@ -50,12 +50,42 @@ CurveByInterp::AddPoint( const Point3d& ptP) ICurve* CurveByInterp::GetCurve( int nMethod, int nType) { - // calcolo le tangenti + // se richieste curve di Bezier cubiche (ottenute da interpolazione con Nurbs) + if ( nType == CUBIC_BEZIERS_LONG) { + // creo la curva composita + PtrOwner pCrv ; + //pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 50 * EPS_SMALL, 50)) ; + //debug + pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 0.1, 100)) ; + if ( IsNull(pCrv) || ! pCrv->IsValid()) + return nullptr ; + return Release( pCrv) ; + } + + // numero di punti + int nSize = int( m_vPnt.size()) ; + + // sono necessari almeno due punti + if ( nSize < 2) + return nullptr ; + + // calcolo le distanze tra i punti per derivarne i parametri + m_vPar.reserve( nSize) ; + double dPar = 0 ; + m_vPar.push_back( dPar) ; + + for ( int i = 1 ; i < nSize ; ++ i) { + double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ; + dPar += dDist ; + m_vPar.push_back( dPar) ; + } + + // calcolo le tangenti if ( nMethod == BESSEL) { if ( ! CalcBesselTangents()) return nullptr ; } - else if ( nType != CUBIC_BEZIERS_LONG) { + else { if ( ! CalcAkimaTangents( nMethod == AKIMA_CORNER)) return nullptr ; } @@ -103,16 +133,6 @@ CurveByInterp::GetCurve( int nMethod, int nType) return ::Release( pCrvCompo) ; } - // se richieste curve di Bezier cubiche (ottenute da interpolazione con Nurbs) - if ( nType == CUBIC_BEZIERS_LONG) { - // creo la curva composita - PtrOwner pCrv ; - pCrv.Set( InterpolatePointSetWithBezier( m_vPnt, 50 * EPS_SMALL, 50)) ; - if ( IsNull(pCrv) || ! pCrv->IsValid()) - return nullptr ; - return Release( pCrv) ; - } - return nullptr ; } @@ -120,233 +140,12 @@ CurveByInterp::GetCurve( int nMethod, int nType) bool CurveByInterp::CalcAkimaTangents( bool bDetectCorner) { - // pulisco i vettori dei parametri e delle tangenti - m_vPar.clear() ; - m_vPrevDer.clear() ; - m_vNextDer.clear() ; - - // numero di punti - int nSize = int( m_vPnt.size()) ; - - // sono necessari almeno due punti - if ( nSize < 2) - return false ; - - // calcolo le distanze tra i punti per derivarne i parametri - m_vPar.reserve( nSize) ; - double dPar = 0 ; - m_vPar.push_back( dPar) ; - for ( int i = 1 ; i < nSize ; ++ i) { - double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ; - dPar += dDist ; - m_vPar.push_back( dPar) ; - } - - // calcolo le derivate - m_vPrevDer.reserve( nSize) ; - m_vNextDer.reserve( nSize) ; - // se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce - if ( nSize == 2) { - // non esiste derivata prima del primo punto - m_vPrevDer.emplace_back( 0, 0, 0) ; - m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ; - m_vPrevDer.push_back( m_vNextDer[0]) ; - // non esiste derivata dopo il secondo e ultimo punto - m_vNextDer.emplace_back( 0, 0, 0) ; - return true ; - } - // verifico se curva chiusa (primo e ultimo punto coincidono) - bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ; - // calcolo le derivate - for ( int i = 0 ; i < nSize ; ++ i) { - Vector3d vtPrevDer ; - Vector3d vtNextDer ; - // primo punto - if ( i == 0) { - // se curva chiusa, come precedente uso il penultimo punto - if ( bClosed) { - // se non ci sono almeno 5 punti - if ( nSize < 5) { - if ( ! CalcCircleMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtNextDer)) - return false ; - vtPrevDer = vtNextDer ; - } - // altrimenti - else { - if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], - m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], bDetectCorner, - vtPrevDer, vtNextDer)) - return false ; - } - } - // altrimenti, uso arco sui primi tre punti - else { - if ( ! CalcCircleStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], vtNextDer)) - return false ; - vtPrevDer = Vector3d( 0, 0, 0) ; - } - } - // ultimo punto - else if ( i == nSize - 1) { - // se curva chiusa, le tg devono coincidere con quelle del primo - if ( bClosed) { - vtPrevDer = m_vPrevDer[0] ; - vtNextDer = m_vNextDer[0] ; - } - // altrimenti, uso arco sugli ultimi tre punti - else { - if ( ! CalcCircleEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], vtPrevDer)) - return false ; - vtNextDer = Vector3d( 0, 0, 0) ; - } - } - // punti intermedi - else { - // se secondo punto - if ( i == 1) { - // se curva aperta o non ci sono almeno 5 punti - if ( ! bClosed || nSize < 5) { - if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) - return false ; - vtNextDer = vtPrevDer ; - } - // altrimenti - else { - if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], bDetectCorner, - vtPrevDer, vtNextDer)) - return false ; - } - } - // se penultimo punto - else if ( i == nSize - 2) { - // se curva aperta o non ci sono almeno 5 punti - if ( ! bClosed || nSize < 5) { - if ( ! CalcCircleMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) - return false ; - vtNextDer = vtPrevDer ; - } - // altrimenti - else { - if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[1] + m_vPar[i+1], m_vPnt[1], bDetectCorner, - vtPrevDer, vtNextDer)) - return false ; - } - } - // altrimenti - else { - if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], bDetectCorner, - vtPrevDer, vtNextDer)) - return false ; - } - } - // salvo la derivata - m_vPrevDer.push_back( vtPrevDer) ; - m_vNextDer.push_back( vtNextDer) ; - } - - return true ; + return ComputeAkimaTangents( bDetectCorner, m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ; } //---------------------------------------------------------------------------- bool CurveByInterp::CalcBesselTangents( void) { - // pulisco i vettori dei parametri e delle tangenti - m_vPar.clear() ; - m_vPrevDer.clear() ; - m_vNextDer.clear() ; - - // numero di punti - int nSize = int( m_vPnt.size()) ; - - // sono necessari almeno due punti - if ( nSize < 2) - return false ; - - // calcolo le distanze tra i punti per derivarne i parametri - m_vPar.reserve( nSize) ; - double dPar = 0 ; - m_vPar.push_back( dPar) ; - for ( int i = 1 ; i < nSize ; ++ i) { - double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ; - dPar += dDist ; - m_vPar.push_back( dPar) ; - } - - // calcolo le derivate - m_vPrevDer.reserve( nSize) ; - m_vNextDer.reserve( nSize) ; - // se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce - if ( nSize == 2) { - // non esiste derivata prima del primo punto - m_vPrevDer.emplace_back( 0, 0, 0) ; - m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ; - m_vPrevDer.push_back( m_vNextDer[0]) ; - // non esiste derivata dopo il secondo e ultimo punto - m_vNextDer.emplace_back( 0, 0, 0) ; - return true ; - } - // verifico se curva chiusa (primo e ultimo punto coincidono) - bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ; - // calcolo le derivate - for ( int i = 0 ; i < nSize ; ++ i) { - Vector3d vtPrevDer ; - Vector3d vtNextDer ; - // primo punto - if ( i == 0) { - // se curva chiusa, come precedente uso il penultimo punto - if ( bClosed) { - if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtNextDer)) - return false ; - vtPrevDer = vtNextDer ; - } - // altrimenti, uso i primi tre punti - else { - if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], - m_vPar[i+2], m_vPnt[i+2], vtNextDer)) - return false ; - vtPrevDer = Vector3d( 0, 0, 0) ; - } - } - // ultimo punto - else if ( i == nSize - 1) { - // se curva chiusa, le tg devono coincidere con quelle del primo - if ( bClosed) { - vtPrevDer = m_vPrevDer[0] ; - vtNextDer = m_vNextDer[0] ; - } - // altrimenti, uso gli ultimi tre punti - else { - if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], - m_vPar[i], m_vPnt[i], vtPrevDer)) - return false ; - vtNextDer = Vector3d( 0, 0, 0) ; - } - } - // punti intermedi - else { - if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], - m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) - return false ; - vtNextDer = vtPrevDer ; - } - // salvo la derivata - m_vPrevDer.push_back( vtPrevDer) ; - m_vNextDer.push_back( vtNextDer) ; - } - - return true ; -} + return ComputeBesselTangents( m_vPar, m_vPnt, m_vPrevDer, m_vNextDer) ; +} \ No newline at end of file diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index c571c4d..202867f 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -281,6 +281,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 06c76e0..0c644f1 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -567,6 +567,9 @@ File di origine\GeoStriping + + File di origine\Geo + From f111827545707d186228bd445147a672e3e5142d Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 5 Feb 2026 16:56:09 +0100 Subject: [PATCH 03/22] EgtGeomKernel : - modificata la CreateByExtrusion per le bezier. --- SurfBezier.cpp | 41 +++++++++++++++++++++-------------------- SurfBezier.h | 2 +- VolZmapVolume.cpp | 1 - 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index f336b34..a553d44 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -4059,6 +4059,9 @@ SurfBezier::CreateByFlatContour( const PolyLine& PL) bool SurfBezier::CreateByRegion( const POLYLINEVECTOR& vPL) { + // la regione passata è riferita al parametrico di una superficie quadrata. + // La superficie viene creata come se fosse una flatregion a partire dai loop passati. + // le polyline in input devono essere già ordinate per area e orientate con il verso giusto ( tenendo conto di chunk e isole) // la prima polyline quindi è il loop esterno del chunk più grande Plane3d plPlane ; @@ -4126,39 +4129,37 @@ SurfBezier::CreateByRegion( const POLYLINEVECTOR& vPL) //---------------------------------------------------------------------------- bool -SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr, bool bDeg3orDeg2) +SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr) { if ( pCrv == nullptr) return false ; - // verifico che la curva passata sia una bezier semplice o una composita di bezier - if ( pCrv->GetType() != CRV_COMPO && pCrv->GetType() != CRV_BEZIER) - return false ; - // se composita verifico che curve siano con lo stesso grado e uniformi come tipo CurveComposite CC ; - CC.AddCurve( pCrv->Clone()) ; + // se composita verifico che curve siano con lo stesso grado e uniformi come tipo bool bRat = false ; - int nDegU = 1 ; - for ( int i = 0 ; i < CC.GetCurveCount() ; ++i) { - if ( CC.GetCurve( i)->GetType() != CRV_BEZIER) - return false ; - const ICurveBezier* pCrvBez = GetCurveBezier( CC.GetCurve( i)) ; - if ( i == 0 ) { - bRat = pCrvBez->IsRational() ; - nDegU = pCrvBez->GetDegree() ; - } - else { - if ( pCrvBez->GetDegree() != nDegU || pCrvBez->IsRational() != bRat) - return false ; + int nDegU = 3 ; + if( pCrv->GetType() != CRV_COMPO) { + CC.AddCurve( CurveToBezierCurve( pCrv, nDegU, bRat)) ; + } + else { + const ICurveComposite* pCCOrig = GetCurveComposite( pCrv) ; + for ( int i = 0 ; i < pCCOrig->GetCurveCount() ; ++i) { + if ( pCCOrig->GetCurve( i)->GetType() != CRV_BEZIER) + CC.AddCurve( CurveToBezierCurve( pCCOrig->GetCurve(i), nDegU, bRat)) ; + else + CC.AddCurve( EditBezierCurve( GetCurveBezier( pCCOrig->GetCurve(i)), nDegU, bRat)) ; } } + if( CC.GetCurveCount() == 0 || ! CC.IsValid()) + return false ; + // riempio la matrice dei punti di controllo // parto dalla curva che sto estrudendo e mi alzo progressivamente seguendo il vettore vtExtr - int nDegV = bDeg3orDeg2 ? 3 : 2 ; + int nDegV = 1 ; int nSpanU = CC.GetCurveCount() ; int nSpanV = 1 ; - Init(nDegU, nDegV, nSpanU, nSpanV, bRat) ; + Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ; for ( int k = 0 ; k < nSpanU ; ++k) { const ICurveBezier* pCrvBezier = GetCurveBezier( CC.GetCurve( k)) ; diff --git a/SurfBezier.h b/SurfBezier.h index 80c4286..bf92b9a 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -143,7 +143,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool IsPlanar( void) const override ; bool CreateByFlatContour( const PolyLine& PL) override ; bool CreateByRegion( const POLYLINEVECTOR& vPL) override ; - bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ; + bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr) override ; 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 ; diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index e1b835f..ba0c1fa 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -1585,7 +1585,6 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c Vector3d vtDirTip = ptP2T - ptP1T ; bool bTopIsPivot = vtDirTop.IsSmall() ; bool bTipIsPivot = vtDirTip.IsSmall() ; - bool bTopAndTipAreEquiverse = vtDirTop * vtDirTip > 0 ; // box dell'intero volume spazzato, nel riferimento object oriented BBox3d bbVol ; From 2023ba3f7d52de63f4970cc0f305e588d1543a7f Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 6 Feb 2026 17:28:28 +0100 Subject: [PATCH 04/22] EgtGeomKernel : - modifica all'approssimazione delle curve tramite bezier. --- CurveAux.cpp | 110 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 26 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index ede91d4..7831265 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -34,7 +34,9 @@ #include "/EgtDev/Extern/Eigen/Dense" #define SAVEAPPROX 0 -#if SAVEAPPROX +#define SAVECURVEPASSED 0 +#define SAVELINEARAPPROX 0 +#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX #include "/EgtDev/Include/EGkGeoObjSave.h" #endif @@ -533,7 +535,8 @@ LineToBezierCurve( const ICurveLine* pCrvLine, int nDeg, bool bMakeRatOrNot) PtrOwner pCrvBezier( CreateCurveBezier()) ; // rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali pCrvBezier->Init( nDeg, true) ; - pCrvBezier->FromLine( *pCrvLine) ; + if( ! pCrvBezier->FromLine( *pCrvLine)) + return nullptr ; if ( bMakeRatOrNot) pCrvBezier->MakeRational() ; return Release( pCrvBezier) ; @@ -1455,19 +1458,12 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, co mX(1) += A2 * tmp ; } mA = mC.fullPivLu().solve(mX) ; - - double C00 = mC(0,0) ; - double C01 = mC(0,1) ; - double C10 = mC(1,0) ; - double C11 = mC(1,1) ; - - double X0 = mX(0) ; - double X1 = mX(1) ; } // l'algoritmo è fatto in modo che alpha1 e alpha2 siano positivi ( se tutto va bene) // io invece ho tenuto le tangenti con la direzione originale, quindi il primo dovrebbe essere positivo e il secondo negativo if ( mA(0) < 0 || mA(1) > 0 || nPoints < 4) { - LOG_DBG_ERR( GetEGkLogger(), "valori di alfa sballati, potrebbe essere la spaziatura dismogenea tra punti, oppure solo la curva da spezzare") + if( mA(0) < 0 || mA(1) > 0) + LOG_DBG_ERR( GetEGkLogger(), "valori di alfa sballati, potrebbe essere la spaziatura dismogenea tra punti") double dDistCorr = Dist( pt3, pt0) / 3 ; mA(0) = dDistCorr ; mA(1) = - dDistCorr ; @@ -1539,50 +1535,105 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nPointMaxErr = 0 ; CalcPointSetApproxError( vPnt, vParam, nFirst, nLast, pCrvBez, dErr, nPointMaxErr) ; - if ( dErr < dTol) { - // verifico anche più finemente - int nCheckPoints = (nLast - nFirst) * 2 ; - CalcApproxError( pCrvOrig->CopyParamRange( nFirst, nLast), pCrvBez, dErr, nCheckPoints) ; + // se sto unendo due punti consecutivi e l'errore è oltre quello richiesto allora restituisco un segmento che unisce i punti + if( nLast - nFirst == 1 && dErr > dTol) { + CurveLine CL ; CL.Set( vPnt[nFirst], vPnt[nLast]) ; + pCrvBez.Set( GetCurveBezier( CurveToBezierCurve( &CL))) ; + dErr = 0 ; } + ++nIter ; bool bSplit = false ; if( nIter == 10 && dErr > dTol) bSplit = true ; // se la curva di approssimazione è ancora molto lontana dalla curva originale allora divido il set di punti in due if ( dErr > dErrSplit || bSplit) { - if( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol)) || - ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol))) + if ( nLast - nFirst > 1) { + if( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol)) || + ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol))) + return nullptr ; + break ; + } + else return nullptr ; - break ; } } if ( pCrvFit->GetCurveCount() > 0) return Release( pCrvFit) ; - else if ( dErr < dTol) + else if ( dErr < dTol && ! IsNull( pCrvBez) && pCrvBez->IsValid()) return Release( pCrvBez) ; else return nullptr ; } +static int nCrvPassed = 0 ; + //---------------------------------------------------------------------------- ICurve* ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) { + +#if SAVECURVEPASSED + SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\CurveDaApprossimare\\"+ToString(nCrvPassed) + ".nge") ; + ++nCrvPassed ; +#endif + //// uso l'algoritmo di Schneider in Grafic Gems I // mi aspetto che non ci siano angoli ( discontinuità della derivata prima) nel risultato desiderato PolyLine plApprox ; - double dAngTolFine = 2 ; - pCrv->ApproxWithLines( dTol, dAngTolFine, ICurve::APL_STD, plApprox) ; + double dAngTolFine = 1 ; + double dLinTolFine = 0.05 ; + pCrv->ApproxWithLines( dLinTolFine, dAngTolFine, ICurve::APL_STD, plApprox) ; + +#if SAVELINEARAPPROX + CurveComposite CC ; CC.FromPolyLine(plApprox) ; + SaveGeoObj( CC.Clone(), "D:\\Temp\\bezier\\approxWithBezier\\approssimazione_lineare.nge") ; +#endif CurveByInterp cbi ; PNTVECTOR vPnt ; Point3d pt ; plApprox.GetFirstPoint( pt) ; do { + if ( ssize(vPnt) != 0) { + vPnt.push_back( Media(vPnt.back(), pt,1./3.)) ; + vPnt.push_back( Media(vPnt.back(), pt,2./3.)) ; + } vPnt.push_back( pt) ; cbi.AddPoint( pt) ; } while ( plApprox.GetNextPoint( pt)) ; + // calcolo la curvatura nei vari punti per identificare zone a curvatura costante + DBLVECTOR vCrvVal( ssize(vPnt)) ; + DBLVECTOR vRad ( ssize( vPnt)) ; + for( int i = 1 ; i < ssize( vPnt) - 1 ; ++i) { + Vector3d vtA = vPnt[i] - vPnt[i-1] ; + Vector3d vtB = vPnt[i+1] - vPnt[i-1] ; + double dR = ( vtA.Len() * vtB.Len() * ( vtA - vtB).Len()) / ( 2 * (vtA ^ vtB).Len()) ; + double dCurvature = dR > 0 ? 1. / dR : 0 ; + vRad[i] = dR ; + vCrvVal[i] = dCurvature ; + } + vCrvVal[0] = vCrvVal[1] ; + vCrvVal.back() = vCrvVal.end()[-2] ; + // identifico le zone a curvatura costante // primo e ultimo punto degli intervalli non devono avere curvatura uguale agli altri perché sono di frontiera + INTINTVECTOR vConstCurv ; + double dCurvaturePrec = vCrvVal[0] ; + int nStart = 0 ; + int nEnd = 1 ; + while ( nStart < ssize( vPnt) - 1) { + dCurvaturePrec = vCrvVal[nEnd] ; + while ( nEnd < ssize( vPnt) - 1 && abs( vCrvVal[nEnd] - dCurvaturePrec) < 0.1) { + dCurvaturePrec = vCrvVal[nEnd] ; + ++nEnd ; + } + vConstCurv.emplace_back( nStart, nEnd) ; + nStart = nEnd ; + ++nEnd ; + } + if( ssize(vConstCurv) == 0) + vConstCurv.emplace_back( 0, ssize( vPnt) - 1) ; + int nPoints = ssize( vPnt) ; DBLVECTOR vParam( nPoints) ; int nFirst = 0 ; @@ -1598,12 +1649,19 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) vNextDer[i].Normalize() ; } - //definisco la bezier che vado a raffinare iterativamente - PtrOwner pCApprox( FitWithBezier( pCrv, vPnt, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol)) ; - if( IsNull( pCApprox) || ! pCApprox->IsValid()) - return nullptr ; + PtrOwner pCCApproxTot( CreateCurveComposite()) ; + for( INTINT iiSE : vConstCurv) { + nFirst = iiSE.first ; + nLast = iiSE.second ; + //definisco la bezier che vado a raffinare iterativamente + PtrOwner pCApprox( FitWithBezier( pCrv, vPnt, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol)) ; + if( IsNull( pCApprox) || ! pCApprox->IsValid()) + return nullptr ; + if( ! pCCApproxTot->AddCurve( Release( pCApprox))) + return nullptr ; + } - return Release( pCApprox) ; + return Release( pCCApproxTot) ; } //---------------------------------------------------------------------------- From ec6eb3e645d10e4e8328eee4a983484c1bfe5de7 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 9 Feb 2026 08:24:16 +0100 Subject: [PATCH 05/22] EgtGeomKernel : - modifica a Trimming - sistemazioni estetiche varie. --- CurveAux.cpp | 129 +++++++------- DistPointCrvBezier.cpp | 2 +- DistPointSurfBz.cpp | 21 +-- IntersCurveCurve.cpp | 10 +- ProjectCurveSurf.cpp | 151 +++++++++++------ SurfBezier.cpp | 167 ++++++++++--------- SurfBezier.h | 4 +- Tool.h | 20 +-- Tree.cpp | 39 +++-- Tree.h | 43 +++-- Trimming.cpp | 371 ++++++++++++++++++++--------------------- VolZmapVolume.cpp | 6 +- 12 files changed, 504 insertions(+), 459 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index 7831265..509158f 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -535,7 +535,7 @@ LineToBezierCurve( const ICurveLine* pCrvLine, int nDeg, bool bMakeRatOrNot) PtrOwner pCrvBezier( CreateCurveBezier()) ; // rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali pCrvBezier->Init( nDeg, true) ; - if( ! pCrvBezier->FromLine( *pCrvLine)) + if ( ! pCrvBezier->FromLine( *pCrvLine)) return nullptr ; if ( bMakeRatOrNot) pCrvBezier->MakeRational() ; @@ -1147,7 +1147,7 @@ FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan) return true ; } // trovo a quale span appartiene il parametro dU - int nKnots = int( vKnots.size()) ; + int nKnots = ssize( vKnots) ; if ( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) { nSpan = nKnots - 1 - nDeg ; return true ; @@ -1173,7 +1173,7 @@ static bool CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis) { // mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1 - if ( vBasis.size() != nDeg + 1) + if ( ssize( vBasis) != nDeg + 1) return false ; vBasis[0] = 1 ; @@ -1312,7 +1312,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa int nItCount = 0 ; while ( dErr > dLinTol && nItCount < 10) { pCrvInt->Clear() ; - int nPoints = int( vPnt.size()) ; + int nPoints = ssize( vPnt) ; int nDeg = 3 ; if ( nPoints < 2) return nullptr ; @@ -1328,7 +1328,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa else if ( nPoints == 3) { // se ho solo tre punti uso un altro algoritmo CurveByInterp cbi ; - for ( int i = 0 ; i < int( vPnt.size()) ; ++i) + for ( int i = 0 ; i < ssize( vPnt) ; ++i) cbi.AddPoint( vPnt[i]) ; pCrvInt->AddCurve( cbi.GetCurve( CurveByInterp::AKIMA_CORNER, CurveByInterp::CUBIC_BEZIERS)) ; if ( ! IsNull( pCrvInt) && pCrvInt->IsValid()) @@ -1360,7 +1360,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa } } - if ( vLen.size() != 0) { + if ( ! vLen.empty()) { if ( nEnd == 0) nEnd = nPoints - 1 ; Vector3d vtStartDir = V_INVALID ; @@ -1402,9 +1402,9 @@ ParamByLen( const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast) int nPoints = nLast - nFirst + 1 ; if ( nPoints < 2) return false ; - if( ssize(vParam) == 0) + if ( vParam.empty()) vParam.resize( nPoints) ; - if( vParam[nFirst] == 0 && vParam[nLast] == 1) + if ( vParam[nFirst] == 0 && vParam[nLast] == 1) return true ; vParam[nFirst] = 0 ; for ( int i = nFirst + 1 ; i <= nLast ; ++i) { @@ -1420,8 +1420,8 @@ ParamByLen( const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast) //---------------------------------------------------------------------------- ICurveBezier* -ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, const Vector3d& vtStartDir, const Vector3d& vtEndDir, - const DBLVECTOR& vParam) +ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, + const Vector3d& vtStartDir, const Vector3d& vtEndDir, const DBLVECTOR& vParam) { // cerco di approssimare un set di punti con una sola bezier cubica non razionale int nPoints = nLast - nFirst + 1 ; @@ -1435,7 +1435,7 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, co pCrvBez->SetControlPoint( 0, pt0) ; pCrvBez->SetControlPoint( 3, pt3) ; Eigen::Vector2d mA ; - if( nPoints > 4) { + if ( nPoints > 4) { // risoluzione sistema Eigen::Matrix2d mC ; mC.setZero() ; Eigen::Vector2d mX ; mX.setZero() ; @@ -1461,8 +1461,8 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, co } // l'algoritmo è fatto in modo che alpha1 e alpha2 siano positivi ( se tutto va bene) // io invece ho tenuto le tangenti con la direzione originale, quindi il primo dovrebbe essere positivo e il secondo negativo - if ( mA(0) < 0 || mA(1) > 0 || nPoints < 4) { - if( mA(0) < 0 || mA(1) > 0) + if ( mA(0) < 0 || mA(1) > 0 || nPoints < 4) { + if ( mA(0) < 0 || mA(1) > 0) LOG_DBG_ERR( GetEGkLogger(), "valori di alfa sballati, potrebbe essere la spaziatura dismogenea tra punti") double dDistCorr = Dist( pt3, pt0) / 3 ; mA(0) = dDistCorr ; @@ -1480,14 +1480,15 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, co //---------------------------------------------------------------------------- bool -CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam, int nFirst, int nLast, const ICurve* pCrvNew, double& dErr, int& nPointMaxErr) +CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam, + int nFirst, int nLast, const ICurve* pCrvNew, double& dErr, int& nPointMaxErr) { dErr = 0 ; // calcolo l'errore di approssimazione for ( int i = nFirst ; i <= nLast ; ++i) { Point3d ptBez ; pCrvNew->GetPointD1D2( vParam[i], ICurve::Side::FROM_MINUS, ptBez) ; double dErrTemp = Dist( vPntOrig[i], ptBez) ; - if( dErrTemp > dErr) { + if ( dErrTemp > dErr) { dErr = dErrTemp ; nPointMaxErr = i ; } @@ -1498,19 +1499,20 @@ CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam, int //---------------------------------------------------------------------------- ICurve* -FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, double dTol) +FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, + int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, double dTol) { - ParamByLen(vPnt, vParam, nFirst, nLast) ; + ParamByLen( vPnt, vParam, nFirst, nLast) ; PtrOwner pCrvFit( CreateCurveComposite()) ; PtrOwner pCrvBez( CreateCurveBezier()) ; double dErr = INFINITO ; double dErrSplit = dTol * 25 ; int nIter = 0 ; - while ( dErr > dTol && nIter < 10) { - if( dErr < INFINITO) { - // riparametrizzo i punti + while ( dErr > dTol && nIter < 10) { + if ( dErr < INFINITO) { + // riparametrizzo i punti for ( int i = nFirst + 1 ; i < nLast ; ++i) { - //questo potrebbe diventare un while appena capisco di quanto si aggiusta il parametro ad ogni iterazione + // questo potrebbe diventare un while appena capisco di quanto si aggiusta il parametro ad ogni iterazione double dCorr = 1 ; do { Vector3d vtDer1, vtDer2 ; @@ -1525,9 +1527,9 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, } } - // fit della curva + // fit della curva pCrvBez.Set( ApproxPointSetWithSingleBezier( vPnt, nFirst, nLast, vNextDer[nFirst], vPrevDer[nLast], vParam)) ; - if( IsNull( pCrvBez) || ! pCrvBez->IsValid()) + if ( IsNull( pCrvBez) || ! pCrvBez->IsValid()) return nullptr ; #if SAVEAPPROX SaveGeoObj( pCrvBez->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\first_approx.nge") ; @@ -1535,8 +1537,8 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nPointMaxErr = 0 ; CalcPointSetApproxError( vPnt, vParam, nFirst, nLast, pCrvBez, dErr, nPointMaxErr) ; - // se sto unendo due punti consecutivi e l'errore è oltre quello richiesto allora restituisco un segmento che unisce i punti - if( nLast - nFirst == 1 && dErr > dTol) { + // se sto unendo due punti consecutivi e l'errore è oltre quello richiesto allora restituisco un segmento che unisce i punti + if ( nLast - nFirst == 1 && dErr > dTol) { CurveLine CL ; CL.Set( vPnt[nFirst], vPnt[nLast]) ; pCrvBez.Set( GetCurveBezier( CurveToBezierCurve( &CL))) ; dErr = 0 ; @@ -1544,12 +1546,12 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, ++nIter ; bool bSplit = false ; - if( nIter == 10 && dErr > dTol) + if ( nIter == 10 && dErr > dTol) bSplit = true ; - // se la curva di approssimazione è ancora molto lontana dalla curva originale allora divido il set di punti in due - if ( dErr > dErrSplit || bSplit) { + // se la curva di approssimazione è ancora molto lontana dalla curva originale allora divido il set di punti in due + if ( dErr > dErrSplit || bSplit) { if ( nLast - nFirst > 1) { - if( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol)) || + if ( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol)) || ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol))) return nullptr ; break ; @@ -1561,20 +1563,19 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, if ( pCrvFit->GetCurveCount() > 0) return Release( pCrvFit) ; - else if ( dErr < dTol && ! IsNull( pCrvBez) && pCrvBez->IsValid()) + else if ( dErr < dTol && ! IsNull( pCrvBez) && pCrvBez->IsValid()) return Release( pCrvBez) ; else return nullptr ; } -static int nCrvPassed = 0 ; - //---------------------------------------------------------------------------- ICurve* ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) { #if SAVECURVEPASSED + static int nCrvPassed = 0 ; SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\CurveDaApprossimare\\"+ToString(nCrvPassed) + ".nge") ; ++nCrvPassed ; #endif @@ -1595,7 +1596,7 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) PNTVECTOR vPnt ; Point3d pt ; plApprox.GetFirstPoint( pt) ; do { - if ( ssize(vPnt) != 0) { + if ( ! vPnt.empty()) { vPnt.push_back( Media(vPnt.back(), pt,1./3.)) ; vPnt.push_back( Media(vPnt.back(), pt,2./3.)) ; } @@ -1604,9 +1605,9 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) } while ( plApprox.GetNextPoint( pt)) ; // calcolo la curvatura nei vari punti per identificare zone a curvatura costante - DBLVECTOR vCrvVal( ssize(vPnt)) ; + DBLVECTOR vCrvVal( ssize( vPnt)) ; DBLVECTOR vRad ( ssize( vPnt)) ; - for( int i = 1 ; i < ssize( vPnt) - 1 ; ++i) { + for ( int i = 1 ; i < ssize( vPnt) - 1 ; ++i) { Vector3d vtA = vPnt[i] - vPnt[i-1] ; Vector3d vtB = vPnt[i+1] - vPnt[i-1] ; double dR = ( vtA.Len() * vtB.Len() * ( vtA - vtB).Len()) / ( 2 * (vtA ^ vtB).Len()) ; @@ -1631,7 +1632,7 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) nStart = nEnd ; ++nEnd ; } - if( ssize(vConstCurv) == 0) + if ( vConstCurv.empty()) vConstCurv.emplace_back( 0, ssize( vPnt) - 1) ; int nPoints = ssize( vPnt) ; @@ -1644,20 +1645,20 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) VCT3DVECTOR vNextDer ; ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ; //normalizzo tutte le derivate - for( int i = 0 ; i < ssize( vPrevDer) ; ++i) { + for ( int i = 0 ; i < ssize( vPrevDer) ; ++i) { vPrevDer[i].Normalize() ; vNextDer[i].Normalize() ; } PtrOwner pCCApproxTot( CreateCurveComposite()) ; - for( INTINT iiSE : vConstCurv) { + for ( INTINT iiSE : vConstCurv) { nFirst = iiSE.first ; nLast = iiSE.second ; //definisco la bezier che vado a raffinare iterativamente PtrOwner pCApprox( FitWithBezier( pCrv, vPnt, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol)) ; - if( IsNull( pCApprox) || ! pCApprox->IsValid()) + if ( IsNull( pCApprox) || ! pCApprox->IsValid()) return nullptr ; - if( ! pCCApproxTot->AddCurve( Release( pCApprox))) + if ( ! pCCApproxTot->AddCurve( Release( pCApprox))) return nullptr ; } @@ -1668,7 +1669,7 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) bool CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int nPoints) { - if( pCrvOri == nullptr || ! pCrvOri->IsValid() || pCrvNew == nullptr || ! pCrvNew->IsValid()){ + if ( pCrvOri == nullptr || ! pCrvOri->IsValid() || pCrvNew == nullptr || ! pCrvNew->IsValid()){ dErr = INFINITO ; return false ; } @@ -1753,7 +1754,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) { // se con nodi extra if ( cnData.bExtraKnotes) { - int nKnotesNbr = int( cnData.vU.size()) ; + int nKnotesNbr = ssize( cnData.vU) ; if ( nKnotesNbr < 4) return false ; cnData.bExtraKnotes = false ; @@ -1767,7 +1768,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) bool bAlreadyChecked = false ; // se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva // wrap della curva su se stessa - if ( cnData.bPeriodic && (int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1)) { + if ( cnData.bPeriodic && ( ssize( cnData.vU) > ssize( cnData.vCP) + cnData.nDeg - 1)) { bool bRepeated = true ; for ( int i = 0 ; i < cnData.nDeg ; ++i) { if ( ! AreSamePointApprox( cnData.vCP[i], cnData.vCP.end()[-cnData.nDeg + i]) ) { @@ -1776,11 +1777,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData) } } bool bFirstAddedAtEnd = false ; - if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){ + if ( ! bRepeated || ( bRepeated && AreSamePointApprox( cnData.vCP[0], cnData.vCP[cnData.nDeg]))) { // salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped DBLVECTOR vU = cnData.vU ; // se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo - if ( int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1 ) { + if ( ssize( cnData.vU) > ssize( cnData.vCP) + cnData.nDeg - 1 ) { // se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) { bFirstAddedAtEnd = true ; @@ -1792,11 +1793,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData) cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ; // controllo eventualmente anche i nodi extra // se ne ho due in più ne tolgo uno in cima e uno in fondo - if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere + if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg + 1) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; } // se ne ho solo uno in più lo tolgo in cima - else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) { + else if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg) { cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end()) ; } } @@ -1823,7 +1824,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // recupero il vettore dei nodi cnData.vU = vU ; // verifico se ho nodi extra - if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { + if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg + 1 ) { // significa che ci sono due nodi extra: // se la curva ha grado maggiore di 1 e i primi due nodi sono uguali allora tolgo quelli if ( cnData.nDeg > 1 && abs(cnData.vU[1] - cnData.vU[0]) < EPS_SMALL) { @@ -1834,7 +1835,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end() - 1) ; } // se ne ho solo uno in più lo tolgo in cima - else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) + else if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg) cnData.vU = vector( cnData.vU.begin() + 1, cnData.vU.end()) ; } bAlreadyChecked = true ; @@ -1859,7 +1860,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // qui aggiungo un controllo se la curva è collassata in un punto ( ho un polo), lascio stare bool bCollapsed = true ; Point3d ptFirst = cnData.vCP.front() ; - for ( int i = 1 ; i < int( cnData.vCP.size()) ; ++i) { + for ( int i = 1 ; i < ssize( cnData.vCP) ; ++i) { if ( ! AreSamePointApprox( ptFirst, cnData.vCP[i])) { bCollapsed = false ; break ; @@ -1876,7 +1877,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData) // agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p // comincio ad aumentare la molteplictià del nodo u_m-p+1 - int nCP = int( cnData.vCP.size()) ; + int nCP = ssize( cnData.vCP) ; int nU = nCP + cnData.nDeg - 1 ; int nDeg = cnData.nDeg ; PNTVECTOR vBC ; @@ -2072,9 +2073,9 @@ NurbsToBezierCurve( const CNurbsData& cnData) if ( cnData.bPeriodic || cnData.bExtraKnotes) return nullptr ; // numero dei nodi - int nU = int( cnData.vCP.size()) + cnData.nDeg - 1 ; + int nU = ssize( cnData.vCP) + cnData.nDeg - 1 ; // controllo relazione nodi - punti di controllo - if ( nU != int( cnData.vU.size())) + if ( nU != ssize( cnData.vU)) return nullptr ; // numero degli intervalli int nInt = nU - 2 * cnData.nDeg + 1 ; @@ -2444,7 +2445,7 @@ CalcCurvesVoronoiDiagram( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, in PtrOwner pVoronoiObj( new( std::nothrow) Voronoi()) ; if ( pVoronoiObj == nullptr) return false ; - for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) { + for ( int i = 0 ; i < ssize( vCrvC) ; i ++) { if ( ! pVoronoiObj->AddCurve( vCrvC[i])) return false ; } @@ -2471,7 +2472,7 @@ CalcCurvesMedialAxis( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, int nS PtrOwner pVoronoiObj( new( std::nothrow) Voronoi()) ; if ( pVoronoiObj == nullptr) return false ; - for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) { + for ( int i = 0 ; i < ssize( vCrvC) ; i ++) { if ( ! pVoronoiObj->AddCurve( vCrvC[i])) return false ; } @@ -2532,7 +2533,7 @@ bool CalcOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, doubl PtrOwner pVoronoiObj( new( std::nothrow) Voronoi()) ; if ( pVoronoiObj == nullptr) return false ; - for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) { + for ( int i = 0 ; i < ssize( vpCrvs) ; i ++) { if ( ! pVoronoiObj->AddCurve( vpCrvs[i])) return false ; } @@ -2562,7 +2563,7 @@ bool CalcFatOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, do PtrOwner pVoronoiObj( new( std::nothrow) Voronoi()) ; if ( pVoronoiObj == nullptr) return false ; - for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) { + for ( int i = 0 ; i < ssize( vpCrvs) ; i ++) { if ( ! pVoronoiObj->AddCurve( vpCrvs[i])) return false ; } @@ -2596,7 +2597,7 @@ ResetCurveVoronoi( const ICurve& crvC) bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) { - if( ssize( vCrv) == 1) + if ( ssize( vCrv) == 1) return true ; ChainCurves chainCrv ; // modifico direttamente le curve passate in input @@ -2616,22 +2617,22 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ICurveComposite* pFirstCrv = vCrv[abs(vIds[0]) - 1] ; for ( int nId : vIds) { bool bInvert = false ; - if( nId < 0) + if ( nId < 0) bInvert = true ; nId = abs( nId) - 1 ; - if( bInvert) + if ( bInvert) vCrv[nId]->Invert() ; - if( ! pFirstCrv->AddCurve( Release( vCrv[nId]), true, dChainTol)) + if ( ! pFirstCrv->AddCurve( Release( vCrv[nId]), true, dChainTol)) return false ; } pFirstCrv->GetEndPoint( ptStart) ; } // elimino gli elementi del vettore che non contengono più curve int c = ssize( vCrv) ; - while( c > -1) { - if( IsNull( vCrv[c])) + while ( c > -1) { + if ( IsNull( vCrv[c])) vCrv.erase( vCrv.begin() + c) ; --c ; } return true ; -} \ No newline at end of file +} diff --git a/DistPointCrvBezier.cpp b/DistPointCrvBezier.cpp index 693d405..9c324a5 100644 --- a/DistPointCrvBezier.cpp +++ b/DistPointCrvBezier.cpp @@ -26,7 +26,7 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier& // distanza non calcolata m_dDist = - 1 ; - if ( &CrvBez == nullptr || ! CrvBez.IsValid()) + if ( ! CrvBez.IsValid()) return ; // determino tolleranza di approssimazione in base a ingombro curva diff --git a/DistPointSurfBz.cpp b/DistPointSurfBz.cpp index 81f6f17..f9107d5 100644 --- a/DistPointSurfBz.cpp +++ b/DistPointSurfBz.cpp @@ -23,10 +23,10 @@ using namespace std ; //---------------------------------------------------------------------------- DistPointSurfBz::DistPointSurfBz( const Point3d& ptP, const ISurfBezier& pSrfBz) - : m_dDist( -1), m_bIsInside( false) + : m_dDist( -1), m_bIsInside( false), m_bIsSurfClosed( false) { // Bezier non valida - if ( &pSrfBz == nullptr || ! pSrfBz.IsValid()) + if ( ! pSrfBz.IsValid()) return ; // Calcolo la distanza Calculate( ptP, pSrfBz) ; @@ -37,9 +37,9 @@ void DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz) { // Inizializzo distanza non calcolata - m_dDist = - 1. ; + m_dDist = -1 ; - // Controllo se la superficie è chiusa + // Controllo se la superficie è chiusa m_bIsSurfClosed = srfBz.IsClosed() ; // Lavoro con l'oggetto superficie trimesh di base @@ -49,17 +49,17 @@ DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz) DistPointSurfTm dpst( ptP, *pStmRef) ; - //recupero il punto a distanza minima sulla trimesh e lo raffino, prima di restituire distanza e punto minimo + // recupero il punto a distanza minima sulla trimesh e lo raffino, prima di restituire distanza e punto minimo Point3d ptMinTm ; dpst.GetMinDistPoint( ptMinTm) ; int nT ; dpst.GetMinDistTriaIndex( nT) ; - //salvo il punto corrispondente nel parametrico + // salvo il punto corrispondente nel parametrico srfBz.UnprojectPointFromStm( nT, ptMinTm, m_ptParam) ; // salvo il punto a minima distanza sulla superficie e la normale alla superficie in quel punto srfBz.GetPointNrmD1D2( m_ptParam.x, m_ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, m_ptMinDistPoint, m_vtN) ; // salvo la distanza minima m_dDist = Dist( ptP, m_ptMinDistPoint) ; - // se il punto è sulla superficie + // se il punto è sulla superficie if ( m_dDist < EPS_SMALL) { m_bIsInside = false ; return ; @@ -96,13 +96,14 @@ DistPointSurfBz::GetMinDistPoint( Point3d& ptMinDistPoint) const //---------------------------------------------------------------------------- bool -DistPointSurfBz::GetParamPoint( Point3d& ptParamPoint) const +DistPointSurfBz::GetParamsAtMinDistPoint( double& dU, double& dV) const { // Distanza non valida if ( m_dDist < -EPS_ZERO) return false ; // Distanza valida - ptParamPoint = m_ptParam ; + dU = m_ptParam.x ; + dV = m_ptParam.y ; return true ; } @@ -116,4 +117,4 @@ DistPointSurfBz::GetNorm( Vector3d& vtN) const // Distanza valida vtN = m_vtN ; return true ; -} \ No newline at end of file +} diff --git a/IntersCurveCurve.cpp b/IntersCurveCurve.cpp index 7aa10d5..d28a668 100644 --- a/IntersCurveCurve.cpp +++ b/IntersCurveCurve.cpp @@ -296,8 +296,8 @@ int IntersCurveCurve::GetInters3DCount( void) { int nCount = 0 ; - for( int i = 0 ; i < m_nIntersCount ; ++i) { - if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) { + for ( int i = 0 ; i < m_nIntersCount ; ++i) { + if ( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) { if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL) ++nCount ; } @@ -365,8 +365,8 @@ IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo) if ( nInd < 0 || nInd >= GetInters3DCount()) return false ; int nCount = - 1 ; - for( int i = 0 ; i < m_nIntersCount ; ++i) { - if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) { + for ( int i = 0 ; i < m_nIntersCount ; ++i) { + if ( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) { if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL) ++nCount ; } @@ -374,7 +374,7 @@ IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo) if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL) ++nCount ; } - if( nCount == nInd) { + if ( nCount == nInd) { aInfo = m_Info[nInd] ; return true ; } diff --git a/ProjectCurveSurf.cpp b/ProjectCurveSurf.cpp index 821d91d..6c189f7 100644 --- a/ProjectCurveSurf.cpp +++ b/ProjectCurveSurf.cpp @@ -19,6 +19,7 @@ #include "/EgtDev/Include/EGkDistPointLine.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkDistPointSurfTm.h" +#include "/EgtDev/Include/EGkDistPointSurfBz.h" #include "/EgtDev/Include/EGkIntersPlanePlane.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h" @@ -92,6 +93,8 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax) Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ; Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ; Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ; + Pt5ax.vtDirU = vPt5ax[j].vtDirU ; + Pt5ax.vtDirV = vPt5ax[j].vtDirV ; Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; Pt5ax.nFlag = P5AX_CVEX ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; @@ -104,6 +107,8 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax) Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ; Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ; Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ; + Pt5ax.vtDirU = vPt5ax[i].vtDirU ; + Pt5ax.vtDirV = vPt5ax[i].vtDirV ; Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; Pt5ax.nFlag = P5AX_CVEX ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; @@ -118,6 +123,8 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax) Pt5ax.ptP = ptInt ; Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; Pt5ax.vtDir1.Normalize() ; Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; Pt5ax.vtDir2.Normalize() ; + Pt5ax.vtDirU = Media( vPt5ax[i].vtDirU, vPt5ax[j].vtDirU) ; Pt5ax.vtDirU.Normalize() ; + Pt5ax.vtDirV = Media( vPt5ax[i].vtDirV, vPt5ax[j].vtDirV) ; Pt5ax.vtDirV.Normalize() ; Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ; Pt5ax.nFlag = P5AX_CONC ; vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ; @@ -233,23 +240,55 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen, } //---------------------------------------------------------------------------- -static bool -ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar, Point5ax& Pt5ax) +static const SurfTriMesh* +MyGetAuxSurf( const ISurf* pSrf) { - // punto sulle supefici a minima distanza + if ( pSrf == nullptr) + return nullptr ; + switch ( pSrf->GetType()) { + case SRF_TRIMESH : + return GetBasicSurfTriMesh( pSrf) ; + case SRF_FLATRGN : + return GetBasicSurfFlatRegion( pSrf)->GetAuxSurf() ; + case SRF_BEZIER : + return GetBasicSurfBezier( pSrf)->GetAuxSurf() ; + default : + return nullptr ; + } +} + +//---------------------------------------------------------------------------- +static bool +ProjectPointOnSurf( const Point3d& ptP, const CISURFPVECTOR& vpSurf, double dPar, Point5ax& Pt5ax) +{ + // punto sulle superfici a minima distanza int nSurfMin = -1 ; - int nTriaMin ; + int nTriaMin = -1 ; + double dUMin = -1, dVMin = -1 ; Point3d ptMin ; - double dMinDist ; - for ( int i = 0 ; i < ssize( vpStm) ; ++ i) { + double dMinDist = NAN ; + for ( int i = 0 ; i < ssize( vpSurf) ; ++ 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 ; + int nSrfType = ( vpSurf[i] != nullptr ? vpSurf[i]->GetType() : GEO_NONE) ; + if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) { + DistPointSurfTm dPS( ptP, *MyGetAuxSurf( vpSurf[i])) ; + double dDist ; + if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) { + nSurfMin = i ; + dPS.GetMinDistPoint( ptMin) ; + dPS.GetMinDistTriaIndex ( nTriaMin) ; + dMinDist = dDist ; + } + } + else if ( nSrfType == SRF_BEZIER) { + DistPointSurfBz dPS( ptP, *GetBasicSurfBezier( vpSurf[i])) ; + double dDist ; + if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) { + nSurfMin = i ; + dPS.GetMinDistPoint( ptMin) ; + dPS.GetParamsAtMinDistPoint( dUMin, dVMin) ; + dMinDist = dDist ; + } } } @@ -257,19 +296,44 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar 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 ; + // calcolo gli altri dati + int nSrfType = ( vpSurf[nSurfMin] != nullptr ? vpSurf[nSurfMin]->GetType() : GEO_NONE) ; + if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) { + // recupero superficie trimesh + const SurfTriMesh* pSurfTm = MyGetAuxSurf( vpSurf[nSurfMin]) ; + // calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo) + Triangle3dEx trTria ; + if ( ! pSurfTm->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.vtDirU = V_NULL ; + Pt5ax.vtDirV = V_NULL ; + Pt5ax.dPar = dPar ; + Pt5ax.nFlag = P5AX_STD ; + } + else if ( nSrfType == SRF_BEZIER) { + Point3d ptSB ; + Vector3d vtN, vtDerU, vtDerV ; + if ( ! GetBasicSurfBezier( vpSurf[nSurfMin])->GetPointNrmD1D2( dUMin, dVMin, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, + ptSB, vtN, &vtDerU, &vtDerV)) + return false ; + vtDerU.Normalize() ; + vtDerV.Normalize() ; + // assegno valori al punto 5assi + Pt5ax.ptP = ptInt ; + Pt5ax.vtDir1 = vtN ; + Pt5ax.vtDir2 = vtN ; + Pt5ax.vtDirU = vtDerU ; + Pt5ax.vtDirV = vtDerV ; + Pt5ax.dPar = dPar ; + Pt5ax.nFlag = P5AX_STD ; + } // ritorno con successo return true ; } @@ -282,31 +346,6 @@ 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) ; @@ -331,7 +370,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, while ( bFound) { // se trovo proiezione, la salvo Point5ax Pt5ax ; - if ( ProjectPointOnSurf( ptP, vpSurfTm, dPar, Pt5ax)) + if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax)) vPt5ax.emplace_back( Pt5ax) ; // passo al successivo bFound = PL.GetNextUPoint( &dPar, &ptP) ; @@ -403,6 +442,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame Pt5ax.ptP = ptInt ; Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir2 = frRefLine.VersZ() ; + Pt5ax.vtDirU = V_NULL ; + Pt5ax.vtDirV = V_NULL ; Pt5ax.dPar = dPar ; Pt5ax.nFlag = P5AX_STD ; // ritorno con successo @@ -557,6 +598,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP Pt5ax.ptP = ptInt ; Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir2 = vtLine ; + Pt5ax.vtDirU = V_NULL ; + Pt5ax.vtDirV = V_NULL ; Pt5ax.dPar = dPar ; Pt5ax.nFlag = P5AX_STD ; // ritorno con successo @@ -696,6 +739,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv Pt5ax.ptP = ptInt ; Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir2 = vtLine ; + Pt5ax.vtDirU = V_NULL ; + Pt5ax.vtDirV = V_NULL ; Pt5ax.dPar = dPar ; Pt5ax.nFlag = P5AX_STD ; // ritorno con successo @@ -852,6 +897,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT Pt5ax.ptP = ptInt ; Pt5ax.vtDir1 = vtN ; Pt5ax.vtDir2 = vtN2 ; + Pt5ax.vtDirU = V_NULL ; + Pt5ax.vtDirV = V_NULL ; Pt5ax.dPar = dPar ; Pt5ax.nFlag = P5AX_STD ; // ritorno con successo diff --git a/SurfBezier.cpp b/SurfBezier.cpp index a553d44..479eb5c 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -877,7 +877,7 @@ SurfBezier::CopyFrom( const SurfBezier& sbSrc) m_pTrimReg = sbSrc.m_pTrimReg->Clone() ; } #ifndef SAVEFAILEDTRIANGULATION - if( sbSrc.GetAuxSurf() != nullptr) + if ( sbSrc.GetAuxSurf() != nullptr) m_pSTM = sbSrc.GetAuxSurf()->Clone() ; #endif for ( int i = 0 ; i < int( sbSrc.m_mCCEdge.size()) ; ++i) { @@ -1075,7 +1075,7 @@ SurfBezier::Load( NgeReader& ngeIn) ICURVEPOVECTOR vCrv ; GetAllPatchesIsocurves( false, vCrv) ; vector vGeo ; - for( int i = 0 ; i < ssize(vCrv) ; ++i) + for ( int i = 0 ; i < ssize(vCrv) ; ++i) vGeo.push_back( vCrv[i]->Clone()) ; SaveGeoObj( vGeo, "D:\\Temp\\bezier\\ruled\\rebuild\\isoCrv.nge") ; #endif @@ -1898,7 +1898,7 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin, bool bUpdateEdges) cons Point3d ptMin = get<0>( vTrees[i]) ; Point3d ptMax = get<1>( vTrees[i]) ; Tree.SetSurf( this, ptMin, ptMax) ; - if( ! Tree.BuildTree( dTol, dSideMin)) { + if ( ! Tree.BuildTree( dTol, dSideMin)) { LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface parametric space couldn't be split in cells") ; return nullptr ; } @@ -3029,10 +3029,10 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in dPtStm.GetMinDistTriaIndex( nTriaIndex) ; // se ho trovato un nuovo triangolo, controllo che questo fosse nella lista dei triangoli equidistanti dal punto originale // sennò ripeto il conto con meno scostamento - if( nTriaOld != nTriaIndex) { + if ( nTriaOld != nTriaIndex) { auto iter = find( vnT.begin(), vnT.end(),nTriaIndex) ; int nIdTria = distance( vnT.begin(), iter) ; - if( nIdTria > ssize( vnT) - 1) { + if ( nIdTria > ssize( vnT) - 1) { ptI2 = ptI + ( ptIPrevOrNext - ptI) * 5 * EPS_SMALL ; DistPointSurfTm dPtStm2( ptI2, *pSurfTm) ; dPtStm2.GetMinDistTriaIndex( nTriaIndex) ; @@ -4138,7 +4138,7 @@ SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr) // se composita verifico che curve siano con lo stesso grado e uniformi come tipo bool bRat = false ; int nDegU = 3 ; - if( pCrv->GetType() != CRV_COMPO) { + if ( pCrv->GetType() != CRV_COMPO) { CC.AddCurve( CurveToBezierCurve( pCrv, nDegU, bRat)) ; } else { @@ -4151,7 +4151,7 @@ SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr) } } - if( CC.GetCurveCount() == 0 || ! CC.IsValid()) + if ( CC.GetCurveCount() == 0 || ! CC.IsValid()) return false ; // riempio la matrice dei punti di controllo @@ -5071,7 +5071,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int if ( j == vMatch1.size()) bAdvance1 = false ; // se trovo che ho uno spigolo allora procedo con la gestione spigoli - if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) { + if ( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) { // se ho uno spigolo su entrambe le curve forzo l'accoppiamento bAdvance0 = true ; bPerfectMatch = true ; @@ -5080,7 +5080,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int ptJoint0 = vPnt1[j+1] ; ptJoint1 = vPnt0[c+1] ; } - else if ( (vEdgeSplit0[c+1] && ! bAdvance1) || (vEdgeSplit1[j+1] && ! bAdvance0)) { + else if (( vEdgeSplit0[c+1] && ! bAdvance1) || (vEdgeSplit1[j+1] && ! bAdvance0)) { bAdvance0 = false ; bAdvance1 = false ; } @@ -5241,28 +5241,28 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // bAdvance0 = true ; // bAdvance1 = true ; // int nParam0, nParam1 ; - // while( bAdvance0) { + // while ( bAdvance0) { // dParam0 = vMatch0[c_temp].second ; // nParam0 = int( round( dParam0)) ; // dParam1 = vMatch1[nParam0].second ; // nParam1 = int( round( dParam1)) ; - // if( abs( nParam1 - c_temp) <= 2) + // if ( abs( nParam1 - c_temp) <= 2) // bAdvance0 = false ; // else // ++ c_temp ; // } - // while( bAdvance1) { + // while ( bAdvance1) { // dParam1 = vMatch1[j_temp].second ; // nParam1 = int( round( dParam1)) ; // dParam0 = vMatch0[nParam1].second ; // nParam0 = int( round( dParam0)) ; - // if( abs( nParam0 - j_temp) <= 2) + // if ( abs( nParam0 - j_temp) <= 2) // bAdvance1 = false ; // else // ++ j_temp ; // } // // se non sono avanzato, allora mi basta accoppiare i due punti in questione - // if( c_temp == c || j_temp == j) { + // if ( c_temp == c || j_temp == j) { // ++c ; // ++j ; // vPairs.emplace_back( c + nSplit0, j + nSplit1) ; @@ -5292,13 +5292,13 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // PtrOwner pCC1 ; // int nPointsBetween0 = 0 ; // int nPointsBetween1 = 0 ; - // if( bAdvance0 && bAdvance1) { + // if ( bAdvance0 && bAdvance1) { // pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ; // pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ; // nPointsBetween0 = c_temp - c ; // nPointsBetween1 = j_temp - j ; // } - // else if( bAdvance0){ + // else if ( bAdvance0) { // pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ; // pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, dParam0)) ; // nPointsBetween0 = c_temp - c ; @@ -5306,7 +5306,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // if ( bIntParam0) // nPointsBetween1 -= 1 ; // } - // else if( bAdvance1){ + // else if ( bAdvance1) { // pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, dParam1)) ; // pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ; // nPointsBetween0 = int( dParam1) - ( c + 1) ; @@ -5337,7 +5337,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // int nJBefore = j ; // //debug // while ( bSplitToAdd) { - // if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) { + // if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) { // LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 1 while reparametrizing some section") ; // return false ; // } @@ -5384,13 +5384,13 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // bSplitToAdd = ! ( c0 == ssize( vdParamPos0) - 1 && c1 == ssize( vdParamPos1) - 1) ; // } // // aggiorno i dati dell'ultima aggiunta - // if( bAdvance0 && ! bAdvance1) { + // if ( bAdvance0 && ! bAdvance1) { // ptLastPointMatch0 = vMatch0[c_temp].first ; // dLastParamMatch0 = vMatch0[c_temp].second ; // ptLastPointMatch1 = vPnt0[c_temp] ; // dLastParamMatch0 = c_temp ; // } - // else if( ! bAdvance0 && bAdvance1) { + // else if ( ! bAdvance0 && bAdvance1) { // ptLastPointMatch0 = vPnt1[j_temp] ; // dLastParamMatch0 = j_temp ; // ptLastPointMatch1 = vMatch1[j_temp].first ; @@ -5406,7 +5406,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int // } } } - bAdvance = ! (c >= int(vMatch0.size()) - 1 && j >= int(vMatch1.size()) - 1) ; + bAdvance = ! ( c >= ssize( vMatch0) - 1 && j >= ssize( vMatch1) - 1) ; } // applico effettivamente gli split @@ -5501,7 +5501,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int vector vGeo ; ICURVEPOVECTOR vCrv ; GetAllPatchesIsocurves( false, vCrv) ; - for( int i = 0 ; i < ssize( vCrv) ; ++i) { + for ( int i = 0 ; i < ssize( vCrv) ; ++i) { vGeo.push_back( vCrv[i]->Clone()) ; } vector vCol( ssize( vCrv)) ; @@ -5883,8 +5883,8 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c { // vCrv è il vettore delle isocurve (nel parametro V) che si vogliono forzare per la creazione della rigata tra Curve0 e Curve1 - //controllo che siano entrambe chiuse o entrambe aperte - if( pCurve0->IsClosed() ^ pCurve1->IsClosed()) + // controllo che siano entrambe chiuse o entrambe aperte + if ( pCurve0->IsClosed() != pCurve1->IsClosed()) return false ; bool bClosed = pCurve0->IsClosed() ; @@ -5934,8 +5934,9 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c Point3d ptU1 = vCrv[i].second ; double dParam0 ; CrvU0.GetParamAtPoint( ptU0, dParam0) ; double dParam1 ; CrvU1.GetParamAtPoint( ptU1, dParam1) ; - if( bClosed && (dParam0 < EPS_SMALL || nSpanU0 - dParam0 < EPS_SMALL) && (dParam1 < EPS_SMALL || nSpanU1 - dParam1 < EPS_SMALL)) { - if( ! bFirstAdded) { + if ( bClosed && ( dParam0 < EPS_SMALL || nSpanU0 - dParam0 < EPS_SMALL) && + ( dParam1 < EPS_SMALL || nSpanU1 - dParam1 < EPS_SMALL)) { + if ( ! bFirstAdded) { dParam0 = 0 ; dParam1 = 0 ; bFirstAdded = true ; @@ -5965,7 +5966,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c dLastParam0 = 0 ; dLastParam1 = 0 ; - if( vIso[0].dParam0 > 0 || vIso[0].dParam1 > 0) + if ( vIso[0].dParam0 > 0 || vIso[0].dParam1 > 0) vPairs.emplace_back( 0, 0) ; for ( int i = 0 ; i < ssize( vIso) ; ++i) { const BIPOINT& pCrv = vCrv[vIso[i].nCrv] ; @@ -6186,7 +6187,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c vector vGeo ; ICURVEPOVECTOR vCrvIso ; GetAllPatchesIsocurves( false, vCrvIso) ; - for( int i = 0 ; i < ssize( vCrvIso) ; ++i) { + for ( int i = 0 ; i < ssize( vCrvIso) ; ++i) { vGeo.push_back( vCrvIso[i]->Clone()) ; } vector vCol( ssize( vCrvIso)) ; @@ -6208,36 +6209,36 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c //---------------------------------------------------------------------------- bool -SurfBezier::RemoveCollapsedSpans() +SurfBezier::RemoveCollapsedSpans( void) { double dTol = EPS_SMALL ; //controllo se ho delle span collassate e le rimuovo - if( m_nSpanU > 1 || m_nSpanV > 1) { + if ( m_nSpanU > 1 || m_nSpanV > 1) { CalcPoles() ; - if( ! m_vbPole[2]) { + if ( ! m_vbPole[2]) { // scorro i punti della prima riga INTVECTOR vnCollapsedSpan ; - for( int i = 0 ; i < m_nSpanU ; ++i) { + for ( int i = 0 ; i < m_nSpanU ; ++i) { bool bSamePoint = true ; Point3d ptFirst = m_vPtCtrl[m_nDegU * i] ; // cerco se trovo tutti i punti in U coincidenti in una delle Span - for( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) { - if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[m_nDegU * i + j], dTol)) + for ( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) { + if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[m_nDegU * i + j], dTol)) bSamePoint = false ; } - if( bSamePoint) { + if ( bSamePoint) { // se trovo un'altra riga collassata do per scontato che tutta span sia collassata ptFirst = m_vPtCtrl[GetInd( m_nDegU * i, 1)] ; - for( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) { - if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( m_nDegU * i + j, 1)], dTol)) + for ( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) { + if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( m_nDegU * i + j, 1)], dTol)) bSamePoint = false ; } - if( bSamePoint) + if ( bSamePoint) vnCollapsedSpan.push_back( i) ; } } int nOldSpanU = m_nSpanU ; - if( ! vnCollapsedSpan.empty()) { + if ( ! vnCollapsedSpan.empty()) { // cancello le span che risultano collassate int nNewSpanU = m_nSpanU - ssize( vnCollapsedSpan) ; int nNewDim = ( m_nDegU * nNewSpanU + 1) * ( m_nDegV * m_nSpanV + 1) ; @@ -6245,21 +6246,21 @@ SurfBezier::RemoveCollapsedSpans() DBLVECTOR vNewWeight( nNewDim) ; int nCurrSkipInd = -1 ; int nCurrSkip = -1 ; - for( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) { + for ( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) { nCurrSkipInd = 0 ; nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ; - for( int i = 0 ; i < m_nSpanU ; ++i) { - if( i != nCurrSkip) { - for( int j = ( i - nCurrSkipInd) ==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) { + for ( int i = 0 ; i < m_nSpanU ; ++i) { + if ( i != nCurrSkip) { + for ( int j = ( i - nCurrSkipInd) ==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) { vNewCtrlPnt[nIndV * ( m_nDegU * nNewSpanU + 1) + (i - nCurrSkipInd) * m_nDegU + j] = m_vPtCtrl[GetInd( m_nDegU * i + j, nIndV)] ; - if( m_bRat) { + if ( m_bRat) { vNewWeight[nIndV * ( m_nDegU * nNewSpanU + 1) + (i - nCurrSkipInd) * m_nDegU + j] = m_vWeCtrl[GetInd( m_nDegU * i + j, nIndV)] ; } } } else { ++nCurrSkipInd ; - if( nCurrSkipInd > ssize( vnCollapsedSpan) - 1) + if ( nCurrSkipInd > ssize( vnCollapsedSpan) - 1) nCurrSkip = -1 ; else nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ; @@ -6270,32 +6271,32 @@ SurfBezier::RemoveCollapsedSpans() // vettori dei punti e numero di span ISurfFlatRegion* pSFRTrim = nullptr ; bool bTrimmed = m_bTrimmed ; - if( bTrimmed) { + if ( bTrimmed) { pSFRTrim = GetTrimRegion() ; m_pTrimReg = nullptr ; } Init( m_nDegU, m_nDegV, nNewSpanU, m_nSpanV, m_bRat) ; m_vPtCtrl = vNewCtrlPnt ; - if( m_bRat) + if ( m_bRat) m_vWeCtrl = vNewWeight ; - if( bTrimmed) { + if ( bTrimmed) { // elimino le span di troppo dallo spazio parametrico PtrOwner pNewTrim( pSFRTrim->Clone()) ; - for( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) { + for ( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) { int nSpan = vnCollapsedSpan[i] ; // tolgo tutta la parte a destra della colonna da togliere PtrOwner pSFRCut ( GetSurfFlatRegionRectangle( ( nOldSpanU - nSpan) * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF + 2)) ; - if( nSpan != 0) { + if ( nSpan != 0) { pSFRCut->Translate( Vector3d( nSpan * SBZ_TREG_COEFF, -1)) ; pNewTrim->Subtract( *pSFRCut) ; } - if( pNewTrim->IsValid()) { + if ( pNewTrim->IsValid()) { // ritaglio dal parametrico originale la parte a destra della colonna da eliminare e la incollo alla parte a sinistra PtrOwner pRightPart( pSFRTrim->Clone()) ; pSFRCut.Set( GetSurfFlatRegionRectangle( ( nSpan + 1) * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF + 2)) ; pSFRCut->Translate( Vector3d( nSpan * SBZ_TREG_COEFF, -1)) ; - if( pRightPart->Subtract( *pSFRCut) && pRightPart->IsValid()) { - if( ! pNewTrim->Add( *pRightPart) || ! pNewTrim->IsValid()) + if ( pRightPart->Subtract( *pSFRCut) && pRightPart->IsValid()) { + if ( ! pNewTrim->Add( *pRightPart) || ! pNewTrim->IsValid()) break ; } } @@ -6307,30 +6308,30 @@ SurfBezier::RemoveCollapsedSpans() } } - if( ! m_vbPole[1]) { + if ( ! m_vbPole[1]) { // scorro i punti della prima colonna INTVECTOR vnCollapsedSpan ; - for( int i = 0 ; i < m_nSpanV ; ++i) { + for ( int i = 0 ; i < m_nSpanV ; ++i) { bool bSamePoint = true ; Point3d ptFirst = m_vPtCtrl[GetInd( 0, i * m_nDegV)] ; // cerco se trovo tutti i punti in U coincidenti in una delle Span - for( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) { - if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 0, i * m_nDegV + j)], dTol)) + for ( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) { + if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 0, i * m_nDegV + j)], dTol)) bSamePoint = false ; } - if( bSamePoint) { + if ( bSamePoint) { // se trovo un'altra colonna collassata do per scontato che tutta span sia collassata ptFirst = m_vPtCtrl[GetInd( 1, i * m_nDegV)] ; - for( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) { - if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 1, i * m_nDegV + j)], dTol)) + for ( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) { + if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 1, i * m_nDegV + j)], dTol)) bSamePoint = false ; } - if( bSamePoint) + if ( bSamePoint) vnCollapsedSpan.push_back( i) ; } } int nOldSpanV = m_nSpanV ; - if( ! vnCollapsedSpan.empty()) { + if ( ! vnCollapsedSpan.empty()) { // cancello le span che risultano collassate int nNewSpanV = m_nSpanV - ssize( vnCollapsedSpan) ; int nNewDim = ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * nNewSpanV + 1) ; @@ -6338,12 +6339,12 @@ SurfBezier::RemoveCollapsedSpans() DBLVECTOR vNewWeight( nNewDim) ; int nCurrSkipInd = 0 ; int nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ; - for( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) { - if( nIndV / m_nDegV != nCurrSkip) { - for( int i = 0 ; i < m_nSpanU ; ++i) { - for( int j = i==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) { + for ( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) { + if ( nIndV / m_nDegV != nCurrSkip) { + for ( int i = 0 ; i < m_nSpanU ; ++i) { + for ( int j = i==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) { vNewCtrlPnt[( nIndV - ( nCurrSkipInd * m_nDegV)) * ( m_nDegU * m_nSpanU + 1) + i * m_nDegU + j] = m_vPtCtrl[GetInd( m_nDegU * i + j, nIndV)] ; - if( m_bRat) { + if ( m_bRat) { vNewWeight[( nIndV - ( nCurrSkipInd * m_nDegV)) * ( m_nDegU * m_nSpanU + 1) + i * m_nDegU + j] = m_vWeCtrl[GetInd( m_nDegU * i + j, nIndV)] ; } } @@ -6352,7 +6353,7 @@ SurfBezier::RemoveCollapsedSpans() else { nIndV += m_nDegV - 1 ; ++nCurrSkipInd ; - if( nCurrSkipInd > ssize( vnCollapsedSpan) - 1) + if ( nCurrSkipInd > ssize( vnCollapsedSpan) - 1) nCurrSkip = -1 ; else nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ; @@ -6362,32 +6363,32 @@ SurfBezier::RemoveCollapsedSpans() // vettori dei punti e numero di span ISurfFlatRegion* pSFRTrim = nullptr ; bool bTrimmed = m_bTrimmed ; - if( bTrimmed) { + if ( bTrimmed) { pSFRTrim = GetTrimRegion() ; m_pTrimReg = nullptr ; } Init( m_nDegU, m_nDegV, m_nSpanU, nNewSpanV, m_bRat) ; m_vPtCtrl = vNewCtrlPnt ; - if( m_bRat) + if ( m_bRat) m_vWeCtrl = vNewWeight ; - if( bTrimmed) { + if ( bTrimmed) { // elimino le span di troppo dallo spazio parametrico PtrOwner pNewTrim( pSFRTrim->Clone()) ; - for( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) { + for ( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) { int nSpan = vnCollapsedSpan[i] ; // tolgo tutta la parte a sopra la riga da togliere PtrOwner pSFRCut ( GetSurfFlatRegionRectangle( m_nSpanU * SBZ_TREG_COEFF + 2, ( nOldSpanV - nSpan) * SBZ_TREG_COEFF)) ; - if( nSpan != 0) { + if ( nSpan != 0) { pSFRCut->Translate( Vector3d( -1, nSpan * SBZ_TREG_COEFF)) ; pNewTrim->Subtract( *pSFRCut) ; } - if( pNewTrim->IsValid()) { + if ( pNewTrim->IsValid()) { // ritaglio dal parametrico originale la parte sopra la riga da eliminare e la incollo alla parte sotto la riga PtrOwner pUpperPart( pSFRTrim->Clone()) ; pSFRCut.Set( GetSurfFlatRegionRectangle( m_nSpanU * SBZ_TREG_COEFF + 2, ( nSpan + 1) * SBZ_TREG_COEFF)) ; pSFRCut->Translate( Vector3d( -1, nSpan * SBZ_TREG_COEFF)) ; - if( pUpperPart->Subtract( *pSFRCut) && pUpperPart->IsValid()) { - if( ! pNewTrim->Add( *pUpperPart) || ! pNewTrim->IsValid()) + if ( pUpperPart->Subtract( *pSFRCut) && pUpperPart->IsValid()) { + if ( ! pNewTrim->Add( *pUpperPart) || ! pNewTrim->IsValid()) break ; } } @@ -6405,7 +6406,7 @@ SurfBezier::RemoveCollapsedSpans() //---------------------------------------------------------------------------- bool -SurfBezier::SwapParameters() +SurfBezier::SwapParameters( void) { // inverto il parametro U con il parametro V // salvo i vecchi dati @@ -6415,7 +6416,7 @@ SurfBezier::SwapParameters() int nDegV = m_nDegU ; bool bTrimmed = m_bTrimmed ; PtrOwner pSFRTRim ; - if( m_bTrimmed) { + if ( m_bTrimmed) { pSFRTRim.Set( GetTrimRegion()) ; m_pTrimReg = nullptr ; } @@ -6423,16 +6424,16 @@ SurfBezier::SwapParameters() // creo il vettore dei punti di controllo PNTVECTOR vNewCtrlPt( GetDim()) ; DBLVECTOR vNewWeight( GetDim()) ; - for( int j = 0 ; j < m_nDegV * m_nSpanV + 1 ; ++j) { - for( int i = 0 ; i < m_nDegU * m_nSpanU + 1 ; ++ i) { + for ( int j = 0 ; j < m_nDegV * m_nSpanV + 1 ; ++j) { + for ( int i = 0 ; i < m_nDegU * m_nSpanU + 1 ; ++ i) { vNewCtrlPt[i * ( nDegU * nSpanU + 1) + j] = m_vPtCtrl[GetInd(i,j)] ; - if( m_bRat) + if ( m_bRat) vNewWeight[i * ( nDegU * nSpanU + 1) + j] = m_vWeCtrl[GetInd(i,j)] ; } } Init( nDegU, nDegV, nSpanU, nSpanV, m_bRat) ; - if( bTrimmed) { + if ( bTrimmed) { pSFRTRim->Mirror( ORIG, Vector3d(1,-1)) ; SetTrimRegion( *pSFRTRim) ; } @@ -6440,4 +6441,4 @@ SurfBezier::SwapParameters() m_vWeCtrl = vNewWeight ; return true ; -} \ No newline at end of file +} diff --git a/SurfBezier.h b/SurfBezier.h index bf92b9a..efdec9b 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -151,8 +151,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW PNTVECTOR GetAllControlPoints( void) const ; bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ; bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ; - bool RemoveCollapsedSpans() override ; - bool SwapParameters() ; + bool RemoveCollapsedSpans( void) override ; + bool SwapParameters( void) ; public : // IGeoObjRW int GetNgeId( void) const override ; diff --git a/Tool.h b/Tool.h index 6b0e43e..65f788c 100644 --- a/Tool.h +++ b/Tool.h @@ -36,25 +36,25 @@ class Tool bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) ; bool SetToolNum( int nToolNum) { m_nCurrentNum = nToolNum ; return true ; } - int GetType() const + int GetType( void) const { return m_nType ; } - int GetToolNum() const + int GetToolNum( void) const { return m_nCurrentNum ; } - double GetHeigth() const + double GetHeigth( void) const { return m_dHeight ; } - double GetTipHeigth() const + double GetTipHeigth( void) const { return m_dTipHeight ; } - double GetRadius() const + double GetRadius( void) const { return m_dRadius ; } - double GetTipRadius() const + double GetTipRadius( void) const { return m_dTipRadius ; } - double GetCornRadius() const + double GetCornRadius( void) const { return m_dRCorner ; } - double GetRefRadius() const + double GetRefRadius( void) const { return m_dRefRadius ; } - double GetMrtChsWidth() const + double GetMrtChsWidth( void) const { return m_dMrtChsWidth ; } - double GetMrtChsThickness() const + double GetMrtChsThickness( void) const { return m_dMrtChsThickness ; } const CurveComposite& GetOutline( void) const { return ( m_Outline) ; } diff --git a/Tree.cpp b/Tree.cpp index 8a7689a..1150b69 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -461,8 +461,8 @@ Tree::Split( int nId, double dSplitValue) dSplitValue < cToSplit.GetTopRight().y - 10 * EPS_SMALL ; Point3d ptP00, ptP01, ptP10, ptP11 ; - if( bGoodSplitVert) { - if( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) { + if ( bGoodSplitVert) { + if ( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) { GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ; GetPoint( dSplitValue, cToSplit.GetBottomRight().y, ptP10) ; GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ; @@ -474,12 +474,13 @@ Tree::Split( int nId, double dSplitValue) GetPoint( dSplitValue, cToSplit.GetTopLeft().y, ptP01) ; GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ; } - if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) && - ( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL)) + if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) && + ( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || + dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL)) bGoodSplitVert = false ; } - if( bGoodSplitHoriz) { - if( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) { + if ( bGoodSplitHoriz) { + if ( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) { GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ; GetPoint( cToSplit.GetBottomRight().x, cToSplit.GetBottomRight().y, ptP10) ; GetPoint( cToSplit.GetTopLeft().x, dSplitValue, ptP01) ; @@ -491,8 +492,9 @@ Tree::Split( int nId, double dSplitValue) GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ; GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ; } - if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) && - ( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL)) + if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) && + ( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || + dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL)) bGoodSplitHoriz = false ; } @@ -1455,7 +1457,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vec ++ nPolyInd ; continue ; } - else if( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE) + else if ( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE) continue ; else { // vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella @@ -1980,7 +1982,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells nCells.push_back( nCell) ; nEdge = -2 ; } - if( ssize( nCells) == 1) + if ( ssize( nCells) == 1) return nCells ; Vector3d vtDir ; @@ -2009,14 +2011,14 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells if ( abs(vtDir.x) < 1 - EPS_SMALL/100 && abs(vtDir.y) < 1 - EPS_SMALL/100 ) ptIntersPlus = ptIntersPlus + vtDir * EPS_SMALL ; // altrimenti ruoto a destra - else if( ( nEdge == 4 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 6 && vtDir.x < - 1 + EPS_SMALL / 100) || + else if (( nEdge == 4 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 6 && vtDir.x < - 1 + EPS_SMALL / 100) || ( nEdge == 5 && vtDir.y > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.y < - 1 + EPS_SMALL / 100)) { Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -45) ; ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ; } // altrimenti ruoto a sinistra - else /*if( ( nEdge == 4 && vtDir.y < - 1 + EPS_SMALL / 100) || ( nEdge == 6 && vtDir.y < 1 - EPS_SMALL / 100) || - ( nEdge == 5 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.x < - 1 + EPS_SMALL / 100)) // + tutti gli altri casi */ { + else /*if (( nEdge == 4 && vtDir.y < - 1 + EPS_SMALL / 100) || ( nEdge == 6 && vtDir.y < 1 - EPS_SMALL / 100) || + ( nEdge == 5 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.x < - 1 + EPS_SMALL / 100)) // + tutti gli altri casi */ { Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 45) ; ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ; } @@ -2138,7 +2140,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) bool bLoopInside = true ; Point3d ptCurr ; int nIdPolygon = - 1; - if( ! pCell->m_vnPolyId.empty()) + if ( ! pCell->m_vnPolyId.empty()) nIdPolygon = pCell->m_vnPolyId[0] ; else return false ; @@ -2178,9 +2180,9 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) } // se l'intersezione e la stessa della precedente allora potrei essere entrato in un loop infinito // se per più volte il punto di intersezione resta più o meno lo stesso allora blocco tutto - if( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) { + if ( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) { ++ nInfiniteLoopCount ; - if( nInfiniteLoopCount == 4) { + if ( nInfiniteLoopCount == 4) { LOG_ERROR( GetEGkLogger(), "Error Triangulating SurfBezier: infinte while loop occured in Tree::TraceLoopLabelCell") return false ; } @@ -2189,7 +2191,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // aggiorno il puntatore alla cella pCell = &m_mTree[nId] ; // recupero l'indice del poligono base associato alla cella - if( ! pCell->m_vnPolyId.empty()) + if ( ! pCell->m_vnPolyId.empty()) nIdPolygon = pCell->m_vnPolyId[0] ; else return false ; @@ -4025,7 +4027,8 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const Point3d ptTl ( ptBL.x, ptTR.y) ; Point3d ptBr ( ptTR.x, ptBL.y) ; - if( ptToAssign.y < ptBL.y - EPS_SMALL || ptToAssign.y > ptTR.y + EPS_SMALL || ptToAssign.x < ptBL.x - EPS_SMALL || ptToAssign.x > ptTR.x + EPS_SMALL) + if ( ptToAssign.y < ptBL.y - EPS_SMALL || ptToAssign.y > ptTR.y + EPS_SMALL || + ptToAssign.x < ptBL.x - EPS_SMALL || ptToAssign.x > ptTR.x + EPS_SMALL) return false ; else if ( AreSamePointXYApprox( ptToAssign, ptTR)) nEdge = 7 ; diff --git a/Tree.h b/Tree.h index 8cf1411..6e1146c 100644 --- a/Tree.h +++ b/Tree.h @@ -23,7 +23,8 @@ #include struct PairHashInt64 { - size_t operator()(const std::pair& key) const { + size_t + operator()( const std::pair& key) const { size_t h1 = std::hash{}(key.first) ; size_t h2 = std::hash{}(key.second) ; return h1 ^ (h2 << 1); // Combine hashes @@ -33,14 +34,20 @@ struct PairHashInt64 { //---------------------------------------------------------------------------- struct Inters { int nIn ; - PNTVECTOR vpt ; int nOut ; + PNTVECTOR vpt ; bool bCCW ; int nChunk ; bool bSortedbyStart ; - // riordino le intersezioni per lato in senso antiorario dal top - // se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR - bool operator < ( Inters& b) + + // nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita 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 + + // riordino le intersezioni per lato in senso antiorario dal top + // se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR + bool + operator < ( Inters& b) { // trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ; @@ -75,7 +82,8 @@ struct Inters { ( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ; } - static bool FirstEncounter( Inters& a, Inters& b) + static bool + FirstEncounter( Inters& a, Inters& b) { // riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima. // ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso @@ -135,18 +143,18 @@ struct Inters { ( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ; } - bool operator == ( Inters& b) + bool + operator == ( Inters& b) { return AreSamePointExact( vpt[0], b.vpt[0]) ; } - bool operator != ( Inters& b) + + bool + operator != ( Inters& b) { return ! AreSamePointExact( vpt[0], b.vpt[0]) ; } } ; -// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita 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 //---------------------------------------------------------------------------- class Cell @@ -160,11 +168,12 @@ class Cell // | | // |_________________| // Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE) - public: - enum Collapsed { TO_VERIFY = -1, // da verificare - NO_COLLAPSE = 0, // non ho coppie di lati collassati - VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati - HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati + + public : + enum Collapsed { TO_VERIFY = -1, // da verificare + NO_COLLAPSE = 0, // non ho coppie di lati collassati + VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati + HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati public : ~Cell( void) {} @@ -336,4 +345,4 @@ class Tree INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch ICRVCOMPOPOVECTOR m_vCCLoop2D ; // vettore che contiene le CurveCompo che rappresentano i loop di trim tenendo conto della divisione in celle std::vector> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim. -} ; \ No newline at end of file +} ; diff --git a/Trimming.cpp b/Trimming.cpp index 77a7e0d..8c04f37 100644 --- a/Trimming.cpp +++ b/Trimming.cpp @@ -167,7 +167,7 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL) PNTMATRIX vvPoints ; Vector3d vtTanCurr = V_INVALID, vtTanNext = V_INVALID ; bool bNewCurve = true ; - int nPoints = int( vPoints.size()) ; + int nPoints = ssize( vPoints) ; for ( int nP = 0 ; nP < nPoints - 2 ; ++ nP) { // Recupero il punto corrente e i due punti successivi Point3d& ptCurr = vPoints[nP] ; @@ -209,8 +209,8 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL) // Se PolyLine originale chiusa if ( PL.IsClosed()) { // Se ho più tratti, potrei riuniore il primo con l'ultimo - if ( int( vvPoints.size()) > 1) { - Point3d& ptCurr = vPoints[int( vPoints.size()) - 2] ; + if ( ssize( vvPoints) > 1) { + Point3d& ptCurr = vPoints[ssize( vPoints) - 2] ; Point3d& ptNext = vPoints[0] ; Point3d& ptNextNext = vPoints[1] ; vtTanCurr = ptNext - ptCurr ; vtTanCurr.Normalize() ; @@ -219,19 +219,19 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL) // Se dentro alla tolleranza if ( dCos > dCosTol) { // Recupero la tangenza del tratto finale dell'ultimo tratto - Point3d& ptLast = vvPoints.back()[int( vvPoints.back().size()) - 1] ; - Point3d& ptLastLast = vvPoints.back()[int( vvPoints.back().size()) - 2] ; + Point3d& ptLast = vvPoints.back()[ssize( vvPoints.back()) - 1] ; + Point3d& ptLastLast = vvPoints.back()[ssize( vvPoints.back()) - 2] ; Vector3d vtTanLast = ptLast - ptLastLast ; vtTanLast.Normalize() ; dCos = vtTanLast * vtTanCurr ; // Se nella tolleranza allora posso allacciare il primo e l'ultimo tratto if ( dCos > dCosTol) { - for ( int i = bNewCurve ? 1 : 0 ; i < int( vvPoints[0].size()) ; ++ i) + for ( int i = bNewCurve ? 1 : 0 ; i < ssize( vvPoints[0]) ; ++ i) vvPoints.back().emplace_back( vvPoints[0][i]) ; vvPoints.erase( vvPoints.begin()) ; } // Altrimenti sposto il punto d'inizio in ptCurr del primo tratto else { - PNTVECTOR vPointsFirst ; vPointsFirst.reserve( vvPoints.front().size() + 1) ; + PNTVECTOR vPointsFirst ; vPointsFirst.reserve( ssize( vvPoints.front()) + 1) ; vPointsFirst.emplace_back( ptCurr) ; for ( const Point3d& pt : vvPoints.front()) vPointsFirst.emplace_back( pt) ; @@ -252,8 +252,8 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL) // Se devo creare una curva nuova, aggiungo il tratto finale if ( bNewCurve) { vvPoints.emplace_back( PNTVECTOR{}) ; - vvPoints.back().emplace_back( vPoints[int( vPoints.size()) - 2]) ; - vvPoints.back().emplace_back( vPoints[int( vPoints.size()) - 1]) ; + vvPoints.back().emplace_back( vPoints[ssize( vPoints) - 2]) ; + vvPoints.back().emplace_back( vPoints[ssize( vPoints) - 1]) ; } } #if DEBUG_ANG_APPROX @@ -271,10 +271,10 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL) #endif // Converto i punti ricavati in PolyLine risultati - for ( int i = 0 ; i < int( vvPoints.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vvPoints) ; ++ i) { vPL.emplace_back( PolyLine()) ; double dPar = -1. ; - for ( int j = 0 ; j < int( vvPoints[i].size()) ; ++ j) { + for ( int j = 0 ; j < ssize( vvPoints[i]) ; ++ j) { vPL.back().AddUPoint( ++ dPar, vvPoints[i][j]) ; } } @@ -580,7 +580,7 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, // Le Patch più corte della tolleranza vengono considerate invalide SimpleBorderVector vSimpleBorder ; vSimpleBorder.reserve( matPLPatches.size()) ; vector> matPatchPar ; matPatchPar.reserve( matPLPatches.size()) ; - for ( int i = 0 ; i < int( matPLPatches.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( matPLPatches) ; ++ i) { vSimpleBorder.emplace_back( SimpleBorder()) ; matPatchPar.emplace_back( set()) ; for ( int j = 0 ; j < ssize( matPLPatches[i]) ; ++ j) { @@ -599,8 +599,8 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, } #if DEBUG_CHAIN_CURVES VC.clear() ; VT.clear() ; - for ( int i = 0 ; i < int( vSimpleBorder.size()) ; ++ i) { - for ( int j = 0 ; j < int( vSimpleBorder[i].size()) ; ++ j) { + for ( int i = 0 ; i < ssize( vSimpleBorder) ; ++ i) { + for ( int j = 0 ; j < ssize( vSimpleBorder[i]) ; ++ j) { VT.emplace_back( matCompoPatches[i][j].Clone()) ; VC.emplace_back( RED) ; IGeoPoint3d* ptS = CreateGeoPoint3d() ; @@ -720,11 +720,11 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, // Si eliminano ora tutte le Patch che si sovrappongono, in modo da ottenere solo un // le Patch che rappresentano il bordo esterno const double MAXPOINT = 10 ; - for ( int nCurrCrv = 0 ; nCurrCrv < int( vSimpleBorder.size()) - 1 ; ++ nCurrCrv) { + for ( int nCurrCrv = 0 ; nCurrCrv < ssize( vSimpleBorder) - 1 ; ++ nCurrCrv) { // Recupero la curva corrente SimpleBorder& CurrCurve = vSimpleBorder[nCurrCrv] ; // Scorro i suoi Edges - for ( int nCurrEdge = 0 ; nCurrEdge < int( CurrCurve.size()) ; ++ nCurrEdge) { + for ( int nCurrEdge = 0 ; nCurrEdge < ssize( CurrCurve) ; ++ nCurrEdge) { // Se Edge cancellato, passo al successivo if ( CurrCurve[nCurrEdge].bErase) continue ; @@ -732,11 +732,11 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, Point3d& ptCurrStart = CurrCurve[nCurrEdge].ptStart ; Point3d& ptCurrEnd = CurrCurve[nCurrEdge].ptEnd ; // Scorro le curve successive - for ( int nNextCrv = nCurrCrv + 1 ; nNextCrv < int( vSimpleBorder.size()) ; ++ nNextCrv) { + for ( int nNextCrv = nCurrCrv + 1 ; nNextCrv < ssize( vSimpleBorder) ; ++ nNextCrv) { // Recupero la curva successiva SimpleBorder& NextCurve = vSimpleBorder[nNextCrv] ; // Scorro i suoi Edges - for ( int nNextEdge = 0 ; nNextEdge < int( NextCurve.size()) ; ++ nNextEdge) { + for ( int nNextEdge = 0 ; nNextEdge < ssize( NextCurve) ; ++ nNextEdge) { // Se Edge cancellato, passo al successivo #if 0 // Se pezze si superficie piccolissime, si rischia di eliminare tutti i @@ -790,11 +790,11 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, } // Recupero solo i sottotratti di curva validi ( quindi che non fanno overlap tra loro) - for ( int nCrv = 0 ; nCrv < int( vSimpleBorder.size()) ; ++ nCrv) { + for ( int nCrv = 0 ; nCrv < ssize( vSimpleBorder) ; ++ nCrv) { // Recupero la curva SimpleBorder& CrvEdge = vSimpleBorder[nCrv] ; // Scorro i suoi edges - for ( int nEdge = 0 ; nEdge < int( CrvEdge.size()) ; ++ nEdge) { + for ( int nEdge = 0 ; nEdge < ssize( CrvEdge) ; ++ nEdge) { // Se edge non attivo, passo al successivo if ( CrvEdge[nEdge].bErase) continue ; @@ -815,15 +815,15 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, } } // Conservo solo le curve valide - for ( int nCrv = 0 ; nCrv < int( vCompoResult.size()) ; ++ nCrv) { - if ( IsNull( vCompoResult[nCrv]) || ! vCompoResult[nCrv]->IsValid()) { + for ( int nCrv = 0 ; nCrv < ssize( vCompoResult) ; ++ nCrv) { + if ( IsNull( vCompoResult[nCrv]) || ! vCompoResult[nCrv]->IsValid()) { vCompoResult.erase( vCompoResult.begin() + nCrv) ; -- nCrv ; } } #if DEBUG_CHAIN_CURVES // Debug per le Patch risultanti VT.clear() ; VC.clear() ; - for ( int i = 0 ; i < int( vCompoResult.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCompoResult) ; ++ i) { VT.emplace_back( vCompoResult[i]->Clone()) ; VC.emplace_back( ORANGE) ; } @@ -854,7 +854,7 @@ ChainCompoPatches( ICRVCOMPOPOVECTOR& vCompoPatches, double dChainTol, // La concatenazione parte dalla curva più lunga double dMaxLen = - INFINITO ; int nInd = 0 ; - for ( int i = 0 ; i < int( vCompoPatches.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCompoPatches) ; ++ i) { double dLen = 0. ; vCompoPatches[i]->GetLength( dLen) ; if ( dLen > dMaxLen) { @@ -868,7 +868,7 @@ ChainCompoPatches( ICRVCOMPOPOVECTOR& vCompoPatches, double dChainTol, // Scorro le curve vCompoChained.reserve( vCompoPatches.size()) ; BOOLVECTOR vbCrvChained( vCompoPatches.size(), false) ; - for ( int nCurrCrv = 0 ; nCurrCrv < int( vCompoPatches.size()) ; ++ nCurrCrv) { + for ( int nCurrCrv = 0 ; nCurrCrv < ssize( vCompoPatches) ; ++ nCurrCrv) { // Se curva già concatenata, passo alla successiva ( no biforcazioni ammesse -> errore ) if ( vbCrvChained[nCurrCrv]) continue ; @@ -881,7 +881,7 @@ ChainCompoPatches( ICRVCOMPOPOVECTOR& vCompoPatches, double dChainTol, for ( int nU = 0 ; nU < vCompoChained.back()->GetCurveCount() ; ++ nU) vCompoChained.back()->SetCurveTempProp( nU, vCompoPatches[nCurrCrv]->GetTempProp( 0), 0) ; // Cerco tra le altre curve disponibili una candidata alla concatenazione - for ( int nNextCrv = 0 ; nNextCrv < int( vCompoPatches.size()) ; ++ nNextCrv) { + for ( int nNextCrv = 0 ; nNextCrv < ssize( vCompoPatches) ; ++ nNextCrv) { if ( nNextCrv == nCurrCrv || vbCrvChained[nNextCrv]) continue ; // Recupero i suoi estremi [ sono tratti lineari, la ricerca è immediata ] @@ -932,7 +932,7 @@ ChainCompoPatches( ICRVCOMPOPOVECTOR& vCompoPatches, double dChainTol, } } // Verifico la validità delle curve ottenute - for ( int i = 0 ; i < int( vCompoChained.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCompoChained) ; ++ i) { if ( IsNull( vCompoChained[i]) || ! vCompoChained[i]->IsValid()) return false ; // Se curva al di sotto della tolleranza, la scarto @@ -1032,7 +1032,7 @@ BreakCompoPathces( ICRVCOMPOPOVECTOR& vCompoChained, double dLinTol, double dAng } } // Se non ho ottenuto esattamente due tratti, non analizzo più la curva corrente - if ( int( vBiPntSplit.size()) != 2) { + if ( ssize( vBiPntSplit) != 2) { LOG_INFO( GetEGkLogger(), "Warning in Trimming : Detected more Curves by Thick values") ; break ; // lascio la curva invariata } @@ -1069,10 +1069,10 @@ BreakCompoPathces( ICRVCOMPOPOVECTOR& vCompoChained, double dLinTol, double dAng if ( vBreakingPts.empty()) return true ; // Se ho punti di rottura in comune, errore - for ( int i = 0 ; i < int( vBreakingPts.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vBreakingPts) ; ++ i) { if ( AreSamePointEpsilon( vBreakingPts[i].first, vBreakingPts[i].second, dLinTol)) return false ; - for ( int j = i + 1 ; j < int( vBreakingPts.size()) ; ++ j) { + for ( int j = i + 1 ; j < ssize( vBreakingPts) ; ++ j) { if ( AreSamePointEpsilon( vBreakingPts[i].first, vBreakingPts[j].first, dLinTol) || AreSamePointEpsilon( vBreakingPts[i].first, vBreakingPts[j].second, dLinTol) || AreSamePointEpsilon( vBreakingPts[i].second, vBreakingPts[j].first, dLinTol) || @@ -1110,7 +1110,7 @@ BreakCompoPathces( ICRVCOMPOPOVECTOR& vCompoChained, double dLinTol, double dAng return false ; for ( const BIPOINT& BiPnts : vBreakingPts) { // Scorro i tratti ( inizialmente la curva stessa) - for ( int i = 0 ; i < int( vCompoParts.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCompoParts) ; ++ i) { // Controllo che la coppia di punti giacia su quella curva if ( ! vCompoParts[i]->IsPointOn( BiPnts.first, dLinTol) || ! vCompoParts[i]->IsPointOn( BiPnts.second, dLinTol)) @@ -1152,7 +1152,7 @@ BreakCompoPathces( ICRVCOMPOPOVECTOR& vCompoChained, double dLinTol, double dAng } } // Memorizzo tutte le curve valide ottenute dai punti di rottura - for ( int i = 0 ; i < int( vCompoParts.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCompoParts) ; ++ i) { if ( ! IsNull( vCompoParts[i]) && vCompoParts[i]->IsValid()) vCrvResult.emplace_back( Release( vCompoParts[i])) ; } @@ -1186,13 +1186,13 @@ BreakCompoPathces( ICRVCOMPOPOVECTOR& vCompoChained, double dLinTol, double dAng if ( ! GetPointSetByAngTol( myPL, ANG_SPLIT, vPL)) return false ; // Se meno di 4 PolyLine non faccio nulla - if ( int( vPL.size()) < 4) { + if ( ssize( vPL) < 4) { LOG_INFO( GetEGkLogger(), "Warning in Trimming : Not Detected 2 Curves") ; return true ; } // Scorro le PolyLine e ricavo le due più corte INTDBLVECTOR vIndPLLen ; vIndPLLen.reserve( vPL.size()) ; - for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vPL) ; ++ i) { double dLen ; vPL[i].GetLength( dLen) ; vIndPLLen.emplace_back( make_pair( i, dLen)) ; } @@ -1301,7 +1301,7 @@ InsertLoopsOfSurf( const ISurf* pSurf, POLYLINEVECTOR& vPL) return false ; // Li inserisco nel vettore ( come insieme di tratti lineari) // NB. Tengo le tolleranze molto basse per ottenere dei loop rappresentativi della geometria - for ( int nL = 0 ; nL < int( vLoops.size()) ; ++ nL) { + for ( int nL = 0 ; nL < ssize( vLoops) ; ++ nL) { if ( ! IsNull( vLoops[nL]) && vLoops[nL]->IsValid()) { vPL.emplace_back( PolyLine()) ; if ( ! vLoops[nL]->ApproxWithLines( EPS_SMALL, EPS_ANG_SMALL, ICurve::APL_STD, vPL.back())) @@ -1427,7 +1427,7 @@ GetSurfBorders( const CISURFPVECTOR& vSurf, const SELVECTOR& vSurfFace, double d // - Loop di una Superficie TriMesh // - Insieme di facce di una supericie TriMesh // Scorro il vettore delle superfici - for ( int nS = 0 ; nS < int( vSurf.size()) ; ++ nS) { + for ( int nS = 0 ; nS < ssize( vSurf) ; ++ nS) { // Recupero la superficie const ISurf* pSurf = vSurf[nS] ; if ( pSurf == nullptr) @@ -1440,9 +1440,9 @@ GetSurfBorders( const CISURFPVECTOR& vSurf, const SELVECTOR& vSurfFace, double d vFaces.push_back( SurfFace.nSub) ; } // Recupero la dimensione del vettore delle PolyLine risultati attuale - int nSize = int( vPLBorders.size()) ; + int nSize = ssize( vPLBorders) ; // Se non ho nessuna faccia e nessun triangolo da scartare, estraggo i bordi complessivi della superficie - if ( int( vFaces.size()) == 1 && vFaces[0] == SEL_SUB_ALL) { + if ( ssize( vFaces) == 1 && vFaces[0] == SEL_SUB_ALL) { if ( ! InsertLoopsOfSurf( pSurf, vPLBorders)) return false ; } @@ -1463,7 +1463,7 @@ GetSurfBorders( const CISURFPVECTOR& vSurf, const SELVECTOR& vSurfFace, double d return false ; } // Associo alle nuove PolyLine ricavate l'indice della superficie corrispondente - for ( int i = nSize ; i < int( vPLBorders.size()) ; ++ i) + for ( int i = nSize ; i < ssize( vPLBorders) ; ++ i) vPLBorders[i].SetTempProp( nS, 0) ; } @@ -1509,52 +1509,36 @@ GetBorderByExtrusion( const SurfTriMesh* pStm, double dThick, double dLinTol, do // Scorro i Loop for ( PolyLine& PLLoop : vPLLoop) { PolyLine PLLoopExtr ; - // Scorro i Segmenti - Point3d ptI, ptE ; - double dUI, dUE ; - bool bFound = PLLoop.GetFirstULine( &dUI, &ptI, &dUE, &ptE) ; + // Scorro i Punti + Point3d ptP ; + double dU ; + bool bFound = PLLoop.GetFirstUPoint( &dU, &ptP) ; double dPar = -1 ; bool bFirst = true ; while ( bFound) { - // Recupero il TriangoloEx del tratto lineare corrente + // Recupero il TriangoloEx associato al punto Triangle3dEx Tria ; - if ( ! pStm->GetTriangle( int( dUI), Tria)) + if ( ! pStm->GetTriangle( lround( dU), Tria)) return false ; - // Tale Triangolo contiene le normali mediate, cerco quelle riferite ai vertici - if ( bFirst) { - int nTriaP = 0 ; - for ( ; nTriaP < 3 ; ++ nTriaP) { - if ( AreSamePointApprox( Tria.GetP( nTriaP), ptI)) - break ; - } - PLLoopExtr.AddUPoint( ++ dPar, ptI - Tria.GetVertexNorm( nTriaP) * dThick) ; - #if DEBUG_BORDERS_BY_NORMALS - IGeoVector3d* _vtN = CreateGeoVector3d() ; _vtN->Set( Tria.GetVertexNorm( nTriaP), ptI) ; - VT.emplace_back( _vtN) ; - Color _myCol = Color( abs( Tria.GetVertexNorm( nTriaP).x), abs( Tria.GetVertexNorm( nTriaP).y), abs( Tria.GetVertexNorm( nTriaP).z)) ; - VC.emplace_back( _myCol) ; - CurveLine _Line ; _Line.Set( ptI, ptI - Tria.GetVertexNorm( nTriaP) * dThick) ; - VT.emplace_back( _Line.Clone()) ; - VC.emplace_back( _myCol) ; - #endif - bFirst = false ; - } + // Cerco il vertice associato al punto int nTriaP = 0 ; for ( ; nTriaP < 3 ; ++ nTriaP) { - if ( AreSamePointApprox( Tria.GetP( nTriaP), ptE)) + if ( AreSamePointApprox( Tria.GetP( nTriaP), ptP)) break ; } - PLLoopExtr.AddUPoint( ++ dPar, ptE - Tria.GetVertexNorm( nTriaP) * dThick) ; + if ( nTriaP == 3) + return false ; + PLLoopExtr.AddUPoint( ++ dPar, ptP - Tria.GetVertexNorm( nTriaP) * dThick) ; #if DEBUG_BORDERS_BY_NORMALS - IGeoVector3d* _vtN = CreateGeoVector3d() ; _vtN->Set( Tria.GetVertexNorm( nTriaP), ptE) ; + IGeoVector3d* _vtN = CreateGeoVector3d() ; _vtN->Set( Tria.GetVertexNorm( nTriaP), ptP) ; VT.emplace_back( _vtN) ; Color _myCol = Color( abs( Tria.GetVertexNorm( nTriaP).x), abs( Tria.GetVertexNorm( nTriaP).y), abs( Tria.GetVertexNorm( nTriaP).z)) ; VC.emplace_back( _myCol) ; - CurveLine _Line ; _Line.Set( ptE, ptE - Tria.GetVertexNorm( nTriaP) * dThick) ; + CurveLine _Line ; _Line.Set( ptP, ptP - Tria.GetVertexNorm( nTriaP) * dThick) ; VT.emplace_back( _Line.Clone()) ; VC.emplace_back( _myCol) ; #endif - bFound = PLLoop.GetNextULine( &dUI, &ptI, &dUE, &ptE) ; + bFound = PLLoop.GetNextUPoint( &dU, &ptP) ; } #if DEBUG_BORDERS_BY_NORMALS ICurveComposite* pC = CreateCurveComposite() ; @@ -1562,8 +1546,9 @@ GetBorderByExtrusion( const SurfTriMesh* pStm, double dThick, double dLinTol, do VT.emplace_back( pC->Clone()) ; VC.emplace_back( AQUA) ; #endif + // Loop valido con almeno 4 punti if ( PLLoopExtr.GetPointNbr() >= 4) { - // Il primo e l'ultimo punto devono coincidere + // Primo e ultimo punto devono coincidere PNTULIST& lPntU = PLLoopExtr.GetUPointList() ; Point3d ptClose = Media( lPntU.front().first, lPntU.back().first) ; lPntU.front().first = ptClose ; @@ -2071,10 +2056,10 @@ ClassifyTriangles( const SurfTriMesh& Stm, const INTVECTOR& vTBox, int nFirstTri // Collezione di triangoli già visitati unordered_set setTria ; setTria.reserve( vTBox.size()) ; // Collezioni di triangoli da analizzare - INTVECTOR vTria ; vTria.reserve( int( vTBox.size()) + 1) ; + INTVECTOR vTria ; vTria.reserve( ssize( vTBox) + 1) ; vTria.push_back( nFirstTria) ; // Collezioni di adiacenze da non riguardare - unordered_map mapAdjToAvoid ; mapAdjToAvoid.reserve( int( vTBox.size() + 1)) ; + unordered_map mapAdjToAvoid ; mapAdjToAvoid.reserve( ssize( vTBox) + 1) ; // Finchè ho triangoli da visitare while ( ! vTria.empty()) { @@ -2221,14 +2206,14 @@ GetBordersByTriaInBox( const SurfTriMesh& Stm, const BBox3d& BBoxCurr, double dL // Per ogni Edge ricavato, conservo solo le parti interne al Box corrente INTVECTOR vEdgeToSave ; vEdgeToSave.reserve( vBiPnts.size()) ; - for ( int nEdge = 0 ; nEdge < int( vBiPnts.size()) ; ++ nEdge) { + for ( int nEdge = 0 ; nEdge < ssize( vBiPnts) ; ++ nEdge) { Point3d& ptL1 = vBiPnts[nEdge].first ; Point3d& ptL2 = vBiPnts[nEdge].second ; Vector3d vtDir = ptL2 - ptL1 ; vtDir.Normalize() ; INTDBLVECTOR vInters ; if ( IntersLineBox( ptL1, ptL2, BBoxCurr, vInters, true)) { - if ( int( vInters.size()) == 2) { + if ( ssize( vInters) == 2) { vEdgeToSave.push_back( nEdge) ; // Se edge sul bordo, lo spezzo if ( vInters[1].first == ILBT_OUT) @@ -2240,14 +2225,14 @@ GetBordersByTriaInBox( const SurfTriMesh& Stm, const BBox3d& BBoxCurr, double dL } unordered_set setBiPntsToSave( vEdgeToSave.begin(), vEdgeToSave.end()) ; int nCurr = 0 ; - for ( int i = 0 ; i < int( vBiPnts.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vBiPnts) ; ++ i) { if ( setBiPntsToSave.count( i)) vBiPnts[nCurr ++] = vBiPnts[i] ; } vBiPnts.resize( nCurr) ; #if DEBUG_FACE_SEARCH - for ( int i = 0 ; i < int( vBiPnts.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vBiPnts) ; ++ i) { ICurveLine* pLine = CreateCurveLine() ; pLine->Set( vBiPnts[i].first, vBiPnts[i].second) ; VT.emplace_back( pLine) ; @@ -2259,7 +2244,7 @@ GetBordersByTriaInBox( const SurfTriMesh& Stm, const BBox3d& BBoxCurr, double dL // Concateno i Segmenti interni al Box corrente BOOLVECTOR vIndInChain ; vIndInChain.resize( vBiPnts.size(), false) ; vCompoChain.reserve( vBiPnts.size()) ; - for ( int i = 0 ; i < int( vBiPnts.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vBiPnts) ; ++ i) { // Se già in Chain, passo al successivo if ( vIndInChain[i]) continue ; @@ -2273,7 +2258,7 @@ GetBordersByTriaInBox( const SurfTriMesh& Stm, const BBox3d& BBoxCurr, double dL vCompoChain.back().AddLine( ptCurrEnd) ; // Punti di controllo per Biforcazioni PNTVECTOR vPtForks ; vPtForks.reserve( vBiPnts.size()) ; - for ( int j = 0 ; j < int( vBiPnts.size()) ; ++ j) { + for ( int j = 0 ; j < ssize( vBiPnts) ; ++ j) { // Controllo un altro Edge non in Chain, recuperando i suoi estremi if ( i == j || vIndInChain[j]) continue ; @@ -2344,7 +2329,7 @@ GetBordersByTriaInBox( const SurfTriMesh& Stm, const BBox3d& BBoxCurr, double dL } #if DEBUG_FACE_SEARCH - for ( int i = 0 ; i < int( vCompoChain.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCompoChain) ; ++ i) { VT.emplace_back( vCompoChain[i].Clone()) ; VC.emplace_back( FUCHSIA) ; } @@ -2426,7 +2411,7 @@ CheckCurvesInBox( const SurfTriMesh& Stm, const COMPOVECTOR& vCompoChain, const return false ; #if DEBUG_FACE_SEARCH - for ( int _i = 0 ; _i < int( vCompoChain.size()) ; ++ _i) { + for ( int _i = 0 ; _i < ssize( vCompoChain) ; ++ _i) { VT.emplace_back( vCompoChain[_i].Clone()) ; VC.emplace_back( PURPLE) ; } @@ -2436,7 +2421,7 @@ CheckCurvesInBox( const SurfTriMesh& Stm, const COMPOVECTOR& vCompoChain, const CurveComposite CompoATmp, CompoBTmp ; // Se ho una sola curva, allora i bordi si sono uniti - if ( int( vCompoChain.size()) == 1) { + if ( ssize( vCompoChain) == 1) { // Approssimo la curva in Patches PolyLine PL ; if ( ! vCompoChain[0].ApproxWithLines( EPS_SMALL, EPS_ANG_SMALL, ICurve::APL_SPECIAL, PL)) @@ -2448,14 +2433,14 @@ CheckCurvesInBox( const SurfTriMesh& Stm, const COMPOVECTOR& vCompoChain, const CompoBTmp.FromPolyLine( matPL[0].back()) ; } // Se due curve di bordo - else if ( int( vCompoChain.size()) == 2) { + else if ( ssize( vCompoChain) == 2) { CompoATmp = vCompoChain[0] ; CompoBTmp = vCompoChain[1] ; } // Se più di due, cerco le due curve più vicine - else if ( int( vCompoChain.size()) > 2) { + else if ( ssize( vCompoChain) > 2) { INTDBLVECTOR vIndSqDist ; vIndSqDist.reserve( vCompoChain.size()) ; - for ( int nCrv = 0 ; nCrv < int( vCompoChain.size()) ; ++ nCrv) { + for ( int nCrv = 0 ; nCrv < ssize( vCompoChain) ; ++ nCrv) { vIndSqDist.emplace_back( make_pair( nCrv, 0.)) ; if ( ! DistPointCurve( ptSel, vCompoChain[nCrv]).GetSqDist( vIndSqDist.back().second)) return false ; @@ -2896,7 +2881,7 @@ CheckBordersInBox( CurveComposite& CompoA, CurveComposite& CompoB, return false ; double dMinSqDist = INFINITO ; int nTria = 0 ; - for ( int nT = 0 ; nT < int( vTBox.size()) ; ++ nT) { + for ( int nT = 0 ; nT < ssize( vTBox) ; ++ nT) { Triangle3d Tria ; if ( ! Stm.GetTriangle( vTBox[nT], Tria)) return false ; @@ -2924,10 +2909,10 @@ CheckBordersInBox( CurveComposite& CompoA, CurveComposite& CompoB, #endif // Se ottengo una sola curva, allora la striscia si è chiusa - if ( int( vCompoChain.size()) <= 1) + if ( ssize( vCompoChain) <= 1) return true ; // Se ottengo ancora due curve, allora la striscia non rispetta lo spessore minimo - bBreak = ( int( vCompoChain.size()) >= 2) ; + bBreak = ( ssize( vCompoChain) >= 2) ; if ( bBreak) { // Se devo fermare la ricerca e ho ancora CompoA e CompoB valide if ( bValidA && bValidB) { @@ -3302,7 +3287,7 @@ IsBorderACircle( const PolyLine& PL, double dLinTol, double dAngTol, Frame3d& fr // Per ogni coppia di punti calcolo la Distanza Massima e Minima dal centro del cerchio locale ( ORIG) double dSqMaxDist = 0. ; double dSqMinDist = INFINITO ; - for ( int i = 0 ; i < int( floor( 0.5 * int( vPts.size()))) ; i = i + 2) { + for ( int i = 0 ; i < ssize( vPts) / 2 ; i = i + 2) { double dSqLineDist = INFINITO ; DistPointLine( ORIG, vPts[i], vPts[i + 1]).GetSqDist( dSqLineDist) ; if ( dSqLineDist < dSqMinDist) { @@ -3562,7 +3547,7 @@ GetTrimmingFinalBorders( ICRVCOMPOPOVECTOR& vCompoBezierEdges, double dLinTol, d return false ; } // Se ho 1 curva, allora cerco di spezzarla - else if ( int( vCompoBezierEdges.size()) == 1) { + else if ( ssize( vCompoBezierEdges) == 1) { // Se sono presenti dei punti di rottura bool bOk = true ; if ( ! vBreakingPts.empty()) @@ -3577,7 +3562,7 @@ GetTrimmingFinalBorders( ICRVCOMPOPOVECTOR& vCompoBezierEdges, double dLinTol, d LOG_INFO( GetEGkLogger(), "Warning in Trimming : Breaking curves failed") ; } // Se ho 2 curve, perfetto ! - else if ( int( vCompoBezierEdges.size()) == 2) + else if ( ssize( vCompoBezierEdges) == 2) return true ; // Se più curve, errore else { @@ -3618,7 +3603,7 @@ GetTrimmingFinalBorders( CISURFPVECTOR& vpSurf, const SELVECTOR& vSurfFaces, dou // Recupero la superficie TriMesh complessiva PtrOwner pStm( nullptr) ; - if ( int( vpSurf.size()) == 1) { + if ( ssize( vpSurf) == 1) { const ISurf* pSurf = vpSurf[0] ; if ( pSurf == nullptr) return false ; @@ -3678,9 +3663,9 @@ GetTrimmingFinalBorders( CISURFPVECTOR& vpSurf, const SELVECTOR& vSurfFaces, dou } // Restituisco le curve orientate correttamente per la creazione della superficie di Bezier - erase_if( vCompoBezierEdges, []( ICurveComposite* pBezierEdge) { - return ( pBezierEdge == nullptr || ! pBezierEdge->IsValid() || pBezierEdge->GetCurveCount() == 0) ; - }) ; + erase_if( vCompoBezierEdges, + []( ICurveComposite* pBezierEdge) { + return ( pBezierEdge == nullptr || ! pBezierEdge->IsValid() || pBezierEdge->GetCurveCount() == 0) ;}) ; for ( int i = 0 ; i < ssize( vCompoBezierEdges) - 1 ; i += 2) { ManageRuledBorders( vCompoBezierEdges[i], vCompoBezierEdges[i+1]) ; // Essendo l'Offset fatto in negativo, entrambe le curve vanno invertite @@ -3707,7 +3692,7 @@ GetTrimmingBezierEdges( ICRVCOMPOPOVECTOR& vCompoRawEdges, double dLinTol, doubl #if DEBUG_EDGES VC.clear() ; VT.clear() ; - for ( int _i = 0 ; _i < int( vCompoRawEdges.size()) ; ++ _i) { + for ( int _i = 0 ; _i < ssize( vCompoRawEdges) ; ++ _i) { VT.emplace_back( vCompoRawEdges[_i]->Clone()) ; VC.emplace_back( RED) ; } @@ -3715,7 +3700,7 @@ GetTrimmingBezierEdges( ICRVCOMPOPOVECTOR& vCompoRawEdges, double dLinTol, doubl // Approssimo i bordi grezzi vBezierEdges.reserve( vCompoRawEdges.size()) ; - for ( int i = 0 ; i < int( vCompoRawEdges.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCompoRawEdges) ; ++ i) { PtrOwner pCompoTmp( CloneCurveComposite( vCompoRawEdges[i])) ; if ( IsNull( pCompoTmp) || ! ApproxBorder( *GetBasicCurveComposite( pCompoTmp), dMyLinTol, dMyAngTol) || @@ -3726,15 +3711,15 @@ GetTrimmingBezierEdges( ICRVCOMPOPOVECTOR& vCompoRawEdges, double dLinTol, doubl } // Restituisco le curve orientate correttamente per la creazione della superficie di Bezier - erase_if( vBezierEdges, []( ICurveComposite* pBezierEdge) { - return ( pBezierEdge == nullptr || ! pBezierEdge->IsValid() || pBezierEdge->GetCurveCount() == 0) ; - }) ; + erase_if( vBezierEdges, + []( ICurveComposite* pBezierEdge) { + return ( pBezierEdge == nullptr || ! pBezierEdge->IsValid() || pBezierEdge->GetCurveCount() == 0) ;}) ; for ( int i = 0 ; i < ssize( vBezierEdges) - 1 ; i += 2) ManageRuledBorders( vBezierEdges[i], vBezierEdges[i+1]) ; #if DEBUG_EDGES VC.clear() ; VT.clear() ; - for ( int _i = 0 ; _i < int( vBezierEdges.size()) ; ++ _i) { + for ( int _i = 0 ; _i < ssize( vBezierEdges) ; ++ _i) { VT.emplace_back( vBezierEdges[_i]->Clone()) ; VC.emplace_back( ORANGE) ; } @@ -3776,7 +3761,7 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, ICURVEPOVECTOR vCrv ; pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ; vSyncPoints.reserve( vCrv.size()) ; - for ( int i = 0 ; i < int( vCrv.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vCrv) ; ++ i) { if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) { #if DEBUG_SYNC_POINTS VT.emplace_back( vCrv[i]->Clone()) ; @@ -4035,14 +4020,14 @@ GetTrimmingAdjSurfs( const CISURFPVECTOR& vSurf, const CISURFPVECTOR& vOtherSurf // Recupero le Patch delle superfici SURFPATCHESVECTOR vSurfPatches ; vSurfPatches.reserve( vSurf.size() + vOtherSurf.size()) ; // --- Superfici Selezionate - for ( int nS = 0 ; nS < int( vSurf.size()) ; ++ nS) { + for ( int nS = 0 ; nS < ssize( vSurf) ; ++ nS) { vSurfPatches.emplace_back( SurfPatches()) ; vSurfPatches.back().pSurf = vSurf[nS] ; if ( ! CalcSurfPatch( vSurf[nS], dLinTol, dAngTol, vSurfPatches.back())) return false ; } // --- Altre Superfici - for ( int nS = 0 ; nS < int( vOtherSurf.size()) ; ++ nS) { + for ( int nS = 0 ; nS < ssize( vOtherSurf) ; ++ nS) { vSurfPatches.emplace_back( SurfPatches()) ; vSurfPatches.back().pSurf = vOtherSurf[nS] ; if ( ! CalcSurfPatch( vOtherSurf[nS], dLinTol, dAngTol, vSurfPatches.back())) @@ -4225,7 +4210,7 @@ GetTrimmingAdjSurfs( const CISURFPVECTOR& vSurf, const CISURFPVECTOR& vOtherSurf // della tolleranza angolare INTVECTOR vSurfToCheck ; INTSET setSurf ; - for ( int i = 0 ; i < int( vSurf.size()) ; ++ i) + for ( int i = 0 ; i < ssize( vSurf) ; ++ i) vSurfToCheck.push_back( i) ; // Finchè ho una superficie da analizzare @@ -4341,7 +4326,7 @@ GetTrimmingAdjSurfs( const CISURFPVECTOR& vSurf, const CISURFPVECTOR& vOtherSurf #endif vSurfToCheck.emplace_back( nOtherSurf) ; OtherPatch.bErase = true ; - if ( nOtherSurf >= int( vSurf.size()) && + if ( nOtherSurf >= ssize( vSurf) && find( vIndOtherSurf.begin(), vIndOtherSurf.end(), nOtherSurf - ssize( vSurf)) == vIndOtherSurf.end()) vIndOtherSurf.push_back( nOtherSurf - ssize( vSurf)) ; } @@ -4466,107 +4451,105 @@ GetTrimmingHoleBorders( const CISURFPVECTOR& vpSurf, const Point3d& ptRef, doubl // Vedo se ci sono curve da accoppiare tra di loro vHoleBorders.reserve( vHoles.size()) ; - if ( ssize( vHoles) > 1) { - for ( int i = 0 ; i < ssize( vHoles) - 1 ; ++ i) { + for ( int i = 0 ; i < ssize( vHoles) - 1 ; ++ i) { + // Recupero la curva corrente, se non presente allora passo alla successiva + if ( IsNull( vHoles[i].pCompoHole)) + continue ; + int nIndJ = -1 ; + // Scorro le curve successive + for ( int j = i + 1 ; nIndJ == -1 && j < ssize( vHoles) ; ++ j) { // Recupero la curva corrente, se non presente allora passo alla successiva if ( IsNull( vHoles[i].pCompoHole)) continue ; - int nIndJ = -1 ; - // Scorro le curve successive - for ( int j = i + 1 ; nIndJ == -1 && j < ssize( vHoles) ; ++ j) { - // Recupero la curva corrente, se non presente allora passo alla successiva - if ( IsNull( vHoles[i].pCompoHole)) - continue ; - // Se il tipo è differente non possono essere in coppia - if ( vHoles[i].nType != vHoles[j].nType) - continue ; - // Essendo della stessa topologia, verifico i parametri - bool bCouple = false ; - Vector3d vtCenCen ; - if ( vHoles[i].nType == HoleType::CIRCLE) { - bCouple = ( abs( vHoles[i].dRad - vHoles[j].dRad) < dMyEdgeLinTol && - AreSameOrOppositeVectorEpsilon( vHoles[i].frCompo.VersZ(), vHoles[j].frCompo.VersZ(), dMyEdgeLinTol)) ; + // Se il tipo è differente non possono essere in coppia + if ( vHoles[i].nType != vHoles[j].nType) + continue ; + // Essendo della stessa topologia, verifico i parametri + bool bCouple = false ; + Vector3d vtCenCen ; + if ( vHoles[i].nType == HoleType::CIRCLE) { + bCouple = ( abs( vHoles[i].dRad - vHoles[j].dRad) < dMyEdgeLinTol && + AreSameOrOppositeVectorEpsilon( vHoles[i].frCompo.VersZ(), vHoles[j].frCompo.VersZ(), dMyEdgeLinTol)) ; + if ( bCouple) { + vtCenCen = ( vHoles[i].frCompo.Orig() - vHoles[j].frCompo.Orig()) ; + bCouple = ( vtCenCen.SqLen() > dMyEdgeLinTol * dMyEdgeLinTol) ; if ( bCouple) { - vtCenCen = ( vHoles[i].frCompo.Orig() - vHoles[j].frCompo.Orig()) ; - bCouple = ( vtCenCen.SqLen() > dMyEdgeLinTol * dMyEdgeLinTol) ; - if ( bCouple) { - bCouple = ( vtCenCen.Normalize() && - AreSameOrOppositeVectorEpsilon( vtCenCen, vHoles[i].frCompo.VersZ(), dMyEdgeLinTol)) ; - } + bCouple = ( vtCenCen.Normalize() && + AreSameOrOppositeVectorEpsilon( vtCenCen, vHoles[i].frCompo.VersZ(), dMyEdgeLinTol)) ; } } - else if ( vHoles[i].nType == HoleType::BUTTONHOLE) { - bCouple = ( abs( vHoles[i].dRad - vHoles[j].dRad) < dMyEdgeLinTol && - abs( vHoles[i].dLen - vHoles[j].dLen) < dMyEdgeLinTol && - AreSameOrOppositeVectorEpsilon( vHoles[i].frCompo.VersZ(), vHoles[j].frCompo.VersZ(), dMyEdgeLinTol)) ; - if ( bCouple) { - vtCenCen = ( vHoles[i].frCompo.Orig() - vHoles[j].frCompo.Orig()) ; - bCouple = ( vtCenCen.SqLen() > dMyEdgeLinTol * dMyEdgeLinTol) ; - if ( bCouple) { - bCouple = ( vtCenCen.Normalize() && - AreSameOrOppositeVectorEpsilon( vtCenCen, vHoles[i].frCompo.VersZ(), dMyEdgeLinTol)) ; - } - } - } - if ( bCouple) - nIndJ = j ; } + else if ( vHoles[i].nType == HoleType::BUTTONHOLE) { + bCouple = ( abs( vHoles[i].dRad - vHoles[j].dRad) < dMyEdgeLinTol && + abs( vHoles[i].dLen - vHoles[j].dLen) < dMyEdgeLinTol && + AreSameOrOppositeVectorEpsilon( vHoles[i].frCompo.VersZ(), vHoles[j].frCompo.VersZ(), dMyEdgeLinTol)) ; + if ( bCouple) { + vtCenCen = ( vHoles[i].frCompo.Orig() - vHoles[j].frCompo.Orig()) ; + bCouple = ( vtCenCen.SqLen() > dMyEdgeLinTol * dMyEdgeLinTol) ; + if ( bCouple) { + bCouple = ( vtCenCen.Normalize() && + AreSameOrOppositeVectorEpsilon( vtCenCen, vHoles[i].frCompo.VersZ(), dMyEdgeLinTol)) ; + } + } + } + if ( bCouple) + nIndJ = j ; + } - // Determino l'indice della curva da conservare - int nInd = i ; - // Se curva non in coppia, allora ho finito, altrimenti devo sceglierne una - if ( nIndJ != -1) { - int nIndToErase = nIndJ ; - // Recupero i due Box - BBox3d BBoxI ; vHoles[i].pCompoHole->GetLocalBBox( BBoxI) ; - BBox3d BBoxJ ; vHoles[nIndJ].pCompoHole->GetLocalBBox( BBoxJ) ; - // Recupero le Coordinate massime di ZGlob - double dZI = BBoxI.GetMax().z ; - double dZJ = BBoxJ.GetMax().z ; - // Se le 2 curve hanno ZGlob massime differente tra loro - if ( abs( dZI - dZJ) > 5. * EPS_SMALL) { - // Tengo la Curva con ZGlob massima - if ( dZJ > dZI) + // Determino l'indice della curva da conservare + int nInd = i ; + // Se curva non in coppia, allora ho finito, altrimenti devo sceglierne una + if ( nIndJ != -1) { + int nIndToErase = nIndJ ; + // Recupero i due Box + BBox3d BBoxI ; vHoles[i].pCompoHole->GetLocalBBox( BBoxI) ; + BBox3d BBoxJ ; vHoles[nIndJ].pCompoHole->GetLocalBBox( BBoxJ) ; + // Recupero le Coordinate massime di ZGlob + double dZI = BBoxI.GetMax().z ; + double dZJ = BBoxJ.GetMax().z ; + // Se le 2 curve hanno ZGlob massime differente tra loro + if ( abs( dZI - dZJ) > 5. * EPS_SMALL) { + // Tengo la Curva con ZGlob massima + if ( dZJ > dZI) + swap( nInd, nIndToErase) ; + } + // Se invece le ZGlob sono circa uguali + else { + // Tengo la Curva più distante dal punto di Riferimento ( se Valido) + if ( ptRef.IsValid()) { + double dSqDistI = INFINITO, dSqDistJ = INFINITO ; + DistPointCurve( ptRef, *vHoles[i].pCompoHole).GetSqDist( dSqDistI) ; + DistPointCurve( ptRef, *vHoles[nIndJ].pCompoHole).GetSqDist( dSqDistJ) ; + if ( dSqDistJ > dSqDistI) swap( nInd, nIndToErase) ; } - // Se invece le ZGlob sono circa uguali - else { - // Tengo la Curva più distante dal punto di Riferimento ( se Valido) - if ( ptRef.IsValid()) { - double dSqDistI = INFINITO, dSqDistJ = INFINITO ; - DistPointCurve( ptRef, *vHoles[i].pCompoHole).GetSqDist( dSqDistI) ; - DistPointCurve( ptRef, *vHoles[nIndJ].pCompoHole).GetSqDist( dSqDistJ) ; - if ( dSqDistJ > dSqDistI) - swap( nInd, nIndToErase) ; - } - } - // Elimino la curva non significativa delle 2 - vHoles[nIndToErase].pCompoHole.Reset() ; } - - // Imposto Estrusione alla curva nInd-esima - Vector3d vtExtr = vHoles[nInd].frCompo.VersZ() ; - // Se Estrusione perpendicolare a Z_AX - if ( OrthoCompo( Z_AX, vtExtr).Len() > 1 - 5. * EPS_SMALL) { - // Se punto di Riferimento valido - if ( ptRef.IsValid()) { - Vector3d vtCenCen = vHoles[nInd].frCompo.Orig() - ptRef ; - vtCenCen.Normalize() ; - vHoles[nInd].pCompoHole->SetExtrusion( ( vtExtr * vtCenCen > 0.) ? vtExtr : - vtExtr) ; - } - else - vHoles[nInd].pCompoHole->SetExtrusion( vtExtr) ; - } - // Se estrusione non perpendicolare a Z_AX - else - vHoles[nInd].pCompoHole->SetExtrusion( ( vtExtr * Z_AX > 0.) ? vtExtr : - vtExtr) ; - - // Imposso Spessore alla curva nInd-esima - vHoles[nInd].pCompoHole->SetThickness( - dMyEdgeThick) ; - - // Memorizzo la curva nInd-esima - vHoleBorders.emplace_back( Release( vHoles[nInd].pCompoHole)) ; + // Elimino la curva non significativa delle 2 + vHoles[nIndToErase].pCompoHole.Reset() ; } + + // Imposto Estrusione alla curva nInd-esima + Vector3d vtExtr = vHoles[nInd].frCompo.VersZ() ; + // Se Estrusione perpendicolare a Z_AX + if ( OrthoCompo( Z_AX, vtExtr).Len() > 1 - 5. * EPS_SMALL) { + // Se punto di Riferimento valido + if ( ptRef.IsValid()) { + Vector3d vtCenCen = vHoles[nInd].frCompo.Orig() - ptRef ; + vtCenCen.Normalize() ; + vHoles[nInd].pCompoHole->SetExtrusion( ( vtExtr * vtCenCen > 0.) ? vtExtr : - vtExtr) ; + } + else + vHoles[nInd].pCompoHole->SetExtrusion( vtExtr) ; + } + // Se estrusione non perpendicolare a Z_AX + else + vHoles[nInd].pCompoHole->SetExtrusion( ( vtExtr * Z_AX > 0.) ? vtExtr : - vtExtr) ; + + // Imposso Spessore alla curva nInd-esima + vHoles[nInd].pCompoHole->SetThickness( - dMyEdgeThick) ; + + // Memorizzo la curva nInd-esima + vHoleBorders.emplace_back( Release( vHoles[nInd].pCompoHole)) ; } return true ; diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index ba0c1fa..63034bb 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -1601,9 +1601,9 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c PNTVECTOR vPntTopStartBack(3) ; PNTVECTOR vPntTopEndBack(3) ; if ( nSub > 1) { - if( bTopIsPivot) + if ( bTopIsPivot) vtDirTop = vtDirTip ; - if( bTipIsPivot) + if ( bTipIsPivot) vtDirTip = vtDirTop ; // determino in che modo collegare il cilindro iniziale con quello finale Vector3d vtTopBaseEnd = vtDirTop - (( vtDirTop * vtLe) * vtLe) ; @@ -1812,7 +1812,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c } } - if( ! bTopIsPivot) { + if ( ! bTopIsPivot) { // superiori if ( dSide > 0) { PNTVECTOR vPntTop01 = cBezTopStartF1->GetAllControlPoints(); From 5ad9c48285d7a8e9249bc16d37018e931b69c508 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Mon, 9 Feb 2026 11:21:06 +0100 Subject: [PATCH 06/22] EgtGeomKernel : - in Trimming rimozione memory Leaks. --- Trimming.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Trimming.cpp b/Trimming.cpp index 8c04f37..956a4fc 100644 --- a/Trimming.cpp +++ b/Trimming.cpp @@ -286,7 +286,7 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL) // Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante // Patches di curve di Bezier static bool -ApproxBorder( CurveComposite& CrvCompo, double dLinTol, double dAngTol) +ApproxBorder( ICurveComposite& CrvCompo, double dLinTol, double dAngTol) { // Controllo dei parametri if ( ! CrvCompo.IsValid()) @@ -361,7 +361,7 @@ ApproxBorder( CurveComposite& CrvCompo, double dLinTol, double dAngTol) #endif if ( CCApprox.IsValid()) - CrvCompo.CopyFrom( CCApprox.Clone()) ; + CrvCompo.CopyFrom( &CCApprox) ; return true ; } @@ -706,7 +706,10 @@ ManagePatches( const POLYLINEVECTOR& vPLBorders, double dLinTol, double dAngTol, for ( auto Iter = setSplitPar.begin() ; Iter != setSplitPar.end() ; ++ Iter) { PtrOwner pCrvPatch( CurrCompo.CopyParamRange( dLastPar, *Iter)) ; if ( ! IsNull( pCrvPatch) && pCrvPatch->IsValid()) { // ad esempio per punti coincidenti - vCompoPatches.emplace_back( *ConvertCurveToBasicComposite( Release( pCrvPatch))) ; + PtrOwner pCompoPatch( ConvertCurveToBasicComposite( Release( pCrvPatch))) ; + if ( IsNull( pCompoPatch) || ! pCompoPatch->IsValid()) + return false ; + vCompoPatches.emplace_back( *Get( pCompoPatch)) ; Point3d ptStart ; vCompoPatches.back().GetStartPoint( ptStart) ; Point3d ptEnd ; vCompoPatches.back().GetEndPoint( ptEnd) ; newSimpleBorder.emplace_back( ptStart, ptEnd, nCurrBorder, false) ; @@ -3655,10 +3658,10 @@ GetTrimmingFinalBorders( CISURFPVECTOR& vpSurf, const SELVECTOR& vSurfFaces, dou if ( IsNull( pCompoLoopExtr) || ! pCompoLoopExtr->FromPolyLine( PLLoopExtr)) continue ; vCompoBezierEdges.emplace_back( Release( pCompoLoop)) ; - if ( ! ApproxBorder( *GetBasicCurveComposite( vCompoBezierEdges.back()), dMyLinTol, dMyAngTol)) + if ( ! ApproxBorder( *vCompoBezierEdges.back(), dMyLinTol, dMyAngTol)) return false ; vCompoBezierEdges.emplace_back( Release( pCompoLoopExtr)) ; - if ( ! ApproxBorder( *GetBasicCurveComposite( vCompoBezierEdges.back()), dMyLinTol, dMyAngTol)) + if ( ! ApproxBorder( *vCompoBezierEdges.back(), dMyLinTol, dMyAngTol)) return false ; } @@ -3703,7 +3706,7 @@ GetTrimmingBezierEdges( ICRVCOMPOPOVECTOR& vCompoRawEdges, double dLinTol, doubl for ( int i = 0 ; i < ssize( vCompoRawEdges) ; ++ i) { PtrOwner pCompoTmp( CloneCurveComposite( vCompoRawEdges[i])) ; if ( IsNull( pCompoTmp) || - ! ApproxBorder( *GetBasicCurveComposite( pCompoTmp), dMyLinTol, dMyAngTol) || + ! ApproxBorder( *pCompoTmp, dMyLinTol, dMyAngTol) || ! vBezierEdges.emplace_back( Release( pCompoTmp))) { LOG_ERROR( GetEGkLogger(), "Error in Trimming : Approxing edge failed") ; return false ; @@ -4176,7 +4179,10 @@ GetTrimmingAdjSurfs( const CISURFPVECTOR& vSurf, const CISURFPVECTOR& vOtherSurf for ( auto Iter = setSplitPar.begin() ; Iter != setSplitPar.end() ; ++ Iter) { PtrOwner pCrvPatch( CurrCompo.CopyParamRange( dLastPar, *Iter)) ; if ( ! IsNull( pCrvPatch) && pCrvPatch->IsValid()) { - vCompoPatches.emplace_back( *ConvertCurveToBasicComposite( Release( pCrvPatch))) ; + PtrOwner pCompoPatch( ConvertCurveToBasicComposite( Release( pCrvPatch))) ; + if ( IsNull( pCompoPatch) || ! pCompoPatch->IsValid()) + return false ; + vCompoPatches.emplace_back( *Get( pCompoPatch)) ; Point3d ptStart ; vCompoPatches.back().GetStartPoint( ptStart) ; Point3d ptEnd ; vCompoPatches.back().GetEndPoint( ptEnd) ; newSimpleBorder.emplace_back( ptStart, ptEnd, nCurrBorder, false) ; From 0987496cafaadf559a7d259aa429e7226331e45b Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 9 Feb 2026 12:48:38 +0100 Subject: [PATCH 07/22] EgtGeomKernel : - piccoli aggiustamenti. --- Trimming.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Trimming.cpp b/Trimming.cpp index 956a4fc..4df8f49 100644 --- a/Trimming.cpp +++ b/Trimming.cpp @@ -286,7 +286,7 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL) // Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante // Patches di curve di Bezier static bool -ApproxBorder( ICurveComposite& CrvCompo, double dLinTol, double dAngTol) +ApproxBorder( CurveComposite& CrvCompo, double dLinTol, double dAngTol) { // Controllo dei parametri if ( ! CrvCompo.IsValid()) @@ -1517,7 +1517,6 @@ GetBorderByExtrusion( const SurfTriMesh* pStm, double dThick, double dLinTol, do double dU ; bool bFound = PLLoop.GetFirstUPoint( &dU, &ptP) ; double dPar = -1 ; - bool bFirst = true ; while ( bFound) { // Recupero il TriangoloEx associato al punto Triangle3dEx Tria ; @@ -3658,10 +3657,10 @@ GetTrimmingFinalBorders( CISURFPVECTOR& vpSurf, const SELVECTOR& vSurfFaces, dou if ( IsNull( pCompoLoopExtr) || ! pCompoLoopExtr->FromPolyLine( PLLoopExtr)) continue ; vCompoBezierEdges.emplace_back( Release( pCompoLoop)) ; - if ( ! ApproxBorder( *vCompoBezierEdges.back(), dMyLinTol, dMyAngTol)) + if ( ! ApproxBorder( *GetBasicCurveComposite( vCompoBezierEdges.back()), dMyLinTol, dMyAngTol)) return false ; vCompoBezierEdges.emplace_back( Release( pCompoLoopExtr)) ; - if ( ! ApproxBorder( *vCompoBezierEdges.back(), dMyLinTol, dMyAngTol)) + if ( ! ApproxBorder( *GetBasicCurveComposite( vCompoBezierEdges.back()), dMyLinTol, dMyAngTol)) return false ; } @@ -3706,7 +3705,7 @@ GetTrimmingBezierEdges( ICRVCOMPOPOVECTOR& vCompoRawEdges, double dLinTol, doubl for ( int i = 0 ; i < ssize( vCompoRawEdges) ; ++ i) { PtrOwner pCompoTmp( CloneCurveComposite( vCompoRawEdges[i])) ; if ( IsNull( pCompoTmp) || - ! ApproxBorder( *pCompoTmp, dMyLinTol, dMyAngTol) || + ! ApproxBorder( *GetBasicCurveComposite( pCompoTmp), dMyLinTol, dMyAngTol) || ! vBezierEdges.emplace_back( Release( pCompoTmp))) { LOG_ERROR( GetEGkLogger(), "Error in Trimming : Approxing edge failed") ; return false ; @@ -4097,14 +4096,16 @@ GetTrimmingAdjSurfs( const CISURFPVECTOR& vSurf, const CISURFPVECTOR& vOtherSurf SurfPatches& OtherSurfPatch = vSurfPatches[j] ; // Recupero i Suoi Bordi e i Parametri associati const SimpleBorderVector& vSimpleOtherBorder = OtherSurfPatch.vBorderPatches ; - const COMPOVECTOR& vCompoBorders = OtherSurfPatch.vCompoBorders ; + #if DEBUG_SURF_PATCHES + const COMPOVECTOR& vCompoBorders = OtherSurfPatch.vCompoBorders ; + #endif // Scorro i suoi bordi for ( int nOtherBorder = 0 ; nOtherBorder < ssize( vSimpleOtherBorder) ; ++ nOtherBorder) { // Recupero le Patch associate const SimpleBorder& vPatchOtherBorder = vSimpleOtherBorder[nOtherBorder] ; // Recupero la Composita associata al Bordo - const CurveComposite& OtherCompoBorder = vCompoBorders[nOtherBorder] ; #if DEBUG_SURF_PATCHES + const CurveComposite& OtherCompoBorder = vCompoBorders[nOtherBorder] ; VT.emplace_back( OtherCompoBorder.Clone()) ; VC.emplace_back( BLACK) ; #endif From e87ef178c2e1dc6c003843a73cdb644e2747ff14 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 10 Feb 2026 15:42:03 +0100 Subject: [PATCH 08/22] EgtGeomKernel : - correzione alla distanza punto- curva di bezier. --- DistPointCrvAux.cpp | 17 +++++++++++++++-- DistPointCrvBezier.cpp | 11 +++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/DistPointCrvAux.cpp b/DistPointCrvAux.cpp index fee8316..7afeb91 100644 --- a/DistPointCrvAux.cpp +++ b/DistPointCrvAux.cpp @@ -116,6 +116,7 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve, vtDiff = ptQ - ptP ; // angolo tra vettore e tangente dTemp = vtDer1 * vtDiff ; + bool bEquiverse = dTemp > 0 ; if ( abs( dTemp) > EPS_ZERO) dSqCosA = dTemp * dTemp / ( vtDer1.SqLen() * vtDiff.SqLen()) ; else @@ -123,8 +124,20 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve, // stima prossimo valore del parametro (Newton : Unext = U - F(U) / F'(U)) dPrevPar = dPar ; dTemp = vtDer2 * vtDiff + vtDer1.SqLen() ; - if ( abs( dTemp) > EPS_ZERO) - dPar = dPrevPar - ( vtDer1 * vtDiff) / dTemp ; + + // se il coseno tra questi due vettori è troppo grande potrei aver avuto una cattiva stima iniziale + // provo quindi ad aggiustare a mano, anziché usare il segno suggerito da newton, che con queste premesse potrebbe divergere + double dCos75 = 0.2588 ; + if ( abs( dTemp) > EPS_ZERO) { + double dDelta = ( vtDer1 * vtDiff) / dTemp ; + if ( dSqCosA > dCos75) { + if ( ( bEquiverse && dDelta > 0) || ( ! bEquiverse && dDelta < 0)) + dDelta *= -1 ; + dPar = dPrevPar + dDelta ; + } + else + dPar = dPrevPar - dDelta ; + } // clipping parametro if ( dPar < approxMin.dParMin) { if ( approxMin.bParMinSing && ! bClampedFromSing) { diff --git a/DistPointCrvBezier.cpp b/DistPointCrvBezier.cpp index 9c324a5..6106698 100644 --- a/DistPointCrvBezier.cpp +++ b/DistPointCrvBezier.cpp @@ -42,6 +42,17 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier& if ( ! CrvBez.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_STD, PL)) return ; + int nDeg = CrvBez.GetDegree() ; + if ( PL.GetPointNbr() < nDeg + 1) { + // costruisco una polilinea con un numero di curve scelto in base al grado della curva + PL.Clear() ; + for ( int i = 0 ; i <= nDeg + 1 ; ++i) { + double dU = double(i) / (nDeg + 1) ; + Point3d ptBez ; + CrvBez.GetPointD1D2( dU, ICurve::Side::FROM_MINUS, ptBez) ; + PL.AddUPoint( dU, ptBez) ; + } + } // cerco la minima distanza per la polilinea MDCVECTOR vApproxMin ; if ( ! CalcMinDistPointPolyLine( ptP, PL, dLinTol, vApproxMin)) From b66522de338da43481fcc0cd45d7f454c5bdf721 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 10 Feb 2026 17:03:46 +0100 Subject: [PATCH 09/22] EgtGeomKernel 3.1a6 : - in CalcPocketing migliorati i casi ottimizzati a Trapezio. --- CalcPocketing.cpp | 166 +++++++++++++++++++++++++++++++++++++--------- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes 2 files changed, 133 insertions(+), 33 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 36cb139..0853045 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -722,7 +722,7 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, boo //---------------------------------------------------------------------------- static bool -AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveComposite* pCrv ) +AssignFeedSpiralOpt( int nOptType, const PocketParams& PockParams, ICurveComposite* pCrv ) { // controllo della curva corrente if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0) @@ -732,24 +732,24 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC if ( ! PockParams.bCalcFeed) return AssignMaxFeed( pCrv, PockParams) ; - switch ( PockParams.nType) { - case POCKET_SPIRALIN : - if ( nOptType == 0) { // Spirale dall'Esterno - for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { - if ( u == 0) // prima circonferenza - pCrv->SetCurveTempParam( 0, GetMinFeed( PockParams), 0) ; - else // semi cerchi in tangenza - pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ; - } + if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_CONFORMAL_ZIGZAG || + PockParams.nType == POCKET_CONFORMAL_ONEWAY) { + if ( nOptType == 0) { // Spirale dall'Esterno + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { + if ( u == 0) // prima circonferenza + pCrv->SetCurveTempParam( 0, GetMinFeed( PockParams), 0) ; + else // semi cerchi in tangenza + pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ; } - else if ( nOptType == 1) { // Trapezoidi - for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) - pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; - } - break ; + } + else if ( nOptType == 1) { // Trapezoidi + for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) + pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; + } + } /* NB. Essendo la funzione CalcSpiral richiamata sia per lo SpiralIN che per lo SpiralOUT le curve sono sempre orientate nello stesso modo, solamente alla fine viene invertita la curva finale per la svuotatura... */ - case POCKET_SPIRALOUT : + else { if ( nOptType == 0) { // Spiral verso l'esterno for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { if ( u > pCrv->GetCurveCount() - 3) // prime semi circonferenze @@ -762,9 +762,6 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; } - break ; - default : - break ; } return true ; @@ -3625,6 +3622,91 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double return true ; } +//---------------------------------------------------------------------------- +static bool +GetZigZagOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParam, + ICurveComposite* pCrvRes) +{ + // controllo dei parametri + if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid()) + return false ; + pCrvRes->Clear() ; + + // ricavo la curva di bordo del chunk corrente + PtrOwner pCrvBorder( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; + if ( IsNull( pCrvBorder) || ! pCrvBorder->IsValid()) + return false ; + pCrvBorder->MergeCurves( 10. * EPS_SMALL, 10. * EPS_ANG_SMALL, true, true) ; + pCrvBorder->SetExtrusion( pSfrChunk->GetNormVersor()) ; + + /* TRAPEZI + - E' richiesto che una dimensione del box della curva sia compatibile con il primo Offset, il + quale sarebbe una singola curva aperta + */ + PtrOwner pCrvTrap( CreateCurveComposite()) ; + if ( IsNull( pCrvTrap)) + return false ; + Frame3d frTrap ; + double dPocketSize ; + int nBase, nSecondBase ; + bool bOkTrap = GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) ; + if ( bOkTrap && pCrvTrap->IsValid()) { + // se la base principale e secondaria sono entrambe chiuse, trascuro il SideStep + int nTmpProp = TEMP_PROP_INVALID ; + bool bBaseCL = ( pCrvTrap->GetCurveTempProp( nBase, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) ; + bool bSecondBaseCL = ( pCrvTrap->GetCurveTempProp( nSecondBase, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) ; + if ( ! bBaseCL || ! bSecondBaseCL) + bOkTrap = ( dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ; + } + if ( bOkTrap && pCrvTrap->IsValid()) { + pCrvTrap->SetExtrusion( Z_AX) ; + CalcTrapezoidSpiral( pCrvTrap, frTrap, dPocketSize, nBase, nSecondBase, PockParam, pCrvRes, bOkTrap) ; + if ( bOkTrap) { + // verifico che tale curva non interferisca con la regione limite + if ( PockParam.SfrLimit.IsValid()) { + double dOffsCheck = PockParam.dRad + PockParam.dRadialOffset - 50. * EPS_SMALL ; // restrittivo per sicurezza + PtrOwner pSfrToolShape( GetSurfFlatRegionFromFatCurve( pCrvRes->Clone(), dOffsCheck, false, false)) ; + bOkTrap = ( ! IsNull( pSfrToolShape) && pSfrToolShape->IsValid()) ; + if ( bOkTrap) { + bOkTrap = ( pSfrToolShape->Intersect( PockParam.SfrLimit) && + ! pSfrToolShape->IsValid()) ; + if ( ! bOkTrap) + pCrvRes->Clear() ; + } + } + if ( bOkTrap) { + // calcolo eventuali uscite e ingressi + if ( pCrvRes->GetTempProp( 0) > 0) { + // Recupero gli estremi della curva corrente e la inverto in base alla Testa + Point3d ptS ; pCrvRes->GetStartPoint( ptS) ; + Point3d ptE ; pCrvRes->GetEndPoint( ptE) ; + Point3d ptSGlob = GetToGlob( ptS, PockParam.frLocXY) ; + Point3d ptEGlob = GetToGlob( ptE, PockParam.frLocXY) ; + if ( ( PockParam.bAboveHead && ptEGlob.z > ptSGlob.z) || + ( ! PockParam.bAboveHead && ptEGlob.z < ptSGlob.z)) + pCrvRes->Invert() ; + if ( PockParam.bInvert) + pCrvRes->Invert() ; + // Assegno la Feed + AssignFeedSpiralOpt( 1, PockParam, pCrvRes) ; + // Calcolo eventuale entrata da fuori + Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ; + vtRef.Invert() ; + bool bIsStartExtended = false ; + if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended)) + return false ; + } + else { + if ( PockParam.bInvert) + pCrvRes->Invert() ; + } + } + } + } + + return true ; +} + //---------------------------------------------------------------------------- static bool GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParam, @@ -3714,8 +3796,15 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& Frame3d frTrap ; double dPocketSize ; int nBase, nSecondBase ; - bool bOkTrap = ( GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) && - dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ; + bool bOkTrap = GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) ; + if ( bOkTrap && pCrvTrap->IsValid()) { + // se la base principale e secondaria sono entrambe chiuse, trascuro il SideStep + int nTmpProp = TEMP_PROP_INVALID ; + bool bBaseCL = ( pCrvTrap->GetCurveTempProp( nBase, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) ; + bool bSecondBaseCL = ( pCrvTrap->GetCurveTempProp( nSecondBase, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) ; + if ( ! bBaseCL || ! bSecondBaseCL) + bOkTrap = ( dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ; + } if ( bOkTrap && pCrvTrap->IsValid()) { pCrvTrap->SetExtrusion( Z_AX) ; CalcTrapezoidSpiral( pCrvTrap, frTrap, dPocketSize, nBase, nSecondBase, PockParam, pCrvRes, bOkTrap) ; @@ -3745,6 +3834,8 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& pCrvRes->Invert() ; if ( PockParam.bInvert) pCrvRes->Invert() ; + // Assegno la Feed + AssignFeedSpiralOpt( 1, PockParam, pCrvRes) ; // Calcolo eventuale entrata da fuori Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ; vtRef.Invert() ; @@ -3798,23 +3889,31 @@ GetPocketingOptimizedCurves( ISurfFlatRegion* pSfr, const PocketParams& PockPara PockParam.nType == POCKET_CONFORMAL_ZIGZAG || PockParam.nType == POCKET_CONFORMAL_ONEWAY) { // curva da resituire PtrOwner pCrvOptSpiral( CreateCurveComposite()) ; - if ( IsNull( pCrvOptSpiral) || - ! GetSpiralOptimizedCurves( pSfrChunk, PockParam, pCrvOptSpiral)) + if ( IsNull( pCrvOptSpiral) || + ! GetSpiralOptimizedCurves( pSfrChunk, PockParam, pCrvOptSpiral)) return false ; // se ho ricavato una curva ottimizzata if ( ! IsNull( pCrvOptSpiral) && pCrvOptSpiral->IsValid() && pCrvOptSpiral->GetCurveCount() > 0) { - vCrvOptCurves.emplace_back( Release( pCrvOptSpiral)) ; + vCrvOptCurves.emplace_back( Release( pCrvOptSpiral)) ; + pSfr->EraseChunk( nCurrChunk) ; + } + else + ++ nCurrChunk ; + } + else if ( PockParam.nType == POCKET_ZIGZAG || PockParam.nType == POCKET_ONEWAY) { + // curva da restituire + PtrOwner pCrvOptZigZag( CreateCurveComposite()) ; + if ( IsNull( pCrvOptZigZag) || + ! GetZigZagOptimizedCurves( pSfrChunk, PockParam, pCrvOptZigZag)) + return false ; + // se ho ricavato una curva ottimizzata + if ( ! IsNull( pCrvOptZigZag) && pCrvOptZigZag->IsValid() && pCrvOptZigZag->GetCurveCount() > 0) { + vCrvOptCurves.emplace_back( Release( pCrvOptZigZag)) ; pSfr->EraseChunk( nCurrChunk) ; } else ++ nCurrChunk ; } - // else if ( PockParam.nType == POCKET_ZIGZAG) - // ; - // else if ( PockParam.nType == POCKET_ONEWAY) - // ; - // else if ( PockParam.nType == POCKET_CONFORMAL_ONEWAY || PockParam.nType == POCKET_CONFORMAL_ZIGZAG) - // ; } return true ; @@ -9218,9 +9317,10 @@ SmoothExtensionLinesByIntersection( ICRVCOMPOPOVECTOR& vCrvPaths, const PocketPa //---------------------------------------------------------------------------- bool CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle, - double dOpenMinSafe, int nType, bool bSmooth, bool bCalcUnclReg, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders, - bool bCalcFeed, const Point3d& ptEndPrec, const ISurfFlatRegion* pSfrLimit, bool bAllOffs, - double dMaxOptSize, double dLiTang, int nLiType, ICRVCOMPOPOVECTOR& vCrvCompoRes) + double dOpenMinSafe, int nType, bool bSmooth, bool bCalcUnclReg, bool bInvert, bool bAvoidOpt, + bool bAllowZigZagOneWayBorders, bool bCalcFeed, const Point3d& ptEndPrec, + const ISurfFlatRegion* pSfrLimit, bool bAllOffs, double dMaxOptSize, double dLiTang, + int nLiType, ICRVCOMPOPOVECTOR& vCrvCompoRes) { // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid() || diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index c8b0b3fa0ba23636a1fd4024657496a3a24824ac..4a5e054e631adc966c9ba5b68e39266781af4bd7 100644 GIT binary patch delta 81 zcmdlNy)SyhH#SDI&FAG5nSs Date: Wed, 11 Feb 2026 11:31:08 +0100 Subject: [PATCH 10/22] EgtGeomKernel : - rimozione memory leaks in CalcPocketing. --- CalcPocketing.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 0853045..0fc2ff2 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -9015,14 +9015,14 @@ CalcSpiralPocketing( const ISurfFlatRegion* pSfr, int nType, const PocketParams& // il tipo può essere solo SpiralIn o SpiralOut if ( nType != POCKET_SPIRALIN && nType != POCKET_SPIRALOUT) return false ; + PtrOwner pSfrLimit( PockParams.SfrLimit.IsValid() ? PockParams.SfrLimit.Clone() : CreateSurfFlatRegion()) ; // calcolo il percorso di svuotatura spiral return ( CalcPocketing( pSfr, PockParams.dRad, PockParams.dRadialOffset, PockParams.dSideStep, PockParams.dAngle, PockParams.dOpenMinSafe, nType, PockParams.bSmooth, PockParams.bCalcUnclearedRegs, PockParams.bInvert, PockParams.bAvoidOpt, PockParams.bAllowZigZagOneWayBorders, PockParams.bCalcFeed, PockParams.ptStart, - PockParams.SfrLimit.IsValid() ? PockParams.SfrLimit.Clone() : CreateSurfFlatRegion(), - PockParams.bAvoidOpt, PockParams.dMaxOptSize, PockParams.dLiTang, PockParams.nLiType, - vCrvCompoRes)) ; + pSfrLimit, PockParams.bAvoidOpt, PockParams.dMaxOptSize, PockParams.dLiTang, + PockParams.nLiType, vCrvCompoRes)) ; } //---------------------------------------------------------------------------- From 5f132ae3d30c22fdb1b8dfd3c4ef91fff3604ba5 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Wed, 11 Feb 2026 12:20:15 +0100 Subject: [PATCH 11/22] EgtGeomKernel 3.1a7 : - ricompilazione con cambio versione. --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 4a5e054e631adc966c9ba5b68e39266781af4bd7..c19879f358962fc9d015788ca8b56b58b2d80750 100644 GIT binary patch delta 236 zcmdlNy)SyhI%aKGhCGIJh8%`WhGK>c1_cHUhESkLCPN8BDnkm89}HwAf_cT0PijeT z{=m$}%xJ#(yqqG4`lwjSxVewp10r;uY4S3`JfN_k6i~QJ7*lvJ3$os9QmsEYnTvVZ l Date: Wed, 11 Feb 2026 15:26:57 +0100 Subject: [PATCH 12/22] EgtGeomKernel : - migliorata approssimazione con curve di bezier. --- CurveAux.cpp | 85 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index 509158f..7404bf3 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -37,6 +37,7 @@ #define SAVECURVEPASSED 0 #define SAVELINEARAPPROX 0 #if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX + static int nCrvPassed = 0 ; #include "/EgtDev/Include/EGkGeoObjSave.h" #endif @@ -589,6 +590,13 @@ ArcToBezierCurve( const ICurveArc* pArc, int nDeg, bool bMakeRatOrNot) PtrOwner pCrvBez( CreateBasicCurveBezier()) ; if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( cArc)) return nullptr ; + if ( ! bMakeRatOrNot) { + Point3d ptCen = pArc->GetCenter() ; + Vector3d vtN = pArc->GetNormVersor() ; + pCrvBez.Set( ApproxArcCurveBezierWithSingleCubic( pCrvBez, ptCen, vtN)) ; + } + if ( IsNull( pCrvBez)) + return nullptr ; // aumento il grado della curva come richiesto while ( pCrvBez->GetDegree() < nDeg) pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ; @@ -1469,8 +1477,6 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, mA(1) = - dDistCorr ; } - double alpah1 = mA(0) ; - double alpha2 = mA(1) ; Point3d pt1 = pt0 + vtStartDir * mA(0) ; Point3d pt2 = pt3 + vtEndDir * mA(1) ; pCrvBez->SetControlPoint( 1, pt1) ; @@ -1500,12 +1506,13 @@ CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam, //---------------------------------------------------------------------------- ICurve* FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, - int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, double dTol) + int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, double dTol, bool bLimitSplit = false) { ParamByLen( vPnt, vParam, nFirst, nLast) ; PtrOwner pCrvFit( CreateCurveComposite()) ; PtrOwner pCrvBez( CreateCurveBezier()) ; double dErr = INFINITO ; + double dErrPrec = INFINITO ; double dErrSplit = dTol * 25 ; int nIter = 0 ; while ( dErr > dTol && nIter < 10) { @@ -1528,31 +1535,49 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, } // fit della curva - pCrvBez.Set( ApproxPointSetWithSingleBezier( vPnt, nFirst, nLast, vNextDer[nFirst], vPrevDer[nLast], vParam)) ; + Vector3d vtStartDir, vtEndDir ; + if ( bLimitSplit) { + vtStartDir = vNextDer[nFirst / 3] ; + vtEndDir = vPrevDer[nLast / 3] ; + } + else { + vtStartDir = vNextDer[nFirst] ; + vtEndDir = vPrevDer[nLast] ; + } + pCrvBez.Set( ApproxPointSetWithSingleBezier( vPnt, nFirst, nLast, vtStartDir, vtEndDir, vParam)) ; if ( IsNull( pCrvBez) || ! pCrvBez->IsValid()) return nullptr ; #if SAVEAPPROX - SaveGeoObj( pCrvBez->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\first_approx.nge") ; + SaveGeoObj( pCrvBez->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\"+ToString(nCrvPassed) + "first_approx.nge") ; #endif int nPointMaxErr = 0 ; CalcPointSetApproxError( vPnt, vParam, nFirst, nLast, pCrvBez, dErr, nPointMaxErr) ; // se sto unendo due punti consecutivi e l'errore è oltre quello richiesto allora restituisco un segmento che unisce i punti - if ( nLast - nFirst == 1 && dErr > dTol) { + if ( ((nLast - nFirst == 1) || ( bLimitSplit && nLast - nFirst == 3)) && dErr > dTol) { CurveLine CL ; CL.Set( vPnt[nFirst], vPnt[nLast]) ; pCrvBez.Set( GetCurveBezier( CurveToBezierCurve( &CL))) ; dErr = 0 ; } + if ( bLimitSplit && nPointMaxErr % 3 != 0) { + nPointMaxErr = 3 * int( round( nPointMaxErr / 3.)) ; + if ( nPointMaxErr == nFirst) + nPointMaxErr += 3 ; + else if( nPointMaxErr == nLast) + nPointMaxErr -= 3 ; + } + ++nIter ; bool bSplit = false ; - if ( nIter == 10 && dErr > dTol) + if ( ( nIter == 10 && dErr > dTol) || dErr > dErrPrec || dErrPrec - dErr < dErrPrec / 20) bSplit = true ; + dErrPrec = dErr ; // se la curva di approssimazione è ancora molto lontana dalla curva originale allora divido il set di punti in due if ( dErr > dErrSplit || bSplit) { - if ( nLast - nFirst > 1) { - if ( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol)) || - ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol))) + if ( nLast - nFirst > 1 && nPointMaxErr - nFirst > 1 && nLast - nPointMaxErr > 1) { + if ( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol, bLimitSplit)) || + ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol, bLimitSplit))) return nullptr ; break ; } @@ -1575,7 +1600,6 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) { #if SAVECURVEPASSED - static int nCrvPassed = 0 ; SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\CurveDaApprossimare\\"+ToString(nCrvPassed) + ".nge") ; ++nCrvPassed ; #endif @@ -1592,44 +1616,42 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) SaveGeoObj( CC.Clone(), "D:\\Temp\\bezier\\approxWithBezier\\approssimazione_lineare.nge") ; #endif - CurveByInterp cbi ; PNTVECTOR vPnt ; + PNTVECTOR vPntOverSampling ; Point3d pt ; plApprox.GetFirstPoint( pt) ; do { - if ( ! vPnt.empty()) { - vPnt.push_back( Media(vPnt.back(), pt,1./3.)) ; - vPnt.push_back( Media(vPnt.back(), pt,2./3.)) ; + if ( ! vPntOverSampling.empty()) { + vPntOverSampling.push_back( Media( vPnt.back(), pt,1./3.)) ; + vPntOverSampling.push_back( Media( vPnt.back(), pt,2./3.)) ; } + vPntOverSampling.push_back( pt) ; vPnt.push_back( pt) ; - cbi.AddPoint( pt) ; } while ( plApprox.GetNextPoint( pt)) ; // calcolo la curvatura nei vari punti per identificare zone a curvatura costante - DBLVECTOR vCrvVal( ssize( vPnt)) ; DBLVECTOR vRad ( ssize( vPnt)) ; for ( int i = 1 ; i < ssize( vPnt) - 1 ; ++i) { Vector3d vtA = vPnt[i] - vPnt[i-1] ; Vector3d vtB = vPnt[i+1] - vPnt[i-1] ; - double dR = ( vtA.Len() * vtB.Len() * ( vtA - vtB).Len()) / ( 2 * (vtA ^ vtB).Len()) ; - double dCurvature = dR > 0 ? 1. / dR : 0 ; + double dR = ( vtA.Len() * vtB.Len() * ( vtA - vtB).Len()) / ( 2 * ( vtA ^ vtB).Len()) ; vRad[i] = dR ; - vCrvVal[i] = dCurvature ; } - vCrvVal[0] = vCrvVal[1] ; - vCrvVal.back() = vCrvVal.end()[-2] ; + vRad[0] = vRad[1] ; + vRad.back() = vRad.end()[-2] ; // identifico le zone a curvatura costante // primo e ultimo punto degli intervalli non devono avere curvatura uguale agli altri perché sono di frontiera INTINTVECTOR vConstCurv ; - double dCurvaturePrec = vCrvVal[0] ; + double dRadPrec = vRad[0] ; int nStart = 0 ; int nEnd = 1 ; while ( nStart < ssize( vPnt) - 1) { - dCurvaturePrec = vCrvVal[nEnd] ; - while ( nEnd < ssize( vPnt) - 1 && abs( vCrvVal[nEnd] - dCurvaturePrec) < 0.1) { - dCurvaturePrec = vCrvVal[nEnd] ; + double dRadTol = max( max( vRad[nEnd], dRadPrec) / 10 , 1.) ; + while ( nEnd < ssize( vPnt) - 1 && abs( vRad[nEnd] - dRadPrec) < dRadTol) { + dRadPrec = vRad[nEnd] ; ++nEnd ; } - vConstCurv.emplace_back( nStart, nEnd) ; + vConstCurv.emplace_back( nStart * 3, nEnd * 3) ; nStart = nEnd ; + dRadPrec = vRad[nEnd] ; ++nEnd ; } if ( vConstCurv.empty()) @@ -1644,6 +1666,13 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) VCT3DVECTOR vPrevDer ; VCT3DVECTOR vNextDer ; ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ; + + int nOverSampling = ssize( vPntOverSampling) ; + vParam.resize( nOverSampling) ; + nFirst = 0 ; + nLast = nOverSampling - 1 ; + ParamByLen( vPntOverSampling, vParam, nFirst, nLast) ; + //normalizzo tutte le derivate for ( int i = 0 ; i < ssize( vPrevDer) ; ++i) { vPrevDer[i].Normalize() ; @@ -1655,7 +1684,7 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) nFirst = iiSE.first ; nLast = iiSE.second ; //definisco la bezier che vado a raffinare iterativamente - PtrOwner pCApprox( FitWithBezier( pCrv, vPnt, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol)) ; + PtrOwner pCApprox( FitWithBezier( pCrv, vPntOverSampling, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol, true)) ; if ( IsNull( pCApprox) || ! pCApprox->IsValid()) return nullptr ; if ( ! pCCApproxTot->AddCurve( Release( pCApprox))) From 2e129d7b068034a2694b472bd9e2521e3f59ac17 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 11 Feb 2026 16:47:01 +0100 Subject: [PATCH 13/22] EgtGeomKernel : - tolto un argomento alla funzione ApproxCurveWithBezier. --- CurveAux.cpp | 2 +- Trimming.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index 7404bf3..ab69a88 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -1596,7 +1596,7 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, //---------------------------------------------------------------------------- ICurve* -ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType) +ApproxCurveWithBezier( const ICurve* pCrv , double dTol) { #if SAVECURVEPASSED diff --git a/Trimming.cpp b/Trimming.cpp index 4df8f49..e96fdf2 100644 --- a/Trimming.cpp +++ b/Trimming.cpp @@ -341,7 +341,7 @@ ApproxBorder( CurveComposite& CrvCompo, double dLinTol, double dAngTol) VC.emplace_back( vColor[ ++ nIndCol]) ; #endif // Approssimo tale curva con una Bezier - PtrOwner pCrvPatchBZ( ApproxCurveWithBezier( &CCPatchApprox, dHalfLinTol, 123456)) ; + PtrOwner pCrvPatchBZ( ApproxCurveWithBezier( &CCPatchApprox, dHalfLinTol)) ; if ( IsNull( pCrvPatchBZ) || ! pCrvPatchBZ->IsValid()) { LOG_ERROR( GetEGkLogger(), "Error : Interpolating points to bezier curve failed") ; return false ; From 6faf5ccde2d9f11bea52a0ac20e712666ad6939e Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 12 Feb 2026 15:46:42 +0100 Subject: [PATCH 14/22] EgtGeomKernel 3.1a8 : - in CalcPocketing migliorati i casi a trapezio. --- CalcPocketing.cpp | 217 ++++++++++++++++++++++++++++++---------------- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes 2 files changed, 142 insertions(+), 75 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 0fc2ff2..cc4655a 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -3441,18 +3441,18 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double Vector3d vtX ; pCrvPocket->GetCurve( 1)->GetStartDir( vtX) ; Frame3d frDim ; frDim.Set( ptOrig, Z_AX, vtX) ; frDim.Invert() ; BBox3d b3Dim ; pCrvPocket->GetBBox( frDim, b3Dim, BBF_EXACT) ; - dMaxLarg = ( vnProp[0] != 0 ? b3Dim.GetDimY() : dPocketSize) ; + dMaxLarg = ( vnProp[0] != TEMP_PROP_CLOSE_EDGE ? b3Dim.GetDimY() : dPocketSize) ; } // calcolo percorso di svuotatura // se lati obliqui sono entrambi chiusi e dimensione svuotatura è maggiore di diametro fresa e minore del doppio gestione speciale - if ( ( bRealTrap && dMaxLarg > PockParams.dRad * 2 + 10 * EPS_SMALL) && + if ( ( bRealTrap && dMaxLarg > dDiam + 10. * EPS_SMALL) && ( ( ( vnProp[0] != TEMP_PROP_CLOSE_EDGE && vnProp[2] != TEMP_PROP_CLOSE_EDGE) && ( vnProp[3] == TEMP_PROP_CLOSE_EDGE && vnProp[1] == TEMP_PROP_CLOSE_EDGE) && - ( max( dLen0, dLen2) < 2 * dDiam + EPS_SMALL)) || + ( max( dLen0, dLen2) < 2. * dDiam + EPS_SMALL)) || ( ( vnProp[1] != TEMP_PROP_CLOSE_EDGE && vnProp[3] != TEMP_PROP_CLOSE_EDGE) && ( vnProp[0] == TEMP_PROP_CLOSE_EDGE && vnProp[2] == TEMP_PROP_CLOSE_EDGE) && - ( max( dLen1, dLen3) < 2 * dDiam + EPS_SMALL)))) { + ( max( dLen0, dLen2) < 2. * dDiam + EPS_SMALL)))) { if ( ! SpecialAdjustTrapezoidSpiralForAngles( pMCrv, ( vnProp[0] == TEMP_PROP_CLOSE_EDGE), pCrvPocket, PockParams, ptRef)) { pMCrv->Clear() ; return false ; @@ -3605,14 +3605,8 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double if ( pMCrv->GetCurveCount() == 0) return true ; - pMCrv->ToGlob( frTrap) ; - if ( PockParams.bInvert) { - pMCrv->Invert() ; - // inverto le proprietà in modo che nProp3 sia sempre legata al punto iniziale e nProp1 a quello finale - swap( vnProp[1], vnProp[3]) ; - } // segno i lati aperti come temp prop della curva int nOpenEdges = vnProp[0] + vnProp[1] * 2 + vnProp[2] * 4 + vnProp[3] * 8 ; pMCrv->SetTempProp( nOpenEdges, 0) ; @@ -3622,6 +3616,131 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double return true ; } +//---------------------------------------------------------------------------- +static bool +IsForcedStepTrapezoid( const ICurveComposite* pCrvTrap, const PocketParams& PockParam, + int nBase, int nSecondBase, bool& bForced) +{ + bForced = false ; + // se la curva non è valida, allora non può essere forzato + if ( pCrvTrap == nullptr || ! pCrvTrap->IsValid()) + return false ; + + // scorro la curva e ricavo le TempProps + array vnProps ; + int nClose = 0 ; + for ( int i = 0 ; i < 4 ; ++ i) { + if ( ! pCrvTrap->GetCurveTempProp( i, vnProps[i], 0)) + return false ; + if ( vnProps[i] == TEMP_PROP_CLOSE_EDGE) + ++ nClose ; + } + + double dDiam = 2. * PockParam.dRad ; + switch ( nClose) { + // se trapezio tutto aperto, allora non è forzato + case 0 : + bForced = false ; + break ; + // se ho un lato chiuso, non è forzato + case 1 : + bForced = false ; + break ; + // se ho due lati chiusi + case 2 : { + if ( nBase < 0 || nBase > 4 || nSecondBase < 0 || nSecondBase > 4) + return false ; + // se entrambe le basi sono chiuse, è forzato + if ( vnProps[nBase] == TEMP_PROP_CLOSE_EDGE && vnProps[nSecondBase] == TEMP_PROP_CLOSE_EDGE) + bForced = true ; + // se entrambe le basi sono aperte + else if ( vnProps[nBase] == TEMP_PROP_OPEN_EDGE && vnProps[nSecondBase] == TEMP_PROP_OPEN_EDGE) { + const ICurve* pCrvOpenBase = pCrvTrap->GetCurve( nBase) ; + const ICurve* pCrvOpenSecondBase = pCrvTrap->GetCurve( nSecondBase) ; + if ( pCrvOpenBase == nullptr || ! pCrvOpenBase->IsValid() || + pCrvOpenSecondBase == nullptr || ! pCrvOpenSecondBase->IsValid()) + return false ; + double dLenOpenBase ; pCrvOpenBase->GetLength( dLenOpenBase) ; + double dLenSecondOpenBase ; pCrvOpenSecondBase->GetLength( dLenSecondOpenBase) ; + bForced = ( dLenOpenBase < dDiam + 10. * EPS_SMALL && + dLenSecondOpenBase < dDiam + 10. * EPS_SMALL) ; + } + // se alternate, non forzo + else + bForced = false ; + } + break ; + // se ho tre lati chiusi + case 3 : { + // diventa forzato se il lato aperto non è grande + double dLenOpen = 0. ; + for ( int i = 0 ; i < 4 ; ++ i) { + if ( vnProps[i] == TEMP_PROP_OPEN_EDGE) { + const ICurve* pCrvOpen = pCrvTrap->GetCurve( i) ; + if ( pCrvOpen == nullptr || ! pCrvOpen->IsValid()) + return false ; + pCrvOpen->GetLength( dLenOpen) ; + break ; + } + } + bForced = ( dLenOpen < dDiam + 10. * EPS_SMALL) ; + } + break ; + // se tutto chiuso, è forzato + case 4 : + bForced = true ; + break ; + default : + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +AdjustTrapeziodLeadIn( ICurveComposite* pCrvRes, const PocketParams& PockParam, + const ISurfFlatRegion* pSfrChunk) +{ + // recupero la TempProp + int nTmpProp = pCrvRes->GetTempProp( 0) ; + // se esiste almeno un aperto + if ( nTmpProp > 0) { + // se solo lato3 aperto + bool bCheckHead = ( nTmpProp != 8 && nTmpProp != 2) ; + if ( nTmpProp == 2) + pCrvRes->Invert() ; // entro dall'unico aperto + if ( bCheckHead) { + // recupero gli estremi della curva corrente e la inverto in base alla Testa + Point3d ptS ; pCrvRes->GetStartPoint( ptS) ; + Point3d ptE ; pCrvRes->GetEndPoint( ptE) ; + Point3d ptSGlob = GetToGlob( ptS, PockParam.frLocXY) ; + Point3d ptEGlob = GetToGlob( ptE, PockParam.frLocXY) ; + if ( ( PockParam.bAboveHead && ptEGlob.z > ptSGlob.z) || + ( ! PockParam.bAboveHead && ptEGlob.z < ptSGlob.z)) + pCrvRes->Invert() ; + } + } + + // Assegno la Feed + AssignFeedSpiralOpt( 1, PockParam, pCrvRes) ; + // Se curva da invertire, inverto + if ( PockParam.bInvert) + pCrvRes->Invert() ; + + // se esiste almeno un aperto, provo ad estendere il percorso + if ( nTmpProp > 0) { + // Calcolo eventuale entrata da fuori + Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ; + vtRef.Invert() ; + bool bIsStartExtended = false ; + if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended)) + return false ; + } + + return true ; +} + //---------------------------------------------------------------------------- static bool GetZigZagOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParam, @@ -3651,11 +3770,10 @@ GetZigZagOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& int nBase, nSecondBase ; bool bOkTrap = GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) ; if ( bOkTrap && pCrvTrap->IsValid()) { - // se la base principale e secondaria sono entrambe chiuse, trascuro il SideStep - int nTmpProp = TEMP_PROP_INVALID ; - bool bBaseCL = ( pCrvTrap->GetCurveTempProp( nBase, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) ; - bool bSecondBaseCL = ( pCrvTrap->GetCurveTempProp( nSecondBase, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) ; - if ( ! bBaseCL || ! bSecondBaseCL) + // verifico se il trapezio ottenuto deve o meno rispettare il SideStep + bool bForcedTrap = false ; + IsForcedStepTrapezoid( pCrvTrap, PockParam, nBase, nSecondBase, bForcedTrap) ; + if ( ! bForcedTrap) bOkTrap = ( dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ; } if ( bOkTrap && pCrvTrap->IsValid()) { @@ -3674,33 +3792,8 @@ GetZigZagOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& pCrvRes->Clear() ; } } - if ( bOkTrap) { - // calcolo eventuali uscite e ingressi - if ( pCrvRes->GetTempProp( 0) > 0) { - // Recupero gli estremi della curva corrente e la inverto in base alla Testa - Point3d ptS ; pCrvRes->GetStartPoint( ptS) ; - Point3d ptE ; pCrvRes->GetEndPoint( ptE) ; - Point3d ptSGlob = GetToGlob( ptS, PockParam.frLocXY) ; - Point3d ptEGlob = GetToGlob( ptE, PockParam.frLocXY) ; - if ( ( PockParam.bAboveHead && ptEGlob.z > ptSGlob.z) || - ( ! PockParam.bAboveHead && ptEGlob.z < ptSGlob.z)) - pCrvRes->Invert() ; - if ( PockParam.bInvert) - pCrvRes->Invert() ; - // Assegno la Feed - AssignFeedSpiralOpt( 1, PockParam, pCrvRes) ; - // Calcolo eventuale entrata da fuori - Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ; - vtRef.Invert() ; - bool bIsStartExtended = false ; - if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended)) - return false ; - } - else { - if ( PockParam.bInvert) - pCrvRes->Invert() ; - } - } + if ( bOkTrap) + AdjustTrapeziodLeadIn( pCrvRes, PockParam, pSfrChunk) ; } } @@ -3755,7 +3848,7 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& ssize( ccClass) == 1 && ccClass[0].nClass == CRVC_OUT) ; // NB. una versione più complessa dovrebbe verificare se la sottrazione tra la // superficie dell'utensile e la regione limite non genera un'altra circonferenza... - // In questo caso si la sottrazione potrebbe essere trattata come una circonferenza + // In questo caso la sottrazione potrebbe essere trattata come una circonferenza // chiusa ed essere ancora svotata a spirale... } } @@ -3798,11 +3891,10 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& int nBase, nSecondBase ; bool bOkTrap = GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) ; if ( bOkTrap && pCrvTrap->IsValid()) { - // se la base principale e secondaria sono entrambe chiuse, trascuro il SideStep - int nTmpProp = TEMP_PROP_INVALID ; - bool bBaseCL = ( pCrvTrap->GetCurveTempProp( nBase, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) ; - bool bSecondBaseCL = ( pCrvTrap->GetCurveTempProp( nSecondBase, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) ; - if ( ! bBaseCL || ! bSecondBaseCL) + // verifico se il trapezio ottenuto deve o meno rispettare il SideStep + bool bForcedTrap = false ; + IsForcedStepTrapezoid( pCrvTrap, PockParam, nBase, nSecondBase, bForcedTrap) ; + if ( ! bForcedTrap) bOkTrap = ( dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ; } if ( bOkTrap && pCrvTrap->IsValid()) { @@ -3821,33 +3913,8 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& pCrvRes->Clear() ; } } - if ( bOkTrap) { - // calcolo eventuali uscite e ingressi - if ( pCrvRes->GetTempProp( 0) > 0) { - // Recupero gli estremi della curva corrente e la inverto in base alla Testa - Point3d ptS ; pCrvRes->GetStartPoint( ptS) ; - Point3d ptE ; pCrvRes->GetEndPoint( ptE) ; - Point3d ptSGlob = GetToGlob( ptS, PockParam.frLocXY) ; - Point3d ptEGlob = GetToGlob( ptE, PockParam.frLocXY) ; - if ( ( PockParam.bAboveHead && ptEGlob.z > ptSGlob.z) || - ( ! PockParam.bAboveHead && ptEGlob.z < ptSGlob.z)) - pCrvRes->Invert() ; - if ( PockParam.bInvert) - pCrvRes->Invert() ; - // Assegno la Feed - AssignFeedSpiralOpt( 1, PockParam, pCrvRes) ; - // Calcolo eventuale entrata da fuori - Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ; - vtRef.Invert() ; - bool bIsStartExtended = false ; - if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended)) - return false ; - } - else { - if ( PockParam.bInvert) - pCrvRes->Invert() ; - } - } + if ( bOkTrap) + AdjustTrapeziodLeadIn( pCrvRes, PockParam, pSfrChunk) ; } } diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index c19879f358962fc9d015788ca8b56b58b2d80750..45a4adc64e0d912f7ac7581966fd065ee60e2085 100644 GIT binary patch delta 238 zcmdlNy)SyhI%aiGhCGIJh8%`ehGHOAV9;O)W+-7u1ma8}FBB-731Uy?R&U)L$1;bB z(PHy&HbrJei^+=Ix|_YYCa?fSZu8k9MBErR_Xv9d`53|-(qLf}{T_^)vy{Iv66=o5 l-Kxcmg85*FdV(FA19V{GW^VP3%$UNHyHyWv?$S140ssQeI)eZJ delta 236 zcmdlNy)SyhI%aKGhCGIJh8%`WhGK>c1_cHUhESkLCPN8BDnkm89}HwAf_cT0PijeT z{=m$}%xJ#(yqqG4`lwjSxVewp10r;uY4S3`JfN_k6i~QJ7*lvJ3$os9QmsEYnTvVZ l Date: Thu, 12 Feb 2026 16:17:11 +0100 Subject: [PATCH 15/22] EgtGeomKernel : - correzione alla triangolazione delle bezier. - riduzione della dimensione minima dei triangoli nelle surf bezier. --- SurfBezier.cpp | 4 +-- SurfBezier.h | 2 +- Tree.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 88 insertions(+), 5 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 479eb5c..cb59300 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1820,7 +1820,7 @@ SurfBezier::GetAuxSurf( void) const } } // eseguo calcolo - m_pSTM = GetApproxSurf( s_dAuxSurfTol, 100 * EPS_SMALL, false) ; + m_pSTM = GetApproxSurf( s_dAuxSurfTol, 10 * EPS_SMALL, false) ; ++nSurf ; if ( m_pSTM != nullptr) m_pSTM->SetTempParam( s_dAuxSurfTol) ; @@ -1855,7 +1855,7 @@ SurfBezier::GetAuxSurfRefined( void) const } } // eseguo calcolo - m_pSTMRefined = GetApproxSurf( s_dAuxSurfRefinedTol, 100 * EPS_SMALL, true) ; + m_pSTMRefined = GetApproxSurf( s_dAuxSurfRefinedTol, 10 * EPS_SMALL, true) ; if ( m_pSTMRefined != nullptr) m_pSTMRefined->SetTempParam( s_dAuxSurfRefinedTol) ; return m_pSTMRefined ; diff --git a/SurfBezier.h b/SurfBezier.h index efdec9b..e3c7faf 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -116,7 +116,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ; const SurfTriMesh* GetAuxSurf( void) const override ; const SurfTriMesh* GetAuxSurfRefined( void) const override ; - SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL, bool bUpdateEdges = false) const override ; + SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 10 * EPS_SMALL, bool bUpdateEdges = false) const override ; // funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione. bool GetLeaves( std::vector>& vLeaves) const override ; bool GetTriangles2D( std::vector>& vTria2D) const override ; diff --git a/Tree.cpp b/Tree.cpp index 1150b69..7713ff7 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -664,8 +664,18 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } } + // calcolo se la parte di superficie nella cella è piatta + PolyLine PL ; + PL.AddUPoint( 0, ptP00) ; + PL.AddUPoint( 1, ptP10) ; + PL.AddUPoint( 2, ptP11) ; + PL.AddUPoint( 3, ptP01) ; + PL.AddUPoint( 4, ptCen) ; + Plane3d plPlane ; + bool bIsFlat = PL.IsFlat( plPlane, dLinTol) ; + // su isoparametriche in U e V - if ( dSagU < dLinTol && dSagV < dLinTol) { + if ( dSagU < dLinTol && dSagV < dLinTol && ! bIsFlat) { // step di verifica in U e in V int nStepU = ( dLenParU > 1. / m_nDegU ? m_nDegU + 1 : 2) ; int nStepV = ( dLenParV > 1. / m_nDegV ? m_nDegV + 1 : 2) ; @@ -726,6 +736,73 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) //{ string sLog = " Da Isoparam : FrecciaU=" + ToString( dSagU, 3) + " FrecciaV=" + ToString( dSagV, 3) ; // LOG_DBG_INFO( GetEGkLogger(), sLog.c_str())} } + else if ( dSagU < dLinTol && dSagV < dLinTol && bIsFlat) { + // se la cella è piatta devo verificare che i bordi siano dei tratti retti, altrimenti potrei commettere un errore di approssimazione + + // bordo inferiore e superiore + double dMaxDist = 0 ; + for ( int i = 0 ; i < 2 ; ++i) { + CurveLine clU ; + if ( i == 0) + clU.Set( ptP00, ptP10) ; + else if ( i == 1) + clU.Set( ptP01, ptP11) ; + double dV = 0 ; + if ( i == 0) + dV = pcToSplit->GetBottomLeft().y ; + else if ( i == 1) + dV = pcToSplit->GetTopRight().y ; + + + int nStepU = 4 ; + for ( int j = 1 ; j < nStepU ; ++ j) { + // parametro U + double dCoeffU = double( j) / nStepU ; + double dU = ( 1 - dCoeffU) * pcToSplit->GetBottomLeft().x + dCoeffU * pcToSplit->GetTopRight().x ; + Point3d ptBez ; + GetPoint( dU, dV, ptBez) ; + DistPointCurve dpc( ptBez, clU) ; + double dDist = 0 ; + dpc.GetDist( dDist) ; + if ( dDist > dMaxDist) + dMaxDist = dDist ; + } + } + if ( dMaxDist > dLinTol) + dSagU = dMaxDist ; + + // bordo sinistro e destro + dMaxDist = 0 ; + for ( int i = 0 ; i < 2 ; ++i) { + CurveLine clV ; + if ( i == 0) + clV.Set( ptP00, ptP01) ; + else if ( i == 1) + clV.Set( ptP10, ptP11) ; + double dU = 0 ; + if ( i == 0) + dU = pcToSplit->GetBottomLeft().x ; + else if ( i == 1) + dU = pcToSplit->GetTopRight().x ; + + int nStepV = 4 ; + for ( int j = 1 ; j < nStepV ; ++ j) { + // parametro in V + double dCoeffV = double( j) / nStepV ; + double dV = ( 1 - dCoeffV) * pcToSplit->GetBottomLeft().y + dCoeffV * pcToSplit->GetTopRight().y ; + Point3d ptBez ; + GetPoint( dU, dV, ptBez) ; + DistPointCurve dpc( ptBez, clV) ; + double dDist = 0 ; + dpc.GetDist( dDist) ; + if ( dDist > dMaxDist) + dMaxDist = dDist ; + } + } + if ( dMaxDist > dLinTol) + dSagV = dMaxDist ; + } + // per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza // misura approssimativa della curvatura in una direzione @@ -736,7 +813,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) bVert = false ; else bVert = ( dSagV <= dSagU) ; - pcToSplit->SetSplitDirVert( bVert) ; + bool bFirstTry = true ; + retry : // verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare double dSideMinVal = 0 ; double dLengMinVal = 0 ; @@ -778,6 +856,11 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax) } else if ( dSagV > dLinTol || dSagU > dLinTol) { bSplit = bDimOk ; + if ( ! bSplit && bFirstTry) { + bFirstTry = false ; + bVert = ! bVert ; + goto retry ; + } //if ( bSplit) // LOG_DBG_INFO( GetEGkLogger(), " Split by SagittaUV") } From f790736fd72cc9dde668d8401b2b0f07dc93b62d Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 12 Feb 2026 16:25:28 +0100 Subject: [PATCH 16/22] EgtGeomKernel : - modificata conversione da linea a bezier. --- CurveAux.cpp | 3 +-- CurveBezier.cpp | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index ab69a88..484367d 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -534,8 +534,7 @@ LineToBezierCurve( const ICurveLine* pCrvLine, int nDeg, bool bMakeRatOrNot) return nullptr ; PtrOwner pCrvBezier( CreateCurveBezier()) ; - // rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali - pCrvBezier->Init( nDeg, true) ; + pCrvBezier->Init( nDeg, false) ; if ( ! pCrvBezier->FromLine( *pCrvLine)) return nullptr ; if ( bMakeRatOrNot) diff --git a/CurveBezier.cpp b/CurveBezier.cpp index b22bc43..5be2d71 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -275,20 +275,19 @@ CurveBezier::FromLine( const ICurveLine& crLine) { if ( m_nStatus != OK || ! crLine.IsValid()) return false ; - double dWeight = 1 ; int nCount = 0 ; Point3d ptStart ; crLine.GetStartPoint( ptStart) ; - SetControlPoint( nCount, ptStart, dWeight) ; + SetControlPoint( nCount, ptStart) ; ++nCount ; double dPart = 1. / m_nDeg ; for ( int i = 1 ; i < m_nDeg ; ++i) { double dU = i * dPart ; Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ; - SetControlPoint( nCount, ptMid, dWeight) ; + SetControlPoint( nCount, ptMid) ; ++nCount ; } Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ; - SetControlPoint( nCount, ptEnd, dWeight) ; + SetControlPoint( nCount, ptEnd) ; ++nCount ; return true ; } From 86338db67d22bf3520e3bf46becd250fcadeab4d Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 17 Feb 2026 09:24:18 +0100 Subject: [PATCH 17/22] EgtGeomKernel : - in CalcPocketing piccola correzione. --- CalcPocketing.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index cc4655a..5cee0cf 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -3792,8 +3792,11 @@ GetZigZagOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& pCrvRes->Clear() ; } } - if ( bOkTrap) + if ( bOkTrap) { AdjustTrapeziodLeadIn( pCrvRes, PockParam, pSfrChunk) ; + // imposto il flag di curva singola + pCrvRes->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ; + } } } @@ -3913,8 +3916,11 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& pCrvRes->Clear() ; } } - if ( bOkTrap) + if ( bOkTrap) { AdjustTrapeziodLeadIn( pCrvRes, PockParam, pSfrChunk) ; + // imposto il flag di curva singola + pCrvRes->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ; + } } } From f9127ce64d737f4a07c3a855ee9284b1e11f258d Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 17 Feb 2026 10:00:13 +0100 Subject: [PATCH 18/22] EgtGeomKernel 3.1b1 : - cambio di versione. --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 45a4adc64e0d912f7ac7581966fd065ee60e2085..116749ecfa5e7a64090f08e5c66f16f7df1421e5 100644 GIT binary patch delta 118 zcmdlNy)SyhCpK0i1|0^&&FAIhnHiHNC(1}}HsD&s0vA2cGW8_Z~*{dkRosZ delta 105 zcmdlNy)SyhCpK0?1|0^A&FAIhnVA!TjE{$f}3`h8vwkXA9er$ From bae8d4651d072b39bd96a8f33f4ac6029e15f6c8 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 19 Feb 2026 11:50:44 +0100 Subject: [PATCH 19/22] EgtGeomKernel : - piccola correzione alla Surf Bez Ruled Guided. --- SurfBezier.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index cb59300..bd41f13 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -6126,8 +6126,9 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c nSpanU0 = CrvU0.GetCurveCount() ; nSpanU1 = CrvU1.GetCurveCount() ; - // aggiungo l'ultima coppia - vPairs.emplace_back( nSpanU0, nSpanU1) ; + // aggiungo l'ultima coppia se necessario + if ( vPairs.back().first != nSpanU0 && vPairs.back().second != nSpanU1) + vPairs.emplace_back( nSpanU0, nSpanU1) ; // trovo il numero di span che dovrà avere la superficie int nSpanU = int(vPairs.size()) - 1 ; From 73bedf4f55bcb8c751d99ee5de0ad30b46ee0c69 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 19 Feb 2026 15:39:43 +0100 Subject: [PATCH 20/22] EgkGeomKernel : - correzione all'intersezione tra curva e piano. --- IntersCurvePlane.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/IntersCurvePlane.cpp b/IntersCurvePlane.cpp index 8ca95fb..2031344 100644 --- a/IntersCurvePlane.cpp +++ b/IntersCurvePlane.cpp @@ -139,8 +139,6 @@ IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Cur void IntersCurvePlane::OrderAndCompleteIntersections() { - if ( m_Info.size() < 2) - return ; // cancello le interesezioni puntuali adiacenti a tratti di sovrapposizione // riempio le info PrevTy e NexyTy sort( m_Info.begin(), m_Info.end(), []( IntCrvPlnInfo& icpA, IntCrvPlnInfo& icpB) { return icpA.Ici[0].dU < icpA.Ici[0].dU ;}) ; From 3c1a7ff1bb547b6d99f3f3611d1bed1a4ac6924d Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Fri, 20 Feb 2026 16:47:42 +0100 Subject: [PATCH 21/22] EgtGeomKernel 3.1b2 : - in Trimming aggiunta prima versione di interpolazione per le curve di sincronizzazione. --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes Trimming.cpp | 245 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 241 insertions(+), 4 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 116749ecfa5e7a64090f08e5c66f16f7df1421e5..22fffabed78535e2b7b1c2a4a298b640af2d20bf 100644 GIT binary patch delta 81 zcmdlNy)SyhH#SD2&FAG5nSs @@ -53,6 +54,7 @@ #define DEBUG_BRK 0 #define DEBUG_BORDERS_BY_NORMALS 0 #define DEBUG_SYNC_POINTS 0 +#define DEBUG_SYNC_INTERPOLATION 0 #define DEBUG_BEZIER_RULED 0 #define DEBUG_CURVATURE 0 #define DEBUG_SIMPLE_PATCHES 0 @@ -63,9 +65,9 @@ #define DEBUG_HOLES 0 #if DEBUG_BASIC_BORDERS || DEBUG_CHAIN_CURVES || DEBUG_ANG_APPROX || DEBUG_BEZIER_INTERP || \ DEBUG_FACE_SEARCH || DEBUG_FACE_SEARCH_TRIA_MODIF || DEBUG_BRK_POINTS || DEBUG_BRK_THICK || \ - DEBUG_BRK || DEBUG_BORDERS_BY_NORMALS || DEBUG_SYNC_POINTS || DEBUG_BEZIER_RULED || DEBUG_CURVATURE || \ - DEBUG_SIMPLE_PATCHES || DEBUG_SURF_PATCHES || DEBUG_RAW_EDGES || DEBUG_EDGES || DEBUG_SHAPE_STM || \ - DEBUG_HOLES || DEBUG + DEBUG_BRK || DEBUG_BORDERS_BY_NORMALS || DEBUG_SYNC_POINTS || DEBUG_SYNC_INTERPOLATION || \ + DEBUG_BEZIER_RULED || DEBUG_CURVATURE || DEBUG_SIMPLE_PATCHES || DEBUG_SURF_PATCHES || \ + DEBUG_RAW_EDGES || DEBUG_EDGES || DEBUG_SHAPE_STM || DEBUG_HOLES || DEBUG #include "CurveLine.h" #include "/EgtDev/Include/EGkGeoObjSave.h" #include "/EgtDev/Include/EgtPerfCounter.h" @@ -3468,6 +3470,95 @@ IsBorderAButtonHole( const PolyLine& PL, double dLinTol, double dAngTol, Frame3d return false ; } +//----------------------------------------------------------------------------- +//-------------------------------- Interpolazioni ----------------------------- +//----------------------------------------------------------------------------- +static bool +InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICurveComposite* pOtherGuide, + const Plane3d& plStart, const Plane3d& plEnd, double dLinTol, + BIPNTVECTOR& vBiPts) +{ + vBiPts.clear() ; + + // Verifico che le curve siano valide + if ( pGuide == nullptr || ! pGuide->IsValid() || + pOtherGuide == nullptr || ! pOtherGuide->IsValid()) + return false ; + + // Recupero la sua lunghezza + double dGuideLen = 0. ; + if ( ! pGuide->GetLength( dGuideLen) || dGuideLen < dLinTol) + return false ; + + // Scorro le curve da restituire + double dProgLen = 0. ; + vBiPts.reserve( pGuide->GetCurveCount() - 1) ; + for ( int i = 0 ; i < pGuide->GetCurveCount() - 1 ; ++ i) { + // Recupero la curva corrente + const ICurve* pCrv = pGuide->GetCurve( i) ; + if ( pCrv == nullptr || ! pCrv->IsValid()) + return false ; + // Ne recupero la lunghezza e aggiorno la lunghezza progressiva + double dLen = 0. ; + if ( ! pCrv->GetLength( dLen)) + return false ; + dProgLen += dLen ; + // Recupero la percentuale di interpolazione rispetto alla lunghezze + double dInterPar = dProgLen / dGuideLen ; + // Interpolo le normali dei piani rispetto a tale valore + Vector3d vtN = Media( plStart.GetVersN(), plEnd.GetVersN(), dInterPar) ; + vtN.Normalize() ; + // Definisco il piano di intersezione + Point3d ptCurr ; + if ( ! pCrv->GetEndPoint( ptCurr)) + return false ; + #if DEBUG_SYNC_INTERPOLATION + Frame3d frPl ; frPl.Set( ptCurr, vtN) ; + PtrOwner frCurr( CreateGeoFrame3d()) ; frCurr->Set( frPl) ; + VT.emplace_back( Release( frCurr)) ; + VC.emplace_back( WHITE) ; + SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ; + #endif + // Recupero il parametro di intersezione tra la curva e il piano + #if 0 + VT.clear() ; VC.clear() ; + PtrOwner PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ; + VT.emplace_back( Release( PT)) ; + VC.emplace_back( AQUA) ; + PtrOwner VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ; + VECT->ChangeBase( ptCurr) ; + PtrOwner pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ; + PtrOwner pSfrPlane( CreateSurfFlatRegion()) ; + pSfrPlane->AddExtLoop( Release( pArc)) ; + VT.emplace_back( Release( pSfrPlane)) ; + VC.emplace_back( Color( 0., 0., 0., .5)) ; + VT.emplace_back( Release( VECT)) ; + VC.emplace_back( BLUE) ; + VT.emplace_back( pOtherGuide->Clone()) ; + VC.emplace_back( WHITE) ; + SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ; + #endif + IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ; + if ( IntCP.GetIntersCount() == 0) + return false ; // ambiguità + // Recupero il punto della prima intersezione trovata + Point3d ptInt ; + double dPar ; + if ( ! IntCP.GetIntersPointNearTo( ptCurr, ptInt, dPar)) + return false ; + #if DEBUG_SYNC_INTERPOLATION + PtrOwner ptG( CreateGeoPoint3d()) ; ptG->Set( ptInt) ; + VT.emplace_back( Release( ptG)) ; + VC.emplace_back( WHITE) ; + SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ; + #endif + // Memorizzo tale punto + vBiPts.emplace_back( make_pair( ptCurr, ptInt)) ; + } + + return true ; +} + //----------------------------------------------------------------------------- //-------------------------------- Funzioni Export ---------------------------- //----------------------------------------------------------------------------- @@ -3738,10 +3829,14 @@ bool GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, double dLinTol, BIPNTVECTOR& vSyncPoints) { + vSyncPoints.clear() ; + // Verifica validità delle curve per la creazione della Bezier rigata PtrOwner pCompoEdge1( ConvertCurveToComposite( pCrvEdge1->Clone())) ; PtrOwner pCompoEdge2( ConvertCurveToComposite( pCrvEdge2->Clone())) ; - vSyncPoints.clear() ; + if ( IsNull( pCompoEdge1) || IsNull( pCompoEdge2) || + ! pCompoEdge1->IsValid() || ! pCompoEdge2->IsValid()) + return false ; // Controllo sulla tolleranza lineare double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; @@ -3783,6 +3878,148 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, return true ; } +//------------------------------------------------------------------------------ +// Funzione per interpolare le Curve di Sincronizzazione tra due Curve di Bordo +bool +GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, + const ICurve* pSync1, const ICurve* pSync2, double dLinTol, + double dAngTol, BIPNTVECTOR& vSyncPoints) +{ + vSyncPoints.clear() ; + + // Verifico la validità dei parametri + if ( pCrvEdge1 == nullptr || ! pCrvEdge1->IsValid() || + pCrvEdge2 == nullptr || ! pCrvEdge2->IsValid() || + pSync1 == nullptr || ! pSync1->IsValid() || + pSync2 == nullptr || ! pSync2->IsValid()) + return false ; + + // Le curve di Bordo devono essere entrambe aperte o entrambe chiuse + if ( pCrvEdge1->IsClosed() != pCrvEdge2->IsClosed()) + return false ; + + // Verifico i valori delle tolleranze + double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ; + double dMyAngTol = Clamp( dAngTol, EPS_ANG_SMALL, 60.) ; + + // Verifico le due curve di sincronizzazione abbiano gli estremi sulle due curve di bordo + Point3d ptS1 ; pSync1->GetStartPoint( ptS1) ; + Point3d ptE1 ; pSync1->GetEndPoint( ptE1) ; + if ( AreSamePointEpsilon( ptS1, ptE1, dMyLinTol)) + return false ; + double dUA, dUB, dUC, dUD ; // [A,C]->Edge1 | [B,D]->Edge2 + if ( ( ! pCrvEdge1->GetParamAtPoint( ptS1, dUA, dMyLinTol) || ! pCrvEdge2->GetParamAtPoint( ptE1, dUB, dMyLinTol)) && + ( ! pCrvEdge1->GetParamAtPoint( ptE1, dUA, dMyLinTol) || ! pCrvEdge2->GetParamAtPoint( ptS1, dUB, dMyLinTol))) + return false ; + Point3d ptS2 ; pSync2->GetStartPoint( ptS2) ; + Point3d ptE2 ; pSync2->GetEndPoint( ptE2) ; + if ( AreSamePointEpsilon( ptS2, ptE2, dMyLinTol)) + return false ; + if ( ( ! pCrvEdge1->GetParamAtPoint( ptS2, dUC, dMyLinTol) || ! pCrvEdge2->GetParamAtPoint( ptE2, dUD, dMyLinTol)) && + ( ! pCrvEdge1->GetParamAtPoint( ptE2, dUC, dMyLinTol) || ! pCrvEdge2->GetParamAtPoint( ptS2, dUD, dMyLinTol))) + return false ; + + // Recupero i due tratti di curva + PtrOwner pCompoGuide1( ConvertCurveToBasicComposite( pCrvEdge1->CopyParamRange( dUA, dUC))) ; + PtrOwner pCompoGuide2( ConvertCurveToBasicComposite( pCrvEdge2->CopyParamRange( dUB, dUD))) ; + if ( IsNull( pCompoGuide1) || IsNull( pCompoGuide2) || + ! pCompoGuide1->IsValid() || ! pCompoGuide2->IsValid()) + return false ; + + // Determino quale curva è la più lunga, servirà come riferimento per la parametrizzazione e l'interpolazione + double dLen1, dLen2 ; + if ( ! pCompoGuide1->GetLength( dLen1) || ! pCompoGuide2->GetLength( dLen2) || + dLen1 < dMyLinTol || dLen2 < dMyLinTol) + return false ; + if ( dLen2 > dLen1) { + swap( pCompoGuide1, pCompoGuide2) ; + swap( dLen1, dLen2) ; + } + if ( pCompoGuide2->IsPointOn( ptS1)) + swap( ptS1, ptE1) ; + if ( pCompoGuide2->IsPointOn( ptS2)) + swap( ptS2, ptE2) ; + + #if DEBUG_SYNC_INTERPOLATION + VT.clear() ; VC.clear() ; + VT.emplace_back( pCompoGuide1->Clone()) ; + VC.emplace_back( AQUA) ; + VT.emplace_back( pCompoGuide2->Clone()) ; + VC.emplace_back( ORANGE) ; + PtrOwner ptG( CreateGeoPoint3d()) ; ptG->Set( ptS1) ; + VT.emplace_back( ptG->Clone()) ; VC.emplace_back( AQUA) ; + ptG->Set( ptE1) ; + VT.emplace_back( ptG->Clone()) ; VC.emplace_back( ORANGE) ; + ptG->Set( ptS2) ; + VT.emplace_back( ptG->Clone()) ; VC.emplace_back( AQUA) ; + ptG->Set( ptE2) ; + VT.emplace_back( ptG->Clone()) ; VC.emplace_back( ORANGE) ; + PtrOwner pLine( CreateCurveLine()) ; pLine->Set( ptS1, ptE1) ; + VT.emplace_back( pLine->Clone()) ; VC.emplace_back( PURPLE) ; + pLine->Set( ptS2, ptE2) ; + VT.emplace_back( pLine->Clone()) ; VC.emplace_back( PURPLE) ; + SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ; + #endif + + // Determino le Normali dei piani di taglio agli agli estremi delle due curve + Vector3d vtStart1, vtStart2 ; + if ( ! pCompoGuide1->GetStartDir( vtStart1) || ! pCompoGuide2->GetStartDir( vtStart2)) + return false ; + Vector3d vtAux = ptE1 - ptS1 ; vtAux.Normalize() ; + Vector3d vtMTan = Media( vtStart1, vtStart2) ; vtMTan.Normalize() ; + Vector3d vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ; + Plane3d plStart ; + if ( ! plStart.Set( ptS1, vtN)) + return false ; + Vector3d vtEnd1, vtEnd2 ; + if ( ! pCompoGuide1->GetEndDir( vtEnd1) || ! pCompoGuide2->GetEndDir( vtEnd2)) + return false ; + vtAux = ptE2 - ptS2 ; vtAux.Normalize() ; + vtMTan = Media( vtEnd1, vtEnd2) ; vtMTan.Normalize() ; + vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ; + Plane3d plEnd ; + if ( ! plEnd.Set( ptS2, vtN)) + return false ; + + #if DEBUG_SYNC_INTERPOLATION + Frame3d frPlStart ; frPlStart.Set( ptS1, plStart.GetVersN()) ; + Frame3d frPlEnd ; frPlEnd.Set( ptS2, plEnd.GetVersN()) ; + PtrOwner frS( CreateGeoFrame3d()) ; frS->Set( frPlStart) ; + PtrOwner frE( CreateGeoFrame3d()) ; frE->Set( frPlEnd) ; + VT.emplace_back( Release( frS)) ; + VC.emplace_back( WHITE) ; + VT.emplace_back( Release( frE)) ; + VC.emplace_back( WHITE) ; + SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ; + #endif + + // Curve di Sincronizzazione del Bordo 1 sul Bordo 2 + BIPNTVECTOR vBiPts1 ; + if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, dMyLinTol, vBiPts1)) + return false ; + + // Curve di Sincronizzazione del Bordo 2 sul Bordo 1 + BIPNTVECTOR vBiPts2 ; + if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, dMyLinTol, vBiPts2)) + return false ; + + // Restituisco le Curve di Sincronizzazione + // [Da Bordo 1 a Bordo 2 originale] + vSyncPoints.reserve( ssize( vBiPts1) + ssize( vBiPts2)) ; + for ( int i = 0 ; i < ssize( vBiPts1) ; ++ i) { + vSyncPoints.emplace_back( vBiPts1[i]) ; + if ( pCrvEdge1->IsPointOn( vBiPts1[i].second, dMyLinTol)) + swap( vSyncPoints.back().first, vSyncPoints.back().second) ; + } + for ( int i = 0 ; i < ssize( vBiPts2) ; ++ i) { + vSyncPoints.emplace_back( vBiPts2[i]) ; + if ( pCrvEdge1->IsPointOn( vBiPts2[i].second, dMyLinTol)) + swap( vSyncPoints.back().first, vSyncPoints.back().second) ; + } + + return true ; +} + //------------------------------------------------------------------------------ // Funzione per il calcolo della superficie di Bezier rigata // NB. Possono essere passati dei parametri opzionali come vIndPriority e vIndVisible : From 6d544f93f4e8f465e5ee6c5a7acac8e08bbe5c62 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 19 Feb 2026 18:15:58 +0100 Subject: [PATCH 22/22] EgtGeomKernel : - miglioramento dell'approssimazione con curve di bezier. --- CurveAux.cpp | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index 484367d..43c1f53 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -1642,8 +1642,11 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol) double dRadPrec = vRad[0] ; int nStart = 0 ; int nEnd = 1 ; + double dRatio = 1.5 ; while ( nStart < ssize( vPnt) - 1) { double dRadTol = max( max( vRad[nEnd], dRadPrec) / 10 , 1.) ; + if ( dRadPrec > dRatio * vRad[nEnd] || dRatio * dRadPrec < vRad[nEnd]) + dRadTol = 0 ; while ( nEnd < ssize( vPnt) - 1 && abs( vRad[nEnd] - dRadPrec) < dRadTol) { dRadPrec = vRad[nEnd] ; ++nEnd ; @@ -1678,16 +1681,27 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol) vNextDer[i].Normalize() ; } + // potrei verificare prima se un tratto è retto e aggiustare le tangenti del tratto precedente e successivo prima di approssimare PtrOwner pCCApproxTot( CreateCurveComposite()) ; for ( INTINT iiSE : vConstCurv) { nFirst = iiSE.first ; nLast = iiSE.second ; - //definisco la bezier che vado a raffinare iterativamente - PtrOwner pCApprox( FitWithBezier( pCrv, vPntOverSampling, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol, true)) ; - if ( IsNull( pCApprox) || ! pCApprox->IsValid()) - return nullptr ; - if ( ! pCCApproxTot->AddCurve( Release( pCApprox))) - return nullptr ; + // riconosco se ho un tratto retto + int nPnt = nFirst / 3 ; + if ( nLast - nFirst == 3 && ( nPnt > 0 && vRad[nPnt] > dRatio * vRad[nPnt - 1]) && ( nPnt < ssize( vRad) && vRad[nPnt]> dRatio * vRad[nPnt + 1])) { + CurveLine CL ; CL.Set( vPntOverSampling[nFirst], vPntOverSampling[nLast]) ; + PtrOwner pCApprox( LineToBezierCurve( &CL, 3, false)) ; + if ( ! pCCApproxTot->AddCurve( Release( pCApprox))) + return nullptr ; + } + else { + //definisco la bezier che vado a raffinare iterativamente + PtrOwner pCApprox( FitWithBezier( pCrv, vPntOverSampling, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol, true)) ; + if ( IsNull( pCApprox) || ! pCApprox->IsValid()) + return nullptr ; + if ( ! pCCApproxTot->AddCurve( Release( pCApprox))) + return nullptr ; + } } return Release( pCCApproxTot) ;