From 76dceb4fc9839b19ea1c78bb5e217a6d9e03f2ca Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 5 Sep 2024 08:52:57 +0200 Subject: [PATCH 01/13] EgtGeomKernel : - aggiunto un commento. --- SfrCreate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/SfrCreate.cpp b/SfrCreate.cpp index ab14894..5756dc1 100644 --- a/SfrCreate.cpp +++ b/SfrCreate.cpp @@ -580,6 +580,7 @@ CalcRegionPolyLines( const POLYLINEVECTOR& vPL, POLYLINEVECTOR& vPLOrd, Vector3d // matrice di interi : ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle // successive i loop interni //INTMATRIX vnPLIndMat ; + // vettore di bool : riferito al vettore originale delle polyline, riporta true se la polyline è stata invertita // ricavo versore normale Plane3d plPlane ; double dArea ; From 623eb6e6305fb18e724274a9982113b97feb2d80 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Thu, 5 Sep 2024 17:37:54 +0200 Subject: [PATCH 02/13] EgtGeomKernel 2.6i1 : - 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 8ddb8912ca78c2a598b70c9d74bba23ed84dcfe8..6a843062d12627d4d3853a7a47f533d30cb3c138 100644 GIT binary patch delta 260 zcmdlNy)SyhI%aKGhCGIJh8%`WhGK>c1_cHUhESkLCPN8BDnkm89}HwAf_cT0PijeT z{=m${%xcM?!(h1iyqr8Ub0(1SQL&V9b04=0LgGBra2s4xtNztex=643-W*`*vUBzl^_RC{=l5Ixkp`x8C7cYNv*F;0BVjzJOBUy delta 262 zcmdlNy)SyhI%aiGhCGIJh8%`ehGHOAV9;O)W+-7u1ma8}FBB-731Uy?R&U)L$1;P7 z)q+8X!Fcm;HhE^|3 Date: Tue, 10 Sep 2024 16:17:50 +0200 Subject: [PATCH 03/13] EgtGeomKernel : - correzione errore nel calcolo offset con Voronoi. --- Voronoi.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Voronoi.cpp b/Voronoi.cpp index 87cd79d..2f01458 100644 --- a/Voronoi.cpp +++ b/Voronoi.cpp @@ -734,14 +734,13 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs) if ( j == 0) pCrvOffs->AddPoint( ptS) ; - // se estremi coincidenti passo alla curva successiva ( da vroni non possono arrivare circonferenze) - if ( AreSamePointApprox( ptS, ptE)) - continue ; - bool bOk = false ; if ( nType == t_site::SEG) bOk = pCrvOffs->AddLine( ptE) ; - else { + else { + // se estremi coincidenti passo alla curva successiva ( da vroni non possono arrivare circonferenze) + if ( AreSamePointApprox( ptS, ptE)) + continue ; PtrOwner pArc( CreateBasicCurveArc()) ; pArc->Set2PRS( ptS, ptE, Dist( ptC, ptS), nType == CCW) ; bOk = pCrvOffs->AddCurve( Release( pArc)) ; From aeff9fb418dd8244ccd7aa2ec3693fa40b39d014 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 19 Sep 2024 09:06:40 +0200 Subject: [PATCH 04/13] =?UTF-8?q?EgtGeomKernel=20:=20-=20in=20sgrossature,?= =?UTF-8?q?=20aggiunta=20modalit=C3=A0=20CONFORMAL=5FZIGZAG=20e=20CONFORMA?= =?UTF-8?q?L=5FONEWAY.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CalcPocketing.cpp | 2097 +++++++++++++++++++++++++++++++++------------ 1 file changed, 1546 insertions(+), 551 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 13f3896..616b585 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -19,6 +19,7 @@ #include "BiArcs.h" #include "SurfFlatRegion.h" #include "GeoConst.h" +#include "Voronoi.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkCurveAux.h" #include "/EgtDev/Include/EGkCalcPocketing.h" @@ -68,14 +69,15 @@ struct PocketParams { double dFeed = 1000 ; // feed di riferimento per frazione double dToolFeed = 1000 ; // feed del tool // ------------------------------------------------------- - bool bAllClosed = true ; // flag per indicare se tutti i bordi sono chiusi + bool bAllClosed = true ; // flag per indicare se tutti i bordi della *pSfr da svuotare sono chiusi + bool bAllOpen = true ; // flag per indicare se tutti i bordi della *pSfr da svuotare sono aperti double dOffsExtra = 2. ; // Offset aggiuntivo per percosi a ZigZag/OneWay se richieste le curve di bordo Frame3d frLocXY ; // frame per conti nel piano XY int nOffsType = ICurve::OFF_FILLET ; // tipologia di Offset per estensione degli aperti double dOpenEdgeRad = 0. ; // raggio effettivo di estensione degli aperti } ; - static double TOL_TRAPEZOID = 50 * EPS_SMALL ; // tolleranza per casi a trapezio SpiralPocket +typedef vector VICRVCOMPOPOVECTOR ; //--------------------------------------------------------------------------- @@ -397,6 +399,8 @@ AssignFeedForOpenEdge( ICurveComposite* pCrv, const ICurveComposite* pCrvOF_orig } } } + else + AssignMaxFeed( pCrv, PockParams) ; return true ; } @@ -706,12 +710,38 @@ ResetCurveTempProps( ICurveComposite* pCrvCompo) //---------------------------------------------------------------------------- static bool -IsChunkAllClosed( const ISurfFlatRegion* pSfr, int nChunk, bool& bAllClose) +GetSfrCrvCompoLoops( const ISurfFlatRegion* pSfr, ICRVCOMPOPOVECTOR& vCrvCompo) +{ + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + vCrvCompo.clear() ; + + // scorro i Chunk della superficie + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { + // scorro i loop del Chunk nC-esimo + for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) { + // recupero il Loop come curva composita + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + // inserisco la curva nel vettore + vCrvCompo.emplace_back( Release( pCrvLoop)) ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +IsChunkAllHomogeneous( const ISurfFlatRegion* pSfr, int nChunk, bool& bAllClose, bool& bAllOpen) { // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid() || nChunk < 0 || nChunk > pSfr->GetChunkCount()) return false ; bAllClose = true ; + bAllOpen = true ; // scorro tutti i loop del Chunk for ( int nL = 0 ; nL < pSfr->GetLoopCount( nChunk) ; ++ nL) { @@ -722,9 +752,11 @@ IsChunkAllClosed( const ISurfFlatRegion* pSfr, int nChunk, bool& bAllClose) // scorro le curve semplici int nCurrProp = TEMP_PROP_INVALID ; for ( int nU = 0 ; nU < pCrvLoop->GetCurveCount() ; ++ nU) { - bAllClose = ( pCrvLoop->GetCurveTempProp( nU, nCurrProp, 0) && + bAllClose = ( bAllClose && pCrvLoop->GetCurveTempProp( nU, nCurrProp, 0) && nCurrProp == TEMP_PROP_CLOSE_EDGE) ; - if ( ! bAllClose) + bAllOpen = ( bAllOpen && pCrvLoop->GetCurveTempProp( nU, nCurrProp, 0) && + nCurrProp == TEMP_PROP_OPEN_EDGE) ; + if ( ! bAllClose && ! bAllOpen) return true ; } } @@ -734,24 +766,78 @@ IsChunkAllClosed( const ISurfFlatRegion* pSfr, int nChunk, bool& bAllClose) //---------------------------------------------------------------------------- static bool -IsSfrAllClosed( const ISurfFlatRegion* pSfr, bool& bAllClose) +IsSfrAllHomogeneous( const ISurfFlatRegion* pSfr, bool& bAllClose, bool& bAllOpen) { // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid()) return false ; bAllClose = true ; + bAllOpen = true ; // ciclo sui Chunk della regione for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { - if ( ! IsChunkAllClosed( pSfr, nC, bAllClose)) + bool bChunkClose = true ; + bool bChunkOpen = true ; + if ( ! IsChunkAllHomogeneous( pSfr, nC, bChunkClose, bChunkOpen)) return false ; - if ( ! bAllClose) + bAllClose = ( bAllClose && bChunkClose) ; + bAllOpen = ( bAllOpen && bChunkOpen) ; + if ( ! bAllClose && ! bAllClose) return true ; } return true ; } +//---------------------------------------------------------------------------- +static bool +IsSfrChunkMadeOnlyByClosedIslands( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParams, + bool& bOK, ICRVCOMPOPOVECTOR& vCrvIsl) +{ + // controllo dei parametri + if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid()) + return false ; + vCrvIsl.clear() ; + bOK = false ; + + // se non esistono isole + if ( pSfrChunk->GetLoopCount( 0) == 1) + return true ; + + // controllo il loop esterno + PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; + if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid()) + return false ; + for ( int i = 0 ; i < pCrvExtLoop->GetCurveCount() ; ++ i) { + int nTmpProp = TEMP_PROP_INVALID ; + if ( pCrvExtLoop->GetCurveTempProp( i, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) + return true ; + } + + // controllo le Isole + bool bOkIsl = true ; + for ( int i = 1 ; i < pSfrChunk->GetLoopCount( 0) && bOkIsl ; ++ i) { + // recupero l'isola + PtrOwner pCrvIsl( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, i))) ; + if ( IsNull( pCrvIsl) || ! pCrvIsl->IsValid()) + return false ; + // controllo le sue TmpProps + for ( int i = 0 ; i < pCrvIsl->GetCurveCount() && bOkIsl ; ++ i) { + int nTmpProp = TEMP_PROP_INVALID ; + bOkIsl = ( pCrvIsl->GetCurveTempProp( i, nTmpProp, 0) && nTmpProp == TEMP_PROP_CLOSE_EDGE) ; + } + if ( bOkIsl) + vCrvIsl.emplace_back( Release( pCrvIsl)) ; + } + + if ( ! bOkIsl) + vCrvIsl.clear() ; + else + bOK = true ; + + return true ; +} + //---------------------------------------------------------------------------- static bool ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketParams& PockParams, @@ -838,7 +924,7 @@ AdjustContourStart( ICurveComposite* pCompo, const PocketParams& PockParams) pCrv = pCompo->GetNextCurve() ; } // se non trovato o troppo corto, cerco il tratto chiuso più lungo in generale ( non lineare) - if ( nMax < 0 || dLenMax < 2. * PockParams.dRad + 2 * PockParams.dRadialOffset) { + if ( nMax < 0 || dLenMax < 1.25 * PockParams.dRad) { i = 0 ; pCrv = pCompo->GetFirstCurve() ; while ( pCrv != nullptr) { @@ -903,6 +989,24 @@ GetHomogeneousParts( ICurveComposite* pCrvCompo, const PocketParams& PockParams, return true ; } +//---------------------------------------------------------------------------- +static bool +GetFirstOffsCrvFromSfr( const ISurfFlatRegion* pSfr, double dOffs, ICRVCOMPOPOVECTOR& vCrvFirstOffs) +{ + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + vCrvFirstOffs.clear() ; + + // creo la regione mediante Offset + PtrOwner pSfrOffs( pSfr->CreateOffsetSurf( dOffs, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrOffs) || ! pSfrOffs->IsValid()) + return false ; + + // inserisco le curve orientante + return ( GetSfrCrvCompoLoops( pSfrOffs, vCrvFirstOffs)) ; +} + //--------------------------------------------------------------------------- static bool CreateSurfFrIncidence( const ICurveComposite* pCrv, const PocketParams& PockParams, @@ -1725,8 +1829,8 @@ GetPocketCurvesByClosedEdges( const ISurfFlatRegion* pSfrChunk, const PocketPara //---------------------------------------------------------------------------- static bool -ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes, - bool& bSkipPocket) +ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, bool bCalcSingleCrv, + ICRVCOMPOPOVECTOR& vCrvCompoRes, bool& bSkipPocket) { // controllo parametri : if ( pSfr == nullptr || ! pSfr->IsValid()) @@ -1734,7 +1838,7 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP bSkipPocket = false ; // controllo se esistono dei lati aperti - if ( ! IsSfrAllClosed( pSfr, PockParams.bAllClosed)) + if ( ! IsSfrAllHomogeneous( pSfr, PockParams.bAllClosed, PockParams.bAllOpen)) return false ; // se lati tutti chiusi, allora non devo fare nulla if ( PockParams.bAllClosed) @@ -1766,16 +1870,16 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP PtrOwner pSfrChunk( pSfr->CloneChunk( nC)) ; if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) return false ; - bool bIsAllRemoved = false ; - GetPocketCurvesByClosedEdges( pSfrChunk, PockParams, vCrvCompoRes, bIsAllRemoved) ; - if ( bIsAllRemoved) { - // se ho rimosso tutto, allora passo la chunk successivo - ++ nChunkOneCurve ; - continue ; + + if ( bCalcSingleCrv) { + bool bIsAllRemoved = false ; + GetPocketCurvesByClosedEdges( pSfrChunk, PockParams, vCrvCompoRes, bIsAllRemoved) ; + if ( bIsAllRemoved) { + // se ho rimosso tutto, allora passo la chunk successivo + ++ nChunkOneCurve ; + continue ; + } } - // controllo se la lavorazione ammatte estensione da aperti - if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) - continue ; // vettore delle isole che userò ( le isole aperte piccole sono trascurate) ICRVCOMPOPOVECTOR vCrvToTIsland ; @@ -1892,6 +1996,7 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP } } + // se ho ottenuto delle curve singole, allora le provo a concatenare // ( tenendo solo le curve al di fuori della superficie limite ( con Offset del raggio del tool) // potrei doverle riconcatenare @@ -1922,12 +2027,32 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, ICRVCOMP return true ; // restituisco la superficie aggiornata ricavata - if ( PockParams.nType != POCKET_CONFORMAL_ZIGZAG) { - if ( ! pSrfFinal->IsValid()) - return false ; - pSfr->Clear() ; - pSfr->CopyFrom( pSrfFinal) ; + if ( ! pSrfFinal->IsValid()) + return false ; + // chiudo le isole che risultano ambigue + for ( int nC = 0 ; nC < pSrfFinal->GetChunkCount() ; ++ nC) { + for ( int nL = 1 ; nL < pSrfFinal->GetLoopCount( nC) ; ++ nL) { + // controllo uniformità + int nCurrTmpProp = TEMP_PROP_INVALID ; + int nPrecTmpProp = TEMP_PROP_INVALID ; + bool bIsMixed = false ; + PtrOwner pCrvIsl( ConvertCurveToComposite( pSrfFinal->GetLoop( nC, nL))) ; + if ( IsNull( pCrvIsl) || ! pCrvIsl->IsValid()) + return false ; + for ( int nU = 0 ; nU < pCrvIsl->GetCurveCount() && ! bIsMixed ; ++ nU) { + pCrvIsl->GetCurveTempProp( nU, nCurrTmpProp, 0) ; + bIsMixed = ( nU != 0 && nCurrTmpProp != nPrecTmpProp) ; + nPrecTmpProp = nCurrTmpProp ; + } + // se proprità non uniformi -> tutta chiusa + if ( bIsMixed) { + for ( int nU = 0 ; nU < pCrvIsl->GetCurveCount() ; ++ nU) + pSrfFinal->SetCurveTempProp( nC, nL, nU, TEMP_PROP_CLOSE_EDGE) ; + } + } } + pSfr->Clear() ; + pSfr->CopyFrom( pSrfFinal) ; return ( pSfr->IsValid() && pSfr->GetChunkCount() > 0) ; } @@ -4170,9 +4295,8 @@ CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ICRVCOMPOPO return false ; double dLenA ; pCrvA->GetLength( dLenA) ; double dLenB ; pCrvB->GetLength( dLenB) ; - if ( dLenA < dLenB) { - pCompoHelp->AddCurve( Release( pCrvA)) ; - } + if ( dLenA < dLenB) + pCompoHelp->AddCurve( Release( pCrvA)) ; else { pCrvB->Invert() ; pCompoHelp->AddCurve( Release( pCrvB)) ; @@ -4535,7 +4659,7 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& // ================= LINK ================================ int nLink_Ind = ( bFollowOrder ? i + 1 : i) ; - // ( Il primo link è nullo, inatti non vi è nessun raccordo per raggiungere il primo Offset) + // ( Il primo link è nullo, infatti non vi è nessun raccordo per raggiungere il primo Offset) if ( nLink_Ind < int( vLinks.size()) && ! IsNull( vLinks[nLink_Ind]) && vLinks[nLink_Ind]->IsValid()) { @@ -4577,6 +4701,13 @@ static bool RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs, ICRVCOMPOPOVECTOR& vOffsFirstCurve, const PocketParams& PockParams) { + /* + E' richiesto che le curve di Offset presentino le seguenti TempProps : + - TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter) [per CONFORMAL] + - TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_LEFT) [per CONFORMAL] + [per SPIRAL le proprietà sono ricavate automaticamente] + */ + // se non ho nessuna superficie valida da svuotare, allora esco if ( pSfrUncleared == nullptr) return false ; @@ -4608,7 +4739,7 @@ RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_SPIRALOUT) bSkip = ( vOffsFirstCurve[j]->IsPointOn( ptCheck, 100 * EPS_SMALL)) ; else if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) - bSkip = vOffs[i]->GetTempProp( 0) == 0 ; + bSkip = ( vOffs[i]->GetTempProp( 0) == 0) ; } if ( bSkip) continue ; @@ -4621,7 +4752,7 @@ RemoveExtraParts( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& vOffs continue ; } else if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) { - if ( nSide != vOffs[i]->GetTempProp( 1)) + if ( nSide == vOffs[i]->GetTempProp( 1)) continue ; } } @@ -4903,8 +5034,6 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con vLinks.clear() ; vLinks.resize( int( vOffs.size())) ; - vector VT ; - // scorro tutte le curva di Offset for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) { @@ -5115,81 +5244,6 @@ CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, return true ; } -//---------------------------------------------------------------------------- -static bool -ExtendGuideByIteration( ICurveComposite* pCompoTempGuide, const ICurveComposite* pCompoPerimeter, - bool bInverted) -{ - // controllo dei parametri - if ( pCompoTempGuide == nullptr || ! pCompoTempGuide->IsValid() || - pCompoPerimeter == nullptr || ! pCompoPerimeter->IsValid()) - return false ; - - const double EXTENSION_VAL = 1000. ; - - // ricavo il punto finale della guida - Point3d ptEndGuide ; pCompoTempGuide->GetEndPoint( ptEndGuide) ; - // direzione finale della guida - Vector3d vtEndGuide ; pCompoTempGuide->GetEndDir( vtEndGuide) ; - // creo un segmento diretto come il chiuso - PtrOwner pSeg( CreateCurveLine()) ; - if ( IsNull( pSeg) || - ! pSeg->Set( ptEndGuide, ptEndGuide + EXTENSION_VAL * vtEndGuide)) - return false ; - // calcolo l'intersezione tra questo segmento e la curva di perimetro aperta - IntersCurveCurve ICC( *pSeg, *pCompoPerimeter) ; - // se l'unica intersezione è il punto iniziale del segmento, allora non estendo la guida - // ( vale anche nel caso di intersezione con Overlap) - if ( ICC.GetIntersCount() == 1) { - IntCrvCrvInfo aInfo ; - if ( ICC.GetIntCrvCrvInfo( 0, aInfo)) { - if ( AreSamePointApprox( aInfo.IciB[0].ptI, ptEndGuide)) - return true ; - } - } - // passo alla PolyLine del perimetro - PolyLine PL ; - pCompoPerimeter->ApproxWithLines( EPS_SMALL, EPS_ANG_SMALL, ICurve::APL_STD, PL) ; - // cerco il punto più esterno rispetto alla direzione del chiuso - Point3d ptPoly ; - PL.GetFirstPoint( ptPoly) ; - while ( PL.GetNextPoint( ptPoly)) { - if ( ! pSeg->Set( ptEndGuide, ptEndGuide + ( ptPoly - ptEndGuide) * EXTENSION_VAL)) - return false ; - // calcolo l'intersezione tra questo segmento e la curva di perimetro aperta - IntersCurveCurve ICC( *pSeg, *pCompoPerimeter) ; - // se una intersezione, allora di Overlap con punto iniziale e finale definito - if ( ICC.GetIntersCount() == 1) { - IntCrvCrvInfo aInfo ; - if ( ICC.GetIntCrvCrvInfo( 0, aInfo)) { - if ( aInfo.bOverlap) { - if ( AreSamePointApprox( aInfo.IciB[0].ptI, ptEndGuide) && - AreSamePointApprox( aInfo.IciB[1].ptI, ptPoly)) - return ( pCompoTempGuide->AddLine( ptPoly)) ; - } - else { - if ( AreSamePointApprox( aInfo.IciB[0].ptI, ptEndGuide)) - return ( pCompoTempGuide->AddLine( ptPoly)) ; - } - } - } - // se più di una intersezione, allora il perimetro deve essere tutto Interno al segmento - // ( Out nel caso in cui ho le curve invertite) - IntCrvCrvInfo aInfo ; - bool bOk = true ; - for ( int i = 0 ; i < ICC.GetIntersCount() && bOk ; ++ i) { - bOk = ( ICC.GetIntCrvCrvInfo( i, aInfo)) ; - bOk = ( aInfo.bOverlap || - ( aInfo.IciB[0].nPrevTy != ( ! bInverted ? CRVC_OUT : CRVC_IN) && - aInfo.IciB[0].nNextTy != ( ! bInverted ? CRVC_OUT : CRVC_IN))) ; - } - if ( bOk) - return ( pCompoTempGuide->AddLine( ptPoly)) ; - } - - return true ; -} - //---------------------------------------------------------------------------- static bool IsCompoMadeBy2DifferentHomogeneousParts( const ICurveComposite* pCompo, const PocketParams& PockParams, @@ -5218,445 +5272,10 @@ IsCompoMadeBy2DifferentHomogeneousParts( const ICurveComposite* pCompo, const Po } } - // controlloo che la curva abbia esattamente due tratti omogenei + // controllo che la curva abbia esattamente due tratti omogenei bOk = ( int( vpCrvs.size()) == 2) ; if ( ! bOk) vpCrvs.clear() ; - return true ; - -} - -//---------------------------------------------------------------------------- -static bool -CalcCrvGuideConformalZigZag( const ISurfFlatRegion* pSfrChunk, PocketParams& PockParams, ICurveComposite* pCompoGuide, - ICurveComposite* pCompoClass, ICurveComposite* pCompoClass_UR) -{ - /* - NB. La curva di classificazione pCompoClass è una curva chiusa che deriva dall'estensione - presso i lati aperti con un tool di ragggio a max( dRad / 8, PockParams.dSideStep / 2). - NB. La curva di classificazione pCompoClass_UR è la curva mediante la quale i Biarchi di - raccordo ( curve a racciolo non devono uscire) ; in questo caso l'estensione della - curva è paragonabile a quella di un tool con raggio - max( dRad / 8, PockParams.dSideStep / 2) + PockParams.Rad - in questo modo il controOffset della regione definisce correttamente la curva per la classificazione - */ - - - // controllo dei parametri - if ( pCompoGuide == nullptr || pCompoClass == nullptr || pCompoClass_UR == nullptr || - pSfrChunk == nullptr || ! pSfrChunk->IsValid()) - return false ; - pCompoGuide->Clear() ; - pCompoClass->Clear() ; - pCompoClass_UR->Clear() ; - - // la superficie deve avere un Chunk e non avere isole - if ( pSfrChunk->GetChunkCount() > 1 || pSfrChunk->GetLoopCount( 0) > 1) - return true ; - - // ricavo la curva di bordo ( la curva che definisce il perimetro) - PtrOwner pCompoPerimeter( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; - if ( IsNull( pCompoPerimeter) || ! pCompoPerimeter->IsValid()) - return false ; - // controllo che sia formata da esattamente due tratti omogenei - bool b2HP = false ; - ICRVCOMPOPOVECTOR vpCrvs ; - if ( ! IsCompoMadeBy2DifferentHomogeneousParts( pCompoPerimeter, PockParams, b2HP, vpCrvs)) - return false ; - if ( ! b2HP) - return true ; - - // allargo curva di Bordo secondo le specifiche di una lavorazione a SpiralIn - double dRad = PockParams.dRad ; - int nOffsType = PockParams.nOffsType ; - PockParams.dRad = max( dRad / 8, PockParams.dSideStep / 2) ; - PockParams.nOffsType = ICurve::OFF_CHAMFER ; - ICRVCOMPOPOVECTOR vCrvEmpty ; - if ( ! AdjustContourWithOpenEdges( pCompoPerimeter, vCrvEmpty, PockParams)) - return false ; - PockParams.dRad = dRad ; - PockParams.nOffsType = nOffsType ; - - // reucupero ora i due tratti uniformi ( della curva allargata) - if ( ! IsCompoMadeBy2DifferentHomogeneousParts( pCompoPerimeter, PockParams, b2HP, vpCrvs) || - ! b2HP) - return false ; - - // la guida inizialmente è data dal tratto chiuso - // il perimetro coincide con il tratto aperto - PtrOwner pCompoTempGuide( Release( vpCrvs[0])) ; - if ( IsNull( pCompoTempGuide) || ! pCompoTempGuide->IsValid()) - return false ; - - // estendo la curva nel suo tratto finale ed iniziale - for ( int i = 0 ; i < 2 ; ++ i) { - if ( ! ExtendGuideByIteration( pCompoTempGuide, vpCrvs[1], ( i == 1))) - return false ; - // se la guida diventa diventa chiusa, allora esco - if ( ! pCompoTempGuide->IsValid() || pCompoTempGuide->IsClosed()) - return true ; - pCompoTempGuide->Invert() ; - vpCrvs[1]->Invert() ; - } - - // tratto iniziale - Vector3d vtStart ; pCompoTempGuide->GetStartDir( vtStart) ; - Point3d ptStart ; pCompoTempGuide->GetStartPoint( ptStart) ; - PtrOwner pLineStart( CreateCurveLine()) ; - if ( IsNull( pLineStart) || ! pLineStart->Set( ptStart - 1000. * vtStart, ptStart)) - return false ; - // tratto finale ( potrebbe intersecare il tratto iniziale) - Vector3d vtEnd ; pCompoTempGuide->GetEndDir( vtEnd) ; - Point3d ptEnd ; pCompoTempGuide->GetEndPoint( ptEnd) ; - PtrOwner pLineEnd( CreateCurveLine()) ; - if ( IsNull( pLineEnd) || ! pLineEnd->Set( ptEnd, ptEnd + 1000. * vtEnd)) - return false ; - IntersCurveCurve ICC( *pLineStart, *pLineEnd) ; - if ( ICC.GetIntersCount() > 0) { - IntCrvCrvInfo aInfo ; - if ( ICC.GetIntCrvCrvInfo( 0, aInfo)) { - pLineStart->TrimStartAtParam( aInfo.IciA[0].dU) ; - pLineEnd->TrimEndAtParam( aInfo.IciB[0].dU) ; - } - } - // le due estensioni vanno tagliate presso i bordi dei lati aperti estesi - IntersCurveCurve ICCLS( *pLineStart, *vpCrvs[1]) ; - if ( ICCLS.GetIntersCount() > 0) { - IntCrvCrvInfo aInfo ; - for ( int i = 0 ; i < ICCLS.GetCrossIntersCount() ; ++ i) { - if ( ICCLS.GetIntCrvCrvInfo( i, aInfo)) { - if ( ! AreSamePointApprox( aInfo.IciA[ aInfo.bOverlap ? 1 : 0].ptI, ptStart)) - pLineStart->ModifyStart( aInfo.IciA[aInfo.bOverlap ? 1 : 0].ptI) ; - } - } - } - IntersCurveCurve ICCLE( *pLineEnd, *vpCrvs[1]) ; - if ( ICCLE.GetIntersCount() > 0) { - IntCrvCrvInfo aInfo ; - for ( int i = 0 ; i < ICCLE.GetCrossIntersCount() ; ++ i) { - if ( ICCLE.GetIntCrvCrvInfo( 0, aInfo)) { - if ( ! AreSamePointApprox( aInfo.IciA[0].ptI, ptEnd)) - pLineEnd->ModifyEnd( aInfo.IciA[0].ptI) ; - } - } - } - pCompoTempGuide->AddCurve( Release( pLineStart), false) ; - pCompoTempGuide->AddCurve( Release( pLineEnd), true) ; - - // recupero la curva guida - pCompoGuide->CopyFrom( pCompoTempGuide) ; - - // recupero la curva di classificazione ( abballendola) - PolyLine PL ; - pCompoPerimeter->ApproxWithLines( 10 * LIN_TOL_MIN, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) ; - PL.RemoveAlignedPoints( 500 * EPS_SMALL) ; - pCompoPerimeter->Clear() ; - pCompoPerimeter->FromPolyLine( PL) ; - pCompoPerimeter->RemoveSmallDefects( 10 * LIN_TOL_MIN, ANG_TOL_STD_DEG, true) ; - pCompoPerimeter->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ; - pCompoClass->CopyFrom( pCompoPerimeter) ; - ResetCurveTempProps( pCompoClass) ; - - // creo la curva di classificazione per le regioni non svuotate - dRad = PockParams.dRad ; - PockParams.dRad = max( dRad / 8, PockParams.dSideStep / 2) + dRad ; - PtrOwner pCompoClassUnclearedRegion( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; - if ( IsNull( pCompoClassUnclearedRegion) || ! pCompoClassUnclearedRegion->IsValid() || - ! AdjustContourWithOpenEdges( pCompoClassUnclearedRegion, vCrvEmpty, PockParams)) - return false ; - PockParams.dRad = dRad ; - if ( pCompoClassUnclearedRegion->IsValid()) { - OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( pCompoClassUnclearedRegion, - PockParams.dRad - PockParams.dRadialOffset, ICurve::OFF_FILLET)) - return false ; - PtrOwner pMyCrv( ConvertCurveToComposite( OffsCrv.GetLongerCurve())) ; - if ( IsNull( pMyCrv) || ! pMyCrv->IsValid()) - return false ; - pCompoClass_UR->CopyFrom( pMyCrv) ; - } - - return true ; -} - -//---------------------------------------------------------------------------- -static bool -AdapthLinkToOffsBySmooth( ICurveComposite* pCrvLink, ICurveComposite* pCrvOffsPrec, - ICurveComposite* pCrvOffsSucc, const PocketParams& PockParams) -{ - // controllo dei parametri - if ( pCrvLink == nullptr || pCrvOffsPrec == nullptr || pCrvOffsSucc == nullptr || - ! pCrvLink->IsValid() || ! pCrvOffsPrec->IsValid() || ! pCrvOffsSucc->IsValid()) - return false ; - - // clono la curva di Link ( in modo da non rovinare l'originale) - PtrOwner pCrvMyLink( CloneCurveComposite( pCrvLink)) ; - if ( IsNull( pCrvMyLink) || ! pCrvMyLink->IsValid()) - return false ; - - // aggiungo la curva finale dell'Offset precedente e la curva iniziale dell'Offset successivo - // al tratto di Link - PtrOwner pCrvPrec( pCrvOffsPrec->GetLastCurve()->Clone()) ; - PtrOwner pCrvSucc( pCrvOffsSucc->GetFirstCurve()->Clone()) ; - if ( IsNull( pCrvPrec) || IsNull( pCrvSucc) || - ! pCrvPrec->IsValid() || ! pCrvSucc->IsValid()) - return false ; - // assegno proprietà di invalidità delle curve - pCrvPrec->SetTempProp( TEMP_PROP_INVALID, 1) ; - pCrvSucc->SetTempProp( TEMP_PROP_INVALID, 1) ; - // aggiungo - if ( ! pCrvMyLink->AddCurve( Release( pCrvPrec), false) || - ! pCrvMyLink->AddCurve( Release( pCrvSucc), true)) - return false ; - - // estendo la curva, in modo da non perdere i tratti estremi - const double EXT_LEN = 1000. ; - if ( ! pCrvMyLink->AddLineTg( EXT_LEN, false) || - ! pCrvMyLink->AddLineTg( EXT_LEN, true)) - return false ; - - // smusso il Link - double dSmoothParam = PockParams.dRad / 8. ; - ModifyCurveToSmoothed( pCrvMyLink, PockParams, dSmoothParam, dSmoothParam, false) ; - - // rimuovo la prima e l'ultima curva ( e quella invalida) - delete( pCrvMyLink->RemoveFirstOrLastCurve( false)) ; // tratto lineare - delete( pCrvMyLink->RemoveFirstOrLastCurve( true)) ; // tratto lineare - const ICurve* pCrvFirst = pCrvMyLink->GetFirstCurve() ; - if ( pCrvFirst != nullptr && pCrvFirst->GetTempProp( 1) == TEMP_PROP_INVALID) // sottocurva di Offs - delete( pCrvMyLink->RemoveFirstOrLastCurve( false)) ; - const ICurve* pCrvLast = pCrvMyLink->GetLastCurve() ; - if ( pCrvLast != nullptr && pCrvLast->GetTempProp( 1) == TEMP_PROP_INVALID) // sottocurva di Offs - delete( pCrvMyLink->RemoveFirstOrLastCurve( true)) ; - - // recupero punto iniziale e finale del Link - Point3d ptS ; pCrvMyLink->GetStartPoint( ptS) ; - Point3d ptE ; pCrvMyLink->GetEndPoint( ptE) ; - // recupero i paramtri sulle curve di Offset - double dUTrim ; - if ( ! pCrvOffsPrec->GetParamAtPoint( ptS, dUTrim, 500 * EPS_SMALL) || - ! pCrvOffsPrec->TrimEndAtParam( dUTrim)) - return false ; - if ( ! pCrvOffsSucc->GetParamAtPoint( ptE, dUTrim, 500 * EPS_SMALL) || - ! pCrvOffsSucc->TrimStartAtParam( dUTrim)) - return false ; - pCrvLink->CopyFrom( pCrvMyLink) ; - return true ; -} - -//---------------------------------------------------------------------------- -static bool -AddConformalZigZag( const ISurfFlatRegion* pSfr, PocketParams& PockParams, - ICRVCOMPOPOVECTOR& vCrvCompoRes) -{ - /* - Calcolo ottimizzato di svuotatura mediante Offset progressivi di una guida, raccordati - rispetto al bordo della superficie di Pocketing mediante logica ZigZag - */ - - // controllo dei parametri - if ( pSfr == nullptr || ! pSfr->IsValid()) - return false ; - vCrvCompoRes.clear() ; - - // ciclo sui chunk della regione - for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { - // recupero il Chunk nC-esimo - PtrOwner pSfrChunk( pSfr->CloneChunk( nC)) ; - if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) - return false ; - - // recupero il massimo Offset del Chunk nC-esimo - double dMaxOffs ; - pSfrChunk->GetMaxOffset( dMaxOffs) ; - // se inferiore del Tool ( ho già svuotato tale Chunk in precedenza) - if ( dMaxOffs < PockParams.dRad + 200 * EPS_SMALL) - continue ; - - // ricavo la guida ideale e la curva su cui tagliare gli Offset a partire dal Chunk nC-esimo - PtrOwner pCrvGuideExt( CreateCurveComposite()) ; - PtrOwner pCrvClass( CreateCurveComposite()) ; - PtrOwner pCrvClassUR( CreateCurveComposite()) ; - if ( IsNull( pCrvGuideExt) || IsNull( pCrvClass) || - ! CalcCrvGuideConformalZigZag( pSfr, PockParams, pCrvGuideExt, pCrvClass, pCrvClassUR)) - return false ; - // se non è stata trovata una guida ideale, allora passo al Chunk successivo - if ( ! pCrvGuideExt->IsValid() || pCrvGuideExt->GetCurveCount() == 0 || - ! pCrvClass->IsValid() || pCrvClass->GetCurveCount() == 0 || - ! pCrvClassUR->IsValid() || pCrvClassUR->GetCurveCount() == 0) { - return true ; - } - - // memorizzo le curve di Offset tagliate a seconda dalla geometria del perimetro - ICRVCOMPOPOVECTOR vOffs ; - const int MAX_ITER = 100 ; - double dOffs = PockParams.dRad + PockParams.dRadialOffset ; - for ( int i = 0 ; i < MAX_ITER ; ++ i) { - OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( pCrvGuideExt, - dOffs, ICurve::OFF_FILLET)) - return false ; - // se invece ne ottengo più di una, controllo se è necessaria - if ( OffsCrv.GetCurveCount() > 1) { - // recupero le curve extra ( tutte tranne la più lunga) - for ( int j = 0 ; j < OffsCrv.GetCurveCount() - 1 ; ++ j) { - // recupero la curva più corta - PtrOwner pCrvShorter( ConvertCurveToComposite( OffsCrv.GetShorterCurve())) ; - if ( ! IsNull( pCrvShorter) && pCrvShorter->IsValid()) { - // controllo se è davvero necessaria per non lasciare materiale - bool bSkip = false ; - if ( pCrvShorter->IsClosed()) { - CheckIfOffsetIsNecessary( pCrvShorter, ( i == 0 ? dOffs : PockParams.dSideStep), - i, PockParams, bSkip) ; - if ( bSkip) - return true ; - } - } - } - } - // se non ottengo nessuna curva, allora ho finito - PtrOwner pCrvOffs( OffsCrv.GetLongerCurve()) ; - if ( IsNull( pCrvOffs) || ! pCrvOffs->IsValid()) - break ; - // se ottengo una curva chiusa, lavorazione non ammessa - if ( pCrvOffs->IsClosed()) - return true ; - // la inverto se numero di Offset progressivo dispari - if ( ( ! IsEven( i) && ! PockParams.bInvert) || - ( IsEven( i) && PockParams.bInvert)) - pCrvOffs->Invert() ; - // classifico la curva rispetto al perimetro, devo tenere solo le parti interne - CRVCVECTOR ccClass ; - IntersCurveCurve ICC( *pCrvOffs, *pCrvClass) ; - if ( ! ICC.GetCurveClassification( 0, EPS_SMALL, ccClass)) - return true ; - // se curva tutta esterna ho finito - if ( int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) - break ; - // scorro tutte le classificazioni ottenute - for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { - // tengo quelle strettamente interne - if ( ccClass[j].nClass == CRVC_IN) { - // recupero la porzione di Offset - PtrOwner pCrvOffs_Int( pCrvOffs->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ; - if ( ! IsNull( pCrvOffs_Int) && pCrvOffs_Int->IsValid()) { - // salvo come prima proprietà temporanea, il numero di Offset progressivo - pCrvOffs_Int->SetTempProp( i, 0) ; - // salvo come seconda proprietà temporanea il lato esterno - pCrvOffs_Int->SetTempProp( ( ! IsEven( i) && ! PockParams.bInvert) || - ( IsEven( i) && PockParams.bInvert) ? - MDS_LEFT : MDS_RIGHT, 1) ; - // salvo la curva - vOffs.emplace_back( ConvertCurveToComposite( Release( pCrvOffs_Int))) ; - } - } - } - dOffs += PockParams.dSideStep ; - } - // se non ho ottenuto Offset, passo al Chunk successivo - if ( vOffs.empty()) - return true ; - - // inverto il vettore degli Offset, in modo da partire dal più esterno fino ad arrivare al - // più interno - reverse( vOffs.begin(), vOffs.end()) ; - - // calcolo la lunghezza del semiperimetro della curva di classificazione - // ( serve per decidere il tratto di curva di raccordo) - double dHalfLenPerimeter ; - pCrvClass->GetLength( dHalfLenPerimeter) ; - dHalfLenPerimeter /= 2. ; - - // creo il vettore dei Link e definisco la tolleranza di Join tra Offset e Link - ICURVEPOVECTOR vLinks( int( vOffs.size())) ; - Point3d ptSplit ; // punto dal quale smussare tutti i percorsi - for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) { - // recupero il parametro iniziale del raccordo sulla curva di perimetro - Point3d ptS ; vOffs[i]->GetEndPoint( ptS) ; - double dUS ; pCrvClass->GetParamAtPoint( ptS, dUS) ; - if ( vOffs[i]->GetTempProp( 0) == 0) - ptSplit = ptS ; - // recupero il parametro finale del raccordo sulla curva di perimetro - Point3d ptE ; vOffs[i+1]->GetStartPoint( ptE) ; - double dUE ; pCrvClass->GetParamAtPoint( ptE, dUE) ; - // recupero il tratto di curva di interesse - PtrOwner pCrvJoint( ConvertCurveToComposite( pCrvClass->CopyParamRange( dUS, dUE))) ; - if ( ! IsNull( pCrvJoint) && pCrvJoint->IsValid()) { - double dLen ; - pCrvJoint->GetLength( dLen) ; - if ( dLen > dHalfLenPerimeter) { - pCrvJoint.Set( ConvertCurveToComposite( pCrvClass->CopyParamRange( dUE, dUS))) ; - pCrvJoint->Invert() ; - } - // solo se non siamo in presenza di curve di primo Offset, aggiungo al Link l'ultima - // curva dell'Offset precedente e la prima curva dell'Offset successivo - if ( vOffs[i]->GetTempProp( 0) > 0 || vOffs[i+1]->GetTempProp( 0) > 0) { - if ( ! AdapthLinkToOffsBySmooth( pCrvJoint, vOffs[i], vOffs[i+1], PockParams)) - return false ; - } - vLinks[i+1].Set( Release( pCrvJoint)) ; - } - } - - // smusso tutte le curve di Offset ( tranne quelle generate alla prima iterazione) - double dSmoothParam = PockParams.dRad / 8. ; - for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { - if ( vOffs[i]->GetTempProp( 0) > 0) - ModifyCurveToSmoothed( vOffs[i], PockParams, dSmoothParam, dSmoothParam, false) ; - } - - // determino la regione piana dove sono contenute le zone non svuotate ( se esistono) - PtrOwner pSfrFirstOffs( CloneSurfFlatRegion( pSfrChunk)) ; - if ( IsNull( pSfrFirstOffs) || ! pSfrFirstOffs->IsValid() || - ! pSfrFirstOffs->Offset( - PockParams.dRad - PockParams.dRadialOffset, ICurve::OFF_FILLET)) - return false ; - ICRVCOMPOPOVECTOR vCrvFirstOffs ; - for ( int nC_ = 0 ; nC_ < pSfrFirstOffs->GetChunkCount() ; ++ nC_) - vCrvFirstOffs.emplace_back( ConvertCurveToComposite( pSfrFirstOffs->GetLoop( nC_, 0))) ; - // inizializzo la regione contenente le parti non svuotate - PtrOwner pSfrUncleared( CreateSurfFlatRegion()) ; - if ( IsNull( pSfrUncleared)) - return false ; - // calcolo la Feed e la regione contenente le parti non svuotate - if ( GetUnclearedRegionAndSetFeed( vCrvFirstOffs, vOffs, vLinks, pCrvClass, PockParams, pSfrUncleared)) { - // Modifico i percorsi - vCrvFirstOffs.clear() ; - vCrvFirstOffs.emplace_back( Release( pCrvClassUR)) ; - if ( ! RemoveExtraParts( pSfrUncleared, vOffs, vCrvFirstOffs, PockParams)) - return false ; - } - - // creo il percorso di svuotatura - PtrOwner pCompoTempPath( CreateCurveComposite()) ; - if ( IsNull( pCompoTempPath)) - return false ; - for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { - if ( ! IsNull( vLinks[i]) && vLinks[i]->IsValid()) { - if ( ! pCompoTempPath->AddCurve( Release( vLinks[i]))) - return false ; - } - if ( ! IsNull( vOffs[i]) && vOffs[i]->IsValid()) { - if ( ! pCompoTempPath->AddCurve( Release( vOffs[i]))) - return false ; - } - } - - // se la curva finale di Pocketing è valida, allora la resituisco - if ( pCompoTempPath->IsValid()) { - // semplifico le curve mediante uniformità delle Feeds - SimplifyCurveByFeeds( pCompoTempPath, PockParams, 10 * EPS_SMALL) ; - // aggiugno il tratto iniziale e finale per entrate da fuori - Vector3d vtStart ; pCompoTempPath->GetStartDir( vtStart) ; - vtStart.Invert() ; - bool bExt = false ; - if ( ! ExtendPath( pCompoTempPath, pSfr, PockParams, vtStart, false, bExt)) - return false ; - Vector3d vtEnd ; pCompoTempPath->GetEndDir( vtEnd) ; - if ( ! ExtendPath( pCompoTempPath, pSfr, PockParams, vtEnd, true, bExt)) - return false ; - // sostituisco la curva - if ( pCompoTempPath->IsValid()) - vCrvCompoRes.emplace_back( Release( pCompoTempPath)) ; - } - } return true ; } @@ -6714,7 +6333,8 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegio return false ; // determino ora il punto di inizio, il tratto per il LeadIn bool bIsChunkClosed = false ; - if ( ! IsChunkAllClosed( pSfrPock, nC, bIsChunkClosed)) + bool bIsChunkAllOpen = false ; + if ( ! IsChunkAllHomogeneous( pSfrPock, nC, bIsChunkClosed, bIsChunkAllOpen)) return false ; if ( ! bIsChunkClosed) { if ( ! AdvanceExtendCurves( vClosedOffs_nC, pSfrOrig, PockParams)) @@ -6796,8 +6416,9 @@ AddZigZag( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar // controllo esistenza di lati aperti per il Chunk attuale bool bIsChunkClosed = true ; + bool bIsChunkAllOpen = true ; if ( ! PockParams.bAllClosed) { - if ( ! IsChunkAllClosed( pSrfPock, nChunkInd, bIsChunkClosed)) + if ( ! IsChunkAllHomogeneous( pSrfPock, nChunkInd, bIsChunkClosed, bIsChunkAllOpen)) return false ; // se il Chunk originale aveva lati aperti, estendo il percorso a ZigZag for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) { @@ -7013,6 +6634,1379 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar return true ; } +//---------------------------------------------------------------------------- +static bool +GetSfrByOpenEdgeExtension( const ISurfFlatRegion* pSfrOrig, PocketParams& PockParams, + double dOffs, int nOffsType, ISurfFlatRegion* pSfrExtended) +{ + // controllo dei parametri + if ( pSfrOrig == nullptr || ! pSfrOrig->IsValid()) + return false ; + + // recupero raggio utensile e tipo di offset corrente + double dMyRad = PockParams.dRad ; + int nMyOffsType = PockParams.nOffsType ; + + // parametri per superficie di classificazione + PockParams.dRad = dOffs ; + PockParams.nOffsType = nOffsType ; + + // estensine presso i lati aperti + ICRVCOMPOPOVECTOR vCrvEmpty ; + bool bSkipPocket ; + pSfrExtended->CopyFrom( pSfrOrig) ; + if ( pSfrExtended == nullptr || ! pSfrExtended->IsValid() || + ! ModifySurfByOpenEdges( pSfrExtended, PockParams, false, vCrvEmpty, bSkipPocket)) + return false ; + + // riporto i parametri originari + PockParams.dRad = dMyRad ; + PockParams.nOffsType = nMyOffsType ; + + return ( pSfrExtended != nullptr && pSfrExtended->IsValid()) ; +} + +//---------------------------------------------------------------------------- +static bool +SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink, + const PocketParams& PockParams, bool bSmoothLeft, bool bSmoothRight, double dSmoothPar, double dTol) +{ + + // controllo dei parametri + if ( pCrvOffs0 == nullptr || ! pCrvOffs0->IsValid() || + pCrvOffs1 == nullptr || ! pCrvOffs1->IsValid() || + pCrvLink == nullptr || ! pCrvLink->IsValid()) + return false ; + + /* + - Data la curva di Link, come prima cosa aggiungo l'ultima curva dell'Offset precedente + e la prima curva dell'Offset successivo. + - Effettuo lo Smusso del Link + - Rimvuovo la prima e l'ultima curva del Link smussato ( Gli estremi del link non vengono + modificati durante l'operazione di smusso + */ + + // curva precedente e successiva + PtrOwner pCrvBef( pCrvOffs0->GetLastCurve()->Clone()) ; + PtrOwner pCrvAft( pCrvOffs1->GetFirstCurve()->Clone()) ; + if ( IsNull( pCrvBef) || IsNull( pCrvAft) || + ! pCrvBef->IsValid() || ! pCrvAft->IsValid()) + return false ; + // estendo il Link + pCrvLink->AddCurve( Release( pCrvBef), false, dTol) ; + pCrvLink->AddCurve( Release( pCrvAft), true, dTol) ; + // smusso + ModifyCurveToSmoothed( pCrvLink, PockParams, dSmoothPar, dSmoothPar, false) ; + // toglo gli estremi + pCrvLink->RemoveFirstOrLastCurve( false) ; + pCrvLink->RemoveFirstOrLastCurve( true) ; + // modifico Offset0 per raccordarlo al nuovo Link + Point3d ptS ; pCrvLink->GetStartPoint( ptS) ; + double dUE ; pCrvOffs0->GetParamAtPoint( ptS, dUE, dTol) ; + if ( ! bSmoothLeft && pCrvOffs0->IsClosed()) + pCrvOffs0->ChangeStartPoint( dUE) ; + else + pCrvOffs0->TrimEndAtParam( dUE) ; + // modifico Offset1 per raccordarlo al nuovo Link + Point3d ptE ; pCrvLink->GetEndPoint( ptE) ; + double dUS ; pCrvOffs1->GetParamAtPoint( ptE, dUS, dTol) ; + if ( ! bSmoothRight && pCrvOffs1->IsClosed()) + pCrvOffs1->ChangeStartPoint( dUS) ; + else + pCrvOffs1->TrimStartAtParam( dUS) ; + + return true ; +} + +static bool +GetConformalLinkForOpenCrv( const ICurveComposite* pCrvOffs0, const ICurveComposite* pCrvOffs1, + const ICRVCOMPOPOVECTOR& vCrvClassBorder, const PocketParams& PockParams, + double dTol, ICurveComposite* pCrvLink) +{ + // controllo dei parametri + if ( pCrvOffs0 == nullptr || ! pCrvOffs0->IsValid() || + pCrvOffs1 == nullptr || ! pCrvOffs1->IsValid()) + return false ; + pCrvLink->Clear() ; + + // ricavo gli estremi del Link + Point3d ptLinkS ; pCrvOffs0->GetEndPoint( ptLinkS) ; + Point3d ptLinkE ; pCrvOffs1->GetStartPoint( ptLinkE) ; + // ricavo i parametri sulla curva di bordo che interessa i due estremi ( 1 sola !) + for ( int i = 0 ; i < int( vCrvClassBorder.size()) ; ++ i) { + if ( vCrvClassBorder[i]->IsPointOn( ptLinkS, dTol) && + vCrvClassBorder[i]->IsPointOn( ptLinkE, dTol)) { + double dPar0 ; vCrvClassBorder[i]->GetParamAtPoint( ptLinkS, dPar0, dTol) ; + double dPar1 ; vCrvClassBorder[i]->GetParamAtPoint( ptLinkE, dPar1, dTol) ; + // ricavo le due curve possibili di Link + PtrOwner pCrvLinkA( vCrvClassBorder[i]->CopyParamRange( dPar0, dPar1)) ; + PtrOwner pCrvLinkB( vCrvClassBorder[i]->CopyParamRange( dPar1, dPar0)) ; + // scelgo quella migliore + double dLenA = 0. ; + if ( ! IsNull( pCrvLinkA) && pCrvLinkA->IsValid()) + pCrvLinkA->GetLength( dLenA) ; + double dLenB = 0. ; + if ( ! IsNull( pCrvLinkB) && pCrvLinkB->IsValid()) { + pCrvLinkB->Invert() ; + pCrvLinkB->GetLength( dLenB) ; + } + if ( dLenA > dLenB) { + if ( ! IsNull( pCrvLinkB) && pCrvLinkB->IsValid()) + pCrvLink->CopyFrom( pCrvLinkB) ; + } + else { + if ( ! IsNull( pCrvLinkA) && pCrvLinkA->IsValid()) + pCrvLink->CopyFrom( pCrvLinkA) ; + } + break ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams, + const ICRVCOMPOPOVECTOR& vCrvClassBorder, const ICRVCOMPOPOVECTOR& vCrvExtendedBorders, + ICurveComposite* pCrvLink) +{ + // controllo validità delle due curve di Offset + if ( pCrvOffs0 == nullptr || ! pCrvOffs0->IsValid() || + pCrvOffs1 == nullptr || ! pCrvOffs1->IsValid()) + return false ; + pCrvLink->Clear() ; + const double TOL = 150 * EPS_SMALL ; + + // flag per curve di Offset aperte o chiuse + bool bOpen0 = ( ! pCrvOffs0->IsClosed()) ; + bool bOpen1 = ( ! pCrvOffs1->IsClosed()) ; + + // se passo da una curva aperta ad un'altra curva aperta ( uso i bordi di pSfrClass) + if ( bOpen0 && bOpen1) { + // ricavo la curva di Link + if ( ! GetConformalLinkForOpenCrv( pCrvOffs0, pCrvOffs1, vCrvClassBorder, PockParams, TOL, pCrvLink)) + return false ; + // smusso il Link raccordandolo + if ( pCrvLink->IsValid()) + SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, true, true, PockParams.dRad / 8., TOL) ; + } + else { + // clono le due curve di Offset + PtrOwner pCrvOffs0_cl( CloneCurveComposite( pCrvOffs0)) ; + PtrOwner pCrvOffs1_cl( CloneCurveComposite( pCrvOffs1)) ; + if ( IsNull( pCrvOffs0_cl) || IsNull( pCrvOffs1_cl) || ! pCrvOffs0_cl->IsValid() || ! pCrvOffs1_cl->IsValid()) + return false ; + // controllo se gli Offset sono stati ricavati alla prima iterazione + bool bFirstIterOffs0 = ( pCrvOffs0->GetTempProp( 0) == 0) ; + bool bFirstIterOffs1 = ( pCrvOffs1->GetTempProp( 0) == 0) ; + // creo la curva che le collegherà + bool bSmooth = PockParams.bSmooth ; + PockParams.bSmooth = false ; + if ( ! CutCurveToConnect( pCrvOffs0, pCrvOffs1, vCrvExtendedBorders, PockParams, + ( ( bOpen0 || bFirstIterOffs0) ? 0. : 10 * EPS_SMALL), + ( ( bOpen1 || bFirstIterOffs1) ? 0. : 10 * EPS_SMALL), + pCrvLink) || + ! pCrvLink->IsValid()) { + // se curva di Link non valida, cerco una strada più semplice + pCrvLink->Clear() ; + pCrvOffs0->CopyFrom( pCrvOffs0_cl) ; + pCrvOffs1->CopyFrom( pCrvOffs1_cl) ; + // recupero i vettori tangente iniziali ( le curve sono chiuse ) + Vector3d vtS, vtE ; + Point3d ptS, ptE ; + if ( ! pCrvOffs0->GetStartDir( vtS) || ! pCrvOffs1->GetStartDir( vtE) || + ! pCrvOffs0->GetStartPoint( ptS) || ! pCrvOffs1->GetStartPoint( ptE)) + return false ; + // creo il bi-arco tra esse + if ( ! CalcBoundedSmoothedLink( ptS, vtS, ptE, vtE, 0.5, vCrvExtendedBorders, PockParams, pCrvLink) || + ! pCrvLink->IsValid()) + return false ; + } + PockParams.bSmooth = bSmooth ; + SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, ! bFirstIterOffs0, ! bFirstIterOffs1, + PockParams.dRad / 16., TOL) ; + // per sicurezza aggiorno i nuovi punti e i nuovi parametri + double dUNewE ; + Point3d ptStartNext ; + pCrvLink->GetEndPoint( ptStartNext) ; + pCrvOffs1->GetParamAtPoint( ptStartNext, dUNewE) ; + pCrvOffs1->ChangeStartPoint( dUNewE) ; + } + + return true ; + +} + +//---------------------------------------------------------------------------- +static bool +CheckConformalRetractLink( const ICurveComposite* pCrvOffs0, const ICurveComposite* pCrvOffs1, + const ICRVCOMPOPOVECTOR& vCrvClassBorder, const PocketParams& PockParams, + bool& bCalcLink) +{ + // controllo dei parametri + if ( pCrvOffs0 == nullptr || ! pCrvOffs0->IsValid() || + pCrvOffs1 == nullptr || ! pCrvOffs1->IsValid()) + return false ; + bCalcLink = true ; // di base calcolo il Link + + // recupero gli estremi di un possibile collegamento tra i punti + Point3d ptA ; pCrvOffs0->GetEndPoint( ptA) ; + Point3d ptB ; pCrvOffs1->GetStartPoint( ptB) ; + // se vicini -> no retroazione + if ( SqDist( ptA, ptB) < 4 * PockParams.dRad * PockParams.dRad + 50 * EPS_SMALL) + return true ; + // se distanti + else { + // controllo se sono aperte + bool bOpen_i = ( ! pCrvOffs0->IsClosed()) ; + bool bOpen_ii = ( ! pCrvOffs1->IsClosed()) ; + // se entrambe aperte + if ( bOpen_i && bOpen_ii) { + // calcolo il collegamento tra le due curve + PtrOwner pCrvLink( CreateCurveComposite()) ; + if ( IsNull( pCrvLink) || + ! GetConformalLinkForOpenCrv( pCrvOffs0, pCrvOffs1, vCrvClassBorder, PockParams, + 25 * EPS_SMALL, pCrvLink)) + return false ; + // se Link valido calcolo la sua lunghezza + double dLinkLen = 0. ; + if ( pCrvLink->IsValid()) + pCrvLink->GetLength( dLinkLen) ; + // minima distanza da ptA + DistPointCurve DistPtACrv( ptA, *pCrvOffs1) ; + double dMyDist ; + if ( DistPtACrv.GetSqDist( dMyDist) && + dMyDist < 4 * PockParams.dRad * PockParams.dRad + 50 * EPS_SMALL) { + bCalcLink = ( dLinkLen < 4 * PockParams.dRad) ; + return true ; + } + // minima distanza da ptB + DistPointCurve DistPtBCrv( ptB, *pCrvOffs0) ; + if ( DistPtBCrv.GetSqDist( dMyDist) && + dMyDist < 4 * PockParams.dRad * PockParams.dRad + 50 * EPS_SMALL) { + bCalcLink = ( dLinkLen < 4 * PockParams.dRad) ; + return true ; + } + } + // ... servono altri controlli ??? ( vedere dai casi) + } + + bCalcLink = false ; + return true ; + +} + +//---------------------------------------------------------------------------- +static bool +GetConformalIndices( const VICRVCOMPOPOVECTOR& vCrvOffs, int nMyInd0, int nMyInd1, + const PocketParams& PockParams, const ICRVCOMPOPOVECTOR& vCrvClassBorder, + int& nInd0, int& nInd1) +{ + // controllo che l'indice sia sensato + if ( vCrvOffs.empty() || nMyInd0 < 0 || nMyInd0 >= int( vCrvOffs.size()) || + ( nMyInd1 < 0 || nMyInd1 >= int( vCrvOffs[nMyInd0].size()))) + return false ; + nInd0 = -1 ; + nInd1 = -1 ; + + // il punto di riferimento è il punto finale della curva corrente + Point3d ptRef ; vCrvOffs[nMyInd0][nMyInd1]->GetEndPoint( ptRef) ; + // controllo se la curva è chiusa o aperta + bool bIsClosed = ( vCrvOffs[nMyInd0][nMyInd1]->IsClosed()) ; + // controllo se la curva è di primo Offset ( in questo caso non ho curve successive) + bool bFistOffs = ( nMyInd0 == int( vCrvOffs.size() - 1)) ; + + // scorro le curve di indice successivo + double dLimInfDist = INFINITO ; + int nInd = -1 ; + for ( int i = 0 ; ! bFistOffs && i < int( vCrvOffs[nMyInd0 + 1].size()) ; ++ i) { + // se non attiva, passo alla successiva + if ( vCrvOffs[nMyInd0 + 1][i]->GetTempProp( 0) != TEMP_PROP_CURVE_ACTIVE) + continue ; + // se di topologia differente, passo alla successiva + if ( ( bIsClosed != vCrvOffs[nMyInd0 + 1][i]->IsClosed())) + continue ; + // se richiede retroazione, passo alla successiva + bool bCalcLink = true ; + if ( ! CheckConformalRetractLink( vCrvOffs[nMyInd0][nMyInd1], vCrvOffs[nMyInd0 + 1][i], + vCrvClassBorder, PockParams, bCalcLink)) + return false ; + if ( ! bCalcLink) + continue ; + // se aperta + if ( ! bIsClosed) { + Point3d ptStart ; vCrvOffs[nMyInd0 + 1][i]->GetStartPoint( ptStart) ; + double dDist = SqDist( ptRef, ptStart) ; + if ( dDist < dLimInfDist) { + dLimInfDist = dDist ; + nInd = i ; + } + } + // se chiusa + else { + DistPointCurve DistPtCrv( ptRef, *vCrvOffs[nMyInd0 + 1][i]) ; + MinDistPCInfo aInfo ; + if ( DistPtCrv.GetMinDistInfo( 0, aInfo)) { + double dDist = SqDist( ptRef, aInfo.ptQ) ; + if ( dDist < dLimInfDist) { + dLimInfDist = dDist ; + nInd = i ; + vCrvOffs[nMyInd0 + 1][i]->ChangeStartPoint( aInfo.dPar) ; + } + } + } + } + // se curva trovata, restituisco gli indici + if ( nInd != -1) { + nInd0 = nMyInd0 + 1 ; + nInd1 = nInd ; + return true ; + } + /* se non ho trovato alcuna curva, allora possono verificarsi le seguenti situazioni : + - all'indice successivo ho solo curve di topologia differente + - ho già percorso tutte le curve topologicamente uguali all'indice successivo + - sono una curva di primo Offset + - tutte le curve all'indice succesivo di topologia equivalente richiedono una retroazione + => devo azzerare nInd0 e ricercare la curva di medesima topologia valida più vicina + */ + nInd0 = 0 ; + nInd = -1 ; + for ( ; nInd0 < int( vCrvOffs.size()) ; ++ nInd0) { + nInd1 = 0 ; + dLimInfDist = INFINITO ; + for ( ; nInd1 < int( vCrvOffs[nInd0].size()) ; ++ nInd1) { + // se non attiva, passo alla successiva + if ( vCrvOffs[nInd0][nInd1]->GetTempProp( 0) != TEMP_PROP_CURVE_ACTIVE) + continue ; + // se di topologia differente, passo alla successiva + if ( ( bIsClosed != vCrvOffs[nInd0][nInd1]->IsClosed())) + continue ; + // se aperta + if ( ! bIsClosed) { + Point3d ptStart ; vCrvOffs[nInd0][nInd1]->GetStartPoint( ptStart) ; + double dDist = SqDist( ptRef, ptStart) ; + if ( dDist < dLimInfDist) { + dLimInfDist = dDist ; + nInd = nInd1 ; + } + } + // se chiusa + else { + DistPointCurve DistPtCrv( ptRef, *vCrvOffs[nInd0][nInd1]) ; + MinDistPCInfo aInfo ; + if ( DistPtCrv.GetMinDistInfo( 0, aInfo)) { + double dDist = SqDist( ptRef, aInfo.ptQ) ; + if ( dDist < dLimInfDist) { + dLimInfDist = dDist ; + nInd = nInd1 ; + vCrvOffs[nInd0][nInd1]->ChangeStartPoint( aInfo.dPar) ; + } + } + } + } + // se curva trovata, restituisco gli indici + if ( nInd != -1) { + nInd1 = nInd ; + return true ; + } + } + + /* se non ho trovato alcuna curva, allora possono verificarsi le seguenti situazioni : + - ho solo curve topologicamente differenti dalla mia + - non ho curve attive + => devo azzerare nInd0 e ricercare la curva valida più vicina + */ + nInd0 = 0 ; + dLimInfDist = INFINITO ; + nInd = -1 ; + for ( ; nInd0 < int( vCrvOffs.size()) ; ++ nInd0) { + nInd1 = 0 ; + for ( ; nInd1 < int( vCrvOffs[nInd0].size()) ; ++ nInd1) { + // se non attiva, passo alla successiva + if ( vCrvOffs[nInd0][nInd1]->GetTempProp( 0) != TEMP_PROP_CURVE_ACTIVE) + continue ; + // se la curva successiva è aperta + if ( ! vCrvOffs[nInd0][nInd1]->IsClosed()) { + Point3d ptStart ; vCrvOffs[nInd0][nInd1]->GetStartPoint( ptStart) ; + double dDist = SqDist( ptRef, ptStart) ; + if ( dDist < dLimInfDist) { + dLimInfDist = dDist ; + nInd = nInd1 ; + } + } + // se la curva successiva è chiusa + else { + DistPointCurve DistPtCrv( ptRef, *vCrvOffs[nInd0][nInd1]) ; + MinDistPCInfo aInfo ; + if ( DistPtCrv.GetMinDistInfo( 0, aInfo)) { + double dDist = SqDist( ptRef, aInfo.ptQ) ; + if ( dDist < dLimInfDist) { + dLimInfDist = dDist ; + nInd = nInd1 ; + vCrvOffs[nInd0][nInd1]->ChangeStartPoint( aInfo.dPar) ; + } + } + } + } + // se curva trovata, restituisco gli indici + if ( nInd != -1) { + nInd1 = nInd ; + return true ; + } + } + + // non ho più curve disponibili + nInd0 = -1 ; + nInd1 = -1 ; + return true ; + +} + +//---------------------------------------------------------------------------- +static bool +AdjustCloseEsgesForConformalGuide( ICurveComposite* pCrvCompo, const PocketParams& PockParams) +{ + // controllo dei parametri + if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) + return false ; + + // se non ho una regione limite, allora non faccio nulla + if ( ! PockParams.SfrLimit.IsValid()) + return true ; + + // piccolo Offset per la superficie di classificazione + PtrOwner pSfrLimit( CloneSurfFlatRegion( &PockParams.SfrLimit)) ; + if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid() || + ! pSfrLimit->Offset( 100 * EPS_SMALL, ICurve::OFF_FILLET)) + return false ; + + // recupero le parti omogenee della curva + ICRVCOMPOPOVECTOR vpCrvs ; + GetHomogeneousParts( pCrvCompo, PockParams, vpCrvs) ; + + // i tratti aperti che fanno overlap con la regione limite diventano chiusi + PtrOwner pCrvFinal( CreateCurveComposite()) ; + if ( IsNull( pCrvFinal)) + return false ; + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { + // nuovo curva + PtrOwner pMyCompo( CreateCurveComposite()) ; + if ( IsNull( pMyCompo)) + return false ; + CRVCVECTOR ccClass ; + if ( pSfrLimit->GetCurveClassification( *vpCrvs[i], EPS_SMALL, ccClass)) { + for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { + // recupero il tratto di curva + PtrOwner pMyCurve( ConvertCurveToComposite( vpCrvs[i]->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) ; + if ( ! IsNull( pMyCurve) && pMyCurve->IsValid()) { + // se non esterna alla regione limite, il sottotratto deve essere chiuso + if ( ccClass[j].nClass != CRVC_OUT) { + for ( int k = 0 ; k < pMyCurve->GetCurveCount() ; ++ k) + pMyCurve->SetCurveTempProp( k, TEMP_PROP_CLOSE_EDGE, 0) ; + } + if ( ! pMyCompo->AddCurve( Release( pMyCurve))) + return true ; // non faccio nulla... + } + } + } + vpCrvs[i].Set( pMyCompo) ; + } + if ( ! pCrvFinal->AddCurve( Release( vpCrvs[i]))) + return true ; // non faccio nulla... + } + if ( pCrvFinal->IsValid()) + pCrvCompo->CopyFrom( pCrvFinal) ; + + return ( pCrvCompo != nullptr && pCrvCompo->IsValid()) ; + +} + +//---------------------------------------------------------------------------- +static bool +GetConformalBordersCrvs( const ISurfFlatRegion* pSfrOrig, PocketParams& PockParams, + ICRVCOMPOPOVECTOR& vCrvCompo) +{ + // controllo dei parametri + if ( pSfrOrig == nullptr || ! pSfrOrig->IsValid()) + return false ; + vCrvCompo.clear() ; + + /* NB. + La regione da costruire è una FlatRegion dove si estendono i lati aperti di R/2 + ( al contrario della pSfrClass che estende i lati aperti di R/8, questa regione + presenta i Chiusi Offsettati verso l'interno di R + OffsR e gli aperti estesi di R/2 + - Per ottenere questo risultato si estende la regione Originale di R + OffsR + R/2 presso + i lati aperti e successivamente si effettua un Offset interno di (-)R + (-)OffsR + */ + + // estendo la superficie + PtrOwner pSfrExtended( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrExtended) || + ! GetSfrByOpenEdgeExtension( pSfrOrig, PockParams, PockParams.dRad + PockParams.dRad / 2., + ICurve::OFF_CHAMFER, pSfrExtended)) + return false ; + + // contro-offset per delimitarla + if ( ! pSfrExtended->Offset( - PockParams.dRad - PockParams.dRadialOffset, ICurve::OFF_FILLET)) + return false ; + + // restituisco i Loops + return ( GetSfrCrvCompoLoops( pSfrExtended, vCrvCompo)) ; + +} + +//---------------------------------------------------------------------------- +static bool +ModifyConformalStartPoint( ICurveComposite* pCrvFirst, const PocketParams& PockParams, + const ISurfFlatRegion* pSfrPock) +{ + // controllo dei parametri + if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid() || + pSfrPock == nullptr || ! pSfrPock->IsValid()) + return false ; + + // se la curva è aperta, allora non devo fare nulla + if ( ! pCrvFirst->IsClosed()) + return true ; + + // ricavo i lati aperti della superficie di classificazione + ICRVCOMPOPOVECTOR vCrvOpenEdges ; + for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfrPock->GetLoopCount( nC) ; ++ nL) { + // recupero il Loop + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrPock->GetLoop( nC, nL))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + // recupero le parti omogenee + ICRVCOMPOPOVECTOR vpCrvs ; + GetHomogeneousParts( pCrvLoop, PockParams, vpCrvs) ; + // recupero le parti interne + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) + vCrvOpenEdges.emplace_back( Release( vpCrvs[i])) ; + } + } + } + // se non ho ricavato tratti aperti, errore + if ( vCrvOpenEdges.empty()) + return false ; + + /* NB. + - Per i casi previsti dalle lavorazioni CONFORMAL devo trovare solo 1 tratto aperto, quindi + considero quello di indice 0 + - Tra la curva pCrvFirst e la curva di lato aperto, devo trovare i punti più vicino + ( per ora l'algoritmo è euristico, bisogna aggiornarlo con VORONOI) + */ + + // Algoritmo Euristico da sostituire con Voronoi : + // 1) Cerco il punto più vicino al lato aperto dato il punto iniziale di pCrvFirst + Point3d ptStart ; pCrvFirst->GetStartPoint( ptStart) ; + DistPointCurve distCalculator0( ptStart, *vCrvOpenEdges[0]) ; + Point3d ptMinDist ; + int nFlag ; + if ( ! distCalculator0.GetMinDistPoint( 0., ptMinDist, nFlag)) + return false ; + // 2) Cerco il punto più vicino su pCrvFirst da ptMinDist + DistPointCurve distCalculator1( ptMinDist, *pCrvFirst) ; + double dMinPar ; + if ( ! distCalculator1.GetParamAtMinDistPoint( 0., dMinPar, nFlag)) + return false ; + // 3) Cambio il punto iniziale di pCrvFirst nel parametro ricavato + pCrvFirst->ChangeStartPoint( dMinPar) ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +CalcConformalOneWayOffs( VICRVCOMPOPOVECTOR& vvCrvOffs, const PocketParams& PockParams, + const ISurfFlatRegion* pSfrPock, ICRVCOMPOPOVECTOR& vCrvOffs) +{ + // pulizia del vettore degli Offset + vCrvOffs.clear() ; + + // inverto il vettore degli Offset, in modo da partire dalle curve più distanti dai chiusi + reverse( vvCrvOffs.begin(), vvCrvOffs.end()) ; + + // determino il punto iniziale della prima curva di Offset + if ( ! ModifyConformalStartPoint( vvCrvOffs[0][0], PockParams, pSfrPock)) + return false ; + + // le curve di Offset vengono riodinate in base alla loro iterazione nel vettore + for ( int i = 0 ; i < int( vvCrvOffs.size()) ; ++ i) { + for ( int j = 0 ; j < int( vvCrvOffs[i].size()) ; ++ j) { + // se la curva corrente è chiusa, cambio il punto iniziale rispetto alla curva precedente + if ( vvCrvOffs[i][j]->IsClosed()) { + if ( ! vCrvOffs.empty()) { + // ricavo il punto finale della curva precedente + Point3d ptEndPrec ; vCrvOffs.back()->GetEndPoint( ptEndPrec) ; + DistPointCurve DistPtCrv( ptEndPrec, *vvCrvOffs[i][j]) ; + double dParS ; + int nFlag ; + // cambio il punto inziale della curva corrente + if ( DistPtCrv.GetParamAtMinDistPoint( 0, dParS, nFlag)) + vvCrvOffs[i][j]->ChangeStartPoint( dParS) ; + } + } + vCrvOffs.emplace_back( Release( vvCrvOffs[i][j])) ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +CalcConformalZigZagOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatRegion* pSfrChunk, + const ISurfFlatRegion* pSfrClass, PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvOffs, + ICURVEPOVECTOR& vCrvLink) +{ + // controllo dei parametri + if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid() || + pSfrClass == nullptr || ! pSfrClass->IsValid()) + return false ; + vCrvOffs.clear() ; + vCrvLink.clear() ; + if ( vvCrvOffs.empty()) + return true ; + + // rendo attive tutte le curve di Offset mediante prima TmpProp + for ( int i = 0 ; i < int( vvCrvOffs.size()) ; ++ i) { + for ( int j = 0 ; j < int( vvCrvOffs[i].size()) ; ++ j) + vvCrvOffs[i][j]->SetTempProp( TEMP_PROP_CURVE_ACTIVE, 0) ; + } + + /* NB. curve di vCrvOffs + TempProp0 -> Se l'offset è attivo/non attivo + TempProp1 -> Side {MDS_LEFT, MDS_RIGHT} per identificare l'interno della curva + TempParam0 -> { vuoto } ; verrà utilizzato per la Feed + TempParam1 -> { vuoto } + */ + + // inverto il vettore degli Offset, in modo da partire dalle curve più distanti dai chiusi + reverse( vvCrvOffs.begin(), vvCrvOffs.end()) ; + + // determino il punto iniziale della prima curva di Offset + if ( ! ModifyConformalStartPoint( vvCrvOffs[0][0], PockParams, pSfrChunk)) + return false ; + + /* NB. + I link che collegano due curve di Offset aperte devono partire dalla prima e, seguendo il + bordo della regione di classificazione ( pSfrClass) arrivano alla seconda. + */ + ICRVCOMPOPOVECTOR vCrvSfrClass ; + if ( ! GetSfrCrvCompoLoops( pSfrClass, vCrvSfrClass)) + return false ; + /* NB. + I link che collegano due curve di Offset chiuse tra di loro vengono calcolati esattamente + come per i percorsi SPIRAL, pertanto devo definire un insieme di curve di primo Offset sui + quali smussare i Link per evitare di uscire dalla regione di svuotatura + */ + ICRVCOMPOPOVECTOR vCrvSfrExtended ; + if ( ! GetConformalBordersCrvs( pSfrChunk, PockParams, vCrvSfrExtended)) + return false ; + /* NB. + Se POCKET_CONFORMAL_ZIGZAG : + - vCrvCompoOffs contiene gli Offset ordinati + - vCrvLinks contiene il link che collega l'Offset (i-1)-esimo con l'Offset (i)-esimo + [ per definizione il primo Link è null] + [ se tra due Offset non c'è Link, allora esso sarà null] + Se POCKET_CONFORMAL_ONEWAY + - vCrvCompoOffs contiene gli Offset ordinati + - vCrvLinks è un vettore di null + + vCrvCompoOffs e vCrvLinks avranno la stessa dimensione + */ + + // ------------ Ordino Gli Offset ------------ + int nInd0 = 0 ; + int nInd1 = 0 ; + while ( nInd0 != -1 && nInd1 != -1) { + // inserisco la curva attuale nel vettore degli Offset + vCrvOffs.emplace_back( CloneCurveComposite( vvCrvOffs[nInd0][nInd1])) ; + // salvo come prima TmpProp il numero di Offset che ha generato tale curva + vCrvOffs.back()->SetTempProp( int( vvCrvOffs.size()) - nInd0 - 1, 0) ; + // disattivo tale curva per la ricerca + vvCrvOffs[nInd0][nInd1]->SetTempProp( TEMP_PROP_CURVE_INACTIVE, 0) ; + // cerco la curva successiva per il percorso + int nNextInd0 = -1 ; + int nNextInd1 = -1 ; + if ( ! GetConformalIndices( vvCrvOffs, nInd0, nInd1, PockParams, vCrvSfrClass, nNextInd0, nNextInd1)) + return false ; + // aggiorno gli indici + nInd0 = nNextInd0 ; + nInd1 = nNextInd1 ; + } + // se non ho ottenuto nulla, esco + if ( vCrvOffs.empty()) + return true ; + + // ------------ Definisco i Link ------------ + // per definizione il primo Link è nullo + vCrvLink.resize( 1) ; + // scorro le curve di Offset a coppie + for ( int i = 0 ; i < int( vCrvOffs.size()) - 1 ; ++ i) { + // controllo se bisogna calcolare il Link tra i due Offset + bool bCalcLink = true ; + if ( ! CheckConformalRetractLink( vCrvOffs[i], vCrvOffs[i+1], vCrvSfrClass, PockParams, bCalcLink)) + return false ; + if ( bCalcLink) { + // se link da calcolare, lo ricavo + PtrOwner pCrvLink( CreateCurveComposite()) ; + if ( IsNull( pCrvLink) || + ! GetConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, vCrvSfrExtended, pCrvLink)) + return false ; + // lo salvo nel vettore dei Link + vCrvLink.emplace_back( Release( pCrvLink)) ; + } + else + vCrvLink.resize( int( vCrvLink.size()) + 1) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const PocketParams& PockParams, + ICRVCOMPOPOVECTOR& vCrvOffs, ICURVEPOVECTOR& vCrvLinks) +{ + // controllo dei parametri + if ( pSfrPock == nullptr || ! pSfrPock->IsValid()) + return false ; + if ( vCrvOffs.empty()) + return true ; + + /* dalla superificie estesa presso i lati aperti, effettuo un Offset interno pari alla somma del + raggio utensile e dell'offset radiale. La ricerca delle zone non svuotate avviene all'interno + di questa regione + */ + ICRVCOMPOPOVECTOR vCrvFirstOffs ; + if ( ! GetFirstOffsCrvFromSfr( pSfrPock, - PockParams.dRad - PockParams.dRadialOffset, vCrvFirstOffs)) + return false ; + // determino eventuale regioni con parti non svuotate e imposto la Feed alle curve + PtrOwner pSfrUncleared( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrUncleared)) + return false ; + if ( GetUnclearedRegionAndSetFeed( vCrvFirstOffs, vCrvOffs, vCrvLinks, nullptr, PockParams, pSfrUncleared)) { + // estendo i percorsi di Offset se richiesto + if ( ! RemoveExtraParts( pSfrUncleared, vCrvOffs, vCrvFirstOffs, PockParams)) + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +AddLeadInToCurveConformalPaths( const ISurfFlatRegion* pSfrOrig, const ISurfFlatRegion* pSfrPock, + const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvPaths) +{ + // controllo dei parametri + if ( pSfrOrig == nullptr || ! pSfrOrig->IsValid() || + pSfrPock == nullptr || ! pSfrPock->IsValid()) + return false ; + for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) { + if ( vCrvPaths[i] == nullptr || ! vCrvPaths[i]->IsValid()) + return false ; + } + + // ricavo le curve aperte della superficie di pocketing + ICRVCOMPOPOVECTOR vCrvOpenEdge ; + { + ICRVCOMPOPOVECTOR vCrvLoops ; + if ( ! GetSfrCrvCompoLoops( pSfrPock, vCrvLoops)) + return false ; + for ( int i = 0 ; i < int( vCrvLoops.size()) ; ++ i) { + ICRVCOMPOPOVECTOR vpCrvs ; + GetHomogeneousParts( vCrvLoops[i], PockParams, vpCrvs) ; + for ( int j = 0 ; j < int( vpCrvs.size()) ; ++ j) { + if ( vpCrvs[j]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) + vCrvOpenEdge.emplace_back( Release( vpCrvs[j])) ; + } + } + } + + // scorro i percorsi ricavati + for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) { + // recupero il punto iniziale del percorso + Point3d ptStart ; vCrvPaths[i]->GetStartPoint( ptStart) ; + // se il punto inziale è interno alla superficie originaria + bool bIsInside ; + if ( IsPointInsideSurfFr( ptStart, pSfrOrig, EPS_SMALL, bIsInside) && bIsInside) { + // definizione del segmento per l'entrata + PtrOwner pSeg( CreateCurveLine()) ; + if ( IsNull( pSeg)) + return false ; + double dSqLenMin = INFINITO ; + // ricavo il punto più vicino alle curve aperte della superficie di classificazione + for ( int j = 0 ; j < int( vCrvOpenEdge.size()) ; ++ j) { + DistPointCurve DistPtCrv( ptStart, *vCrvOpenEdge[j]) ; + Point3d ptMinDist ; + int nFlag ; + // controllo se il segmento che congiunge i due estremi non rovina il grezzo + bool bSafe = ( DistPtCrv.GetMinDistPoint( 0, ptMinDist, nFlag)) ; + // se troppo piccolo, non faccio nulla + double dSqSegLen = SqDist( ptStart, ptMinDist) ; + if ( dSqSegLen < SQ_EPS_SMALL) { + pSeg.Set( CreateCurveLine()) ; + break ; + } + // creazione del segmento + if ( bSafe) { + PtrOwner pCurrSeg( CreateCurveLine()) ; + if ( IsNull( pCurrSeg) || ! pCurrSeg->Set( ptMinDist, ptStart)) + return false ; + double dSqSegLen = SqDist( ptStart, ptMinDist) ; + if ( PockParams.SfrLimit.IsValid()) { + PtrOwner pSfrLimit( CloneSurfFlatRegion( &PockParams.SfrLimit)) ; + if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid() || + ! pSfrLimit->Offset( PockParams.dRad + PockParams.dRadialOffset, ICurve::OFF_FILLET)) + return false ; + // controllo distanza segmento + CRVCVECTOR ccClass ; + bSafe = ( pSfrLimit->GetCurveClassification( *pSeg, EPS_SMALL, ccClass) && + int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) ; + } + if ( bSafe && dSqSegLen < dSqLenMin) { + dSqLenMin = dSqSegLen ; + pSeg.Set( pCurrSeg) ; + } + } + } + // se segmento trovato, lo aggiungo alla curva + if ( pSeg->IsValid()) { + if ( ! vCrvPaths[i]->AddCurve( Release( pSeg), false, 25 * EPS_SMALL)) + return false ; + vCrvPaths[i]->SetCurveTempParam( 0, GetMinFeed( PockParams), 0) ; + } + } + + // estendo il percorso sul tratto iniziale e finale ( se ammissibile) + Vector3d vtTan ; vCrvPaths[i]->GetStartDir( vtTan) ; + vtTan.Invert() ; + bool bOkExtended ; + if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, false, bOkExtended)) + return false ; + // se il segmento non ha subito estensione e il primo Offset era chiuso, allora ritento + if ( ! bOkExtended && bIsInside) { + PtrOwner pCrvPathCL( CloneCurveComposite( vCrvPaths[i])) ; + if ( IsNull( pCrvPathCL) || ! pCrvPathCL->IsValid()) + return false ; + pCrvPathCL->ExtendStartByLen( 1.5 * PockParams.dRad) ; + if ( ! ExtendPath( pCrvPathCL, pSfrOrig, PockParams, vtTan, false, bOkExtended)) + return false ; + if ( bOkExtended) + vCrvPaths[i].Set( pCrvPathCL) ; + } + vCrvPaths[i]->GetEndDir( vtTan) ; + if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, true, bOkExtended)) + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +ChainConformalOffsWithLinks( ICRVCOMPOPOVECTOR& vCrvOffs, ICURVEPOVECTOR& vCrvLink, + ICRVCOMPOPOVECTOR& vCrvPaths) +{ + // se non ho Offset non devo concatenare nulla + if ( vCrvOffs.empty()) + return true ; + // le curve di Offset devono essere definite e valide + for ( int i = 0 ; i < int( vCrvOffs.size()) ; ++ i) { + if ( vCrvOffs[i] == nullptr || ! vCrvOffs[i]->IsValid()) + return false ; + } + vCrvPaths.clear() ; + + // percorso corrente + PtrOwner pCrvPath( CreateCurveComposite()) ; + if ( IsNull( pCrvPath)) + return false ; + for ( int i = 0 ; i < int( vCrvOffs.size()) - 1 ; ++ i) { + // aggiungo l'Offset corrente + if ( ! pCrvPath->AddCurve( Release( vCrvOffs[i]))) + return false ; + // se il Link per l'Offset successivo è valido, lo aggiungo + if ( ! IsNull( vCrvLink[i+1]) && vCrvLink[i+1]->IsValid()) { + if ( ! pCrvPath->AddCurve( Release( vCrvLink[i+1]))) + return false ; + } + // se Link non valido, ho terminato il percorso corrente + else { + vCrvPaths.emplace_back( Release( pCrvPath)) ; + pCrvPath.Set( CreateCurveComposite()) ; + if ( IsNull( pCrvPath)) + return false ; + } + } + if ( ! pCrvPath->AddCurve( Release( vCrvOffs.back()))) + return false ; + vCrvPaths.emplace_back( Release( pCrvPath)) ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +ExtendGuideByIteration( ICurveComposite* pCompoTempGuide, const ICurveComposite* pCompoPerimeter, + bool bInverted) +{ + // controllo dei parametri + if ( pCompoTempGuide == nullptr || ! pCompoTempGuide->IsValid() || + pCompoPerimeter == nullptr || ! pCompoPerimeter->IsValid()) + return false ; + + const double EXTENSION_VAL = 1000. ; + + // ricavo il punto finale della guida + Point3d ptEndGuide ; pCompoTempGuide->GetEndPoint( ptEndGuide) ; + // direzione finale della guida + Vector3d vtEndGuide ; pCompoTempGuide->GetEndDir( vtEndGuide) ; + // creo un segmento diretto come il chiuso + PtrOwner pSeg( CreateCurveLine()) ; + if ( IsNull( pSeg) || + ! pSeg->Set( ptEndGuide, ptEndGuide + EXTENSION_VAL * vtEndGuide)) + return false ; + // calcolo l'intersezione tra questo segmento e la curva di perimetro aperta + IntersCurveCurve ICC( *pSeg, *pCompoPerimeter) ; + // se l'unica intersezione è il punto iniziale del segmento, allora non estendo la guida + // ( vale anche nel caso di intersezione con Overlap) + if ( ICC.GetIntersCount() == 1) { + IntCrvCrvInfo aInfo ; + if ( ICC.GetIntCrvCrvInfo( 0, aInfo)) { + if ( AreSamePointApprox( aInfo.IciB[0].ptI, ptEndGuide)) + return true ; + } + } + // passo alla PolyLine del perimetro + PolyLine PL ; + pCompoPerimeter->ApproxWithLines( EPS_SMALL, EPS_ANG_SMALL, ICurve::APL_STD, PL) ; + // cerco il punto più esterno rispetto alla direzione del chiuso + Point3d ptPoly ; + PL.GetFirstPoint( ptPoly) ; + while ( PL.GetNextPoint( ptPoly)) { + if ( ! pSeg->Set( ptEndGuide, ptEndGuide + ( ptPoly - ptEndGuide) * EXTENSION_VAL)) + return false ; + // calcolo l'intersezione tra questo segmento e la curva di perimetro aperta + IntersCurveCurve ICC( *pSeg, *pCompoPerimeter) ; + // se una intersezione, allora di Overlap con punto iniziale e finale definito + if ( ICC.GetIntersCount() == 1) { + IntCrvCrvInfo aInfo ; + if ( ICC.GetIntCrvCrvInfo( 0, aInfo)) { + if ( aInfo.bOverlap) { + if ( AreSamePointApprox( aInfo.IciB[0].ptI, ptEndGuide) && + AreSamePointApprox( aInfo.IciB[1].ptI, ptPoly)) + return ( pCompoTempGuide->AddLine( ptPoly)) ; + } + else { + if ( AreSamePointApprox( aInfo.IciB[0].ptI, ptEndGuide)) + return ( pCompoTempGuide->AddLine( ptPoly)) ; + } + } + } + // se più di una intersezione, allora il perimetro deve essere tutto Interno al segmento + // ( Out nel caso in cui ho le curve invertite) + IntCrvCrvInfo aInfo ; + bool bOk = true ; + for ( int i = 0 ; i < ICC.GetIntersCount() && bOk ; ++ i) { + bOk = ( ICC.GetIntCrvCrvInfo( i, aInfo)) ; + bOk = ( aInfo.bOverlap || + ( aInfo.IciB[0].nPrevTy != ( ! bInverted ? CRVC_OUT : CRVC_IN) && + aInfo.IciB[0].nNextTy != ( ! bInverted ? CRVC_OUT : CRVC_IN))) ; + } + if ( bOk) + return ( pCompoTempGuide->AddLine( ptPoly)) ; + } + + return true ; +} + + +//---------------------------------------------------------------------------- +static bool +CalcConformalGuide( const ICurveComposite* pCrvCloseEdge, const ICurveComposite* pCrvOpenEdge, + const PocketParams& PockParams, ICurveComposite* pCrvGuide) +{ + // controllo dei parametri + if ( pCrvCloseEdge == nullptr || ! pCrvCloseEdge->IsValid() || + pCrvOpenEdge == nullptr || ! pCrvOpenEdge->IsValid()) + return false ; + pCrvGuide->Clear() ; + + // creo una copia temporanea delle curve + PtrOwner pCrvCL( CloneCurveComposite( pCrvCloseEdge)) ; + PtrOwner pCrvOP( CloneCurveComposite( pCrvOpenEdge)) ; + if ( IsNull( pCrvCL) || IsNull( pCrvOP) || ! pCrvCL->IsValid() || ! pCrvOP->IsValid()) + return false ; + + // estendo la curva nel suo tratto finale ed iniziale + for ( int i = 0 ; i < 2 ; ++ i) { + if ( ! ExtendGuideByIteration( pCrvCL, pCrvOP, ( i == 1))) + return false ; + if ( ! pCrvCL->IsValid()) + return true ; + pCrvCL->Invert() ; + pCrvOP->Invert() ; + // se la curva diventa chiusa, allora ho la guida + if ( pCrvCL->IsClosed()) { + pCrvGuide->CopyFrom( pCrvCL) ; + if ( i == 1) + pCrvGuide->Invert() ; + return true ; + } + } + + // tratto iniziale + Vector3d vtStart ; pCrvCL->GetStartDir( vtStart) ; + Point3d ptStart ; pCrvCL->GetStartPoint( ptStart) ; + PtrOwner pLineStart( CreateCurveLine()) ; + if ( IsNull( pLineStart) || ! pLineStart->Set( ptStart - 1000. * vtStart, ptStart)) + return false ; + // tratto finale ( potrebbe intersecare il tratto iniziale) + Vector3d vtEnd ; pCrvCL->GetEndDir( vtEnd) ; + Point3d ptEnd ; pCrvCL->GetEndPoint( ptEnd) ; + PtrOwner pLineEnd( CreateCurveLine()) ; + if ( IsNull( pLineEnd) || ! pLineEnd->Set( ptEnd, ptEnd + 1000. * vtEnd)) + return false ; + + // controllo eventuale intersezione + IntersCurveCurve ICC( *pLineStart, *pLineEnd) ; + if ( ICC.GetIntersCount() > 0) { + // se esiste allora spezzo sia il tratto iniziale che finale nel punto di intersezione + IntCrvCrvInfo aInfo ; + if ( ICC.GetIntCrvCrvInfo( 0, aInfo)) { + pLineStart->TrimStartAtParam( aInfo.IciA[0].dU) ; + pLineEnd->TrimEndAtParam( aInfo.IciB[0].dU) ; + } + } + + // le due estensioni vanno tagliate presso i bordi dei lati aperti estesi; rischierei di non + // riuscire a passare presso dei lati aperti vicini ai tratti lineari di estensione + IntersCurveCurve ICCLS( *pLineStart, *pCrvOP) ; + if ( ICCLS.GetIntersCount() > 0) { + IntCrvCrvInfo aInfo ; + for ( int i = 0 ; i < ICCLS.GetCrossIntersCount() ; ++ i) { + if ( ICCLS.GetIntCrvCrvInfo( i, aInfo)) { + if ( ! AreSamePointApprox( aInfo.IciA[ aInfo.bOverlap ? 1 : 0].ptI, ptStart)) + pLineStart->ModifyStart( aInfo.IciA[aInfo.bOverlap ? 1 : 0].ptI) ; + } + } + } + IntersCurveCurve ICCLE( *pLineEnd, *pCrvOP) ; + if ( ICCLE.GetIntersCount() > 0) { + IntCrvCrvInfo aInfo ; + for ( int i = 0 ; i < ICCLE.GetCrossIntersCount() ; ++ i) { + if ( ICCLE.GetIntCrvCrvInfo( 0, aInfo)) { + if ( ! AreSamePointApprox( aInfo.IciA[0].ptI, ptEnd)) + pLineEnd->ModifyEnd( aInfo.IciA[0].ptI) ; + } + } + } + + // aggiungo i tratti lineari di estensione della curva + pCrvCL->AddCurve( Release( pLineStart), false) ; + pCrvCL->AddCurve( Release( pLineEnd), true) ; + + // recupero la curva guida + pCrvGuide->CopyFrom( pCrvCL) ; + return true ; + +} + +//---------------------------------------------------------------------------- +static bool +GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pSfrClass, const PocketParams& PockParam, + VICRVCOMPOPOVECTOR& vCrvOffs) +{ + // controllo dei parametri + if ( pSfrClass == nullptr || ! pSfrClass->IsValid() || + pSfrChunk == nullptr || ! pSfrChunk->IsValid()) + return false ; + vCrvOffs.clear() ; + + /* NB + vCrvOffs è un vettore di vettori di curve composite. Per ogni Offset progressivo i-esimo + vengono salvate tutte le parti interne j-esime alla pSfrClass. + ( la posizione del vettore ICRVCOMPOPOVECTOR int VICRVCOMPOPOVECTOR è il numero di iterazione + progressiva di Offset) + */ + + /* controllo se il chunk è svuotabile con lavorazione conformal + Sono previsti due casi di lavorazioni conformal : + 1) Non esistono Isole e il bordo esterno è formato da due tratti disomogenei + 2) Esistono solo Isole chiuse e il bordo esterno è tutto aperto + */ + bool bOk = false ; + ICRVCOMPOPOVECTOR vCrvCloseEdges ; // tratti chiusi da cui calcolare gli Offset + + // 1) Non esistono Isole e il bordo esterno è formato da due tratti disomogenei + if ( pSfrChunk->GetLoopCount( 0) == 1) { + // recupero la curva di bordo + ICRVCOMPOPOVECTOR vpCrvs ; + PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; + if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid() || + ! AdjustCloseEsgesForConformalGuide( pCrvExtLoop, PockParam) || + ! IsCompoMadeBy2DifferentHomogeneousParts( pCrvExtLoop, PockParam, bOk, vpCrvs)) + return false ; + if ( ! bOk) + return true ; + // recupero la guida ideale + PtrOwner pCrvGuide( CreateCurveComposite()) ; + if ( IsNull( pCrvGuide) || + ! CalcConformalGuide( vpCrvs[0], vpCrvs[1], PockParam, pCrvGuide)) + return false ; + if ( ! pCrvGuide->IsValid()) + return true ; + // la guida definisce il tratto chiuso per gli Offsets + vCrvCloseEdges.emplace_back( Release( pCrvGuide)) ; + } + // 2) Esistono solo Isole chiuse e il bordo esterno è tutto aperto + else { + if ( ! IsSfrChunkMadeOnlyByClosedIslands( pSfrChunk, PockParam, bOk, vCrvCloseEdges)) + return false ; + if ( ! bOk) + return true ; + } + + /* Calcolo degli Offsets */ + // Oggetto Voronoi per curve chiuse + Voronoi myVRONI ; + for ( int i = 0 ; i < int( vCrvCloseEdges.size()) ; ++ i) { + vCrvCloseEdges[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + myVRONI.AddCurve( Release( vCrvCloseEdges[i])) ; + } + int MAX_ITER = 1000 ; + int nIter = 0 ; + double dOffs = PockParam.dRad + PockParam.dRadialOffset ; + double dOffsPrec = 0. ; + bool bStopSmallRad = false ; + while ( nIter < MAX_ITER) { + // determino se le curve vanno invertite o meno + // essendo FatCurve, la parte interna alla regione di classificazione è invertita + bool bInvert = false ; + if ( PockParam.nType == POCKET_CONFORMAL_ZIGZAG) + bInvert = ! ( ( ! IsEven( nIter) && ! PockParam.bInvert) || ( IsEven( nIter) && PockParam.bInvert)) ; + else if ( PockParam.nType == POCKET_CONFORMAL_ONEWAY) + bInvert = ! ( PockParam.bInvert) ; + // recupero gli Offset dei tratti chiusi + ICURVEPOVECTOR vFatCrv ; + if ( ! myVRONI.CalcFatCurve( vFatCrv, dOffs, false, false)) + return false ; + // vettore di Curve dentro alla regione di classificazione + ICRVCOMPOPOVECTOR vCrvOffsInside ; + // per tutte le curve ottenute, tengo solo per le parti interne alla regione di classificazione + bool bStop = true ; + for ( int j = 0 ; j < int( vFatCrv.size()) ; ++ j) { + CRVCVECTOR ccClass ; + if ( ! pSfrClass->GetCurveClassification( *vFatCrv[j], EPS_SMALL, ccClass)) + return false ; + for ( int k = 0 ; k < int( ccClass.size()) ; ++ k) { + if ( ccClass[k].nClass == CRVC_IN) { + // almeno una curva in trovata + bStop = false ; + // recupero il tratto di curva + PtrOwner pMyCrv( vFatCrv[j]->CopyParamRange( ccClass[k].dParS, ccClass[k].dParE)) ; + if ( ! IsNull( pMyCrv) && pMyCrv->IsValid()) { + // inverto se necessario + if ( bInvert) + pMyCrv->Invert() ; + // salvo come seconda proprietà temporanea il lato interno + pMyCrv->SetTempProp( bInvert ? MDS_LEFT : MDS_RIGHT, 1) ; + // memorizzo la curva nel vettore + vCrvOffsInside.emplace_back( ConvertCurveToComposite( Release( pMyCrv))) ; + } + } + } + } + // concateno se necessario ( per tolleranza Offset) + if ( ! ChainCompoCurves( vCrvOffsInside)) + return false ; + // controllo se serve un raggio più piccolo di svuotatura + bool bSmallRad = ( nIter == 0 ? dOffs < PockParam.dRad + EPS_ZERO : dOffs - dOffsPrec < PockParam.dRad + EPS_ZERO) ; + // se ho trovato delle curve interne + if ( ! bStop) { + dOffsPrec = dOffs ; + dOffs += PockParam.dSideStep ; + // inserisco le curva ricavate all'iterazione nIter nel vettore + vCrvOffs.resize( ++ nIter) ; // incremento nIter + for ( int i = 0 ; i < int( vCrvOffsInside.size()) ; ++ i) { + vCrvOffsInside[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; + vCrvOffs.back().emplace_back( Release( vCrvOffsInside[i])) ; + } + // se devo terminare, interrompo il loop + if ( bStopSmallRad) + break ; + } + // se non ho ricavato curve ma serve un offset del raggio utensile + else if ( ! bSmallRad) { + dOffs = dOffsPrec + ( nIter == 0 ? PockParam.dRad + PockParam.dRadialOffset : PockParam.dRad) ; + bStopSmallRad = true ; + } + else + break ; + } + + // smusso le curve di Offset ( ad eccezione di quelle generate alla prima iterazione) + double dSmoothPar = PockParam.dRad / 8. ; + for ( int i = 1 ; i < int( vCrvOffs.size()) ; ++ i) { + for ( int j = 0 ; j < int( vCrvOffs[i].size()) ; ++ j) + ModifyCurveToSmoothed( vCrvOffs[i][j], PockParam, dSmoothPar, dSmoothPar, false) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +GetConformalSfrClassChunk( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pSfrClass, + INTVECTOR& vnChunk) +{ + // controllo dei parametri + if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid() || + pSfrClass == nullptr || ! pSfrClass->IsValid()) + return false ; + vnChunk.clear() ; + + // se la superficie di classificazione ha un solo chunk, esco + if ( pSfrClass->GetChunkCount() == 1) { + vnChunk.emplace_back( 0) ; + return true ; + } + + // controllo quali Chunk di pSfrClass intersecano la pSfrChunk + for ( int nC = 0 ; nC < pSfrClass->GetChunkCount() ; ++ nC) { + // recupero il Chunk nC-esimo + PtrOwner pSfrClassChunk( pSfrClass->CloneChunk( nC)) ; + if ( IsNull( pSfrClassChunk) || ! pSfrClass->IsValid()) + return false ; + // controllo se l'intersezione non è vuota + pSfrClassChunk->Intersect( *pSfrChunk) ; + if ( ! IsNull( pSfrClassChunk) && pSfrClassChunk->IsValid()) + vnChunk.push_back( nC) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, + PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes) +{ + // controllo dei parametri + if ( pSfrPock == nullptr || ! pSfrPock->IsValid() || + pSfrOrig == nullptr || ! pSfrOrig->IsValid()) + return true ; + + // se superifice tutta aperta, lavoro in SPIRAL_IN + if ( PockParams.bAllOpen) + return ( AddSpiralIn( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ; + // se superficie tutta chiusa, lavoro in SPIRAL_OUT + if ( PockParams.bAllClosed) + return ( AddSpiralOut( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ; + + // Definisco la superficie di classificazione ( su essa vengono tagliate le curve progressive + // di Offset + /* NB + La superficie di classificazione è ottenuta estendendo di R/4 i lati aperti ( in modo + da compensare il fattore di smusso R/8 sulle curve di Offset) + Dato che questa superficie serve per classficiare le curve di Offset, posso estendere i lati + aperti mediante Offset di tipo Chamfer; in questo modo semplifico la classificazione + */ + PtrOwner pSfrClass( pSfrPock->CreateOffsetSurf( - ( 3. * PockParams.dRad / 4.) - PockParams.dRadialOffset, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrClass) || ! pSfrClass->IsValid()) + return false ; + + // recupero la dimensione del vettore delle curve da resituire ( nel caso dovessi lavorare in SPIRAL_IN) + int nDim = int( vCrvCompoRes.size()) ; + + // scorro i chunk della superficie da lavorare + for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { + // controllo se il Chunk ha tutte proprietà omogenee tra loro + bool bClose, bOpen ; + if ( ! IsChunkAllHomogeneous( pSfrPock, nC, bClose, bOpen)) + return false ; + // recupero il Chunk come regione piana + PtrOwner pSfrChunk( pSfrPock->CloneChunk( nC)) ; + if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) + return false ; + // se Chunk tutto aperto, lo lavoro in SPIRAL_IN + if ( bOpen) { + if ( ! AddSpiralIn( pSfrChunk, pSfrOrig, PockParams, vCrvCompoRes)) + return false ; + } + // se Chunk tutto chiuso, lo lavoro in SPIRAL_OUT + else if ( bClose) { + if ( ! AddSpiralOut( pSfrChunk, pSfrOrig, PockParams, vCrvCompoRes)) + return false ; + } + // se Chunk non omogeneo + else { + // ricavo il Chunk della superficie di classificazione corrente + INTVECTOR vnChunk ; + if ( ! GetConformalSfrClassChunk( pSfrChunk, pSfrClass, vnChunk)) + return false ; + // per tutti i Chunk classificati + for ( int i = 0 ; i < int( vnChunk.size()) ; ++ i) { + // ricavo il chunk di classificazione i-esimo + PtrOwner pSfrClassChunk( pSfrClass->CloneChunk( vnChunk[i])) ; + if ( IsNull( pSfrClassChunk) || ! pSfrClassChunk->IsValid()) + return false ; + // ricavo gli Offset ( se possibili) dei tratti chiusi del Chunk + VICRVCOMPOPOVECTOR vvCrvOffs ; + if ( ! GetConformalOffsets( pSfrChunk, pSfrClassChunk, PockParams, vvCrvOffs)) + return false ; + // se non ottengo Curve di Offset, lavoro in SpiralIn ( il Chunk ha dei lati aperti) + if ( vvCrvOffs.empty()) { + vCrvCompoRes.resize( nDim) ; // pulisco il vettore di curve + // NB. Facendo un offset interno di 3R/4 potrebbero essersi splittati dei Chunks + return ( AddSpiralIn( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ; + } + else { + // definisco vettore degli Offset e dei Link + ICRVCOMPOPOVECTOR vCrvOffs ; + ICURVEPOVECTOR vCrvLink ; + // se lavorazione CONFORMAL_ZIGZAG + if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) { + // ordino le curve di Offset e raccordo + if ( ! CalcConformalZigZagOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrClassChunk, PockParams, vCrvOffs, vCrvLink)) + return false ; + } + // se lavorazione CONFORMAL_ONEWAY + else if ( PockParams.nType == POCKET_CONFORMAL_ONEWAY) { + // ordino le curve di Offset + if ( ! CalcConformalOneWayOffs( vvCrvOffs, PockParams, pSfrChunk, vCrvOffs)) + return false ; + // i Link non esistono + vCrvLink.resize( int( vCrvOffs.size())) ; + } + // estendo i percorsi per eventuali regioni non svuotate e calcolo le Feed + if ( ! ExtendConformalOffsAndSetFeed( pSfrPock, PockParams, vCrvOffs, vCrvLink)) + return false ; + // concateno Offset e Links + ICRVCOMPOPOVECTOR vCrvPaths ; + if ( ! ChainConformalOffsWithLinks( vCrvOffs, vCrvLink, vCrvPaths)) + return false ; + // estendo i percorsi per entrate/uscite dai lati aperti + if ( ! AddLeadInToCurveConformalPaths( pSfrOrig, pSfrChunk, PockParams, vCrvPaths)) + return false ; + // aggiungo i percorsi ricavati + for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) + vCrvCompoRes.emplace_back( Release( vCrvPaths[i])) ; + } + } + } + } + + return true ; +} + //---------------------------------------------------------------------------- bool CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle, @@ -7023,7 +8017,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double if ( pSfr == nullptr || ! pSfr->IsValid() || dStep < 10 * EPS_SMALL || ( nType != POCKET_ZIGZAG && nType != POCKET_ONEWAY && nType != POCKET_SPIRALIN && - nType != POCKET_SPIRALOUT && nType != POCKET_CONFORMAL_ZIGZAG)) + nType != POCKET_SPIRALOUT && nType != POCKET_CONFORMAL_ZIGZAG && nType != POCKET_CONFORMAL_ONEWAY)) return false ; // pulizia vettore delle curve elementari @@ -7063,7 +8057,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double // ------------ gestione dei lati aperti ------------------- // modifico la superficie da svuotare estendendo i lati aperti bool bSkipPocket = false ; // se la superficie si svuota mediante curve singole di primo Offset dei chiusi - if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams, vCrvCompoRes, bSkipPocket)) + if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams, true, vCrvCompoRes, bSkipPocket)) return false ; // se le curve di primo offset che ho ottenuto, svuotano tutta la superficie, allora ho finito if ( bSkipPocket) { @@ -7096,7 +8090,8 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double return false ; break ; case POCKET_CONFORMAL_ZIGZAG : - if ( ! AddConformalZigZag( pSfr_Loc, myParams, vCrvCompoRes)) + case POCKET_CONFORMAL_ONEWAY : + if ( ! AddConformal( pSfrAdj, pSfr_Loc, myParams, vCrvCompoRes)) return false ; break ; } @@ -7422,4 +8417,4 @@ CalcZigZagInfill( const ISurfFlatRegion* pSfr, double dStep, bool bSmooth, bool } return true ; -} +} \ No newline at end of file From da7e9dd6e2d3b480c80c4efcc5ddde17a0468481 Mon Sep 17 00:00:00 2001 From: SaraP Date: Thu, 19 Sep 2024 16:28:19 +0200 Subject: [PATCH 05/13] =?UTF-8?q?EgtGeomKernel=20:=20-=20aggiunte=20funzio?= =?UTF-8?q?ni=20per=20calcolare=20Voronoi=20e=20medial=20axis=20di=20pi?= =?UTF-8?q?=C3=B9=20curve.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CurveAux.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CurveAux.cpp b/CurveAux.cpp index dec95b4..f4a44e5 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -1796,6 +1796,22 @@ CalcCurveVoronoiDiagram( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, int nBound) return pVoronoiObj->CalcVoronoiDiagram( vCrvs, nBound) ; } +//---------------------------------------------------------------------------- +bool +CalcCurvesVoronoiDiagram( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, int nBound) +{ + // creo oggetto Voronoi con le curve passate + PtrOwner pVoronoiObj( new( std::nothrow) Voronoi()) ; + if ( pVoronoiObj == nullptr) + return false ; + for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) { + if ( ! pVoronoiObj->AddCurve( vCrvC[i])) + return false ; + } + + return pVoronoiObj->CalcVoronoiDiagram( vCrvs, nBound) ; +} + //---------------------------------------------------------------------------- bool CalcCurveMedialAxis( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, int nSide) @@ -1807,6 +1823,22 @@ CalcCurveMedialAxis( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, int nSide) return pVoronoiObj->CalcMedialAxis( vCrvs, nSide) ; } +//---------------------------------------------------------------------------- +bool +CalcCurvesMedialAxis( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, int nSide) +{ + // creo oggetto Voronoi con le curve passate + PtrOwner pVoronoiObj( new( std::nothrow) Voronoi()) ; + if ( pVoronoiObj == nullptr) + return false ; + for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) { + if ( ! pVoronoiObj->AddCurve( vCrvC[i])) + return false ; + } + + return pVoronoiObj->CalcMedialAxis( vCrvs, nSide) ; +} + //---------------------------------------------------------------------------- bool CalcCurveFatCurve( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids) From 60729d5f398f47a4de36e5a3237e80a06b5bc478 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Fri, 20 Sep 2024 09:29:02 +0200 Subject: [PATCH 06/13] EgtGeomKernel : - Semplificazione codice in CalcPocketing. --- CalcPocketing.cpp | 1795 ++++++++++++++++++++++++--------------------- 1 file changed, 949 insertions(+), 846 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 616b585..61ec038 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -1826,20 +1826,76 @@ GetPocketCurvesByClosedEdges( const ISurfFlatRegion* pSfrChunk, const PocketPara return true ; } +//---------------------------------------------------------------------------- +static bool +GetSinglePocketingCurves( ISurfFlatRegion* pSfr, const PocketParams& PockParams, + ICRVCOMPOPOVECTOR& vCrvSingleCurves) +{ + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + vCrvSingleCurves.clear() ; + + // tengo una copia della superficie ( serve per l'estensione dei percorsi fuori dal grezzo) + PtrOwner pSfr_clone( CloneSurfFlatRegion( pSfr)) ; + if ( IsNull( pSfr_clone) || ! pSfr_clone->IsValid()) + return false ; + + // scorro i Chunk della superficie + int nChunks = pSfr->GetChunkCount() ; + int nCurrChunk = 0 ; + for ( int i = 0 ; i < nChunks ; ++ i) { + + // recupero il Chunk corrente + PtrOwner pSfrChunk( pSfr->CloneChunk( nCurrChunk)) ; + if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) + return false ; + + // se il Chunk corrente si svuota con curva singola, allora lo rimuovo dalla superficie + bool bRemoved = false ; + GetPocketCurvesByClosedEdges( pSfrChunk, PockParams, vCrvSingleCurves, bRemoved) ; + if ( bRemoved) + pSfr->EraseChunk( nCurrChunk) ; + else + ++ nCurrChunk ; + } + + // se ho ottenuto delle curve singole, allora le provo a concatenare + // ( tenendo solo le curve al di fuori della superficie limite con Offset del raggio del tool) + // potrei doverle riconcatenare + if ( ! ChainCompoCurves( vCrvSingleCurves)) + return false ; + // estendo le curve, definendo ptStart e calcolando le Feeds + if ( ! AdvanceExtendCurves( vCrvSingleCurves, pSfr_clone, PockParams)) + return false ; + // imposto le Feed per tali curve se richiesto + for ( int i = 0 ; i < int( vCrvSingleCurves.size()) ; ++ i) { + /* + Idea : Feed proporzionale al minimo Offset per annullare la regione + -> Massimo parametro sui bisettori di VORONOI + */ + // recupero il MaxOffset per la curva + double dMaxOffs = vCrvSingleCurves[i]->GetTempParam( 0) ; + // calcolo la Feed proporzionale a tale Offset + double dFeed ; + GetFeedForParam( 2 * dMaxOffs, PockParams, dFeed) ; + AssignCustomFeed( vCrvSingleCurves[i], PockParams, dFeed) ; + // imposto il flag di curva singola + vCrvSingleCurves[i]->SetTempProp( TEMP_PROP_SINGLE_CURVE, 0) ; + } + + return true ; +} + //---------------------------------------------------------------------------- static bool -ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, bool bCalcSingleCrv, - ICRVCOMPOPOVECTOR& vCrvCompoRes, bool& bSkipPocket) +ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams) { // controllo parametri : if ( pSfr == nullptr || ! pSfr->IsValid()) return true ; // <- se superficie non valida, allora non ho niente da impostare sui suoi lati - bSkipPocket = false ; - // controllo se esistono dei lati aperti - if ( ! IsSfrAllHomogeneous( pSfr, PockParams.bAllClosed, PockParams.bAllOpen)) - return false ; // se lati tutti chiusi, allora non devo fare nulla if ( PockParams.bAllClosed) return true ; @@ -1853,38 +1909,11 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, bool bCa if ( IsNull( pSrfFinal)) return false ; - // numero di chunk rimovibili mediante una sola curva di Offset seguente il tratto chiuso - int nChunkOneCurve = 0 ; - // numero complessivo di Chunk da svuotare - int nChunk = pSfr->GetChunkCount() ; - // per ogni Chunck della superificie ottenuta... - for ( int nC = 0 ; nC < nChunk ; ++ nC) { + for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) { - // controllo se seguendo i chiusi posso svuotare l'interno chunk - /* - nel caso in cui il chunk c-esimo può essere svuotato da una o più curve che seguono - il/i tratto/i chiuso/i, queste vengono salvate direttamente nei percorsi di svuotatura. - Il chuck c-esimo verrà poi ignorato ( quindi nessuna estensione presso gli aperti) - */ - PtrOwner pSfrChunk( pSfr->CloneChunk( nC)) ; - if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) - return false ; - - if ( bCalcSingleCrv) { - bool bIsAllRemoved = false ; - GetPocketCurvesByClosedEdges( pSfrChunk, PockParams, vCrvCompoRes, bIsAllRemoved) ; - if ( bIsAllRemoved) { - // se ho rimosso tutto, allora passo la chunk successivo - ++ nChunkOneCurve ; - continue ; - } - } - - // vettore delle isole che userò ( le isole aperte piccole sono trascurate) - ICRVCOMPOPOVECTOR vCrvToTIsland ; - // flag per sapere se c'è stata almeno una modifica in un loop del Chunk nC-esimo - bool bIsChunkModified = false ; + // flag per indicare se il Chunk è stato modificato mediante estensione degli aperti + bool bIsChunkModified = true ; // ricavo il Loop esterno ( External Loop) PtrOwner pCrvEL( ConvertCurveToComposite( pSfr->GetLoop( nC, 0))) ; @@ -1905,8 +1934,6 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, bool bCa int nProp0 = TEMP_PROP_INVALID ; for ( int u = 0 ; u < pCrvEL->GetCurveCount() && ! bSomeOpen ; ++ u) bSomeOpen = ( pCrvEL->GetCurveTempProp( u, nProp0, 0) && nProp0 == TEMP_PROP_OPEN_EDGE) ; - - // se trovo dei lati aperti if ( bSomeOpen) { // allorargo il Loop esterno presso i lati aperti if ( ! AdjustContourWithOpenEdges( pCrvEL, vCrvIsl, PockParams)) @@ -1915,8 +1942,9 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, bool bCa } // controllo i bordi delle isole ottenute - // NB. L'isola può essere tutta aperta o tutta chiusa ( se non uniforme, passo a tutta chiusa) - // La definizione di isola con proprietà non uniformi non è definita... + // NB. L'isola può essere tutta aperta o tutta chiusa ( se non uniforme, la forzo chiusa) + // [ La definizione di isola con proprietà non uniformi non è definita ] + ICRVCOMPOPOVECTOR vCrvToTIsland ; // isole che considero valide for ( int nI = 0 ; nI < int( vCrvIsl.size()) ; ++ nI) { // controllo uniformità int nCurrTmpProp = TEMP_PROP_INVALID ; @@ -1945,7 +1973,7 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, bool bCa // se l'isola è trascurabile passo alla successiva if ( dMaxOffs < 2 * PockParams.dRad + 2 * PockParams.dRadialOffset) continue ; - // altrimenti, estendo l'isola aperta + // altrimenti la restringo ICRVCOMPOPOVECTOR vCrvOther ; vCrvOther.emplace_back( pCrvEL->Clone()) ; for ( int nII = 0 ; nII < int( vCrvIsl.size()) ; ++ nII) { @@ -1957,10 +1985,10 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, bool bCa bIsChunkModified = true ; } // conservo l'isola ( estesa o meno) - vCrvToTIsland.emplace_back( pCrvIsl->Clone()) ; + vCrvToTIsland.emplace_back( pCrvIsl->Clone()) ; // <-- valida } - // se c'è stata almeno una modifica di lato aperto al Chunk (nC-esimo), devo ricreare il Chunk + // se c'è stata almeno una modifica di lato aperto al Chunk ( nC-esimo), devo ricreare il Chunk // con i nuovi loop ricavati ( Chunk dopo Chunk creo la superficie finale) if ( bIsChunkModified) { /* @@ -1990,46 +2018,17 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, bool bCa else { // aggiungo il Chunk alla superficie finale if ( pSrfFinal->GetChunkCount() == 0) - pSrfFinal.Set( pSfrChunk) ; - else if ( ! pSrfFinal->Add( *pSfrChunk)) + pSrfFinal.Set( pSfr->CloneChunk( nC)) ; + else if ( ! pSrfFinal->Add( *pSfr->CloneChunk( nC))) return false ; } } - - - // se ho ottenuto delle curve singole, allora le provo a concatenare - // ( tenendo solo le curve al di fuori della superficie limite ( con Offset del raggio del tool) - // potrei doverle riconcatenare - if ( ! ChainCompoCurves( vCrvCompoRes)) - return false ; - // estendo le curve, definendo ptStart e calcolando le Feeds - if ( ! AdvanceExtendCurves( vCrvCompoRes, pSfr, PockParams)) - return false ; - // imposto le Feed per tali curve se richiesto - for ( int i = 0 ; i < int( vCrvCompoRes.size()) ; ++ i) { - /* - Idea : Feed proporzionale al minimo Offset per annullare la regione - -> Massimo parametro sui bisettori di VORONOI - */ - // recupero il MaxOffset per la curva - double dMaxOffs = vCrvCompoRes[i]->GetTempParam( 0) ; - // calcolo la Feed proporzionale a tale Offset - double dFeed ; - GetFeedForParam( 2 * dMaxOffs, PockParams, dFeed) ; - AssignCustomFeed( vCrvCompoRes[i], PockParams, dFeed) ; - // imposto il flag di curva singola - vCrvCompoRes[i]->SetTempProp( TEMP_PROP_SINGLE_CURVE, 0) ; - } - - // se ho rimosso tutti i Chunk con una singola curva, allora ho terminato la svuotatura - bSkipPocket = ( nChunk == nChunkOneCurve) ; - if ( bSkipPocket) - return true ; - - // restituisco la superficie aggiornata ricavata + // se la superficie finale estesa non è valida, errore if ( ! pSrfFinal->IsValid()) return false ; - // chiudo le isole che risultano ambigue + + + // chiudo le isole che risultano ambigue ( quindi non omgenee) for ( int nC = 0 ; nC < pSrfFinal->GetChunkCount() ; ++ nC) { for ( int nL = 1 ; nL < pSrfFinal->GetLoopCount( nC) ; ++ nL) { // controllo uniformità @@ -2051,694 +2050,13 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams, bool bCa } } } + + // restituisco la superficie estesa pSfr->Clear() ; pSfr->CopyFrom( pSrfFinal) ; return ( pSfr->IsValid() && pSfr->GetChunkCount() > 0) ; } -// *************************************************************************** -// ------------- SCELTA DEL PUNTO INIZIALE ----------------------------------- -// *************************************************************************** - -//---------------------------------------------------------------------------- -static bool -GetParamOnOpenCurve( const ICurveComposite* pCompo, const PocketParams& PockParams, bool& bOutStart, - Point3d& ptStart, Vector3d& vtOut) -{ - // controllo dei parametri - if ( pCompo == nullptr || ! pCompo->IsValid()) - return false ; - - // verifico se tutti i lati sono aperti - bool bAllOpen = true ; - const ICurve* pMyCrv = pCompo->GetFirstCurve() ; - while ( pMyCrv != nullptr) { - if ( pMyCrv->GetTempProp() != TEMP_PROP_OPEN_EDGE) { - bAllOpen = false ; - break ; - } - pMyCrv = pCompo->GetNextCurve() ; - } - - // richiedo lunghezza superiore a diametro utensile più doppio offset radiale - double dRefLen = ( bAllOpen ? 0. : ( 2 * PockParams.dRad) + 2 * PockParams.dRadialOffset - EPS_SMALL) ; - double dMaxLen = dRefLen ; - // ciclo sulle singole curve - bool bFound = false ; - const ICurve* pPrevCrv = pCompo->GetLastCurve() ; - double dLenPrev = 0. ; - if ( pPrevCrv != nullptr && pPrevCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE) - pPrevCrv->GetLength( dLenPrev) ; - const ICurve* pCrv = pCompo->GetFirstCurve() ; - while ( pCrv != nullptr) { - // analizzo la curva successiva - const ICurve* pNextCrv = pCompo->GetNextCurve() ; - bool bNextOk = ( pNextCrv != nullptr) ; - if ( ! bNextOk) - pNextCrv = pCompo->GetFirstCurve() ; - double dLenNext = 0. ; - if ( pNextCrv != nullptr && pNextCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE) - pNextCrv->GetLength( dLenNext) ; - // verifico la curva corrente - if ( pCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE) { - // contributo dalle entità adiacenti ( se non tutte aperte) - double dLenAgg = 0. ; - if ( ! bAllOpen) { - if ( pPrevCrv != nullptr && pPrevCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE) { - Vector3d vtPrevEnd ; pPrevCrv->GetEndDir( vtPrevEnd) ; - Vector3d vtStart ; pCrv->GetStartDir( vtStart) ; - dLenAgg += max( 0.4, vtPrevEnd * vtStart) * dLenPrev ; - } - if ( pNextCrv != nullptr && pNextCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE) { - Vector3d vtEnd ; pCrv->GetEndDir( vtEnd) ; - Vector3d vtNextStart ; pNextCrv->GetStartDir( vtNextStart) ; - dLenAgg += max( 0.4, vtEnd * vtNextStart) * dLenNext ; - } - } - // entità corrente - double dLen = 0 ; - if ( pCrv->GetLength( dLen)) { - const double LEN_TOL = 1 ; - // se di lunghezza praticamente uguale - if ( bFound && dLen + dLenAgg > dRefLen && abs( dLen + dLenAgg - dMaxLen) < LEN_TOL) { - Point3d ptTest ; - pCrv->GetMidPoint( ptTest) ; - if ( ( PockParams.bAboveHead && ptTest.z > ptStart.z + 100 * EPS_SMALL) || - ( ! PockParams.bAboveHead && ptTest.z < ptStart.z - 100 * EPS_SMALL) || - ( abs( ptTest.z - ptStart.z) < 100 * EPS_SMALL && ptTest.y < ptStart.y - 100 * EPS_SMALL)) { - dMaxLen = max( dMaxLen, dLen + dLenAgg) ; - ptStart = ptTest ; - // versore ortogonale verso l'esterno - pCrv->GetMidDir( vtOut) ; - vtOut.Rotate( Z_AX, 0, -1) ; - } - } - // se più lunga ( o non già trovata) - else if ( dLen + dLenAgg > dMaxLen || ! bFound) { - dMaxLen = dLen + dLenAgg ; - if ( pCrv->GetPointD1D2( .5, ICurve::FROM_MINUS, ptStart, &vtOut)) { - // versore ortogonale verso l'esterno - vtOut.Normalize() ; - vtOut.Rotate( Z_AX, 0, -1) ; - bFound = true ; - } - } - dLenPrev = dLen ; - } - } - else - dLenPrev = 0 ; - // vado alla successiva - pPrevCrv = pCrv ; - pCrv = ( bNextOk ? pNextCrv : nullptr) ; - } - - return bFound ; -} - -//---------------------------------------------------------------------------- -static bool -GetPtStartOnOpenEdgeByOrigCurve( const ICurveComposite* pCrvOrig, const PocketParams& PockParams, - const ICurveComposite* pCrvCompo, Point3d& ptStart, Vector3d& vtMidOut, - bool& bMidOut) -{ - // controllo dei parametri - if ( pCrvOrig == nullptr || ! pCrvOrig->IsValid() || - pCrvCompo == nullptr || ! pCrvCompo->IsValid()) - return false ; - bMidOut = false ; - - // cerco il lato aperto più lungo ( sufficientemente lungo) - double dLenRef = ( 2 * PockParams.dRad + 2 * PockParams.dRadialOffset) - 50 * EPS_SMALL ; - for ( int i = 0 ; i < pCrvOrig->GetCurveCount() ; ++ i) { - // escludo le sottocurve chiuse - if ( pCrvOrig->GetCurve( i)->GetTempProp( 0) == TEMP_PROP_CLOSE_EDGE) - continue ; - // recupero la curva i-esima aperta dalla curva originale - const ICurve* pCrvOpen = pCrvOrig->GetCurve( i) ; - if ( pCrvOpen == nullptr || ! pCrvOpen->IsValid()) - return false ; - // ricavo la lunghezza di tale curva - double dLen = 0. ; - pCrvOpen->GetLength( dLen) ; - // se lunghezza accettabile o maggiore della massima trovata - if ( dLen > dLenRef) { - Point3d ptSTmp ; - Vector3d vtMidOutTmp ; - // ricavo il punto medio e il vettore tangente ad esso associato - if ( pCrvOpen->GetPointD1D2( 0.5, ICurve::FROM_MINUS, ptSTmp, &vtMidOutTmp)) { - // cerco la sottocurva più vicina a ptSTmp - int nFlag ; - double dMyPar ; - if ( DistPointCurve( ptSTmp, *pCrvCompo).GetParamAtMinDistPoint( 0, dMyPar, nFlag)) { - int nCrv = int( floor( dMyPar)) ; - // recupero tale sottocurva e controllo che anche essa sia OPEN - const ICurve* pMyCrv = pCrvCompo->GetCurve( nCrv) ; - if ( pMyCrv != nullptr && pMyCrv->IsValid() && pMyCrv->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { - // recupero ptStart - pMyCrv->GetMidPoint( ptStart) ; - // versore d'uscita - vtMidOutTmp.Normalize() ; - vtMidOutTmp.Rotate( Z_AX, - ANG_RIGHT) ; - vtMidOut = vtMidOutTmp ; - // flag per possibile entrata da fuori - bMidOut = true ; - // aggiornamento della lunghezza di riferimento - dLenRef = dLen ; - } - } - } - } - } - - return true ; -} - -//---------------------------------------------------------------------------- -static bool -GetPtStartOnOpenEdgeByPtRef( const Point3d& ptRef, const PocketParams& PockParams, - const ICurveComposite* pCrvCompo, const ICurveComposite* pCrvOrig, - Point3d& ptStart, Vector3d& vtMidOut, bool& bMidOut) -{ - // controllo dei parametri - if ( ! ptRef.IsValid() || pCrvCompo == nullptr || ! pCrvCompo->IsValid() || - ! ptRef.IsValid()) - return false ; - bMidOut = false ; - - // lunghezza minima di riferimento per un lato aperto valido - double dLenRef = ( 2 * PockParams.dRad + 2 * PockParams.dRadialOffset) - 50 * EPS_SMALL ; - - // cerco la curva OPEN a minima distanza da ptRef, sufficientemente lunga - int nStartCrv = -1 ; - double dMinDist = INFINITO ; - for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) { - // considero solo le sottocurve OPEN - if ( pCrvCompo->GetCurve( i)->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { - // sufficientemente lunghe - double dLen ; - if ( pCrvCompo->GetCurve( i)->GetLength( dLen) && dLen > dLenRef) { - DistPointCurve DPC( ptRef, *pCrvCompo->GetCurve( i)) ; - double dCurrDist = INFINITO ; - // sufficiententemente vicine a ptRef - if ( DPC.GetSqDist( dCurrDist) && dCurrDist < dMinDist) { - dMinDist = dCurrDist ; - nStartCrv = i ; - } - } - } - } - - // se non ho trovato nulla, allora cerco un punto iniziale valido su una sottocurva OPEN - if ( nStartCrv == -1 && pCrvOrig != nullptr && pCrvOrig->IsValid()) { - return GetPtStartOnOpenEdgeByOrigCurve( pCrvOrig, PockParams, pCrvCompo, ptStart, vtMidOut, bMidOut) ; - } - // se ho trovato la curva più vicina, cerco un punto iniziale valido - else { - const ICurve* pMyCrv = pCrvCompo->GetCurve( nStartCrv) ; - if ( pMyCrv != nullptr && pMyCrv->IsValid()) { - // ricavo ptStart e vettore tangente - if ( pMyCrv->GetPointD1D2( .5, ICurve::FROM_MINUS, ptStart, &vtMidOut)) { - // versore ortogonale verso l'esterno - vtMidOut.Normalize() ; - vtMidOut.Rotate( Z_AX, 0, -1) ; - // flag per possibile entrata da fuori - bMidOut = true ; - } - } - } - - return true ; - -} - -//---------------------------------------------------------------------------- -static bool -GetPtStartOnHomogeousEdges( const ICurveComposite* pCrvCompo, const PocketParams& PockParams, - int nType, const Point3d& ptRef, bool& bMidOut, Point3d& ptStart, - Vector3d& vtMidOut) -{ - // controllo dei parametri - if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) - return false ; - bMidOut = false ; - - // analizzo i sottotratti omogenei - ICRVCOMPOPOVECTOR vpCrvs ; - PtrOwner pCrvCompoClone( CloneCurveComposite( pCrvCompo)) ; - if ( IsNull( pCrvCompoClone) || ! pCrvCompoClone->IsValid()) - return false ; - GetHomogeneousParts( pCrvCompoClone, PockParams, vpCrvs) ; - - // se ho un solo tratto omogeneo e coerente al tipo scelto ... - if ( int( vpCrvs.size()) == 1 && vpCrvs[0]->GetTempProp( 0) == nType) { - // ... e non ho un punto di riferimento valido - if ( ! ptRef.IsValid()) { - // il punto iniziale è già definito - pCrvCompoClone->GetStartPoint( ptStart) ; - } - // ho un punto di riferimento valido - else { - // cerco il punto più vicino - DistPointCurve DistPtCrv( ptRef, *pCrvCompoClone) ; - int nFlag ; - if ( ! DistPtCrv.GetMinDistPoint( 0, ptStart, nFlag)) - return false ; - } - bMidOut = ( nType == TEMP_PROP_OPEN_EDGE) ; - return true ; - } - - // scorro i tratti omogenei e cerco il tratto del tipo definito più lungo - int nMaxInd = -1 ; - double dMaxLen = 0. ; - for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { - // considero solo i tratti aperti - if ( vpCrvs[i]->GetTempProp( 0) == nType) { - // calcolo la lunghezza del tratto aperto - double dLen ; - vpCrvs[i]->GetLength( dLen) ; - if ( dLen > dMaxLen) { - dMaxLen = dLen ; - nMaxInd = i ; - } - } - } - - // recupero il tratto del tipo definito più lungo - if ( nMaxInd != -1) { - // recupero il parametro alla sua metà - double dParIn ; - vpCrvs[nMaxInd]->GetParamAtLength( 0.5 * dMaxLen, dParIn) ; - // se tratto OPEN - if ( nType == TEMP_PROP_OPEN_EDGE) { - bMidOut = true ; - vpCrvs[nMaxInd]->GetPointD1D2( dParIn, ICurve::FROM_MINUS, ptStart, &vtMidOut) ; - vtMidOut.Normalize() ; - vtMidOut.Rotate( Z_AX, 0, -1) ; - } - // se tratto CLOSED - else - vpCrvs[nMaxInd]->GetPointD1D2( dParIn, ICurve::FROM_MINUS, ptStart) ; - } - - return true ; -} - -//---------------------------------------------------------------------------- -static bool -GetPtStartOnGenericEdge( const ICurveComposite* pCrvCompo, const PocketParams& PockParams, - Point3d& ptStart) -{ - // controllo dei parametri - if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) - return false ; - pCrvCompo->GetStartPoint( ptStart) ; - - // scorro tutte le curve - double dLenRef = 0. ; - bool bAllShort = true ; // flag per curve tutte piccole - for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) { - // ricavo la curva i-esima dalla curva originale - const ICurve* pMyCrv = pCrvCompo->GetCurve( i) ; - if ( pMyCrv == nullptr || ! pMyCrv->IsValid()) - return false ; - // ricavo la lunghezza di tale curva - double dLen = 0. ; - pMyCrv->GetLength( dLen) ; - // se lunghezza accettabile o maggiore della massima trovata, ricavo ptStart - if ( dLen > dLenRef) { - if ( pMyCrv->GetMidPoint( ptStart)) { - dLenRef = dLen ; - bAllShort = false ; - } - } - } - - // se curve tutte piccole - if ( bAllShort) { - bool bMidOutFake ; - Vector3d vtMidOutFake ; - if ( ! GetPtStartOnHomogeousEdges( pCrvCompo, PockParams, TEMP_PROP_CLOSE_EDGE, P_INVALID, - bMidOutFake, ptStart, vtMidOutFake)) - return false ; - } - - return true ; -} - -//---------------------------------------------------------------------------- -static bool -GetPtStartOnGenericEdgeByPtRef( const ICurveComposite* pCrvCompo, const PocketParams& PockParams, - const Point3d& ptRef, Point3d& ptStart) -{ - // controllo dei parametri - if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid() || pCrvCompo->GetCurveCount() == 0 || - ! ptRef.IsValid()) - return false ; - - // ordino le curve di pCrvCompo in base alla vicinanza da ptRef - // - vector> vCrvInfoDist ; vCrvInfoDist.resize( pCrvCompo->GetCurveCount()) ; - // scorro le curve di pCrvCompo - for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) { - vCrvInfoDist[i].first = i ; - // calcolo la distanza tra la curva i-esima e ptRef - double dDist = INFINITO ; - DistPointCurve DistPtCrv( ptRef, *pCrvCompo->GetCurve( i)) ; - DistPtCrv.GetSqDist( dDist) ; - vCrvInfoDist[i].second = dDist ; - } - // ordino il vettore in base alla distanza - sort( vCrvInfoDist.begin(), vCrvInfoDist.end(), [] ( const pair& a, const pair& b) { - return a.second < b.second ; - }) ; - - // cerco un parametro iniziale valido per le sottocurve ordinate - double dLenRef = 2 * PockParams.dRad + 2 * PockParams.dRadialOffset ; - for ( int i = 0 ; i < int( vCrvInfoDist.size()) ; ++ i) { - // recupero la curva i-esima - const ICurve* pMyCrv = pCrvCompo->GetCurve( vCrvInfoDist[i].first) ; - if ( pMyCrv != nullptr && pMyCrv->IsValid()) { - // controllo che sia abbastanza lunga e aggiorno ptStart - double dLen = 0. ; - pMyCrv->GetLength( dLen) ; - if ( dLen > dLenRef) { - if ( pMyCrv->GetPointD1D2( .5, ICurve::FROM_MINUS, ptStart)) - return true ; - } - } - } - - // alla peggio... - bool bMidOutFake ; - Vector3d vtMidOutFake ; - return GetPtStartOnHomogeousEdges( pCrvCompo, PockParams, TEMP_PROP_CLOSE_EDGE, ptRef, - bMidOutFake, ptStart, vtMidOutFake) ; -} - -//---------------------------------------------------------------------------- -static bool -AssignOpenCloseTmpPropToFirstOffsCurve( ICurveComposite* pCrv, const PocketParams& PockParams, - const ISurfFlatRegion* pSfrToWork, bool& bSomeOpen) -{ - // controllo dei parametri - if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0 || - pSfrToWork == nullptr || ! pSfrToWork->IsValid() || pSfrToWork->GetChunkCount() != 1) - return false ; - bSomeOpen = false ; // flag per presenza di lati aperti - int nInd = -1 ; // indice della prima curva che non è "raccordo" di Offset - - // scorro tutte le curve presenti in pCrv ( curva da cui devo entrare) - for ( int i = 0 ; i < pCrv->GetCurveCount() ; ++ i) { - // nProp0 -> #curva il cui Offset ha generato la curva i-esima di pCrv - int nProp0 = 0 ; pCrv->GetCurveTempProp( i, nProp0, 0) ; - // nProp1 -> #loop che contiene la curva espressa in nProp0 - int nProp1 = 0 ; pCrv->GetCurveTempProp( i, nProp1, 1) ; - - // se questa curva non è un "raccordo" di Offset - if ( nProp0 > 0) { - // aggiorno la proprietà della curva da cui devo entrare - int nTempProp = TEMP_PROP_CLOSE_EDGE ; - pSfrToWork->GetCurveTempProp( 0, nProp1, nProp0 - 1, nTempProp, 0) ; - pCrv->SetCurveTempProp( i, nTempProp, 0) ; - // se la curva è aperta, aggiorno il Flag - if ( nTempProp == TEMP_PROP_OPEN_EDGE && ! bSomeOpen) - bSomeOpen = true ; - // salvo l'indice della prima curva trovata che non è un "raccordo" di Offset - if ( nInd == -1) - nInd = i ; - } - // se questa curva è un "raccordo" di Offset - else { - pCrv->SetCurveTempProp( i, TEMP_PROP_SMOOTH, 0) ; - pCrv->SetCurveTempProp( i, TEMP_PROP_SMOOTH, 1) ; - } - } - - // cambio il punto iniziale all'inizio della prima curva che non deriva da un "raccordo" - Point3d ptStart ; - if ( nInd != -1) { - if ( ! pCrv->GetStartPoint( ptStart)) - return false ; - pCrv->ChangeStartPoint( nInd) ; // la prima curva non è un "raccordo" di Offset - } - - // scorro tutte le curve successive alla prima - for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++ i) { - int nTmpProp0, nTmpProp1 ; - // se "raccordo" copio la tempProp precedente - if (( pCrv->GetCurveTempProp( i, nTmpProp0, 0) && nTmpProp0 == TEMP_PROP_SMOOTH) && - ( pCrv->GetCurveTempProp( i, nTmpProp1, 1) && nTmpProp1 == TEMP_PROP_SMOOTH)) - // copio la temp prop della curva precedente - pCrv->SetCurveTempProp( i, pCrv->GetCurve( i-1)->GetTempProp( 0), 0) ; - - } - - // lascio invariato il punto iniziale della curva originaria - if ( nInd != -1) { - double dUNewS ; - pCrv->GetParamAtPoint( ptStart, dUNewS) ; - pCrv->ChangeStartPoint( dUNewS) ; - } - - return true ; -} - -//---------------------------------------------------------------------------- -static bool -SetPtStartForPath( ICurveComposite* pCrvOffs, const PocketParams& PockParams, const ISurfFlatRegion* pSrfToWork, - const Point3d& ptEndPrec, Point3d& ptStart, Vector3d& vtMidOut, bool& bMidOut, - const ICurveComposite* pCrvOrig) -{ - /* - Come prima cosa ricavo i lati aperti equivalenti dal primo Offset; Facendo l'Offset di una curva - chiusa ho all'interno delle temp prop delle sottcurve due informazioni : - // nTmpProp0 -> #curva il cui Offset ha generato la curva i-esima attuale - // nTmpProp1 -> #loop che contiene la curva espressa in nTmpProp0 - - Quindi dal contorno con i lati aperti impostati, posso settare i lati aperti "equivalenti" - anche sulla curva di primo Offset. - NB. Il tool entra dalla curva di primo Offset, non dal bordo della regione da svuotare; quindi - l'entrata va calcolata sul primo Offset, non sulla curva di bordo della FlatRegion di Pocketing. - */ - - // controllo dei parametri - if ( pCrvOffs == nullptr || ! pCrvOffs->IsValid() || pCrvOffs->GetCurveCount() == 0 || - pSrfToWork == nullptr || ! pSrfToWork->IsValid() || pSrfToWork->GetChunkCount() != 1) - return false ; - - // assegno proprietà di OPEN/CLOSE alle sottocurve dell'offset corrente - bool bSomeOpen = false ; - if ( ! AssignOpenCloseTmpPropToFirstOffsCurve( pCrvOffs, PockParams, pSrfToWork, bSomeOpen)) - return false ; - - // punto valido per l'entrata ... - bMidOut = false ; - if ( bSomeOpen) { - // se esistono lati aperti... - if ( pCrvOrig != nullptr && pCrvOrig->IsValid()) { - // ... e non ho un punto di riferimento, lo cerco sulla curva originale - if ( ! ptEndPrec.IsValid()) { - if ( ! GetPtStartOnOpenEdgeByOrigCurve( pCrvOrig, PockParams, pCrvOffs, ptStart, vtMidOut, bMidOut)) - return false ; - } - // ... e ho un punto di riferimento - else { - if ( ! GetPtStartOnOpenEdgeByPtRef( ptEndPrec, PockParams, pCrvOffs, pCrvOrig, ptStart, vtMidOut, bMidOut)) - return false ; - } - } - // se punto non trovato precedentemente, tento con una sottocurva OPEN generica - if ( ! bMidOut) { - if ( ! GetParamOnOpenCurve( pCrvOffs, PockParams, bMidOut, ptStart, vtMidOut)) - return false ; - } - // se queste curve sono troppo corte, analizzo le parti uniformi - if ( ! bMidOut) { - if ( ! GetPtStartOnHomogeousEdges( pCrvOffs, PockParams, TEMP_PROP_OPEN_EDGE, ptEndPrec, - bMidOut, ptStart, vtMidOut)) - return false ; - } - } - // se sottocurve tutte CLOSED o un punto iniziale non valido, lo cerco su un lato generico - if ( ! bMidOut) { - if ( ! ptEndPrec.IsValid()) { - if ( ! GetPtStartOnGenericEdge( pCrvOffs, PockParams, ptStart)) - return false ; - } - else { - if ( ! GetPtStartOnGenericEdgeByPtRef( pCrvOffs, PockParams, ptEndPrec, ptStart)) - return false ; - } - } - - // imposto il punto iniziale scelto - double dPar = 0. ; - if ( ! pCrvOffs->GetParamAtPoint( ptStart, dPar) || ! pCrvOffs->ChangeStartPoint( dPar)) - pCrvOffs->ChangeStartPoint( .5) ; - return true ; -} - -//---------------------------------------------------------------------------- -static bool -SetAdvancedPtStartForPath( ICRVCOMPOPOVECTOR& vCrvOffsAct, const PocketParams& PockParams, const ISurfFlatRegion* pSrfToWork, - const Point3d& ptEndPrec, Point3d& ptStart, Vector3d& vtMidOut, - bool& bMidOut, int& nIndex, ICRVCOMPOPOVECTOR& vCrvOrigChunkLoops) -{ - // controllo dei parametri - for ( int i = 0 ; i < int( vCrvOffsAct.size()) ; ++ i) - if ( IsNull( vCrvOffsAct[i]) || ! vCrvOffsAct[i]->IsValid() || vCrvOffsAct[i]->GetCurveCount() == 0) - return false ; - if ( pSrfToWork == nullptr || ! pSrfToWork->IsValid() || pSrfToWork->GetChunkCount() != 1) - return false ; - nIndex = 0 ; - - // scorro le curve di primo Offset - // NB. in prima posizione ho il primo Offset del loop esterno, a seguire le isole - // NB. Se non riesco ad entrare in nessuna curva, allora tengo valida quella calcolata per il loop esterno - bool bMidOut_fist = false ; - Vector3d vtMidOut_first ; - Point3d ptStart_first ; - for ( int i = 0 ; i < int( vCrvOffsAct.size()) ; ++ i) { - // cambio il suo punto d'inizio dell'Offset attuale - if ( SetPtStartForPath( vCrvOffsAct[i], PockParams, pSrfToWork, ptEndPrec, ptStart, vtMidOut, - bMidOut, i < ( int( vCrvOrigChunkLoops.size())) ? Get( vCrvOrigChunkLoops[i]) : nullptr)) - vCrvOffsAct[i]->GetStartPoint( ptStart) ; - else - return false ; - // se ho trovato un'entrata valida da un lato aperto, ho finito - if ( bMidOut) { - nIndex = i ; // salvo l'indice del vettore - return true ; - } - // se sono nel loop esterno e non ho trovato un'entrata da un lato aperto, salvo i risultati ottenuti - else if ( i == 0) { - bMidOut_fist = bMidOut ; - vtMidOut_first = vtMidOut ; - ptStart_first = ptStart ; - } - } - - // in questo caso non ho trovato un'entrata da un lato aperto in nessuna curva ( potrebbero essere tutte chiuse) - bMidOut = bMidOut_fist ; - vtMidOut = vtMidOut_first ; - ptStart = ptStart_first ; - return true ; - -} - -// *************************************************************************** -//---------------------------- CASI OTTIMIZZATI ------------------------------ -// *************************************************************************** - -//---------------------------------------------------------------------------- -static bool -GetOptCrvIndex( const ISurfFlatRegion* pSfrOrig, const ISurfFlatRegion* pSfrChunk, - const PocketParams& PockParams, int nReg, ICRVCOMPOPOVECTOR& vCrvOrig) -{ - - /* - NB. La superficie da lavorare è stata estesa presso i lati aperti; cerco il Chunk - di riferimento sulla superficie originale ed estraggo le sue curve ( in prima posizione - il loop esterno e a seguire le isole); queste curve verranno utilizzate per la scelta - dei casi ottimizzati ( trapezi, circonferenze, ecc ecc..) - */ - - // controllo dei parametri - if ( pSfrOrig == nullptr || ! pSfrOrig->IsValid() || - pSfrChunk == nullptr || ! pSfrChunk->IsValid()) - return false ; - - // se la superficie originale ha un solo Chunk, allora le curve originali sono già trovate - for ( int l = 0 ; l < pSfrOrig->GetLoopCount( 0) ; ++ l) - vCrvOrig.emplace_back( ConvertCurveToComposite( pSfrOrig->GetLoop( 0, l))) ; - if ( pSfrOrig->GetChunkCount() == 1) - return true ; - - // vettore di indici dei chunk candidati - INTVECTOR vInds ; - - // scorro tutti i Chunk della superficie orginaria - for ( int c = 0 ; c < int( pSfrOrig->GetChunkCount()) ; ++ c) { - // la classificazione può essere fatta semplicemente guardando il Loop esterno - PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrOrig->GetLoop( c, 0))) ; - if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid()) - return false ; - // classifico il Chunk attuale con la curva in esame - CRVCVECTOR ccClass ; - if ( pSfrChunk->GetCurveClassification( *pCrvExtLoop, EPS_SMALL, ccClass)) { - // se il Chunk attuale è stato esteso presso presso i lati aperti mi aspetto che esso non sia più - // grande del chunk originale ( se non ci sono lati aperti, allora coincide ) - // se il ccClass non contiene parti classificate come esterne allora il Chunk di riferimento è il c-esimo - bool bIsThis = true ; - for ( int k = 0 ; k < int( ccClass.size()) && bIsThis ; ++ k) { - if ( ccClass[k].nClass == CRVC_OUT) - bIsThis = false ; - } - if ( bIsThis) - vInds.push_back( c) ; - } - } - // se ho un solo indice allora ho già identificato le curve originali - if ( int( vInds.size()) == 1) { - vCrvOrig.clear() ; - for ( int l = 0 ; l < pSfrOrig->GetLoopCount( vInds[0]) ; ++ l) - vCrvOrig.emplace_back( ConvertCurveToComposite( pSfrOrig->GetLoop( vInds[0], l))) ; - return true ; - } - // altrimenti... - /* - NB. Come parametro alla funzione è stato passato "nReg"; Facendo il primo Offset del Chunk attuale - questo verrà diviso in n sottoregioni; devo considerare la nReg-esima - Situazione: Estendendo presso i lati aperti, due ( o più) chunk si sono uniti formandone uno unico - Quando effettuo il primo offset ( del diametro del materiale + offset radiale), questo Chunk si splitterà in n Chunk; - Uno ( o più) di questi nuovi chunk potrebbe corrispondere ad un caso ottimizzato. - Devo recuperare il Chunk della superficie originaria ( che non essendo estesa presso i lati aperti - ha la geomtria originale) - */ - - // effettuo un Offset del Chunk per simulare la creazione degli n Chunks - double dOffs = PockParams.dRad + PockParams.dRadialOffset ; - PtrOwner pSfrRefChunk( pSfrChunk->Clone()) ; - if ( IsNull( pSfrRefChunk) || - ! pSfrRefChunk->Offset( - dOffs, ICurve::OFF_FILLET)) - return false ; - - // clono il Chunk nReg-esimo se esiste - pSfrRefChunk.Set( pSfrRefChunk->CloneChunk( nReg)) ; - if ( IsNull( pSfrRefChunk)) - return true ; // bisogna passare al ( pSfrChunk + 1)-esimo se esiste - - // scorro tutti i Chunk della superficie orginaria e ripeto la classificazione - // NB. Questa volta posso fermarmi al primo Chunk classificato come non esterno - for ( int c = 0 ; c < int( pSfrOrig->GetChunkCount()) ; ++ c) { - // come prima recupero il Loop esterno - PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrOrig->GetLoop( c, 0))) ; - if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid()) - return false ; - // classificazione - CRVCVECTOR ccClass ; - if ( pSfrRefChunk->GetCurveClassification( *pCrvExtLoop, EPS_SMALL, ccClass)) { - bool bIsThis = true ; - for ( int k = 0 ; k < int( ccClass.size()) && bIsThis ; ++ k) { - if ( ccClass[k].nClass == CRVC_OUT) - bIsThis = false ; - } - if ( bIsThis) { - vCrvOrig.clear() ; - for ( int l = 0 ; l < pSfrOrig->GetLoopCount( c) ; ++ l) - vCrvOrig.emplace_back( ConvertCurveToComposite( pSfrOrig->GetLoop( c, l))) ; - return true ; // esco - } - } - } - - return true ; // alla peggio non considero casi ottimizzati e svuoto normalmente... - -} - - //---------------------------------------------------------------------------- static bool OptimizedSpiralCirle( const ICurveComposite* pCrvCompo, const double dToll, double& dRad, @@ -3992,6 +3310,834 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double return true ; } +//---------------------------------------------------------------------------- +static bool +GetSpiralOptimizedCurves( 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()) ; + + // recupero i tratti con proprietà uniformi + ICRVCOMPOPOVECTOR vpCrvs ; + GetHomogeneousParts( pCrvBorder, PockParam, vpCrvs) ; + if ( vpCrvs.size() > 1) { + // unisco il primo e l'ultimo se estremi compatibili + Point3d ptE ; vpCrvs.back()->GetEndPoint( ptE) ; + Point3d ptS ; vpCrvs[0]->GetStartPoint( ptS) ; + if ( AreSamePointApprox( ptS, ptE)) { + vpCrvs[0]->AddCurve( Release( vpCrvs.back()), false) ; + vpCrvs.erase( vpCrvs.end() - 1) ; + } + } + if ( vpCrvs.empty()) + return false ; + + /* SPIRALE EUCLIDEA + - E' richiesto che la curva di bordo sia una circonferenza tutta OPEN o tutta CLOSED + */ + bool bOkSpiral = ( int( vpCrvs.size()) == 1) ; + if ( bOkSpiral) { + // controllo che sia una circonferenza + Point3d ptCen ; double dRad ; + if ( ! OptimizedSpiralCirle( pCrvBorder, 50 * EPS_SMALL, dRad, ptCen, bOkSpiral)) + return false ; + // se è una circonferenza + if ( bOkSpiral) { + double dOffs = PockParam.dRad + PockParam.dRadialOffset ; + // se curva tutta Open, allora ingrandisco il raggio + if ( vpCrvs[0]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) + dRad += 1.05 * PockParam.dRad + PockParam.dRadialOffset ; + // se curva chiusa, controllo che il raggio sia compatibile con il primo Offset + else + bOkSpiral = ( dRad - dOffs > 10 * EPS_SMALL) ; + if ( bOkSpiral) { + double dIntRad = 0 ; + bool bOkSpiral = CalcCircleSpiral( ptCen, pSfrChunk->GetNormVersor(), dRad - dOffs, dIntRad, PockParam, pCrvRes) ; + if ( bOkSpiral && pCrvRes->IsValid() && pCrvRes->GetCurveCount() > 0) { + // se curva di bordo OPEN, imposto i parametri per LeadIn + if ( vpCrvs[0]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { + Vector3d vtMidOut ; + pCrvRes->GetStartDir( vtMidOut) ; + vtMidOut.Rotate( pSfrChunk->GetNormVersor(), PockParam.bInvert ? ANG_RIGHT : - ANG_RIGHT) ; + bool bIsExtended ; + ExtendPath( pCrvRes, pSfrChunk, PockParam, vtMidOut, false, bIsExtended) ; + } + return true ; + } + } + } + } + + /* 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()) { + pCrvTrap->SetExtrusion( Z_AX) ; + CalcTrapezoidSpiral( pCrvTrap, frTrap, dPocketSize, nBase, nSecondBase, PockParam, pCrvRes, bOkTrap) ; + if ( bOkTrap) + return true ; + } + + return true ; + +} + +//---------------------------------------------------------------------------- +static bool +GetPocketingOptimizedCurves( ISurfFlatRegion* pSfr, const PocketParams& PockParam, + ICRVCOMPOPOVECTOR& vCrvOptCurves) +{ + // controllo dei parametri + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + vCrvOptCurves.clear() ; + + // se non sono richiesti i casi ottimizzati esco + if ( PockParam.bAvoidOpt) + return true ; + + // scorro i Chunk della superficie + int nChunks = pSfr->GetChunkCount() ; + int nCurrChunk = 0 ; + for ( int i = 0 ; i < nChunks ; ++ i) { + + // recupero il Chunk corrente + PtrOwner pSfrChunk( pSfr->CloneChunk( nCurrChunk)) ; + if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) + return false ; + + // se il Chunk ha isole, non ho casi ottimizzati + if ( pSfrChunk->GetLoopCount( 0) > 1) { + ++ nCurrChunk ; + continue ; + } + + // ricavo le curve ottimizzate a seconda della lavorazione richiesta + if ( PockParam.nType == POCKET_SPIRALIN || PockParam.nType == POCKET_SPIRALOUT) { + // curva da resituire + PtrOwner pCrvOptSpiral( CreateCurveComposite()) ; + 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)) ; + 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 ; +} + +// *************************************************************************** +// ------------- SCELTA DEL PUNTO INIZIALE ----------------------------------- +// *************************************************************************** + +//---------------------------------------------------------------------------- +static bool +GetParamOnOpenCurve( const ICurveComposite* pCompo, const PocketParams& PockParams, bool& bOutStart, + Point3d& ptStart, Vector3d& vtOut) +{ + // controllo dei parametri + if ( pCompo == nullptr || ! pCompo->IsValid()) + return false ; + + // verifico se tutti i lati sono aperti + bool bAllOpen = true ; + const ICurve* pMyCrv = pCompo->GetFirstCurve() ; + while ( pMyCrv != nullptr) { + if ( pMyCrv->GetTempProp() != TEMP_PROP_OPEN_EDGE) { + bAllOpen = false ; + break ; + } + pMyCrv = pCompo->GetNextCurve() ; + } + + // richiedo lunghezza superiore a diametro utensile più doppio offset radiale + double dRefLen = ( bAllOpen ? 0. : ( 2 * PockParams.dRad) + 2 * PockParams.dRadialOffset - EPS_SMALL) ; + double dMaxLen = dRefLen ; + // ciclo sulle singole curve + bool bFound = false ; + const ICurve* pPrevCrv = pCompo->GetLastCurve() ; + double dLenPrev = 0. ; + if ( pPrevCrv != nullptr && pPrevCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE) + pPrevCrv->GetLength( dLenPrev) ; + const ICurve* pCrv = pCompo->GetFirstCurve() ; + while ( pCrv != nullptr) { + // analizzo la curva successiva + const ICurve* pNextCrv = pCompo->GetNextCurve() ; + bool bNextOk = ( pNextCrv != nullptr) ; + if ( ! bNextOk) + pNextCrv = pCompo->GetFirstCurve() ; + double dLenNext = 0. ; + if ( pNextCrv != nullptr && pNextCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE) + pNextCrv->GetLength( dLenNext) ; + // verifico la curva corrente + if ( pCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE) { + // contributo dalle entità adiacenti ( se non tutte aperte) + double dLenAgg = 0. ; + if ( ! bAllOpen) { + if ( pPrevCrv != nullptr && pPrevCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE) { + Vector3d vtPrevEnd ; pPrevCrv->GetEndDir( vtPrevEnd) ; + Vector3d vtStart ; pCrv->GetStartDir( vtStart) ; + dLenAgg += max( 0.4, vtPrevEnd * vtStart) * dLenPrev ; + } + if ( pNextCrv != nullptr && pNextCrv->GetTempProp() == TEMP_PROP_OPEN_EDGE) { + Vector3d vtEnd ; pCrv->GetEndDir( vtEnd) ; + Vector3d vtNextStart ; pNextCrv->GetStartDir( vtNextStart) ; + dLenAgg += max( 0.4, vtEnd * vtNextStart) * dLenNext ; + } + } + // entità corrente + double dLen = 0 ; + if ( pCrv->GetLength( dLen)) { + const double LEN_TOL = 1 ; + // se di lunghezza praticamente uguale + if ( bFound && dLen + dLenAgg > dRefLen && abs( dLen + dLenAgg - dMaxLen) < LEN_TOL) { + Point3d ptTest ; + pCrv->GetMidPoint( ptTest) ; + if ( ( PockParams.bAboveHead && ptTest.z > ptStart.z + 100 * EPS_SMALL) || + ( ! PockParams.bAboveHead && ptTest.z < ptStart.z - 100 * EPS_SMALL) || + ( abs( ptTest.z - ptStart.z) < 100 * EPS_SMALL && ptTest.y < ptStart.y - 100 * EPS_SMALL)) { + dMaxLen = max( dMaxLen, dLen + dLenAgg) ; + ptStart = ptTest ; + // versore ortogonale verso l'esterno + pCrv->GetMidDir( vtOut) ; + vtOut.Rotate( Z_AX, 0, -1) ; + } + } + // se più lunga ( o non già trovata) + else if ( dLen + dLenAgg > dMaxLen || ! bFound) { + dMaxLen = dLen + dLenAgg ; + if ( pCrv->GetPointD1D2( .5, ICurve::FROM_MINUS, ptStart, &vtOut)) { + // versore ortogonale verso l'esterno + vtOut.Normalize() ; + vtOut.Rotate( Z_AX, 0, -1) ; + bFound = true ; + } + } + dLenPrev = dLen ; + } + } + else + dLenPrev = 0 ; + // vado alla successiva + pPrevCrv = pCrv ; + pCrv = ( bNextOk ? pNextCrv : nullptr) ; + } + + return bFound ; +} + +//---------------------------------------------------------------------------- +static bool +GetPtStartOnOpenEdgeByOrigCurve( const ICurveComposite* pCrvOrig, const PocketParams& PockParams, + const ICurveComposite* pCrvCompo, Point3d& ptStart, Vector3d& vtMidOut, + bool& bMidOut) +{ + // controllo dei parametri + if ( pCrvOrig == nullptr || ! pCrvOrig->IsValid() || + pCrvCompo == nullptr || ! pCrvCompo->IsValid()) + return false ; + bMidOut = false ; + + // cerco il lato aperto più lungo ( sufficientemente lungo) + double dLenRef = ( 2 * PockParams.dRad + 2 * PockParams.dRadialOffset) - 50 * EPS_SMALL ; + for ( int i = 0 ; i < pCrvOrig->GetCurveCount() ; ++ i) { + // escludo le sottocurve chiuse + if ( pCrvOrig->GetCurve( i)->GetTempProp( 0) == TEMP_PROP_CLOSE_EDGE) + continue ; + // recupero la curva i-esima aperta dalla curva originale + const ICurve* pCrvOpen = pCrvOrig->GetCurve( i) ; + if ( pCrvOpen == nullptr || ! pCrvOpen->IsValid()) + return false ; + // ricavo la lunghezza di tale curva + double dLen = 0. ; + pCrvOpen->GetLength( dLen) ; + // se lunghezza accettabile o maggiore della massima trovata + if ( dLen > dLenRef) { + Point3d ptSTmp ; + Vector3d vtMidOutTmp ; + // ricavo il punto medio e il vettore tangente ad esso associato + if ( pCrvOpen->GetPointD1D2( 0.5, ICurve::FROM_MINUS, ptSTmp, &vtMidOutTmp)) { + // cerco la sottocurva più vicina a ptSTmp + int nFlag ; + double dMyPar ; + if ( DistPointCurve( ptSTmp, *pCrvCompo).GetParamAtMinDistPoint( 0, dMyPar, nFlag)) { + int nCrv = int( floor( dMyPar)) ; + // recupero tale sottocurva e controllo che anche essa sia OPEN + const ICurve* pMyCrv = pCrvCompo->GetCurve( nCrv) ; + if ( pMyCrv != nullptr && pMyCrv->IsValid() && pMyCrv->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { + // recupero ptStart + pMyCrv->GetMidPoint( ptStart) ; + // versore d'uscita + vtMidOutTmp.Normalize() ; + vtMidOutTmp.Rotate( Z_AX, - ANG_RIGHT) ; + vtMidOut = vtMidOutTmp ; + // flag per possibile entrata da fuori + bMidOut = true ; + // aggiornamento della lunghezza di riferimento + dLenRef = dLen ; + } + } + } + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +GetPtStartOnOpenEdgeByPtRef( const Point3d& ptRef, const PocketParams& PockParams, + const ICurveComposite* pCrvCompo, const ICurveComposite* pCrvOrig, + Point3d& ptStart, Vector3d& vtMidOut, bool& bMidOut) +{ + // controllo dei parametri + if ( ! ptRef.IsValid() || pCrvCompo == nullptr || ! pCrvCompo->IsValid() || + ! ptRef.IsValid()) + return false ; + bMidOut = false ; + + // lunghezza minima di riferimento per un lato aperto valido + double dLenRef = ( 2 * PockParams.dRad + 2 * PockParams.dRadialOffset) - 50 * EPS_SMALL ; + + // cerco la curva OPEN a minima distanza da ptRef, sufficientemente lunga + int nStartCrv = -1 ; + double dMinDist = INFINITO ; + for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) { + // considero solo le sottocurve OPEN + if ( pCrvCompo->GetCurve( i)->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { + // sufficientemente lunghe + double dLen ; + if ( pCrvCompo->GetCurve( i)->GetLength( dLen) && dLen > dLenRef) { + DistPointCurve DPC( ptRef, *pCrvCompo->GetCurve( i)) ; + double dCurrDist = INFINITO ; + // sufficiententemente vicine a ptRef + if ( DPC.GetSqDist( dCurrDist) && dCurrDist < dMinDist) { + dMinDist = dCurrDist ; + nStartCrv = i ; + } + } + } + } + + // se non ho trovato nulla, allora cerco un punto iniziale valido su una sottocurva OPEN + if ( nStartCrv == -1 && pCrvOrig != nullptr && pCrvOrig->IsValid()) { + return GetPtStartOnOpenEdgeByOrigCurve( pCrvOrig, PockParams, pCrvCompo, ptStart, vtMidOut, bMidOut) ; + } + // se ho trovato la curva più vicina, cerco un punto iniziale valido + else { + const ICurve* pMyCrv = pCrvCompo->GetCurve( nStartCrv) ; + if ( pMyCrv != nullptr && pMyCrv->IsValid()) { + // ricavo ptStart e vettore tangente + if ( pMyCrv->GetPointD1D2( .5, ICurve::FROM_MINUS, ptStart, &vtMidOut)) { + // versore ortogonale verso l'esterno + vtMidOut.Normalize() ; + vtMidOut.Rotate( Z_AX, 0, -1) ; + // flag per possibile entrata da fuori + bMidOut = true ; + } + } + } + + return true ; + +} + +//---------------------------------------------------------------------------- +static bool +GetPtStartOnHomogeousEdges( const ICurveComposite* pCrvCompo, const PocketParams& PockParams, + int nType, const Point3d& ptRef, bool& bMidOut, Point3d& ptStart, + Vector3d& vtMidOut) +{ + // controllo dei parametri + if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) + return false ; + bMidOut = false ; + + // analizzo i sottotratti omogenei + ICRVCOMPOPOVECTOR vpCrvs ; + PtrOwner pCrvCompoClone( CloneCurveComposite( pCrvCompo)) ; + if ( IsNull( pCrvCompoClone) || ! pCrvCompoClone->IsValid()) + return false ; + GetHomogeneousParts( pCrvCompoClone, PockParams, vpCrvs) ; + + // se ho un solo tratto omogeneo e coerente al tipo scelto ... + if ( int( vpCrvs.size()) == 1 && vpCrvs[0]->GetTempProp( 0) == nType) { + // ... e non ho un punto di riferimento valido + if ( ! ptRef.IsValid()) { + // il punto iniziale è già definito + pCrvCompoClone->GetStartPoint( ptStart) ; + } + // ho un punto di riferimento valido + else { + // cerco il punto più vicino + DistPointCurve DistPtCrv( ptRef, *pCrvCompoClone) ; + int nFlag ; + if ( ! DistPtCrv.GetMinDistPoint( 0, ptStart, nFlag)) + return false ; + } + bMidOut = ( nType == TEMP_PROP_OPEN_EDGE) ; + return true ; + } + + // scorro i tratti omogenei e cerco il tratto del tipo definito più lungo + int nMaxInd = -1 ; + double dMaxLen = 0. ; + for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { + // considero solo i tratti aperti + if ( vpCrvs[i]->GetTempProp( 0) == nType) { + // calcolo la lunghezza del tratto aperto + double dLen ; + vpCrvs[i]->GetLength( dLen) ; + if ( dLen > dMaxLen) { + dMaxLen = dLen ; + nMaxInd = i ; + } + } + } + + // recupero il tratto del tipo definito più lungo + if ( nMaxInd != -1) { + // recupero il parametro alla sua metà + double dParIn ; + vpCrvs[nMaxInd]->GetParamAtLength( 0.5 * dMaxLen, dParIn) ; + // se tratto OPEN + if ( nType == TEMP_PROP_OPEN_EDGE) { + bMidOut = true ; + vpCrvs[nMaxInd]->GetPointD1D2( dParIn, ICurve::FROM_MINUS, ptStart, &vtMidOut) ; + vtMidOut.Normalize() ; + vtMidOut.Rotate( Z_AX, 0, -1) ; + } + // se tratto CLOSED + else + vpCrvs[nMaxInd]->GetPointD1D2( dParIn, ICurve::FROM_MINUS, ptStart) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +GetPtStartOnGenericEdge( const ICurveComposite* pCrvCompo, const PocketParams& PockParams, + Point3d& ptStart) +{ + // controllo dei parametri + if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) + return false ; + pCrvCompo->GetStartPoint( ptStart) ; + + // scorro tutte le curve + double dLenRef = 0. ; + bool bAllShort = true ; // flag per curve tutte piccole + for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) { + // ricavo la curva i-esima dalla curva originale + const ICurve* pMyCrv = pCrvCompo->GetCurve( i) ; + if ( pMyCrv == nullptr || ! pMyCrv->IsValid()) + return false ; + // ricavo la lunghezza di tale curva + double dLen = 0. ; + pMyCrv->GetLength( dLen) ; + // se lunghezza accettabile o maggiore della massima trovata, ricavo ptStart + if ( dLen > dLenRef) { + if ( pMyCrv->GetMidPoint( ptStart)) { + dLenRef = dLen ; + bAllShort = false ; + } + } + } + + // se curve tutte piccole + if ( bAllShort) { + bool bMidOutFake ; + Vector3d vtMidOutFake ; + if ( ! GetPtStartOnHomogeousEdges( pCrvCompo, PockParams, TEMP_PROP_CLOSE_EDGE, P_INVALID, + bMidOutFake, ptStart, vtMidOutFake)) + return false ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +GetPtStartOnGenericEdgeByPtRef( const ICurveComposite* pCrvCompo, const PocketParams& PockParams, + const Point3d& ptRef, Point3d& ptStart) +{ + // controllo dei parametri + if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid() || pCrvCompo->GetCurveCount() == 0 || + ! ptRef.IsValid()) + return false ; + + // ordino le curve di pCrvCompo in base alla vicinanza da ptRef + // + vector> vCrvInfoDist ; vCrvInfoDist.resize( pCrvCompo->GetCurveCount()) ; + // scorro le curve di pCrvCompo + for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) { + vCrvInfoDist[i].first = i ; + // calcolo la distanza tra la curva i-esima e ptRef + double dDist = INFINITO ; + DistPointCurve DistPtCrv( ptRef, *pCrvCompo->GetCurve( i)) ; + DistPtCrv.GetSqDist( dDist) ; + vCrvInfoDist[i].second = dDist ; + } + // ordino il vettore in base alla distanza + sort( vCrvInfoDist.begin(), vCrvInfoDist.end(), [] ( const pair& a, const pair& b) { + return a.second < b.second ; + }) ; + + // cerco un parametro iniziale valido per le sottocurve ordinate + double dLenRef = 2 * PockParams.dRad + 2 * PockParams.dRadialOffset ; + for ( int i = 0 ; i < int( vCrvInfoDist.size()) ; ++ i) { + // recupero la curva i-esima + const ICurve* pMyCrv = pCrvCompo->GetCurve( vCrvInfoDist[i].first) ; + if ( pMyCrv != nullptr && pMyCrv->IsValid()) { + // controllo che sia abbastanza lunga e aggiorno ptStart + double dLen = 0. ; + pMyCrv->GetLength( dLen) ; + if ( dLen > dLenRef) { + if ( pMyCrv->GetPointD1D2( .5, ICurve::FROM_MINUS, ptStart)) + return true ; + } + } + } + + // alla peggio... + bool bMidOutFake ; + Vector3d vtMidOutFake ; + return GetPtStartOnHomogeousEdges( pCrvCompo, PockParams, TEMP_PROP_CLOSE_EDGE, ptRef, + bMidOutFake, ptStart, vtMidOutFake) ; +} + +//---------------------------------------------------------------------------- +static bool +AssignOpenCloseTmpPropToFirstOffsCurve( ICurveComposite* pCrv, const PocketParams& PockParams, + const ISurfFlatRegion* pSfrToWork, bool& bSomeOpen) +{ + // controllo dei parametri + if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0 || + pSfrToWork == nullptr || ! pSfrToWork->IsValid() || pSfrToWork->GetChunkCount() != 1) + return false ; + bSomeOpen = false ; // flag per presenza di lati aperti + int nInd = -1 ; // indice della prima curva che non è "raccordo" di Offset + + // scorro tutte le curve presenti in pCrv ( curva da cui devo entrare) + for ( int i = 0 ; i < pCrv->GetCurveCount() ; ++ i) { + // nProp0 -> #curva il cui Offset ha generato la curva i-esima di pCrv + int nProp0 = 0 ; pCrv->GetCurveTempProp( i, nProp0, 0) ; + // nProp1 -> #loop che contiene la curva espressa in nProp0 + int nProp1 = 0 ; pCrv->GetCurveTempProp( i, nProp1, 1) ; + + // se questa curva non è un "raccordo" di Offset + if ( nProp0 > 0) { + // aggiorno la proprietà della curva da cui devo entrare + int nTempProp = TEMP_PROP_CLOSE_EDGE ; + pSfrToWork->GetCurveTempProp( 0, nProp1, nProp0 - 1, nTempProp, 0) ; + pCrv->SetCurveTempProp( i, nTempProp, 0) ; + // se la curva è aperta, aggiorno il Flag + if ( nTempProp == TEMP_PROP_OPEN_EDGE && ! bSomeOpen) + bSomeOpen = true ; + // salvo l'indice della prima curva trovata che non è un "raccordo" di Offset + if ( nInd == -1) + nInd = i ; + } + // se questa curva è un "raccordo" di Offset + else { + pCrv->SetCurveTempProp( i, TEMP_PROP_SMOOTH, 0) ; + pCrv->SetCurveTempProp( i, TEMP_PROP_SMOOTH, 1) ; + } + } + + // cambio il punto iniziale all'inizio della prima curva che non deriva da un "raccordo" + Point3d ptStart ; + if ( nInd != -1) { + if ( ! pCrv->GetStartPoint( ptStart)) + return false ; + pCrv->ChangeStartPoint( nInd) ; // la prima curva non è un "raccordo" di Offset + } + + // scorro tutte le curve successive alla prima + for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++ i) { + int nTmpProp0, nTmpProp1 ; + // se "raccordo" copio la tempProp precedente + if (( pCrv->GetCurveTempProp( i, nTmpProp0, 0) && nTmpProp0 == TEMP_PROP_SMOOTH) && + ( pCrv->GetCurveTempProp( i, nTmpProp1, 1) && nTmpProp1 == TEMP_PROP_SMOOTH)) + // copio la temp prop della curva precedente + pCrv->SetCurveTempProp( i, pCrv->GetCurve( i-1)->GetTempProp( 0), 0) ; + + } + + // lascio invariato il punto iniziale della curva originaria + if ( nInd != -1) { + double dUNewS ; + pCrv->GetParamAtPoint( ptStart, dUNewS) ; + pCrv->ChangeStartPoint( dUNewS) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +SetPtStartForPath( ICurveComposite* pCrvOffs, const PocketParams& PockParams, const ISurfFlatRegion* pSrfToWork, + const Point3d& ptEndPrec, Point3d& ptStart, Vector3d& vtMidOut, bool& bMidOut, + const ICurveComposite* pCrvOrig) +{ + /* + Come prima cosa ricavo i lati aperti equivalenti dal primo Offset; Facendo l'Offset di una curva + chiusa ho all'interno delle temp prop delle sottcurve due informazioni : + // nTmpProp0 -> #curva il cui Offset ha generato la curva i-esima attuale + // nTmpProp1 -> #loop che contiene la curva espressa in nTmpProp0 + + Quindi dal contorno con i lati aperti impostati, posso settare i lati aperti "equivalenti" + anche sulla curva di primo Offset. + NB. Il tool entra dalla curva di primo Offset, non dal bordo della regione da svuotare; quindi + l'entrata va calcolata sul primo Offset, non sulla curva di bordo della FlatRegion di Pocketing. + */ + + // controllo dei parametri + if ( pCrvOffs == nullptr || ! pCrvOffs->IsValid() || pCrvOffs->GetCurveCount() == 0 || + pSrfToWork == nullptr || ! pSrfToWork->IsValid() || pSrfToWork->GetChunkCount() != 1) + return false ; + + // assegno proprietà di OPEN/CLOSE alle sottocurve dell'offset corrente + bool bSomeOpen = false ; + if ( ! AssignOpenCloseTmpPropToFirstOffsCurve( pCrvOffs, PockParams, pSrfToWork, bSomeOpen)) + return false ; + + // punto valido per l'entrata ... + bMidOut = false ; + if ( bSomeOpen) { + // se esistono lati aperti... + if ( pCrvOrig != nullptr && pCrvOrig->IsValid()) { + // ... e non ho un punto di riferimento, lo cerco sulla curva originale + if ( ! ptEndPrec.IsValid()) { + if ( ! GetPtStartOnOpenEdgeByOrigCurve( pCrvOrig, PockParams, pCrvOffs, ptStart, vtMidOut, bMidOut)) + return false ; + } + // ... e ho un punto di riferimento + else { + if ( ! GetPtStartOnOpenEdgeByPtRef( ptEndPrec, PockParams, pCrvOffs, pCrvOrig, ptStart, vtMidOut, bMidOut)) + return false ; + } + } + // se punto non trovato precedentemente, tento con una sottocurva OPEN generica + if ( ! bMidOut) { + if ( ! GetParamOnOpenCurve( pCrvOffs, PockParams, bMidOut, ptStart, vtMidOut)) + return false ; + } + // se queste curve sono troppo corte, analizzo le parti uniformi + if ( ! bMidOut) { + if ( ! GetPtStartOnHomogeousEdges( pCrvOffs, PockParams, TEMP_PROP_OPEN_EDGE, ptEndPrec, + bMidOut, ptStart, vtMidOut)) + return false ; + } + } + // se sottocurve tutte CLOSED o un punto iniziale non valido, lo cerco su un lato generico + if ( ! bMidOut) { + if ( ! ptEndPrec.IsValid()) { + if ( ! GetPtStartOnGenericEdge( pCrvOffs, PockParams, ptStart)) + return false ; + } + else { + if ( ! GetPtStartOnGenericEdgeByPtRef( pCrvOffs, PockParams, ptEndPrec, ptStart)) + return false ; + } + } + + // imposto il punto iniziale scelto + double dPar = 0. ; + if ( ! pCrvOffs->GetParamAtPoint( ptStart, dPar) || ! pCrvOffs->ChangeStartPoint( dPar)) + pCrvOffs->ChangeStartPoint( .5) ; + return true ; +} + +//---------------------------------------------------------------------------- +static bool +SetAdvancedPtStartForPath( ICRVCOMPOPOVECTOR& vCrvOffsAct, const PocketParams& PockParams, const ISurfFlatRegion* pSrfToWork, + const Point3d& ptEndPrec, Point3d& ptStart, Vector3d& vtMidOut, + bool& bMidOut, int& nIndex, ICRVCOMPOPOVECTOR& vCrvOrigChunkLoops) +{ + // controllo dei parametri + for ( int i = 0 ; i < int( vCrvOffsAct.size()) ; ++ i) + if ( IsNull( vCrvOffsAct[i]) || ! vCrvOffsAct[i]->IsValid() || vCrvOffsAct[i]->GetCurveCount() == 0) + return false ; + if ( pSrfToWork == nullptr || ! pSrfToWork->IsValid() || pSrfToWork->GetChunkCount() != 1) + return false ; + nIndex = 0 ; + + // scorro le curve di primo Offset + // NB. in prima posizione ho il primo Offset del loop esterno, a seguire le isole + // NB. Se non riesco ad entrare in nessuna curva, allora tengo valida quella calcolata per il loop esterno + bool bMidOut_fist = false ; + Vector3d vtMidOut_first ; + Point3d ptStart_first ; + for ( int i = 0 ; i < int( vCrvOffsAct.size()) ; ++ i) { + // cambio il suo punto d'inizio dell'Offset attuale + if ( SetPtStartForPath( vCrvOffsAct[i], PockParams, pSrfToWork, ptEndPrec, ptStart, vtMidOut, + bMidOut, i < ( int( vCrvOrigChunkLoops.size())) ? Get( vCrvOrigChunkLoops[i]) : nullptr)) + vCrvOffsAct[i]->GetStartPoint( ptStart) ; + else + return false ; + // se ho trovato un'entrata valida da un lato aperto, ho finito + if ( bMidOut) { + nIndex = i ; // salvo l'indice del vettore + return true ; + } + // se sono nel loop esterno e non ho trovato un'entrata da un lato aperto, salvo i risultati ottenuti + else if ( i == 0) { + bMidOut_fist = bMidOut ; + vtMidOut_first = vtMidOut ; + ptStart_first = ptStart ; + } + } + + // in questo caso non ho trovato un'entrata da un lato aperto in nessuna curva ( potrebbero essere tutte chiuse) + bMidOut = bMidOut_fist ; + vtMidOut = vtMidOut_first ; + ptStart = ptStart_first ; + return true ; + +} + +// *************************************************************************** +//---------------------------- CASI OTTIMIZZATI ------------------------------ +// *************************************************************************** + +//---------------------------------------------------------------------------- +static bool +GetOptCrvIndex( const ISurfFlatRegion* pSfrOrig, const ISurfFlatRegion* pSfrChunk, + const PocketParams& PockParams, int nReg, ICRVCOMPOPOVECTOR& vCrvOrig) +{ + + /* + NB. La superficie da lavorare è stata estesa presso i lati aperti; cerco il Chunk + di riferimento sulla superficie originale ed estraggo le sue curve ( in prima posizione + il loop esterno e a seguire le isole); queste curve verranno utilizzate per la scelta + dei casi ottimizzati ( trapezi, circonferenze, ecc ecc..) + */ + + // controllo dei parametri + if ( pSfrOrig == nullptr || ! pSfrOrig->IsValid() || + pSfrChunk == nullptr || ! pSfrChunk->IsValid()) + return false ; + + // se la superficie originale ha un solo Chunk, allora le curve originali sono già trovate + for ( int l = 0 ; l < pSfrOrig->GetLoopCount( 0) ; ++ l) + vCrvOrig.emplace_back( ConvertCurveToComposite( pSfrOrig->GetLoop( 0, l))) ; + if ( pSfrOrig->GetChunkCount() == 1) + return true ; + + // vettore di indici dei chunk candidati + INTVECTOR vInds ; + + // scorro tutti i Chunk della superficie orginaria + for ( int c = 0 ; c < int( pSfrOrig->GetChunkCount()) ; ++ c) { + // la classificazione può essere fatta semplicemente guardando il Loop esterno + PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrOrig->GetLoop( c, 0))) ; + if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid()) + return false ; + // classifico il Chunk attuale con la curva in esame + CRVCVECTOR ccClass ; + if ( pSfrChunk->GetCurveClassification( *pCrvExtLoop, EPS_SMALL, ccClass)) { + // se il Chunk attuale è stato esteso presso presso i lati aperti mi aspetto che esso non sia più + // grande del chunk originale ( se non ci sono lati aperti, allora coincide ) + // se il ccClass non contiene parti classificate come esterne allora il Chunk di riferimento è il c-esimo + bool bIsThis = true ; + for ( int k = 0 ; k < int( ccClass.size()) && bIsThis ; ++ k) { + if ( ccClass[k].nClass == CRVC_OUT) + bIsThis = false ; + } + if ( bIsThis) + vInds.push_back( c) ; + } + } + // se ho un solo indice allora ho già identificato le curve originali + if ( int( vInds.size()) == 1) { + vCrvOrig.clear() ; + for ( int l = 0 ; l < pSfrOrig->GetLoopCount( vInds[0]) ; ++ l) + vCrvOrig.emplace_back( ConvertCurveToComposite( pSfrOrig->GetLoop( vInds[0], l))) ; + return true ; + } + // altrimenti... + /* + NB. Come parametro alla funzione è stato passato "nReg"; Facendo il primo Offset del Chunk attuale + questo verrà diviso in n sottoregioni; devo considerare la nReg-esima + Situazione: Estendendo presso i lati aperti, due ( o più) chunk si sono uniti formandone uno unico + Quando effettuo il primo offset ( del diametro del materiale + offset radiale), questo Chunk si splitterà in n Chunk; + Uno ( o più) di questi nuovi chunk potrebbe corrispondere ad un caso ottimizzato. + Devo recuperare il Chunk della superficie originaria ( che non essendo estesa presso i lati aperti + ha la geomtria originale) + */ + + // effettuo un Offset del Chunk per simulare la creazione degli n Chunks + double dOffs = PockParams.dRad + PockParams.dRadialOffset ; + PtrOwner pSfrRefChunk( pSfrChunk->Clone()) ; + if ( IsNull( pSfrRefChunk) || + ! pSfrRefChunk->Offset( - dOffs, ICurve::OFF_FILLET)) + return false ; + + // clono il Chunk nReg-esimo se esiste + pSfrRefChunk.Set( pSfrRefChunk->CloneChunk( nReg)) ; + if ( IsNull( pSfrRefChunk)) + return true ; // bisogna passare al ( pSfrChunk + 1)-esimo se esiste + + // scorro tutti i Chunk della superficie orginaria e ripeto la classificazione + // NB. Questa volta posso fermarmi al primo Chunk classificato come non esterno + for ( int c = 0 ; c < int( pSfrOrig->GetChunkCount()) ; ++ c) { + // come prima recupero il Loop esterno + PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrOrig->GetLoop( c, 0))) ; + if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid()) + return false ; + // classificazione + CRVCVECTOR ccClass ; + if ( pSfrRefChunk->GetCurveClassification( *pCrvExtLoop, EPS_SMALL, ccClass)) { + bool bIsThis = true ; + for ( int k = 0 ; k < int( ccClass.size()) && bIsThis ; ++ k) { + if ( ccClass[k].nClass == CRVC_OUT) + bIsThis = false ; + } + if ( bIsThis) { + vCrvOrig.clear() ; + for ( int l = 0 ; l < pSfrOrig->GetLoopCount( c) ; ++ l) + vCrvOrig.emplace_back( ConvertCurveToComposite( pSfrOrig->GetLoop( c, l))) ; + return true ; // esco + } + } + } + + return true ; // alla peggio non considero casi ottimizzati e svuoto normalmente... + +} + //---------------------------------------------------------------------------- static bool ModifyCurveToSmoothed( ICurveComposite* pCrv, const PocketParams& PockParams, double dRightLen, double dLeftLen, bool bAsParam) @@ -5297,69 +5443,6 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int if ( IsNull( pSrfToWork) || pSrfToWork->GetChunkCount() == 0) return false; - // ---------------------------------- Casi ottimizzati ---------------------------------- - bool bHasIsland = ( pSrfPock->GetLoopCount( 0) > 1) ; - // se non ho isole e curva valida allora controllo casi ottimizzati - if ( ! PockParams.bAvoidOpt && ! bHasIsland && - ( ! vCrvOrigChunkLoops.empty()) && ! IsNull( vCrvOrigChunkLoops[0])) { - // --------------------------- caso spirale --------------------------------------- - PtrOwner pCrvBorder( ConvertCurveToComposite( pSrfPock->GetLoop( 0, 0))) ; - if ( IsNull( pCrvBorder) || ! pCrvBorder->IsValid()) - return false ; - pCrvBorder->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; - pCrvBorder->SetExtrusion( pSrfPock->GetNormVersor()) ; // setto l'estrusione della curva - Vector3d vtN = pSrfPock->GetNormVersor() ; // vettore normale per caso circonferenza - Point3d ptCen ; double dRad ; - bool bIsCircle = false ; - if ( ! OptimizedSpiralCirle( pCrvBorder, 50 * EPS_SMALL, dRad, ptCen, bIsCircle)) - return false ; - if ( bIsCircle && dRad - dOffs > 10 * EPS_SMALL) { - double dIntRad = 0 ; - if ( nReg == 0) { - bool bOk = CalcCircleSpiral( ptCen, vtN, dRad - dOffs, dIntRad, PockParams, pMCrv) ; - if ( bOk) { - pMCrv->GetStartPoint( ptStart) ; - for ( int u = 0 ; u < pCrvBorder->GetCurveCount() ; ++ u) { - if ( pCrvBorder->GetCurve( u)->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { - bMidOut = true ; - pMCrv->GetStartDir( vtMidOut) ; - vtMidOut.Rotate( pSrfPock->GetNormVersor(), PockParams.bInvert ? ANG_RIGHT : - ANG_RIGHT) ; - break ; - } - } - nReg = 1 ; - return true ; - } - else - return false ; - } - else - return true ; - } - // -------------------------- caso trapezoide --------------------------------------- - PtrOwner pCrvTrap( CreateCurveComposite()) ; - if ( IsNull( pCrvTrap)) - return false ; - Frame3d frTrap ; - double dPocketSize ; - int nBase, nSecondBase ; - if ( ! GetTrapezoidFromShape( vCrvOrigChunkLoops[0], pCrvTrap, frTrap, PockParams, dPocketSize, nBase, nSecondBase)) - return false ; - if ( pCrvTrap->IsValid()) { - pCrvTrap->SetExtrusion( Z_AX) ; - if ( nReg == 0) { - CalcTrapezoidSpiral( pCrvTrap, frTrap, dPocketSize, nBase, nSecondBase, PockParams, pMCrv, bOptimizedTrap) ; - if ( bOptimizedTrap) { - nReg = 1 ; - return true ; - } - } - else - return true ; - } - - } - // ciclo di offset verso l'interno const int MAX_ITER = 1000 ; int nIter = 0 ; @@ -6652,11 +6735,9 @@ GetSfrByOpenEdgeExtension( const ISurfFlatRegion* pSfrOrig, PocketParams& PockPa PockParams.nOffsType = nOffsType ; // estensine presso i lati aperti - ICRVCOMPOPOVECTOR vCrvEmpty ; - bool bSkipPocket ; pSfrExtended->CopyFrom( pSfrOrig) ; if ( pSfrExtended == nullptr || ! pSfrExtended->IsValid() || - ! ModifySurfByOpenEdges( pSfrExtended, PockParams, false, vCrvEmpty, bSkipPocket)) + ! ModifySurfByOpenEdges( pSfrExtended, PockParams)) return false ; // riporto i parametri originari @@ -8043,7 +8124,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double ! myParams.frLocXY.Rotate( ptCenter, pSfr->GetNormVersor() , myParams.dAngle)) return false ; - // porto la superficie da svuotare in tale sistema + // porto la superficie da svuotare nel sistema di riferimento lungo Z_AX PtrOwner pSfrAdj( pSfr->Clone()) ; if ( IsNull( pSfrAdj) || ! pSfrAdj->ToLoc( myParams.frLocXY)) return false ; @@ -8053,52 +8134,74 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double // porto il punto iniziale di riferimento ( se valido) in tale sistema if ( myParams.ptStart.IsValid()) myParams.ptStart.ToLoc( myParams.frLocXY) ; - - // ------------ gestione dei lati aperti ------------------- - // modifico la superficie da svuotare estendendo i lati aperti - bool bSkipPocket = false ; // se la superficie si svuota mediante curve singole di primo Offset dei chiusi - if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams, true, vCrvCompoRes, bSkipPocket)) + // controllo se esistono supercicie tutta chiusa o tutta aperta + if ( ! IsSfrAllHomogeneous( pSfr, myParams.bAllClosed, myParams.bAllOpen)) return false ; - // se le curve di primo offset che ho ottenuto, svuotano tutta la superficie, allora ho finito - if ( bSkipPocket) { - // riporto le curve in Globale - for ( int i = 0 ; i < int( vCrvCompoRes.size()) ; ++ i) - vCrvCompoRes[i]->ToGlob( myParams.frLocXY) ; - return true ; + + // ------------ recupero le singole curve di svuotatura ------------------- + ICRVCOMPOPOVECTOR vCrvSingleCurves ; + if ( ! GetSinglePocketingCurves( pSfrAdj, myParams, vCrvSingleCurves)) + return false ; + for ( int i = 0 ; i < int( vCrvSingleCurves.size()) ; ++ i) { + vCrvSingleCurves[i]->ToGlob( myParams.frLocXY) ; + vCrvCompoRes.emplace_back( Release( vCrvSingleCurves[i])) ; } + // se ho svuotato tutta la superficie, allora ho finito + if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) + return true ; + + // ------------ casi ottimizzati ------------------------------------------ + ICRVCOMPOPOVECTOR vCrvOptCurves ; + if ( ! GetPocketingOptimizedCurves( pSfrAdj, myParams, vCrvOptCurves)) + return false ; + for ( int i = 0 ; i < int( vCrvOptCurves.size()) ; ++ i) { + vCrvOptCurves[i]->ToGlob( myParams.frLocXY) ; + vCrvCompoRes.emplace_back( Release( vCrvOptCurves[i])) ; + } + // se ho svuotato tutta la superficie, allora ho finito + if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) + return true ; + + // ------------ estensione lati aperti ------------------------------------ + if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams)) + return false ; + // porto una copia della superficie originale nel frame creato PtrOwner pSfr_Loc( CloneSurfFlatRegion( pSfr)) ; if ( IsNull( pSfr_Loc) || ! pSfr_Loc->IsValid() || ! pSfr_Loc->ToLoc( myParams.frLocXY)) return false ; // ------------ calcolo delle curve elementari della superficie ------------------- + ICRVCOMPOPOVECTOR vCrvCompoPock ; switch ( nType) { case POCKET_ZIGZAG : - if ( ! AddZigZag( pSfrAdj, pSfr_Loc, myParams, vCrvCompoRes)) + if ( ! AddZigZag( pSfrAdj, pSfr_Loc, myParams, vCrvCompoPock)) return false ; break ; case POCKET_ONEWAY : - if ( ! AddOneWay( pSfrAdj, pSfr_Loc, myParams, vCrvCompoRes)) + if ( ! AddOneWay( pSfrAdj, pSfr_Loc, myParams, vCrvCompoPock)) return false ; break ; case POCKET_SPIRALIN : - if ( ! AddSpiralIn( pSfrAdj, pSfr_Loc, myParams, vCrvCompoRes)) + if ( ! AddSpiralIn( pSfrAdj, pSfr_Loc, myParams, vCrvCompoPock)) return false ; break ; case POCKET_SPIRALOUT : - if ( ! AddSpiralOut( pSfrAdj, pSfr_Loc, myParams, vCrvCompoRes)) + if ( ! AddSpiralOut( pSfrAdj, pSfr_Loc, myParams, vCrvCompoPock)) return false ; break ; case POCKET_CONFORMAL_ZIGZAG : case POCKET_CONFORMAL_ONEWAY : - if ( ! AddConformal( pSfrAdj, pSfr_Loc, myParams, vCrvCompoRes)) + if ( ! AddConformal( pSfrAdj, pSfr_Loc, myParams, vCrvCompoPock)) return false ; break ; } // riporto tutte le curve ottenute in globale - for ( int i = 0 ; i < int( vCrvCompoRes.size()) ; ++ i) - vCrvCompoRes[i]->ToGlob( myParams.frLocXY) ; + for ( int i = 0 ; i < int( vCrvCompoPock.size()) ; ++ i) { + vCrvCompoPock[i]->ToGlob( myParams.frLocXY) ; + vCrvCompoRes.emplace_back( Release( vCrvCompoPock[i])) ; + } return true ; } From dc070c45562dc2485381d8da118d5892a8e1a875 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 23 Sep 2024 13:01:07 +0200 Subject: [PATCH 07/13] EgtgeomKernel : - aggiunta funzione GetLoopCurveCount a FlatRegion. --- SurfFlatRegion.cpp | 13 +++++++++++++ SurfFlatRegion.h | 1 + 2 files changed, 14 insertions(+) diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index 844e0cc..503198b 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -1166,6 +1166,19 @@ SurfFlatRegion::GetLoop( int nChunk, int nLoop) const return pCrv ; } +//---------------------------------------------------------------------------- +int +SurfFlatRegion::GetLoopCurveCount( int nChunk, int nLoop) const +{ + // recupero il loop nel riferimento intrinseco + const ICurve* pMyCrv = GetMyLoop( nChunk, nLoop) ; + if ( pMyCrv == nullptr) + return 0 ; + // restituisco il numero di curve di cui è composto + const ICurveComposite* pMyCompo = GetCurveComposite( pMyCrv) ; + return ( pMyCompo == nullptr ? 1 : pMyCompo->GetCurveCount()) ; +} + //---------------------------------------------------------------------------- bool SurfFlatRegion::ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index be42bea..70b865e 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -109,6 +109,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ; int GetLoopCount( int nChunk) const override ; + int GetLoopCurveCount( int nChunk, int nLoop) const override ; ICurve* GetLoop( int nChunk, int nLoop) const override ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni) bool ApproxLoopWithLines( int nChunk, int nLoop, double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const override ; bool SetCurveTempProp( int nChunk, int nLoop, int nCrv, int nProp, int nPropInd = 0) override ; From 4ffb7087bdb5add6a7be8aaa3911245fb231b492 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 26 Sep 2024 12:22:51 +0200 Subject: [PATCH 08/13] EgtGeomKernel : - In CalcPocketing, migliorati i percorsi Conformal. --- CalcPocketing.cpp | 332 +++++++++++++++++++++++++++++++--------------- 1 file changed, 224 insertions(+), 108 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 61ec038..6c75003 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -6750,7 +6750,7 @@ GetSfrByOpenEdgeExtension( const ISurfFlatRegion* pSfrOrig, PocketParams& PockPa //---------------------------------------------------------------------------- static bool SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink, - const PocketParams& PockParams, bool bSmoothLeft, bool bSmoothRight, double dSmoothPar, double dTol) + const PocketParams& PockParams, bool bFirstOffs0, bool bFirstOffs1, double dSmoothPar, double dTol) { // controllo dei parametri @@ -6758,17 +6758,12 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve pCrvOffs1 == nullptr || ! pCrvOffs1->IsValid() || pCrvLink == nullptr || ! pCrvLink->IsValid()) return false ; - - /* - - Data la curva di Link, come prima cosa aggiungo l'ultima curva dell'Offset precedente - e la prima curva dell'Offset successivo. - - Effettuo lo Smusso del Link - - Rimvuovo la prima e l'ultima curva del Link smussato ( Gli estremi del link non vengono - modificati durante l'operazione di smusso - */ - // curva precedente e successiva - PtrOwner pCrvBef( pCrvOffs0->GetLastCurve()->Clone()) ; + PtrOwner pCrvBef ; + if ( bFirstOffs0 && pCrvOffs0->IsClosed()) + pCrvBef.Set( pCrvOffs0->GetFirstCurve()->Clone()) ; + else + pCrvBef.Set( pCrvOffs0->GetLastCurve()->Clone()) ; PtrOwner pCrvAft( pCrvOffs1->GetFirstCurve()->Clone()) ; if ( IsNull( pCrvBef) || IsNull( pCrvAft) || ! pCrvBef->IsValid() || ! pCrvAft->IsValid()) @@ -6782,16 +6777,19 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve pCrvLink->RemoveFirstOrLastCurve( false) ; pCrvLink->RemoveFirstOrLastCurve( true) ; // modifico Offset0 per raccordarlo al nuovo Link - Point3d ptS ; pCrvLink->GetStartPoint( ptS) ; - double dUE ; pCrvOffs0->GetParamAtPoint( ptS, dUE, dTol) ; - if ( ! bSmoothLeft && pCrvOffs0->IsClosed()) - pCrvOffs0->ChangeStartPoint( dUE) ; - else + if ( bFirstOffs0 && pCrvOffs0->IsClosed()) { + pCrvOffs0->AddCurve( pCrvLink->GetFirstCurve()->Clone()) ; + pCrvLink->RemoveFirstOrLastCurve( false) ; + } + else { + Point3d ptS ; pCrvLink->GetStartPoint( ptS) ; + double dUE ; pCrvOffs0->GetParamAtPoint( ptS, dUE, dTol) ; pCrvOffs0->TrimEndAtParam( dUE) ; + } // modifico Offset1 per raccordarlo al nuovo Link Point3d ptE ; pCrvLink->GetEndPoint( ptE) ; double dUS ; pCrvOffs1->GetParamAtPoint( ptE, dUS, dTol) ; - if ( ! bSmoothRight && pCrvOffs1->IsClosed()) + if ( bFirstOffs1 && pCrvOffs1->IsClosed()) pCrvOffs1->ChangeStartPoint( dUS) ; else pCrvOffs1->TrimStartAtParam( dUS) ; @@ -6849,7 +6847,7 @@ GetConformalLinkForOpenCrv( const ICurveComposite* pCrvOffs0, const ICurveCompos //---------------------------------------------------------------------------- static bool GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams, - const ICRVCOMPOPOVECTOR& vCrvClassBorder, const ICRVCOMPOPOVECTOR& vCrvExtendedBorders, + const ICRVCOMPOPOVECTOR& vCrvClassBorder, const ICRVCOMPOPOVECTOR& vCrvExtendedBorders, ICurveComposite* pCrvLink) { // controllo validità delle due curve di Offset @@ -6870,7 +6868,7 @@ GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocket return false ; // smusso il Link raccordandolo if ( pCrvLink->IsValid()) - SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, true, true, PockParams.dRad / 8., TOL) ; + SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, false, false, PockParams.dRad / 8., TOL) ; } else { // clono le due curve di Offset @@ -6905,7 +6903,7 @@ GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocket return false ; } PockParams.bSmooth = bSmooth ; - SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, ! bFirstIterOffs0, ! bFirstIterOffs1, + SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, bFirstIterOffs0, bFirstIterOffs1, PockParams.dRad / 16., TOL) ; // per sicurezza aggiorno i nuovi punti e i nuovi parametri double dUNewE ; @@ -7302,47 +7300,9 @@ ModifyConformalStartPoint( ICurveComposite* pCrvFirst, const PocketParams& PockP //---------------------------------------------------------------------------- static bool -CalcConformalOneWayOffs( VICRVCOMPOPOVECTOR& vvCrvOffs, const PocketParams& PockParams, - const ISurfFlatRegion* pSfrPock, ICRVCOMPOPOVECTOR& vCrvOffs) -{ - // pulizia del vettore degli Offset - vCrvOffs.clear() ; - - // inverto il vettore degli Offset, in modo da partire dalle curve più distanti dai chiusi - reverse( vvCrvOffs.begin(), vvCrvOffs.end()) ; - - // determino il punto iniziale della prima curva di Offset - if ( ! ModifyConformalStartPoint( vvCrvOffs[0][0], PockParams, pSfrPock)) - return false ; - - // le curve di Offset vengono riodinate in base alla loro iterazione nel vettore - for ( int i = 0 ; i < int( vvCrvOffs.size()) ; ++ i) { - for ( int j = 0 ; j < int( vvCrvOffs[i].size()) ; ++ j) { - // se la curva corrente è chiusa, cambio il punto iniziale rispetto alla curva precedente - if ( vvCrvOffs[i][j]->IsClosed()) { - if ( ! vCrvOffs.empty()) { - // ricavo il punto finale della curva precedente - Point3d ptEndPrec ; vCrvOffs.back()->GetEndPoint( ptEndPrec) ; - DistPointCurve DistPtCrv( ptEndPrec, *vvCrvOffs[i][j]) ; - double dParS ; - int nFlag ; - // cambio il punto inziale della curva corrente - if ( DistPtCrv.GetParamAtMinDistPoint( 0, dParS, nFlag)) - vvCrvOffs[i][j]->ChangeStartPoint( dParS) ; - } - } - vCrvOffs.emplace_back( Release( vvCrvOffs[i][j])) ; - } - } - - return true ; -} - -//---------------------------------------------------------------------------- -static bool -CalcConformalZigZagOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatRegion* pSfrChunk, - const ISurfFlatRegion* pSfrClass, PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvOffs, - ICURVEPOVECTOR& vCrvLink) +CalcConformalOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatRegion* pSfrChunk, + const ISurfFlatRegion* pSfrClass, PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvOffs, + ICURVEPOVECTOR& vCrvLink) { // controllo dei parametri if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid() || @@ -7373,21 +7333,21 @@ CalcConformalZigZagOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatR if ( ! ModifyConformalStartPoint( vvCrvOffs[0][0], PockParams, pSfrChunk)) return false ; - /* NB. - I link che collegano due curve di Offset aperte devono partire dalla prima e, seguendo il - bordo della regione di classificazione ( pSfrClass) arrivano alla seconda. - */ - ICRVCOMPOPOVECTOR vCrvSfrClass ; - if ( ! GetSfrCrvCompoLoops( pSfrClass, vCrvSfrClass)) - return false ; - /* NB. - I link che collegano due curve di Offset chiuse tra di loro vengono calcolati esattamente - come per i percorsi SPIRAL, pertanto devo definire un insieme di curve di primo Offset sui - quali smussare i Link per evitare di uscire dalla regione di svuotatura - */ - ICRVCOMPOPOVECTOR vCrvSfrExtended ; - if ( ! GetConformalBordersCrvs( pSfrChunk, PockParams, vCrvSfrExtended)) - return false ; + /* NB. + I link che collegano due curve di Offset aperte devono partire dalla prima e, seguendo il + bordo della regione di classificazione ( pSfrClass) arrivano alla seconda. + */ + ICRVCOMPOPOVECTOR vCrvSfrClass ; + if ( ! GetSfrCrvCompoLoops( pSfrClass, vCrvSfrClass)) + return false ; + /* NB. + I link che collegano due curve di Offset chiuse tra di loro vengono calcolati esattamente + come per i percorsi SPIRAL, pertanto devo definire un insieme di curve di primo Offset sui + quali smussare i Link per evitare di uscire dalla regione di svuotatura + */ + ICRVCOMPOPOVECTOR vCrvSfrExtended ; + if ( ! GetConformalBordersCrvs( pSfrChunk, PockParams, vCrvSfrExtended)) + return false ; /* NB. Se POCKET_CONFORMAL_ZIGZAG : - vCrvCompoOffs contiene gli Offset ordinati @@ -7425,25 +7385,29 @@ CalcConformalZigZagOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatR return true ; // ------------ Definisco i Link ------------ - // per definizione il primo Link è nullo - vCrvLink.resize( 1) ; - // scorro le curve di Offset a coppie - for ( int i = 0 ; i < int( vCrvOffs.size()) - 1 ; ++ i) { - // controllo se bisogna calcolare il Link tra i due Offset - bool bCalcLink = true ; - if ( ! CheckConformalRetractLink( vCrvOffs[i], vCrvOffs[i+1], vCrvSfrClass, PockParams, bCalcLink)) - return false ; - if ( bCalcLink) { - // se link da calcolare, lo ricavo - PtrOwner pCrvLink( CreateCurveComposite()) ; - if ( IsNull( pCrvLink) || - ! GetConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, vCrvSfrExtended, pCrvLink)) - return false ; - // lo salvo nel vettore dei Link - vCrvLink.emplace_back( Release( pCrvLink)) ; + if ( PockParams.nType == POCKET_CONFORMAL_ONEWAY) + vCrvLink.resize( vCrvOffs.size()) ; + else { + // per definizione il primo Link è nullo + vCrvLink.resize( 1) ; + // scorro le curve di Offset a coppie + for ( int i = 0 ; i < int( vCrvOffs.size()) - 1 ; ++ i) { + // controllo se bisogna calcolare il Link tra i due Offset + bool bCalcLink = true ; + if ( ! CheckConformalRetractLink( vCrvOffs[i], vCrvOffs[i+1], vCrvSfrClass, PockParams, bCalcLink)) + return false ; + if ( bCalcLink) { + // se link da calcolare, lo ricavo + PtrOwner pCrvLink( CreateCurveComposite()) ; + if ( IsNull( pCrvLink) || + ! GetConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, vCrvSfrExtended, pCrvLink)) + return false ; + // lo salvo nel vettore dei Link + vCrvLink.emplace_back( Release( pCrvLink)) ; + } + else + vCrvLink.resize( int( vCrvLink.size()) + 1) ; } - else - vCrvLink.resize( int( vCrvLink.size()) + 1) ; } return true ; @@ -7590,6 +7554,166 @@ AddLeadInToCurveConformalPaths( const ISurfFlatRegion* pSfrOrig, const ISurfFlat return true ; } +//---------------------------------------------------------------------------- +static bool +OrderConformalPaths( ICRVCOMPOPOVECTOR& vCrvPaths, const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pSfrOrig, + PocketParams& PockParams) +{ + // controllo dei parametri + if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid() || + pSfrOrig == nullptr || ! pSfrOrig->IsValid()) + return false ; + if ( int( vCrvPaths.size()) < 2) + return true ; + + // superficie di controllo per parti isolate + PtrOwner pSfrToRemove( CloneSurfFlatRegion( pSfrChunk)) ; + if ( IsNull( pSfrToRemove) || ! pSfrToRemove->IsValid() || + ! pSfrToRemove->Intersect( *pSfrOrig)) + return false ; + + // creo le regioni piane di svuotatura dei percorsi + ISURFFRPOVECTOR vSfrRemoved ; vSfrRemoved.resize( vCrvPaths.size()) ; + for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) { + // creo la regione di svuotatura di tale percorso + vSfrRemoved[i].Set( GetSurfFlatRegionFromFatCurve( CloneCurveComposite( vCrvPaths[i]), PockParams.dRad, false, false)) ; + if ( IsNull( vSfrRemoved[i]) || ! vSfrRemoved[i]->IsValid()) + return false ; + } + + // scorro i percorsi ricavati + INTVECTOR vInds ; vInds.resize( vCrvPaths.size(), -1) ; + int nChunkRef = pSfrToRemove->GetChunkCount() ; + for ( int i = 0 ; i < int( vInds.size()) ; ++ i) { + int j = 0 ; + INTVECTOR vTempInds ; + for ( ; j < int( vCrvPaths.size()) ; ++ j) { + // se indice già presente + if ( find( vInds.begin(), vInds.end(), j) != vInds.end()) + continue ; + // se sottraendo questa regione a quella originale ottengo più isole, allora non è il percorso ideale + PtrOwner pSfrRemain( CloneSurfFlatRegion( pSfrToRemove)) ; + if ( IsNull( pSfrRemain) || ! pSfrRemain->IsValid()) + continue ; + pSfrRemain->Subtract( *vSfrRemoved[j]) ; + // se aumento il numero di Chunk, allora non è il percorso ideale + if ( pSfrRemain->GetChunkCount() > nChunkRef) + continue ; + vTempInds.push_back( j) ; + } + if ( vTempInds.empty()) { + // se non ho trovato curva candidate, prendo l'indice disponibile più basso + for ( int k = 0 ; k < int( vInds.size()) ; ++ k) { + if ( find( vInds.begin(), vInds.end(), k) != vInds.end()) + continue ; + vInds[i] = k ; + break ; + } + } + else if ( int( vTempInds.size()) == 1) { + // se la candidata è singola, allora è lei + vInds[i] = vTempInds[0] ; + if ( PockParams.nType == POCKET_CONFORMAL_ONEWAY) { + if ( vCrvPaths[vInds[i]]->IsClosed() && i > 0) { + Point3d ptS ; vCrvPaths[vInds[i-1]]->GetStartPoint( ptS) ; + DistPointCurve DistCalculator( ptS, *vCrvPaths[vInds[i]]) ; + int nFlag ; double dUS ; + DistCalculator.GetParamAtMinDistPoint( 0, dUS, nFlag) ; + vCrvPaths[vInds[i]]->ChangeStartPoint( dUS) ; + } + } + } + else { + // se lavorazione conformal ZigZag + if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) { + // se ne ho trovate di più, allora euristicamente prendo la più corta + double dMinLen = INFINITO ; + for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) { + // privilegio le aperte + if ( vCrvPaths[vTempInds[k]]->IsClosed()) + continue ; + double dLen ; vCrvPaths[vTempInds[k]]->GetLength( dLen) ; + if ( dLen < dMinLen) { + dMinLen = dLen ; + vInds[i] = vTempInds[k] ; + } + } + // cerco solo tra le chiuse se non ho aperte + if ( dMinLen > INFINITO - 1) { + for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) { + if ( vCrvPaths[vTempInds[k]]->IsClosed()) { + double dLen ; vCrvPaths[vTempInds[k]]->GetLength( dLen) ; + if ( dLen < dMinLen) { + dMinLen = dLen ; + vInds[i] = vTempInds[k] ; + } + } + } + } + } + // se lavorazione conformal OneWay + else { + // se ne ho trovate di più, cerco euristicamente la più vicina al punto iniziale della curva + // se prima in assoluto, allora prendo la più corta + if ( i == 0) { + double dMinLen = INFINITO ; + for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) { + double dLen ; vCrvPaths[vTempInds[k]]->GetLength( dLen) ; + if ( dLen < dMinLen) { + dMinLen = dLen ; + vInds[i] = vTempInds[k] ; + } + } + } + // altrimenti + else { + double dSqMinDist = INFINITO ; + Point3d ptS ; vCrvPaths[vInds[i-1]]->GetStartPoint( ptS) ; + Point3d ptTmpS ; + for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) { + if ( vCrvPaths[vTempInds[k]]->IsClosed()) + continue ; + vCrvPaths[vTempInds[k]]->GetStartPoint( ptTmpS) ; + double dMyDist = SqDist( ptS, ptTmpS) ; + if ( dMyDist < dSqMinDist) { + dSqMinDist = dMyDist ; + vInds[i] = vTempInds[k] ; + } + } + if ( dSqMinDist > INFINITO - 1) { + for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) { + if ( vCrvPaths[vTempInds[k]]->IsClosed()) { + DistPointCurve DistCalculator( ptS, *vCrvPaths[vTempInds[k]]) ; + double dMySqDist ; + DistCalculator.GetSqDist( dMySqDist) ; + if ( dMySqDist < dSqMinDist) { + dSqMinDist = dMySqDist ; + vInds[i] = vTempInds[k] ; + double dUS ; + int nFlag ; + DistCalculator.GetParamAtMinDistPoint( 0, dUS, nFlag) ; + vCrvPaths[vTempInds[k]]->ChangeStartPoint( dUS) ; + } + } + } + } + } + } + } + // aggiorno la regione da svuotare e il numero di Chunk che si sono formati + pSfrToRemove->Subtract( *vSfrRemoved[vInds[i]]) ; + nChunkRef = pSfrToRemove->GetChunkCount() ; + } + + // riordino i percorsi trovati + ICRVCOMPOPOVECTOR vCrvOrderedPaths ; vCrvOrderedPaths.resize( vCrvPaths.size()) ; + for ( int i = 0 ; i < int( vInds.size()) ; ++ i) + vCrvOrderedPaths[i].Set( vCrvPaths[vInds[i]]) ; + swap( vCrvOrderedPaths, vCrvPaths) ; + + return true ; +} + //---------------------------------------------------------------------------- static bool ChainConformalOffsWithLinks( ICRVCOMPOPOVECTOR& vCrvOffs, ICURVEPOVECTOR& vCrvLink, @@ -8053,20 +8177,9 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, // definisco vettore degli Offset e dei Link ICRVCOMPOPOVECTOR vCrvOffs ; ICURVEPOVECTOR vCrvLink ; - // se lavorazione CONFORMAL_ZIGZAG - if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) { - // ordino le curve di Offset e raccordo - if ( ! CalcConformalZigZagOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrClassChunk, PockParams, vCrvOffs, vCrvLink)) - return false ; - } - // se lavorazione CONFORMAL_ONEWAY - else if ( PockParams.nType == POCKET_CONFORMAL_ONEWAY) { - // ordino le curve di Offset - if ( ! CalcConformalOneWayOffs( vvCrvOffs, PockParams, pSfrChunk, vCrvOffs)) - return false ; - // i Link non esistono - vCrvLink.resize( int( vCrvOffs.size())) ; - } + // ordino le curve di Offset e raccordo + if ( ! CalcConformalOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrClassChunk, PockParams, vCrvOffs, vCrvLink)) + return false ; // estendo i percorsi per eventuali regioni non svuotate e calcolo le Feed if ( ! ExtendConformalOffsAndSetFeed( pSfrPock, PockParams, vCrvOffs, vCrvLink)) return false ; @@ -8077,6 +8190,9 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, // estendo i percorsi per entrate/uscite dai lati aperti if ( ! AddLeadInToCurveConformalPaths( pSfrOrig, pSfrChunk, PockParams, vCrvPaths)) return false ; + // ordino i percorsi trovati + if ( ! OrderConformalPaths( vCrvPaths, pSfrChunk, pSfrOrig, PockParams)) + return false ; // aggiungo i percorsi ricavati for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) vCrvCompoRes.emplace_back( Release( vCrvPaths[i])) ; From 0c0eb9ef8f1e4e95f3a3792617f5067b579d64fa Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Thu, 26 Sep 2024 19:58:03 +0200 Subject: [PATCH 09/13] EgtGeomKernel 2.6i2 : - 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 6a843062d12627d4d3853a7a47f533d30cb3c138..a8155acdd449fad07e2799d460119623513d0cb1 100644 GIT binary patch delta 94 zcmdlNy)SyhFE&P_&A-_cnHh~HD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-Vf-5U delta 94 zcmdlNy)SyhFE&QQ&A-_cnHdcyD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-U|t&X From 8f8597d442fbe510c4f2462906446a23e204166a Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 1 Oct 2024 12:41:15 +0200 Subject: [PATCH 10/13] EgtGeomKernel : - In CalcPocketing, piccola modifica in lavorazioni Conformal. --- CalcPocketing.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 6c75003..3fa3f19 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -8128,9 +8128,6 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, if ( IsNull( pSfrClass) || ! pSfrClass->IsValid()) return false ; - // recupero la dimensione del vettore delle curve da resituire ( nel caso dovessi lavorare in SPIRAL_IN) - int nDim = int( vCrvCompoRes.size()) ; - // scorro i chunk della superficie da lavorare for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { // controllo se il Chunk ha tutte proprietà omogenee tra loro @@ -8169,9 +8166,8 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, return false ; // se non ottengo Curve di Offset, lavoro in SpiralIn ( il Chunk ha dei lati aperti) if ( vvCrvOffs.empty()) { - vCrvCompoRes.resize( nDim) ; // pulisco il vettore di curve - // NB. Facendo un offset interno di 3R/4 potrebbero essersi splittati dei Chunks - return ( AddSpiralIn( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ; + if ( ! AddSpiralIn( pSfrChunk, pSfrOrig, PockParams, vCrvCompoRes)) + return false ; } else { // definisco vettore degli Offset e dei Link From a98b6bcc09a707b1c42a025b8e85a85801465f08 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Wed, 2 Oct 2024 13:13:16 +0200 Subject: [PATCH 11/13] EgtGeomKernel : - in CalcPocketing estesi i percorsi OneWay - piccole migliorie su selezione punto iniziale per curve singole. --- CalcPocketing.cpp | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 3fa3f19..6689b35 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -1845,12 +1845,10 @@ GetSinglePocketingCurves( ISurfFlatRegion* pSfr, const PocketParams& PockParams, int nChunks = pSfr->GetChunkCount() ; int nCurrChunk = 0 ; for ( int i = 0 ; i < nChunks ; ++ i) { - // recupero il Chunk corrente PtrOwner pSfrChunk( pSfr->CloneChunk( nCurrChunk)) ; if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) return false ; - // se il Chunk corrente si svuota con curva singola, allora lo rimuovo dalla superficie bool bRemoved = false ; GetPocketCurvesByClosedEdges( pSfrChunk, PockParams, vCrvSingleCurves, bRemoved) ; @@ -1873,7 +1871,27 @@ GetSinglePocketingCurves( ISurfFlatRegion* pSfr, const PocketParams& PockParams, /* Idea : Feed proporzionale al minimo Offset per annullare la regione -> Massimo parametro sui bisettori di VORONOI + se le curve risultano aperte, cambio il loro punto iniziale a seconda dell'estensione fatta */ + if ( vCrvSingleCurves[i]->IsValid() && vCrvSingleCurves[i]->GetCurveCount() != 0 && + ! vCrvSingleCurves[i]->IsClosed()) { + int nTempProp_firstCrv = vCrvSingleCurves[i]->GetFirstCurve()->GetTempProp( 0) ; + int nTempProp_lastCrv = vCrvSingleCurves[i]->GetLastCurve()->GetTempProp( 0) ; + // se estremi entrambi estesi + if ( nTempProp_firstCrv == TEMP_PROP_OUT_START && nTempProp_lastCrv == TEMP_PROP_OUT_START) { + if ( PockParams.ptStart.IsValid()) { + Point3d ptStart ; vCrvSingleCurves[i]->GetStartPoint( ptStart) ; + double dSqDist_first = SqDist( PockParams.ptStart, ptStart) ; + Point3d ptEnd ; vCrvSingleCurves[i]->GetEndPoint( ptEnd) ; + double dSqDist_last = SqDist( PockParams.ptStart, ptEnd) ; + if ( dSqDist_last < dSqDist_first) + vCrvSingleCurves[i]->Invert() ; + } + } + // se invece l'estensione è alla fine + else if ( nTempProp_lastCrv == TEMP_PROP_OUT_START) + vCrvSingleCurves[i]->Invert() ; + } // recupero il MaxOffset per la curva double dMaxOffs = vCrvSingleCurves[i]->GetTempParam( 0) ; // calcolo la Feed proporzionale a tale Offset @@ -6704,6 +6722,17 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar pCrvSegCompo->AddCurve( Release( pCrvSeg)) ; // calcolo la Feed AssignFeedZigZagOneWay( pCrvSegCompo, false, vCrvNull, vLineUnder, vCrvCompoNull, PockParams) ; + // estendo presso lati aperti se richiesto + if ( ! PockParams.bAllClosed) { + Vector3d vtRef ; pCrvSegCompo->GetStartDir( vtRef) ; + vtRef.Invert() ; + bool bIsExtended = false ; + if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, false,bIsExtended)) + return false ; + pCrvSegCompo->GetEndDir( vtRef) ; + if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, true, bIsExtended)) + return false ; + } vCrvCompoRes.emplace_back( Release( pCrvSegCompo)) ; } } @@ -8125,8 +8154,10 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, aperti mediante Offset di tipo Chamfer; in questo modo semplifico la classificazione */ PtrOwner pSfrClass( pSfrPock->CreateOffsetSurf( - ( 3. * PockParams.dRad / 4.) - PockParams.dRadialOffset, ICurve::OFF_FILLET)) ; - if ( IsNull( pSfrClass) || ! pSfrClass->IsValid()) - return false ; + if ( IsNull( pSfrClass)) + return false ; + if ( ! pSfrClass->IsValid()) + return true ; // non posso svuotare nulla // scorro i chunk della superficie da lavorare for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { From 0317c375577761337dd5af6fb74aa732bbd4b6d3 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Wed, 2 Oct 2024 17:25:24 +0200 Subject: [PATCH 12/13] EgtGeomKernel 2.6j1 : - piccoli ritocchi a superfici di Bezier. --- EgtGeomKernel.rc | Bin 11710 -> 11718 bytes SurfBezier.cpp | 48 ++++++++++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index a8155acdd449fad07e2799d460119623513d0cb1..87e3278b0294fbaff71dffb82a2f7080365198ce 100644 GIT binary patch delta 126 zcmdlNeJpyzH#T-d1_K5i2E)z2+2om-vlt8~D{|{@_TuVcfy>Wy)SyhH#SyF1|0^Y&G-4vGfl1&(wY2&Q-wK`!DzCguGetEndPoint( pt3DEnd) ; bool bThroughEdge = false ; BOOLVECTOR vbThroughEdge ; - if ( ! UnprojectPoint(pt3D, pt2D, pt3DEnd, &bThroughEdge, pPlCut)) + if ( ! UnprojectPoint( pt3D, pt2D, pt3DEnd, &bThroughEdge, pPlCut)) return false ; vbThroughEdge.push_back( bThroughEdge) ; @@ -2034,7 +2034,7 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& return false ; // se il precedente era passato attraverso l'edge ed era un edge di polo allora devo sistemare le coordinate - if( bPrevIsPole){ + if ( bPrevIsPole) { // se il punto precedente era di polo allora devo correggere le sue coordinate 2D if ( bHorizontalPole) pt2DPrev.x = pt2D.x ; @@ -2045,12 +2045,12 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vtDir.Normalize() ; // se mi accorgo che sto per tracciare un taglio lungo un bordo posso semplicemente evitarlo double dDelta = 10 * EPS_SMALL ; - if ( (1 - abs(vtDir.x) < SQ_EPS_SMALL && (pt2D.y < dDelta || m_nSpanV * SBZ_TREG_COEFF - pt2D.y < dDelta)) || // parallelo agli edge 0 e 2 e su uno di questi - (1 - abs(vtDir.y) < SQ_EPS_SMALL && (pt2D.x < dDelta || m_nSpanU * SBZ_TREG_COEFF - pt2D.x < dDelta))) { // parallello agli edge 1 e 3 e su uno di questi + if ( ( 1 - abs( vtDir.x) < SQ_EPS_SMALL && ( pt2D.y < dDelta || m_nSpanV * SBZ_TREG_COEFF - pt2D.y < dDelta)) || // parallelo agli edge 0 e 2 e su uno di questi + ( 1 - abs( vtDir.y) < SQ_EPS_SMALL && ( pt2D.x < dDelta || m_nSpanU * SBZ_TREG_COEFF - pt2D.x < dDelta))) { // parallello agli edge 1 e 3 e su uno di questi ++ nRejected ; continue ; } - if ( bThroughEdge && vbThroughEdge.back()) { + if ( bThroughEdge && vbThroughEdge.back()) { double dParamH, dParamL ; dParamH = m_nSpanV * SBZ_TREG_COEFF ; dParamL = m_nSpanU * SBZ_TREG_COEFF ; @@ -2058,8 +2058,8 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& // ( i punti per periodicità hanno coordinate diverse anche se dovrebbero averle uguali, quindi il segmento attraversa tutto lo spazio parametrico, anche se in realtà è lungo il bordo di chiusura) // potrei star tracciando un taglio sul bordo di chiusura // controllo se sto tracciando una linea che unisce due lati di chiusura, allora in realtà sdtarei tracciando un taglio sull'edge e quindi posso non tracciarlo - if ( (abs( vtDir.x) > abs( vtDir.y) && Dist( pt2D, pt2DPrev) > dParamL * 0.5) || - (abs( vtDir.y) > abs( vtDir.x) && Dist( pt2D, pt2DPrev) > dParamH * 0.5)) { + if ( ( abs( vtDir.x) > abs( vtDir.y) && Dist( pt2D, pt2DPrev) > dParamL * 0.5) || + ( abs( vtDir.y) > abs( vtDir.x) && Dist( pt2D, pt2DPrev) > dParamH * 0.5)) { ++ nRejected ; continue ; } @@ -2073,12 +2073,14 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& Point3d ptNear ; pCrv0->GetStartPoint( ptNear) ; INTVECTOR vId ; bool bAdded = true ; - while( chainC.GetChainFromNear( pt3D, false, vId)) { + while ( chainC.GetChainFromNear( pt3D, false, vId)) { PtrOwner pCC2D ( CreateCurveComposite()) ; + if ( IsNull( pCC2D)) + return false ; for ( int i = 0 ; i < int( vId.size()) ; ++ i) { // creo un segmento di retta - ICurveLine* pLine( CreateCurveLine()) ; - if ( pLine == nullptr) + PtrOwner pLine( CreateCurveLine()) ; + if ( IsNull( pLine)) return false ; // recupero gli estremi (non vanno mai invertiti per opzione di concatenamento) int nInd = abs( vId[i]) - 1 ; @@ -2086,12 +2088,12 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& Point3d ptEnd = vBPnt[nInd].second ; // provo ad accodarlo alla composita bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 && - pLine->Set( ptStart, ptEnd)) ; - bAdded = bAdded && pCC2D->AddCurve( pLine, true, dToler) ; + pLine->Set( ptStart, ptEnd)) ; + bAdded = bAdded && pCC2D->AddCurve( Release( pLine), true, dToler) ; ptNear = ( bAdded ? ptEnd : ptStart) ; } if ( pCC2D->IsValid()) - vpCC.emplace_back( Release(pCC2D)) ; + vpCC.emplace_back( Release( pCC2D)) ; } return true ; } @@ -2100,31 +2102,31 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& bool SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler, const Plane3d* pPlCut) const { - // se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro e sposto il punto finale nel punto di fine della curva che sto ignorando + // se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro e sposto il punto finale nel punto di fine della curva che sto ignorando double dCrvLen ; if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler) return true ; - // se curva chiusa entro 5 volte la tolleranza ma considerata aperta, la chiudo bene + // se curva chiusa entro 5 volte la tolleranza ma considerata aperta, la chiudo bene Point3d ptStart, ptEnd ; if ( pCrvCompo->GetStartPoint( ptStart) && - pCrvCompo->GetEndPoint( ptEnd) && - AreSamePointEpsilon( ptStart, ptEnd, 5. * dToler) && - ! AreSamePointApprox( ptStart, ptEnd)) { - // porto il punto finale a coincidere esattamente con l'inizio + pCrvCompo->GetEndPoint( ptEnd) && + AreSamePointEpsilon( ptStart, ptEnd, 5 * dToler) && + ! AreSamePointApprox( ptStart, ptEnd)) { + // porto il punto finale a coincidere esattamente con l'inizio pCrvCompo->ModifyEnd( ptStart) ; } - // unisco segmenti allineati + // unisco segmenti allineati pCrvCompo->MergeCurves( 0.5 * dToler, ANG_TOL_STD_DEG) ; - // porto la curva nello spazio parametrico + // porto la curva nello spazio parametrico ICRVCOMPOPVECTOR vCC ; if ( ! UnprojectCurveFromStm( pCrvCompo, vCC, pPlCut)) return false ; for ( int i = 0 ; i < int( vCC.size()); ++i) { - // le curve aperte le tengo da parte per giuntarle alla fine col bordo + // le curve aperte le tengo da parte per giuntarle alla fine col bordo if ( ! vCC[i]->IsClosed() ) vpCCOpen.emplace_back( vCC[i]) ; - // le curve chiuse le metto tutte insieme subito + // le curve chiuse le metto tutte insieme subito else vpCCClosed.emplace_back( vCC[i]) ; } From 9a638b9470fffe20be9e3221b8bc6638d0925862 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Fri, 4 Oct 2024 12:57:20 +0200 Subject: [PATCH 13/13] EgtGeomKernel : - In CalcPocketing corretti errori per casi a trapezio - migliorata la gestione delle curve singole di svuotatura. --- CalcPocketing.cpp | 155 ++++++++++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 75 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 6689b35..8db84a6 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -1706,21 +1706,17 @@ GetPocketCurvesByClosedEdges( const ISurfFlatRegion* pSfrChunk, const PocketPara // scorro i chiusi e sottraggo la regione da loro creata mediante l'utensile // NB. Queste curve sono orientate in maniera corretta ICRVCOMPOPOVECTOR vCrvCompoRes_tmp ; // salvo il vettore di curve offsettate del raggio utensile + Voronoi myVRONI ; for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) { // se tratto chiuso - if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_CLOSE_EDGE) { - OffsetCurve OffsCrv ; // con offset verso l'interno ( è il loop esterno) - if ( OffsCrv.Make( vpCrvs[i], - PockParams.dRad - PockParams.dRadialOffset, ICurve::OFF_FILLET)) { - PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; - while ( ! IsNull( pOffLongestCrv)) { - // salvo la curva corrente - vCrvCompoRes_tmp.emplace_back( ConvertCurveToComposite( Release( pOffLongestCrv))) ; - // passo alla successiva - pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ; - } - } - } + if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_CLOSE_EDGE) + myVRONI.AddCurve( vpCrvs[i]) ; } + // offset delle parti chiuse + ICURVEPOVECTOR vCrvVroniOffs ; + myVRONI.CalcOffset( vCrvVroniOffs, - PockParams.dRad - PockParams.dRadialOffset + EPS_SMALL, ICurve::OFF_FILLET) ; + for ( int i = 0 ; i < int( vCrvVroniOffs.size()) ; ++ i) + vCrvCompoRes_tmp.emplace_back( ConvertCurveToComposite( Release( vCrvVroniOffs[i]))) ; /* Casi gestiti : @@ -2077,8 +2073,8 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams) //---------------------------------------------------------------------------- static bool -OptimizedSpiralCirle( const ICurveComposite* pCrvCompo, const double dToll, double& dRad, - Point3d& ptC, bool& bIsCirlce) +OptimizedSpiralCircle( const ICurveComposite* pCrvCompo, const double dToll, double& dRad, + Point3d& ptC, bool& bIsCirlce) { /* restituisce il centro e il raggio di una circonfereza che approssima pCrvCompo */ @@ -2298,15 +2294,17 @@ PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, const double dDiam int& nSecondBase, bool& bOk, ICurveComposite* pCrvTrap) { // controllo parametri - if ( pCrvCompo == nullptr) + if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid() || + nBase < 0 || nBase >= pCrvCompo->GetCurveCount() || + nSecondBase < 0 || nSecondBase >= pCrvCompo->GetCurveCount()) return false ; bOk = false ; // le parti tra le due basi devono essere tutte omogenee ( o tutte aperte o tutte chiuse) // pCrvTest0 sarà la parte destra, pCrvTest1 la parte sinistra Point3d ptSB0, ptSB1 ,ptEB0, ptEB1 ; - PtrOwner pCrvTest0( pCrvCompo->Clone()) ; - PtrOwner pCrvTest1( pCrvCompo->Clone()) ; + PtrOwner pCrvTest0( CloneCurveComposite( pCrvCompo)) ; + PtrOwner pCrvTest1( CloneCurveComposite( pCrvCompo)) ; pCrvCompo->GetCurve( nBase)->GetStartPoint( ptSB0) ; pCrvCompo->GetCurve( nBase)->GetEndPoint( ptEB0) ; pCrvCompo->GetCurve( nSecondBase)->GetStartPoint( ptSB1) ; @@ -2338,31 +2336,22 @@ PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, const double dDiam // se lato destro aperto ( estendo il punto finale della base principale e il punto iniziale // della base secondaria fino al lato destro del box) bool bCopyRight = false ; - if ( pCrvTest0->GetCurve( 0)->GetTempProp( 0) == 1) { - if ( nType == 0) { - pCrvTrap->GetCurve( 0)->GetStartPoint( ptEB0) ; - pCrvTrap->GetCurve( 1)->GetStartPoint( ptSB1) ; - } - else { - pCrvTrap->GetCurve( 0)->GetEndPoint( ptEB0) ; - pCrvTrap->GetCurve( 1)->GetEndPoint( ptSB1) ; - } + if ( pCrvTest0->GetCurve( 0)->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { + int nCrvRight_ref = ( nType == 0 ? 0 : 1) ; + pCrvTrap->GetCurve( nCrvRight_ref)->GetStartPoint( ptEB0) ; + pCrvTrap->GetCurve( nCrvRight_ref)->GetEndPoint( ptSB1) ; } // se lato destro chiuso else bCopyRight = true ; + // se lato sinistro aperto ( estendo il punto finale della base secondaria e il punto iniziale // della base primaria dino al lato sinistro del box) bool bCopyLeft = false ; - if ( pCrvTest1->GetCurve( 0)->GetTempProp( 0) == 1) { - if ( nType == 0) { - pCrvTrap->GetCurve( 2)->GetEndPoint( ptEB1) ; - pCrvTrap->GetCurve( 0)->GetStartPoint( ptSB0) ; - } - else { - pCrvTrap->GetCurve( 1)->GetEndPoint( ptEB1) ; - pCrvTrap->GetCurve( 2)->GetEndPoint( ptSB0) ; - } + if ( pCrvTest1->GetCurve( 0)->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { + int nCrvLeft_ref = ( nType == 0 ? 2 : 3) ; + pCrvTrap->GetCurve( nCrvLeft_ref)->GetStartPoint( ptEB1) ; + pCrvTrap->GetCurve( nCrvLeft_ref)->GetEndPoint( ptSB0) ; } // se lato sinistro chiuso else @@ -2377,7 +2366,7 @@ PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, const double dDiam pCrvTrap->AddCurve( Release( pCrvTest0)) ; else { pCrvTrap->AddLine( ptSB1) ; - pCrvTrap->SetCurveTempProp( pCrvTrap->GetCurveCount() - 1, 1, 0) ; // aperta + pCrvTrap->SetCurveTempProp( pCrvTrap->GetCurveCount() - 1, TEMP_PROP_OPEN_EDGE, 0) ; // aperta } nSecondBase = pCrvTrap->GetCurveCount() ; pCrvTrap->AddLine( ptEB1) ; @@ -2385,7 +2374,7 @@ PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, const double dDiam pCrvTrap->AddCurve( Release( pCrvTest1)) ; else { pCrvTrap->Close() ; - pCrvTrap->SetCurveTempProp( pCrvTrap->GetCurveCount() - 1, 1, 0) ; // aperta + pCrvTrap->SetCurveTempProp( pCrvTrap->GetCurveCount() - 1, TEMP_PROP_OPEN_EDGE, 0) ; // aperta } // verifico dimensione x della svuotatura nel caso tutto chiuso @@ -2393,7 +2382,7 @@ PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, const double dDiam double dLen0 = 0, dLen2 = 0 ; pCrvTrap->GetCurve( nBase)->GetLength( dLen0) ; pCrvTrap->GetCurve( nSecondBase)->GetLength( dLen2) ; - if ( dLen0 < dDiam - EPS_SMALL || dLen2 < dDiam - EPS_SMALL) { + if ( dLen0 < dDiam - EPS_SMALL || dLen2 < dDiam - EPS_SMALL) { pCrvTrap->Clear() ; return true ; } @@ -2439,8 +2428,18 @@ GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTr dPocketSize = vtOrtho.Len() ; if ( ! CalcTrapezoidSpiralLocalFrame( pCrvTrap, vtDir, frTrap)) return false ; - bool bBaseOpen = false ; - bBaseOpen = ( pCrvTrap->GetCurve( 0)->GetTempProp( 0) == 1 || pCrvTrap->GetCurve( 2)->GetTempProp( 0) == 1) ; + // assegno le tempProp della curva trapezio + for ( int nU = 0 ; nU < 4 ; ++ nU) { + Vector3d vtCrvDir ; pCrvTrap->GetCurve( nU)->GetStartDir( vtCrvDir) ; + for ( int nI = 0 ; nI < pCrvCompo->GetCurveCount() ; ++ nI) { + Vector3d vtCurrCrvDir ; pCrvTrap->GetCurve( nI)->GetStartDir( vtCurrCrvDir) ; + if ( AreSameVectorEpsilon( vtCrvDir, vtCurrCrvDir, 150 * EPS_SMALL)) { + pCrvTrap->SetCurveTempProp( nU, pCrvCompo->GetCurve( nI)->GetTempProp( 0), 0) ; + break ; + } + } + } + bool bBaseOpen = ( pCrvTrap->GetCurve( 0)->GetTempProp( 0) == 1 || pCrvTrap->GetCurve( 2)->GetTempProp( 0) == 1) ; // controllo dimensioni della svuotatura if ( ! ( bBaseOpen && dPocketSize < dDiam + EPS_SMALL) && abs( dPocketSize - dDiam) > EPS_SMALL) { @@ -2730,7 +2729,6 @@ GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTr } } - // se non ho trovato delle basi, allora cerco in maniera generale un trapezoide ( se esiste) if ( nBase == -1) { bool bOK = false ; @@ -2773,6 +2771,12 @@ GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTr } } } + if ( ! bOK) { + pCrvTrap->Clear() ; + nBase = -1 ; + nSecondBase = -1 ; + return true ; + } } // la curva a trapezio deve evere almeno 4 lati @@ -3345,35 +3349,23 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& pCrvBorder->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; pCrvBorder->SetExtrusion( pSfrChunk->GetNormVersor()) ; - // recupero i tratti con proprietà uniformi - ICRVCOMPOPOVECTOR vpCrvs ; - GetHomogeneousParts( pCrvBorder, PockParam, vpCrvs) ; - if ( vpCrvs.size() > 1) { - // unisco il primo e l'ultimo se estremi compatibili - Point3d ptE ; vpCrvs.back()->GetEndPoint( ptE) ; - Point3d ptS ; vpCrvs[0]->GetStartPoint( ptS) ; - if ( AreSamePointApprox( ptS, ptE)) { - vpCrvs[0]->AddCurve( Release( vpCrvs.back()), false) ; - vpCrvs.erase( vpCrvs.end() - 1) ; - } - } - if ( vpCrvs.empty()) - return false ; - /* SPIRALE EUCLIDEA - E' richiesto che la curva di bordo sia una circonferenza tutta OPEN o tutta CLOSED */ - bool bOkSpiral = ( int( vpCrvs.size()) == 1) ; + bool bOkSpiral = true ; + int nTempPropRef = pCrvBorder->GetCurve( 0)->GetTempProp( 0) ; + for ( int nU = 1 ; nU < pCrvBorder->GetCurveCount() && bOkSpiral ; ++ nU) + bOkSpiral = ( pCrvBorder->GetCurve( nU)->GetTempProp( 0) == nTempPropRef) ; if ( bOkSpiral) { // controllo che sia una circonferenza Point3d ptCen ; double dRad ; - if ( ! OptimizedSpiralCirle( pCrvBorder, 50 * EPS_SMALL, dRad, ptCen, bOkSpiral)) + if ( ! OptimizedSpiralCircle( pCrvBorder, 50 * EPS_SMALL, dRad, ptCen, bOkSpiral)) return false ; // se è una circonferenza if ( bOkSpiral) { double dOffs = PockParam.dRad + PockParam.dRadialOffset ; // se curva tutta Open, allora ingrandisco il raggio - if ( vpCrvs[0]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) + if ( nTempPropRef == TEMP_PROP_OPEN_EDGE) dRad += 1.05 * PockParam.dRad + PockParam.dRadialOffset ; // se curva chiusa, controllo che il raggio sia compatibile con il primo Offset else @@ -3383,7 +3375,7 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& bool bOkSpiral = CalcCircleSpiral( ptCen, pSfrChunk->GetNormVersor(), dRad - dOffs, dIntRad, PockParam, pCrvRes) ; if ( bOkSpiral && pCrvRes->IsValid() && pCrvRes->GetCurveCount() > 0) { // se curva di bordo OPEN, imposto i parametri per LeadIn - if ( vpCrvs[0]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) { + if ( nTempPropRef == TEMP_PROP_OPEN_EDGE) { Vector3d vtMidOut ; pCrvRes->GetStartDir( vtMidOut) ; vtMidOut.Rotate( pSfrChunk->GetNormVersor(), PockParam.bInvert ? ANG_RIGHT : - ANG_RIGHT) ; @@ -3410,12 +3402,25 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& if ( bOkTrap && pCrvTrap->IsValid()) { pCrvTrap->SetExtrusion( Z_AX) ; CalcTrapezoidSpiral( pCrvTrap, frTrap, dPocketSize, nBase, nSecondBase, PockParam, pCrvRes, bOkTrap) ; - if ( bOkTrap) - return true ; + if ( bOkTrap) { + // calcolo eventuali uscite e ingressi + if ( pCrvRes->GetTempProp( 0) > 0) { + Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ; + vtRef.Invert() ; + bool bIsStartExtended = false ; + if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, bIsStartExtended)) + return false ; + pCrvRes->GetEndDir( vtRef) ; + bool bIsEndExtended = false ; + if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, true, bIsEndExtended)) + return false ; + if ( bIsEndExtended && ! bIsStartExtended) + pCrvRes->Invert() ; + } + } } return true ; - } //---------------------------------------------------------------------------- @@ -8281,18 +8286,6 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double if ( ! IsSfrAllHomogeneous( pSfr, myParams.bAllClosed, myParams.bAllOpen)) return false ; - // ------------ recupero le singole curve di svuotatura ------------------- - ICRVCOMPOPOVECTOR vCrvSingleCurves ; - if ( ! GetSinglePocketingCurves( pSfrAdj, myParams, vCrvSingleCurves)) - return false ; - for ( int i = 0 ; i < int( vCrvSingleCurves.size()) ; ++ i) { - vCrvSingleCurves[i]->ToGlob( myParams.frLocXY) ; - vCrvCompoRes.emplace_back( Release( vCrvSingleCurves[i])) ; - } - // se ho svuotato tutta la superficie, allora ho finito - if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) - return true ; - // ------------ casi ottimizzati ------------------------------------------ ICRVCOMPOPOVECTOR vCrvOptCurves ; if ( ! GetPocketingOptimizedCurves( pSfrAdj, myParams, vCrvOptCurves)) @@ -8305,6 +8298,18 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) return true ; + // ------------ recupero le singole curve di svuotatura ------------------- + ICRVCOMPOPOVECTOR vCrvSingleCurves ; + if ( ! GetSinglePocketingCurves( pSfrAdj, myParams, vCrvSingleCurves)) + return false ; + for ( int i = 0 ; i < int( vCrvSingleCurves.size()) ; ++ i) { + vCrvSingleCurves[i]->ToGlob( myParams.frLocXY) ; + vCrvCompoRes.emplace_back( Release( vCrvSingleCurves[i])) ; + } + // se ho svuotato tutta la superficie, allora ho finito + if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) + return true ; + // ------------ estensione lati aperti ------------------------------------ if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams)) return false ;