From b1e30147ea2fdc8df345b6ceb54dc3c86bfedffb Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Wed, 29 Nov 2023 12:04:52 +0100 Subject: [PATCH] EgtGeomKernel : - eliminata la funzione GetZigZagInfill dalla classe SurfFlatRegion ( sostituita da CalcZigZagInfill) - modifica alle funzioni di Pocketing. --- CalcPocketing.cpp | 502 ++++++++++++++++++++++++--------------------- SurfFlatRegion.cpp | 248 ---------------------- SurfFlatRegion.h | 1 - 3 files changed, 263 insertions(+), 488 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 2362cd0..e485509 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -1,4 +1,4 @@ -//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- // EgalTech 2023-2023 //---------------------------------------------------------------------------- // File : EGkCalcPocketing.h Data : 16.11.23 Versione : 2.5j1 @@ -37,10 +37,10 @@ using namespace std ; // Calcolo delle curve elementari di Pocketing //---------------------------------------------------------------------------- -enum { POCKET_SUB_ZIGZAG = 0, - POCKET_SUB_ONEWAY = 1, - POCKET_SUB_SPIRALIN = 2, - POCKET_SUB_SPIRALOUT = 3} ; +enum { POCKET_ZIGZAG = 0, + POCKET_ONEWAY = 1, + POCKET_SPIRALIN = 2, + POCKET_SPIRALOUT = 3 } ; // variabili d'appoggio ( per non passare troppi parametri tra le funzioni secondarie) int TYPE ; @@ -55,31 +55,31 @@ AdjustContourStart( ICurveComposite* pCompo) // creo un vettore di indici che definisce l'ordine delle curve chiuse in base alla lunghezza INTVECTOR vInd ; vInd.reserve( pCompo->GetCurveCount()) ; - // vettore di indici già utilizzati + // vettore di indici già utilizzati INTVECTOR vIndUsed ; vIndUsed.reserve( pCompo->GetCurveCount()) ; - double dMaxLen = -INFINITO ; - int nCurrInd = 0 ; - bool bStop = false ; + double dMaxLen = -INFINITO ; // lunghezza massima + int nCurrInd = 0 ; // indice della curva scelta + bool bStop = false ; // flag per stoppare la ricerca della curva - // imbroglio mettendo chiuse tutte le curve ---- + // mettendo chiuse tutte le curve ( in questo caso non servono i lati aperti) for ( int u = 0 ; u < pCompo->GetCurveCount() ; ++ u) { pCompo->SetCurveTempProp( u, 0, 0) ; pCompo->SetCurveTempProp( u, 0, 1) ; } + // miglioro la curva per la ricerca pCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; - // --------------------------------------------- + // scorro tutte le curve for ( int c = 0 ; c < pCompo->GetCurveCount() && ! bStop ; ++ c) { bStop = true ; for ( int i = 0 ; i < pCompo->GetCurveCount() ; ++ i) { - int nProp_i ; - // se la curva i-esima non è già stata considerata ed è aperta... + // se la curva i-esima non è già stata considerata ed è aperta... if ( find( vIndUsed.begin(), vIndUsed.end(), i) == vIndUsed.end() && - pCompo->GetCurveTempProp( i, nProp_i, 0) && nProp_i == 0) { + pCompo->GetCurveTempProp( i, nProp_i, 0) && nProp_i == 0) { - // creo la curva i-esima + // ricavo la curva i-esima const ICurve* pCrv_i( pCompo->GetCurve( i)) ; double dLen_i ; @@ -98,7 +98,7 @@ AdjustContourStart( ICurveComposite* pCompo) // ora che ho riempito il vettore di indici lo scorro e cerco di entrare in questi lati chiusi secondo l'ordine for ( int i = 0 ; i < ( int)vInd.size() ; ++ i) { pCompo->ChangeStartPoint( vInd[0] + 0.5) ; - // imbroglio + // in questo caso mi fermo al primo per semplicità break ; } @@ -119,10 +119,10 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, return false ; ICURVEPOVECTOR vCrvStepsToFill ; // vettore delle Curve da raccordare (curve della composita) - ICURVEPOVECTOR vCrvArcs ; // vettore contenente gli Archi (tra le curve della composita) - INTVECTOR vArcsToJump ; // vettore di indici per gli archi saltati (nel caso non si riesca a raccordare ...) + ICURVEPOVECTOR vCrvArcs ; // vettore contenente gli Archi (tra le curve della composita) + INTVECTOR vArcsToJump ; // vettore di indici per gli archi saltati (nel caso non si riesca a raccordare ...) - // se nella composita ho meno di due curve allora non c'è nulla da raccordare + // se nella composita ho meno di due curve allora non c'è nulla da raccordare const ICurve* pMyCrv = pCrv->GetFirstCurve() ; while ( pMyCrv != nullptr) { vCrvStepsToFill.emplace_back( pMyCrv->Clone()) ; @@ -131,7 +131,7 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, if ( vCrvStepsToFill.size() < 2) return true ; - // controllo se la curva è chiusa (nel caso inserisco nel vettore la prima curva due volte, all'inizio e alla fine) + // controllo se la curva è chiusa ( nel caso inserisco nel vettore la prima curva due volte, all'inizio e alla fine) if ( pCrv->IsClosed()) { const ICurve* pMyCrvFirst = pCrv->GetFirstCurve() ; if ( pMyCrvFirst == nullptr) @@ -143,7 +143,7 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, // riempio il vettore degli archi, scorro tutte le curve da raccordare ( la i-esima e la (i+1)-esima) for ( int i = 0 ; i < int( vCrvStepsToFill.size()) - 1 ; ++ i) { - // controllo che le curve non siano già tangenti + // controllo che le curve non siano già tangenti Vector3d vtS, vtE ; if ( ! vCrvStepsToFill[i]->GetEndDir( vtS) || ! vCrvStepsToFill[i+1]->GetStartDir( vtE)) continue ; @@ -153,7 +153,7 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, continue ; } - + // ricavo i valori parametrici associati double dLen_act ; vCrvStepsToFill[i]->GetLength( dLen_act) ; double dLen_succ ; vCrvStepsToFill[i+1]->GetLength( dLen_succ) ; double dUE_ref = 1. ; @@ -163,8 +163,9 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, if ( dLen_succ > dRightLen) dUS_ref = dRightLen / dLen_succ ; + // se valori trattati come parametri... if ( bAsParam) { - // cerco i parametri corrispondenti sulle due curve + // ... cerco i parametri corrispondenti sulle due curve double dU_cm_S = 0 ; double dULast1 = 1 ; double dULast2 = 1 ; vCrvStepsToFill[i]->GetDomain( dU_cm_S, dULast1) ; dUE_ref = ( 1 - dRightLen) * dULast1 ; @@ -179,11 +180,11 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, ! vCrvStepsToFill[i+1]->GetPointD1D2( dUS_ref, ICurve::FROM_MINUS, ptE)) return false ; - dRadius = Dist( ptS, ptE) ; // uso come raggio la distanza tra i due punti + dRadius = Dist( ptS, ptE) ; // uso come raggio la distanza tra i due punti ( limite superiore valido) - int nMaxTestForArcs = 3 ; // tentativi per creare l'arco - int nIterForArcs = 0 ; - bool IntersBTWArcs = false ; + int nMaxTestForArcs = 3 ; // tentativi per creare l'arco + int nIterForArcs = 0 ; // numero di intersezioni con altre curve + bool IntersBTWArcs = false ; // caso particolare in cui due archi di raccordo si intersecano causa curva piccola // creo l'arco di raccordo e controllo che non sia troppo piccolo PtrOwner pCrvArc( CreateFillet( *vCrvStepsToFill[i], ptS, *vCrvStepsToFill[i+1], ptE, Z_AX, dRadius, dPar1, dPar2)) ; @@ -201,7 +202,7 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, IntersBTWArcs = true ; } - // se ho intersezioni tra archi o l'arco creato non è valido, allora provo altre nMaxTestForArcs volte a ricrearlo avvicinando i punti + // se ho intersezioni tra archi o l'arco creato non è valido, allora provo altre nMaxTestForArcs volte a ricrearlo avvicinando i punti while (( IsNull( pCrvArc) || IntersBTWArcs) && nIterForArcs < nMaxTestForArcs) { dUE_ref = ( 1 + dUE_ref ) * 0.5 ; @@ -235,7 +236,7 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, vArcsToJump.push_back( -1) ; // da considerare } - // creo la curva che restituirò + // creo la curva che restituirò PtrOwner pCrvCO_temp( CreateCurveComposite()) ; if ( IsNull( pCrvCO_temp)) return false ; @@ -253,14 +254,14 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, return false ; if ( i == 0) { // ... e sono nella prima iterazione ... - if ( ! pCrv->IsClosed()) { // ... e se la curva è aperta -> la inserisco nel nuovo percorso + if ( ! pCrv->IsClosed()) { // ... e se la curva è aperta -> la inserisco nel nuovo percorso if ( ! pCrvCO_temp->AddCurve( GetCurve( vCrvStepsToFill[0]->CopyParamRange( 0, dUE_ref)))) return false ; } ptFirstPoint = ptArcS ; - // ... e se la curva è chiusa -> non la inserisco nel nuovo percorso + // ... e se la curva è chiusa -> non la inserisco nel nuovo percorso } - else { // ... e non sono nella prima iterazione (non ha importanza se la curva è chiusa o aperta...) + else { // ... e non sono nella prima iterazione (non ha importanza se la curva è chiusa o aperta...) if ( ! vCrvStepsToFill[i]->GetParamAtPoint( ptArcHelp, dUS_ref) || ! pCrvCO_temp->AddCurve( GetCurve( vCrvStepsToFill[i]->CopyParamRange( dUS_ref, dUE_ref)))) return false ; @@ -283,7 +284,7 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, } ptFirstPoint = ptArcHelp ; } - else { // ... e non sono nella prima iterazione (non ha importanza se la curva è chiusa o aperta...) + else { // ... e non sono nella prima iterazione (non ha importanza se la curva è chiusa o aperta...) double dUS_cm ; if ( ! vCrvStepsToFill[i]->GetParamAtPoint( ptArcHelp, dUS_ref) || ! vCrvStepsToFill[i]->GetDomain( dUS_cm, dUE_ref) || @@ -310,7 +311,7 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, return false ; } - // ripristino il punto inziale se la curva è chiusa + // ripristino il punto inziale se la curva è chiusa double dNewDU ; if ( ! pCrv->IsClosed()) { if ( ! pCrvCO_temp->GetParamAtPoint( ptArcHelp, dNewDU)) @@ -318,6 +319,7 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, pCrvCO_temp->ChangeStartPoint( dNewDU) ; } + // restituisco pCrv->Clear() ; pCrv->AddCurve( Release( pCrvCO_temp)) ; @@ -328,17 +330,18 @@ ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, double dLeftLen, static bool CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) { + // pulisco pCrvLink->Clear() ; // recupero il vettore estrusione dal bordo esterno offsettato della superficie Vector3d vtExtr ; vOffIslands[0]->GetExtrusion( vtExtr) ; - // determino il riferimento naturale della svuotatura (OCS con il vettore estrusione come asse Z) + // determino il riferimento naturale della svuotatura ( OCS con il vettore estrusione come asse Z) Frame3d frLoc ; frLoc.Set( ORIG, vtExtr) ; - // non serve collegare ( può capitare nel tagliare percorsi con isole complesse) + // non serve collegare ( può capitare nel tagliare percorsi con isole complesse) if ( AreSamePointApprox( ptStart, ptEnd)) return true ; @@ -350,21 +353,22 @@ CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCOMPOPOVECTOR } // creo la retta che li unisce - PtrOwner pLine( CreateCurveComposite()) ; - if ( ! pLine->AddPoint( ptStart) || ! pLine->AddLine( ptEnd)) + PtrOwner pCompoLine( CreateCurveComposite()) ; + if ( ! pCompoLine->AddPoint( ptStart) || ! pCompoLine->AddLine( ptEnd)) return false ; - pLine->SetExtrusion( vtExtr) ; + pCompoLine->SetExtrusion( vtExtr) ; // la porto in locale al riferimento della svuotatura - CurveLocal LineLoc( pLine, GLOB_FRM, frLoc) ; // ... per le intersezioni + CurveLocal LineLoc( pCompoLine, GLOB_FRM, frLoc) ; // ... per le intersezioni // creo la nuova curva formata dai tratti di linee INTERNI alle isole e dai tratti sul bordo degli offset - PtrOwner pCompo( pLine->Clone()) ; + PtrOwner pCompo( pCompoLine->Clone()) ; if ( IsNull( pCompo) ) return false ; if ( ! pCompo->LocToLoc( GLOB_FRM, frLoc) ) return false; - PtrOwner pCompoHelp( pLine->Clone()) ; + // memorizzo il tratto lineare nel caso qualche operazione fallisse + PtrOwner pCompoHelp( pCompoLine->Clone()) ; if ( IsNull( pCompoHelp)) return false ; if ( ! pCompoHelp->LocToLoc( GLOB_FRM, frLoc)) @@ -388,7 +392,7 @@ CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCOMPOPOVECTOR pCompo->GetPointD1D2( ccClass[j].dParE, ICurve::FROM_MINUS, ptE) ; double dOffE ; vOffIslands[i]->GetParamAtPoint( ptE, dOffE) ; - // recupero i due possibili percorsi e uso il più corto + // recupero i due possibili percorsi e uso il più corto PtrOwner pCrvA( GetCurve( vOffIslands[i]->CopyParamRange( dOffS, dOffE))) ; PtrOwner pCrvB( GetCurve( vOffIslands[i]->CopyParamRange( dOffE, dOffS))) ; @@ -425,20 +429,24 @@ CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCOMPOPOVECTOR //----------------------------------------------------------------------------- static bool -ModifyBiArc( ICurve* pBiArcLink, double dToll, ICurveComposite* pNewBiArc) { +ModifyBiArc( ICurve* pBiArcLink, double dToll, ICurveComposite* pNewBiArc) +{ + // controllo dei parametri if ( pBiArcLink == nullptr) return false ; if ( dToll > 0.99 || dToll < 0.01) return false ; pNewBiArc->Clear() ; + // dominio double dUS, dUE ; pBiArcLink->GetDomain( dUS, dUE) ; - PtrOwner pArc1( GetCurve( pBiArcLink->CopyParamRange( dUS, (dUS + dUE) / 2))) ; + // prendo i due archi della curva BiArco + PtrOwner pArc1( GetCurve( pBiArcLink->CopyParamRange( dUS, ( dUS + dUE) / 2))) ; PtrOwner pArc2( GetCurve( pBiArcLink->CopyParamRange(( dUS + dUE ) / 2, dUE))) ; - if ( IsNull(pArc1) || ! pArc1->IsValid() || IsNull( pArc2) || ! pArc2->IsValid()) + if ( IsNull( pArc1) || ! pArc1->IsValid() || IsNull( pArc2) || ! pArc2->IsValid()) return false ; // primo pezzo @@ -461,6 +469,7 @@ ModifyBiArc( ICurve* pBiArcLink, double dToll, ICurveComposite* pNewBiArc) { PtrOwner pLine2( CreateCurveLine()) ; pLine2->Set( pt2A, pt2B) ; // Linea + // ricostruisco il nuovo link if ( ! pNewBiArc->AddCurve( Release( pArc1A)) || ! pNewBiArc->AddCurve( Release( pLine1)) || ! pNewBiArc->AddCurve( Release( pArc1B)) || @@ -515,7 +524,6 @@ CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const P PtrOwner pCompo( GetCurveComposite( pBiArcLink->Clone())) ; if ( IsNull( pCompo)) return false ; - PtrOwner pCompoHelp( GetCurveComposite( pBiArcLink->Clone())) ; if ( IsNull( pCompoHelp)) return false ; @@ -540,7 +548,7 @@ CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const P pCompo->GetPointD1D2( ccClass[j].dParE, ICurve::FROM_MINUS, ptE) ; double dOffE ; vOffIslands[i]->GetParamAtPoint( ptE, dOffE, 1500 * EPS_SMALL) ; - // recupero i due possibili percorsi e uso il più corto + // recupero i due possibili percorsi e uso il più corto PtrOwner pCrvA( GetCurve( vOffIslands[i]->CopyParamRange( dOffS, dOffE))) ; PtrOwner pCrvB( GetCurve( vOffIslands[i]->CopyParamRange( dOffE, dOffS))) ; @@ -580,7 +588,7 @@ CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const P } - // se il BiArco è troppo piccolo allora lo approssimo con un segmento + // se il BiArco è troppo piccolo allora lo approssimo con un segmento BBox3d bBox3 ; if ( pCompo->GetLocalBBox( bBox3)) { double dRadBB ; @@ -591,6 +599,7 @@ CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const P } } + // smusso e restituisco ModifyCurveToSmoothed( pCompo, 0.05, 0.05, true) ; pCrvLink->AddCurve( Release( pCompo)) ; @@ -608,14 +617,16 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, ICRVCOMPOPOVE return false ; pCrvLink->Clear() ; + // curva finale da restituire PtrOwner ptCrvFinal( CreateCurveComposite()) ; if ( IsNull( ptCrvFinal)) return false ; - // Prendo i punti, i vettori tangenti e i parametri di essi per le curve - Point3d ptSS, ptSE, ptES, ptEE ; Vector3d vS, vE ; double dUSS, dUSE, dUES, dUEE, dLenS, dLenE ; - dUSS = 0; dUSE = 0; - + // Prendo i punti, i vettori tangenti e i parametri di essi per le curve + Point3d ptSS, ptSE, ptES, ptEE ; + Vector3d vS, vE ; + double dUSS, dUSE, dUES, dUEE, dLenS, dLenE ; + dUSS = 0 ; dUSE = 0 ; pCrvS->GetEndPoint( ptSE) ; pCrvS->GetStartPoint( ptSS) ; pCrvE->GetStartPoint( ptES) ; @@ -627,27 +638,27 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, ICRVCOMPOPOVE pCrvS->GetLength( dLenS) ; pCrvE->GetLength( dLenE) ; - // se ho una curva di primo Offset allora non devo accorciarla ... + // se ho una curva di primo Offset allora non devo accorciarla ... ( si per bordi esterni che per isole) for ( int i = 0 ; i < int( vFirstOffset.size()) ; ++ i) { if ( vFirstOffset[i]->IsPointOn( ptSS) && vFirstOffset[i]->IsPointOn( ptSE)) dLenPercS = 0 ; if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE)) dLenPercE = 0 ; } - - double dLStepS = dLenPercS * dLenS ; - double dLStepE = dLenPercE * dLenE ; + double dLStepS = dLenPercS < EPS_SMALL ? 0. : RAD ; + double dLStepE = dLenPercE < EPS_SMALL ? 0. : RAD ; dLenE = 0 ; // calcolo i possibili BiArchi tra le due curve int nIter = 0 ; + // taglio la curva al massimo nMaxIter-volte e mi fermo al taglio più opportuno while ( nIter < nMaxIter) { // calcolo il BiArco PtrOwner ptBiArc( CreateCurveComposite()) ; if ( ! CalcBoundedSmootedLink( ptSE, vS, ptES, vE, 0.5, vFirstOffset, ptBiArc) || - ptBiArc->GetCurveCount() == 0) + ptBiArc->GetCurveCount() == 0) return false ; ptCrvFinal->Clear() ; @@ -669,7 +680,7 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, ICRVCOMPOPOVE bInterr = true ; } if ( bInterr) - break ; // così come ultimo arco ho quello precedente (valido) + break ; // così come ultimo arco ho quello precedente (valido) // se ho trovato un BiArco valido, allora accorcio le due curve di Offset dLenS -= dLStepS ; @@ -724,7 +735,6 @@ GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICU } } - // ---- le seguenti regioni sono distinte per calcolar emeglio la Feed ---- // 2) Creo la regione svuotata dal Tool negli Offset, nei Links e sia dagli Offsets che dai Links PtrOwner pSrfTool_Offs( CreateSurfFlatRegion()) ; PtrOwner pSrfTool_Links( CreateSurfFlatRegion()) ; @@ -732,17 +742,17 @@ GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICU if ( IsNull( pSrfTool_Offs) || IsNull( pSrfTool_Links) || IsNull( pSrfTool)) return false ; - // creo un vettore che conterrà solamente i Link percorsi fino ad Ora + // creo un vettore che conterrà solamente i Link percorsi fino ad Ora ICRVCOMPOPOVECTOR vLinks_done ; - for ( int i = TYPE == POCKET_SUB_SPIRALIN ? 0 : ( int)vCrvs.size() - 1 ; - TYPE == POCKET_SUB_SPIRALIN ? i < int( vCrvs.size()) : i >= 0 ; - TYPE == POCKET_SUB_SPIRALIN ? ++ i : -- i) { + for ( int i = TYPE == POCKET_SPIRALIN ? 0 : ( int)vCrvs.size() - 1 ; + TYPE == POCKET_SPIRALIN ? i < int( vCrvs.size()) : i >= 0 ; + TYPE == POCKET_SPIRALIN ? ++ i : -- i) { // ================= LINK ================================ if ( i <= ( int)vLinks.size() && ! IsNull( vLinks[i]) && vLinks[i]->IsValid()) { - // Feed + // prendo il Link i-esimo come composita ( potrebbe essere tratto lineare) PtrOwner pCompoLink_i( CreateCurveComposite()) ; if ( IsNull( pCompoLink_i)) return false ; @@ -768,17 +778,16 @@ GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICU } // ================== OFFSET ============================= - // aggiorno la superficie svuotata PtrOwner pCrvOffs_i( CloneCurveComposite( vCrvs[i])) ; if ( IsNull( pCrvOffs_i)) return false ; PtrOwner pSrfToolRegOffi( GetSurfFlatRegionFromFatCurve( Release( pCrvOffs_i) , RAD + 5 * EPS_SMALL, false, false)) ; if ( ! IsNull( pSrfToolRegOffi)) { - if ( ! pSrfTool_Offs->IsValid() || pSrfTool_Offs->GetChunkCount() == 0) - pSrfTool_Offs.Set( Release( pSrfToolRegOffi)) ; - else - pSrfTool_Offs->Add( *pSrfToolRegOffi) ; + if ( ! pSrfTool_Offs->IsValid() || pSrfTool_Offs->GetChunkCount() == 0) + pSrfTool_Offs.Set( Release( pSrfToolRegOffi)) ; + else + pSrfTool_Offs->Add( *pSrfToolRegOffi) ; } } @@ -796,15 +805,16 @@ GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICU //---------------------------------------------------------------------------- static bool -RemoveFirstLoopFromSfr( ISurfFlatRegion* pSrfOrig) { - +RemoveFirstLoopFromSfr( ISurfFlatRegion* pSrfOrig) +{ + // controllo dei parametri if ( pSrfOrig == nullptr) return true ; - + // superficie da restituire PtrOwner pSrfRes( CreateSurfFlatRegion()) ; if ( IsNull( pSrfRes)) return false ; - + // scorro tutti i chunk tranne il primo ( escludo quindi il primo chunk) for ( int c = 1 ; c < pSrfOrig->GetChunkCount() ; ++ c) { PtrOwner pSrfHelp( CreateSurfFlatRegion()) ; if ( IsNull( pSrfHelp)) @@ -816,7 +826,7 @@ RemoveFirstLoopFromSfr( ISurfFlatRegion* pSrfOrig) { else pSrfRes->Add( *( pSrfHelp)) ; } - + // restituisco pSrfOrig->Clear() ; pSrfOrig->CopyFrom( pSrfRes) ; @@ -837,7 +847,7 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT if ( pChunkToCut == nullptr) return false ; - // curva che l'utensile dovrà seguire per svuotare la regione e curva di ingombro del tool + // curva che l'utensile dovrà seguire per svuotare la regione e curva di ingombro del tool PtrOwner pCrvStepByStepPath( CreateCurveComposite()) ; if ( IsNull( pCrvStepByStepPath)) return false ; @@ -851,7 +861,7 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT while ( pSrfChunkToCutClone->IsValid() && pSrfChunkToCutClone->GetChunkCount() != 0 && pSrfChunkToCutClone->GetArea( dArea) && dArea > 10 * EPS_SMALL) { - // finchè restano parti non svuotate la cui area totale è suffcientemente grande... + // finchè restano parti non svuotate la cui area totale è suffcientemente grande... if ( nIter > 25) // troppi tentativi... break ; @@ -864,7 +874,7 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT break ; double dAreaExt ; - // se l'area del chunk è piccola... rimuovo il chunk dalla superficie da svuotare + // se l'area del chunk è piccola... rimuovo il chunk dalla superficie da svuotare if ( pSrfBiggerChunk->GetArea( dAreaExt) && dAreaExt < 10 * EPS_SMALL) { if ( ! RemoveFirstLoopFromSfr( pSrfChunkToCutClone)) return false ; @@ -895,13 +905,13 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT pSrfTest->Subtract( *pSrfTool) ; if( IsNull( pSrfTest) || ! pSrfTest->IsValid() || ! pSrfTest->GetArea( dArea) || dArea < 10 * EPS_SMALL || bForceCentroid) { - if ( nIter == 1) { // se prima iterazione -> ritorno il centroide com punto + if ( nIter == 1) { // se prima iterazione -> ritorno il centroide con punto nOptFlag = 1 ; ptCentroid = ptC ; return true ; } else { // se non sono alla prima iterazione -> memorizzo il centroide nel vettore - // controllo di non aver trovato un centroide già inserito ( per simmetria del chunk) + // controllo di non aver trovato un centroide già inserito ( per simmetria del chunk) for ( int cen = 0 ; cen < int( vPtCentroid.size()) ; ++ cen) { if ( AreSamePointApprox( vPtCentroid[cen], ptC)) { pSrfChunkToCutClone->Clear() ; @@ -934,12 +944,13 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT if ( IsNull( pCrvMedAx)) return false ; if ( ! pCrvMedAx->FromPolyLine( PlMedAx)) { - // se questo medial Axis è troppo piccolo e la polyLine non è convertitibile in curva composita ... + // se questo medial Axis è troppo piccolo e la polyLine non è convertitibile in curva composita ... bForceCentroid = true ; // 2a) forzo ad andare nel centroide -- nIter ; // 2b) scalo una iterzione continue ; } + // abbellisco la curva pCrvMedAx->MergeCurves( 100 * EPS_SMALL, 100 * EPS_ANG_SMALL, false) ; PolyArc PlMedAxArc ; pCrvMedAx->ApproxWithArcsEx( 500 * EPS_SMALL, ANG_TOL_STD_DEG, 20.0, PlMedAxArc) ; @@ -949,7 +960,6 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT -- nIter ; continue ; } - // smusso la curva ModifyCurveToSmoothed( pCrvMedAx, 0.025, 0.025, true) ; // se curva valida la inserisco nel vettore, altrimenti forzo il centroide @@ -961,7 +971,6 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT continue ; } - // 3) guardo quale regione svuoto con questa curva PtrOwner pSrfRemoved( GetSurfFlatRegionFromFatCurve( Release( pCrvMedAx), RAD + 5 * EPS_SMALL, false, false)) ; if ( IsNull( pSrfRemoved) || ! pSrfRemoved->IsValid()) @@ -975,7 +984,7 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT } - // se entrambi i vettori sono vuoti l'area originaria era più piccola di 10 * EPS_SMALL -> non faccio nulla + // se entrambi i vettori sono vuoti l'area originaria era più piccola di 10 * EPS_SMALL -> non faccio nulla if (( int)vCrvCoMedAxi.size() == 0 && ( int)vPtCentroid.size() == 0) { nOptFlag = 0 ; return true ; @@ -990,9 +999,9 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT // parametri iniziali del primo e ultimo medial Axis trovato if ( ! vCrvCoMedAxi[0]->GetStartPoint( ptSOriginal) || - ! vCrvCoMedAxi.back()->GetEndPoint( ptEOriginal) || - ! vCrvCoMedAxi[0]->GetStartDir( vtSOriginal) || - ! vCrvCoMedAxi.back()->GetEndDir( vtEOriginal)) + ! vCrvCoMedAxi.back()->GetEndPoint( ptEOriginal) || + ! vCrvCoMedAxi[0]->GetStartDir( vtSOriginal) || + ! vCrvCoMedAxi.back()->GetEndDir( vtEOriginal)) return false ; pCrvPath->AddCurve( vCrvCoMedAxi[0]->Clone()) ; // inserisco il primo medial Axis nel percorso finale @@ -1001,9 +1010,9 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT Point3d ptS, ptE ; Vector3d vtS, vtE ; // parametri iniziali del medialAxis i-esimo e (i-1)esimo if ( ! vCrvCoMedAxi[i]->GetStartPoint( ptE) || - ! vCrvCoMedAxi[i-1]->GetEndPoint( ptS) || - ! vCrvCoMedAxi[i]->GetStartDir( vtE) || - ! vCrvCoMedAxi[i-1]->GetEndDir( vtS)) + ! vCrvCoMedAxi[i-1]->GetEndPoint( ptS) || + ! vCrvCoMedAxi[i]->GetStartDir( vtE) || + ! vCrvCoMedAxi[i-1]->GetEndDir( vtS)) return false ; PtrOwner pCrvLink( CreateCurveComposite()) ; @@ -1024,14 +1033,14 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT if ( ! CalcBoundedLink( ptEOriginal, ptSOriginal, vOffsFirstCurve, pCrvCoBackLink)) return false ; - // se ho trovato dei centroidi li unisco nei punti più vicini a questo percorso + // se ho trovato dei centroidi li unisco nei punti più vicini a questo percorso for ( int i = 0 ; i < int( vPtCentroid.size()) ; ++ i) { - // 1) cerco il punto sulla curva più vicino al centroide i + // 1) cerco il punto sulla curva più vicino al centroide i Point3d ptClosestOnPath ; int nFlag ; if ( ! DistPointCurve( vPtCentroid[i], *pCrvPath).GetMinDistPoint( EPS_SMALL, ptClosestOnPath, nFlag)) return false ; - // 2) spezzo la curva al paramtro del punto più vicino + // 2) spezzo la curva al paramtro del punto più vicino double dU ; if ( ! pCrvPath->GetParamAtPoint( ptClosestOnPath, dU)) return false ; @@ -1048,7 +1057,7 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT if ( ! pCrvPath->GetPointTang( dU, ICurve::FROM_MINUS, ptH, vtTanCpt)) return false ; - // 4) collego i due punti (centroide e punto più vicino alla curva) + // 4) collego i due punti (centroide e punto più vicino alla curva) PtrOwner pCrvPath1( CreateCurveComposite()) ; if ( IsNull( pCrvPath1)) return false ; @@ -1064,7 +1073,7 @@ RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRVCOMPOPOVECT pCrvPath->AddCurve( Release( pCrvB)) ; } - // la curva resitituita è una curva aperta che ha come primo punto il punto iniziale del primo medialAxis + // la curva resitituita è una curva aperta che ha come primo punto il punto iniziale del primo medialAxis // la curva restituita collega tutti i medial Axis tra di loro // la curva restitutita collega tutti i centroidi con delle circonferenze // la curva restituita ha come punto finale l'ultimo punto dell'ultimo medial Axis @@ -1094,15 +1103,15 @@ CutOffsetToClosestPoint( ICRVCOMPOPOVECTOR& vCurves, const Point3d& ptFocus, // scorro tutti gli offset ad eccezione del primo ( a meno di averne uno solo ) for ( int j = ( int)vCurves.size() == 1 ? 0 : 1 ; j < int( vCurves.size()) ; ++ j) { - // non ho offset nulli, però controllo... + // non ho offset nulli, però controllo... if( IsNull( vCurves[j])) continue ; - // prendo il punto più vicino + // prendo il punto più vicino if ( ! DistPointCurve( ptFocus, *vCurves[j]).GetMinDistPoint( EPS_SMALL, ptCl_H, nFlag)) continue ; - // cerco il punto in assoluto più vicino + // cerco il punto in assoluto più vicino if ( dDistance > Dist( ptCl_H, ptFocus)) { dDistance = Dist( ptCl_H, ptFocus) ; ptCL = ptCl_H ; @@ -1143,7 +1152,7 @@ CutLinkToClosestPoint( ICURVEPOVECTOR& vCurves, ICRVCOMPOPOVECTOR& vOffs, const nIndex = - 1 ; bFound = false ; - // scorro tutti i link cercando il più vicino + // scorro tutti i link cercando il più vicino for ( int j = 0 ; j < int( vCurves.size()) ; ++ j) { // escludo i links nulli ... @@ -1188,15 +1197,17 @@ CutCurveByOffsets( ICurveComposite* pCurve, ICRVCOMPOPOVECTOR& vOffs) { if (( int)vOffs.size() == 0) return true ; + // vettore di curve ausiliario ICRVCOMPOPOVECTOR vOffOrig( vOffs.size()) ; - for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { + for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) vOffOrig[i].Set( vOffs[i]->Clone()) ; - } + // punto iniziale corrente Point3d ptStart ; if ( ! pCurve->GetStartPoint( ptStart)) return false ; + // curve d'appoggio PtrOwner pCompo( pCurve->Clone()) ; PtrOwner pCompoHelp( pCurve->Clone()) ; PtrOwner pOffCheck( CreateCurveComposite()) ; @@ -1205,32 +1216,32 @@ CutCurveByOffsets( ICurveComposite* pCurve, ICRVCOMPOPOVECTOR& vOffs) { int nTypeOfCut = -1 ; + // scorro tutte le curve for ( int i = 0; i < int( vOffOrig.size()) ; ++ i) { + // controllo se la curva è quella attuale if ( vOffOrig[i]->IsPointOn( ptStart)) pOffCheck.Set( vOffOrig[i]->Clone()) ; - - CRVCVECTOR ccClass ; + // classificazione + CRVCVECTOR ccClass ; IntersCurveCurve intCC( *pCompo, *vOffOrig[i]) ; intCC.GetCurveClassification( 0, 10 * EPS_SMALL, ccClass) ; - if ( ! pCompoHelp->Clear()) return false ; - + // se In/Out if ( ccClass.size() > 1) { if ( ccClass[0].nClass == CRVC_IN) nTypeOfCut = CRVC_OUT ; else nTypeOfCut = CRVC_IN ; - + // scorro le classificazioni ottenute for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) { if ( ccClass[j].nClass == nTypeOfCut) { - Point3d ptS ; pCompo->GetPointD1D2( ccClass[j].dParS, ICurve::FROM_PLUS, ptS) ; double dOffS ; vOffOrig[i]->GetParamAtPoint( ptS, dOffS) ; Point3d ptE ; pCompo->GetPointD1D2( ccClass[j].dParE, ICurve::FROM_MINUS, ptE) ; double dOffE ; vOffOrig[i]->GetParamAtPoint( ptE, dOffE) ; - // recupero i due possibili percorsi e uso il più corto + // recupero i due possibili percorsi e uso il più corto PtrOwner pCrvA( GetCurve( vOffOrig[i]->CopyParamRange( dOffS, dOffE))) ; PtrOwner pCrvB( GetCurve( vOffOrig[i]->CopyParamRange( dOffE, dOffS))) ; @@ -1282,7 +1293,7 @@ CutCurveByOffsets( ICurveComposite* pCurve, ICRVCOMPOPOVECTOR& vOffs) { pCompo->AddCurve( pCompoHelp->Clone()) ; } } - + // restituisco la nuova curva pCurve->Clear() ; pCurve->AddCurve( Release( pCompo)) ; @@ -1292,8 +1303,9 @@ CutCurveByOffsets( ICurveComposite* pCurve, ICRVCOMPOPOVECTOR& vOffs) { //---------------------------------------------------------------------------- static bool GetNewCurvetWithCentroid( const ICurveComposite* pCrvH1, const ICurveComposite* pCrvH2, Point3d& ptC, - bool bCir, ICRVCOMPOPOVECTOR& VFirstOff, ICurveComposite* pCrvNewCurve) { - + bool bCir, ICRVCOMPOPOVECTOR& VFirstOff, ICurveComposite* pCrvNewCurve) +{ + // creazione dei due possibili percorsi per raggiungere il centroide PtrOwner pPath1( CreateCurveComposite()) ; PtrOwner pPath2( CreateCurveComposite()) ; if ( IsNull( pPath1) || IsNull( pPath2)) @@ -1321,7 +1333,7 @@ GetNewCurvetWithCentroid( const ICurveComposite* pCrvH1, const ICurveComposite* if ( ! AreSameVectorApprox( vtS_cir, vtS_CrvH1)) pPath1->Invert() ; - // controllo che la circonferenza sia ammissibile ( solo che non esca dalle prime curve di Offset ) + // controllo che la circonferenza sia ammissibile ( solo che non esca dalle prime curve di Offset) Point3d ptCrvS ; pPath1->GetStartPoint( ptCrvS) ; if ( ! CutCurveByOffsets( pPath1, VFirstOff)) // taglio la curva sugli Offsets return false ; @@ -1340,7 +1352,7 @@ GetNewCurvetWithCentroid( const ICurveComposite* pCrvH1, const ICurveComposite* if ( ! pCrvNewCurve->AddCurve( pPath1->Clone())) // aggiungo la circonferenza return false ; if ( pCrvH2 != nullptr && pCrvH2->GetFirstCurve() != nullptr) - if ( ! pCrvNewCurve->AddCurve(( pCrvH2->Clone()))) // aggiungo la fine + if ( ! pCrvNewCurve->AddCurve(( pCrvH2->Clone()))) // aggiungo la fine return false ; } else { // creo un BiArco @@ -1394,7 +1406,7 @@ ManageSmoothAndAutoInters( ICurveComposite* pCrv, ICurveComposite* pCrvPath, ICu pCrvPath->GetEndPoint( ptHS) ; bool bFound = false ; - int nIter = -45 ; + int nIter = - 45 ; // angolo incrementale nel caso di autointersezioni while ( ! bFound && nIter < 45) { vTanE.Rotate( Z_AX, 90 - nIter) ; // vettore perpendicolare @@ -1482,8 +1494,9 @@ ManageSmoothAndAutoInters( ICurveComposite* pCrv, ICurveComposite* pCrvPath, ICu //---------------------------------------------------------------------------- static bool GetNewCurvetWithPath( const ICurveComposite* pCrvH1, const ICurveComposite* pCrvH2, ICurveComposite* pCrvPath, - ICRVCOMPOPOVECTOR& VFirstOff, ICRVCOMPOPOVECTOR& VoffsCl, ICurveComposite* pCrvNewCurve) { - + ICRVCOMPOPOVECTOR& VFirstOff, ICRVCOMPOPOVECTOR& VoffsCl, ICurveComposite* pCrvNewCurve) +{ + // inizializzo i due possibili percorsi PtrOwner pPath1( CreateCurveComposite()) ; PtrOwner pPath2( CreateCurveComposite()) ; if ( IsNull( pPath1) || IsNull( pPath2) || pCrvPath == nullptr) @@ -1491,7 +1504,6 @@ GetNewCurvetWithPath( const ICurveComposite* pCrvH1, const ICurveComposite* pCr pCrvNewCurve->Clear() ; Point3d ptS, ptE, ptH ; Vector3d vtTanS, vtTanE, vtH ; - if ( ! pCrvPath->GetStartPoint( ptE) || ! pCrvPath->GetStartDir( vtTanE) || ! pCrvPath->GetEndPoint( ptH) || @@ -1682,7 +1694,7 @@ ChoosePath( const ICurveComposite* pCrv1, const ICurveComposite* pCrv2, int nP, CR2 = dRot2 / max( dRot1, dRot2) ; } - // funzione peso ( bilancio tra lunghezze e rotazioni complessive pesate ) + // funzione peso ( bilancio tra lunghezze e rotazioni complessive pesate) double Fp1 = ( nP == 0 ? dPerP : ( 1 - dPerP)) * ( CL1 + dSmallLines1) + ( nP == 0 ? ( 1 - dPerP) : dPerP) * ( CR1 + dSmallArcs1) ; double Fp2 = ( nP == 0 ? dPerP : ( 1 - dPerP)) * ( CL2 + dSmallLines2) + ( nP == 0 ? ( 1 - dPerP) : dPerP) * ( CR2 + dSmallArcs2) ; @@ -1713,15 +1725,15 @@ RemoveExtraParts( ISurfFlatRegion* pSrfToCut, ICRVCOMPOPOVECTOR& vOffs, ICRVCOMP if ( IsNull( pCrvPath)) return false ; - // nel caso la regione si svuoti con un centroide -> ptGoTo è il centroide - // nel caso la regione si svuoti con un medial Axis -> ptGoTo è il punto iniziale - // -> ptGoTo è il punto finale + // nel caso la regione si svuoti con un centroide -> ptGoTo è il centroide + // nel caso la regione si svuoti con un medial Axis -> ptGoTo è il punto iniziale + // -> ptGoTo è il punto finale Point3d ptGoTo, ptGoToI ; // flag : 0 -> non faccio nulla | 1 -> svuoto con centroide | 2 -> svuoto con un percorso int nOptFlag = 0 ; // ricavo il flag - // ptGoTo è il centroide, pCrvPath è la curva da seguire per svuotare la regione ( nel caso non bastasse il centroide) + // ptGoTo è il centroide, pCrvPath è la curva da seguire per svuotare la regione ( nel caso non bastasse il centroide) if ( ! RemoveExtraPartByMedialAxis( pSrfChunkToCut, vOffsFirstCurve, nOptFlag, ptGoTo, pCrvPath) || nOptFlag == 0) continue ; @@ -1732,7 +1744,7 @@ RemoveExtraParts( ISurfFlatRegion* pSrfToCut, ICRVCOMPOPOVECTOR& vOffs, ICRVCOMP continue ; // una volta trovata la curva di medial Axis ( se la regione non si svuota semplicemente passando per il - // centroide, controllo in quale direzione è più conveniente percorrerla ... ( I = Inverso) + // centroide, controllo in quale direzione è più conveniente percorrerla ... ( I = Inverso) PtrOwner pCrvH1( CreateCurveComposite()) ; PtrOwner pCrvH2( CreateCurveComposite()) ; PtrOwner pCrvH1I( CreateCurveComposite()) ; @@ -1742,8 +1754,8 @@ RemoveExtraParts( ISurfFlatRegion* pSrfToCut, ICRVCOMPOPOVECTOR& vOffs, ICRVCOMP int nIndexO = 0 ; int nIndexOI = 0 ; - // cerco il punto pià vicino a ptGoTo sugli tra i vari Offset ( escludendo il primo ) - // NB. PtGoTo è il centroide o il punto iniziale del percorso di medial Axis non invertito + // cerco il punto pià vicino a ptGoTo sugli tra i vari Offset ( escludendo il primo ) + // NB. PtGoTo è il centroide o il punto iniziale del percorso di medial Axis non invertito if ( ! CutOffsetToClosestPoint( vOffs, ptGoTo, pCrvH1, pCrvH2, nIndexO)) continue ; if ( nOptFlag == 2) // se ho un percorso di Medial Axis, lo cerco anche per PtGoToI @@ -1883,80 +1895,87 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, double dRad, double dStep, bool bSm ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset PtrOwner pSrfAct( CloneSurfFlatRegion( pSrfToWork)) ; // regione attuale - PtrOwner pSrfPrec( CloneSurfFlatRegion( pSrfToWork)) ; // regione precedente - if ( IsNull( pSrfAct) || IsNull( pSrfPrec) || pSrfAct->GetChunkCount() == 0 || pSrfPrec->GetChunkCount() == 0) + if ( IsNull( pSrfAct) || pSrfAct->GetChunkCount() == 0) return false ; + double dOffsPrec = dOffs ; while ( nIter < MAX_ITER) { - // salvo la regione - pSrfPrec.Set( pSrfAct->Clone()) ; - if ( ! pSrfAct->Offset( - dOffs, ICurve::OFF_FILLET)) - return false ; - if ( ! pSrfAct->IsValid()) { - pSrfAct.Set( pSrfPrec->Clone()) ; - if ( ! pSrfAct->Offset( - dOffs + 5 * EPS_SMALL, ICurve::OFF_FILLET)) - return false ; + // ricavo la regione piana da VRONI + PtrOwner pSfrOffsVR( pSrfAct->CreateOffsetSurf( - dOffs, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrOffsVR)) + return false ; + if ( ! pSfrOffsVR->IsValid()) { + pSfrOffsVR.Set( pSrfAct->CreateOffsetSurf( - dOffs + 5 * EPS_SMALL, ICurve::OFF_FILLET)) ; + if ( IsNull( pSfrOffsVR)) + return false ; } - // estraggo il contorno della FlatRegion (ciclo i Chunks e prendo i rispettivi Loops) + // alla prima iterazione svuoto la regione nReg-esima passata alla funzione CalcSpiral if ( nIter == 0) { - PtrOwner pSrfChunknReg( pSrfAct->CloneChunk( nReg)) ; - nReg = pSrfAct->GetChunkCount() ; // aggiorno il nuovo valore delle regioni - if ( IsNull( pSrfChunknReg)) // se supero i chunk ottenuti + PtrOwner pSrfChunknReg( pSfrOffsVR->CloneChunk( nReg)) ; + nReg = pSfrOffsVR->GetChunkCount() ; // aggiorno il nuovo valore delle regioni + if ( IsNull( pSrfChunknReg)) // se supero i chunk ottenuti return true ; - pSrfAct.Set( pSrfChunknReg) ; } - int nChunks = pSrfAct->GetChunkCount() ; // numero di Chunk attuali + // numero di Chunk attuali + int nChunks = pSfrOffsVR->GetChunkCount() ; for ( int i = 0 ; i < nChunks ; ++ i) { // per ogni chunk... - int nLoops = pSrfAct->GetLoopCount( i) ; + int nLoops = pSfrOffsVR->GetLoopCount( i) ; for ( int j = 0 ; j < nLoops ; ++ j) { // per ogni loop... - PtrOwner ptoCCBorder( ConvertCurveToComposite( pSrfAct->GetLoop( i, j))) ; - if ( j > 0) // inverto l'orientamento delle curve interne (offset delle isole trovate) - ptoCCBorder->Invert() ; - // controllo quali regioni di Offset possono essere sostituite - bool bInsert = true ; - if ( bInsert) - vOffs.emplace_back( Release( ptoCCBorder)) ; - PtrOwner ptoCCExtBorder( ConvertCurveToComposite( pSrfAct->GetLoop( i, j))) ; - if ( nIter == 0) // salvo il bordo per i link (non invertiti) - vOffsFirstCurve.emplace_back( Release( ptoCCExtBorder)) ; + PtrOwner pCrvCompoBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ; + if ( IsNull( pCrvCompoBorder) || ! pCrvCompoBorder->IsValid()) + return false ; + if ( j > 0) // inverto l'orientamento delle curve interne ( offset delle isole trovate) + pCrvCompoBorder->Invert() ; + // inserisco nel vettore degli Offset + vOffs.emplace_back( Release( pCrvCompoBorder)) ; + // salvo le curve di Offset esterne della prima iterazione + if ( nIter == 0) { // salvo il bordo per i link ( non invertiti) + PtrOwner pCrvCompoExtBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ; + vOffsFirstCurve.emplace_back( Release( pCrvCompoExtBorder)) ; + } } } - bool bSmallRad = ( nIter == 0 ? dOffs < dRad + EPS_ZERO : dOffs < dRad + EPS_ZERO) ; + // controllo se serve un raggio più piccolo di svuotatura + bool bSmallRad = ( nIter == 0 ? dOffs - dOffsPrec < dRad + EPS_ZERO : dOffs - dOffsPrec < dRad + EPS_ZERO) ; + // memorizzo il valore di Offset per l'iterazione successiva + dOffsPrec = dOffs ; + // se ho trovato dei chunk, allora aggiorno l'Offset per la passata successiva if ( nChunks > 0) - dOffs = dStep ; - else if ( ! bSmallRad) { - pSrfAct.Set( pSrfPrec) ; - dOffs = ( nIter == 0 ? dRad : dRad) ; // superfluo, effettivamente non ho l'offset radiale - } + dOffs += dStep ; + // se devo usare un Offset più piccolo... + else if ( ! bSmallRad) + dOffs += ( nIter == 0 ? dRad : dRad) ; // superfluo, effettivamente non ho l'offset radiale + // altrimenti ho finito la regione da svuotare... else break ; - ++ nIter ; + ++ nIter ; // aggiorno iterazione } // se non ho trovato curve di Offset allora esco if (( int)vOffs.size() == 0) return true ; - // cambio il punto iniziale della prima Curva di Offset + // cambio il punto iniziale della prima Curva di Offset AdjustContourStart( vOffs[0]) ; // smusso le curve di offset ( ad eccezione della prima, se richisto) ICRVCOMPOPOVECTOR vOffsClosedCurves( vOffs.size()) ; // vettore con tutte le curve di Offset Chiuse - for ( int i = 0 ; i < int( vOffs.size()) ; ++i ) { - if ( i != 0) + for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { + if ( i != 0) { ModifyCurveToSmoothed( vOffs[i], RAD / 8, RAD/8, false) ; - // imbroglio - if ( i != 0) vOffs[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; + } vOffsClosedCurves[i].Set( vOffs[i]->Clone()) ; + // NB. Salvo questo vettore in quanto il BiArco di raccordo tra la curva (i)-esima e la (i+1)-esima potrebbe + // intersecare altre curve oltre queste due. ( CutCurveToConnect( ...)) } for ( int i = 0 ; i < int( vOffsFirstCurve.size()) ; ++ i) { @@ -1973,77 +1992,89 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, double dRad, double dStep, bool bSm for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) { + // prendo il punto iniziale Point3d ptS ; if ( ! vOffs[i]->GetStartPoint( ptS)) return false ; - // setto i default delle variabili + // setto i default delle variabili if ( ! DistPointCurve( ptS, *vOffs[i+1]).GetMinDistPoint( EPS_SMALL, ptHelp, nFlag)) return false ; dDist = INFINITO ; + // scorro le curve successive for ( int j = i + 1 ; j <= int( vOffs.size()) - 1 ; ++ j) { - // cerco il punto più vicino della curva - Point3d ptE ; + // cerco il punto più vicino della curva + Point3d ptE ; if ( ! DistPointCurve( ptS, *vOffs[j]).GetMinDistPoint( EPS_SMALL, ptE, nFlag)) return false ; + // memorizzo l'indice della curva più vicina ( aggiornando il valore della distanza) if ( dDist > Dist( ptS, ptE) ) { dDist = Dist( ptS, ptE) ; nClosestInd = j ; ptHelp.Set( ptE.x, ptE.y, ptE.z) ; } } - // avendo la curva più vicina ... - // 1) scambio la curva i con la curva nClosestInd + // 1) scambio la curva i con la curva più vicina trovata ( se non è la successiva) if ( nClosestInd != i + 1) { PtrOwner ptoCCHelp( Release( vOffs[i + 1])) ; vOffs[i + 1].Set( vOffs[nClosestInd]) ; vOffs[nClosestInd].Set( ptoCCHelp) ; } - // 2) cambio il suo punto iniziale ... + // 2) cambio il suo punto iniziale ( nel punto più vicino trovato)... double dU ; Point3d ptNE( ptHelp.x, ptHelp.y, ptHelp.z) ; if ( ! vOffs[i + 1]->GetParamAtPoint( ptNE, dU)) return false ; vOffs[i + 1]->ChangeStartPoint( dU) ; - // 2.1) Accorcio la curva per velocizzare ... - if (( int)vOffs.size() > 1) { // accorcio se ho almeno due Offset - // copio le curve i e i+1 nel caso non riesca a tagliarle ... + // 2.1) Accorcio la curva per raccordarla con la successiva ... + if (( int)vOffs.size() > 1) { // se ho almeno un Offset + // copio le curve (i)-esime e (i+1)-esime double dUNS, dUNE ; PtrOwner pCrvTest( CreateCurveComposite()) ; // possibile collegamento tra la curva i ed i+1 + if ( IsNull( pCrvTest)) + return false ; PtrOwner pOff_i0( CloneCurveComposite( vOffs[i])) ; PtrOwner pOff_i1( CloneCurveComposite( vOffs[i + 1])) ; - // cerco di tagliare le curve, ottenendo il collegamento - // NB. se la curva di offset è la prima, non devo tagliarla, accorcio solo le successive ... + // cerco di tagliare le curve e di raccordarle ( -> ottenendo il collegamento) + // NB. se la curva di offset è la prima, non devo tagliarla, accorcio solo le successive ( se non bordi di isole) ... if ( ! SMOOTH || ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsClosedCurves, vOffsFirstCurve, pCrvTest, i == 0 ? 0 : 0.01, 0.01, 2)) { - // se non sono riuscito, ritorno alla configurazione iniziale + // se non sono riuscito ad accorcirle, ritorno alla configurazione iniziale PtrOwner pCrvLink( CreateCurveComposite()) ; + if ( IsNull( pCrvLink)) + return false ; + // vettori tangenti per raccordo Vector3d vS, vE ; - vOffs[i].Set( pOff_i0) ; vOffs[i+1].Set( pOff_i1) ; + vOffs[i].Set( pOff_i0) ; + vOffs[i+1].Set( pOff_i1) ; if ( ! vOffs[i]->GetStartDir( vS) || ! vOffs[i+1]->GetStartDir( vE)) return false ; + // calcolo il raccordo if ( CalcBoundedSmootedLink( ptS, vS, ptNE, vE, 0.5, vOffsFirstCurve, pCrvLink)) vLinks[i + 1].Set( pCrvLink) ; // aggiorno il collegamento else return false ; - + // passo alla successiva continue ; } + // ricavo i parametri nei punti scelti if ( ! pCrvTest->GetStartPoint( ptS) || - ! pCrvTest->GetEndPoint( ptNE) || - ! vOffs[i]->GetParamAtPoint( ptS, dUNS) || - ! vOffs[i+1]->GetParamAtPoint( ptNE, dUNE)) + ! pCrvTest->GetEndPoint( ptNE) || + ! vOffs[i]->GetParamAtPoint( ptS, dUNS) || + ! vOffs[i+1]->GetParamAtPoint( ptNE, dUNE)) return false ; - + // imposto il nuovo punto inziale della curva successiva vOffs[i+1]->ChangeStartPoint( dUNE) ; PtrOwner pCrvNewOffS( CloneCurveComposite( vOffs[i])) ; + if ( IsNull( pCrvNewOffS) || ! pCrvNewOffS->IsValid()) + return false ; if ( dUNS > EPS_SMALL) { // se parametro di trim sufficientemente grande pCrvNewOffS.Set( GetCurveComposite( vOffs[i]->CopyParamRange( 0, dUNS))) ; // sostituisco la curva i-esima con quella tagliata @@ -2051,17 +2082,14 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, double dRad, double dStep, bool bSm vOffs[i].Set( pCrvNewOffS) ; } // aggiorno il collegamento - vLinks[i + 1].Set( pCrvTest) ; + vLinks[i+1].Set( pCrvTest) ; } } - // copio il vettore degli Offset per settare poi la Feed - ICRVCOMPOPOVECTOR vOffsFeed ; vOffsFeed.reserve(( int)vOffs.size()) ; - for ( int i = 0 ; i < ( int)vOffs.size() ; ++ i) - vOffsFeed.emplace_back( vOffs[i]->Clone()) ; - // 3) controllo eventuali parti non svuotate... PtrOwner pSrfToCut( CreateSurfFlatRegion()) ; + if ( IsNull( pSrfToCut)) + return false ; if ( GetUnclearedRegion( vOffsFirstCurve, vOffs, vLinks, pSrfToCut)) { // 4) Modifico i percorsi if ( ! RemoveExtraParts( pSrfToCut, vOffs, vOffsClosedCurves, vOffsFirstCurve, vLinks)) @@ -2071,13 +2099,13 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, double dRad, double dStep, bool bSm // calcolo il percorso di ritorno if (( int)vOffs.size() >= 2) { pRCrv->Clear() ; - // punto inziale e finale | vettore iniziale e finale + // punto inziale e finale | vettore tangente iniziale e finale Point3d ptStart ; vOffs.back()->GetEndPoint( ptStart) ; Point3d ptEnd ; vOffs.front()->GetStartPoint( ptEnd) ; Vector3d vtStart ; vOffs.back()->GetEndDir( vtStart) ; Vector3d vtEnd ; vOffs.front()->GetStartDir( vtEnd) ; - // calcolo il ritorno (garantendo che non esca dalla svuotatura) + // calcolo il ritorno ( garantendo che non esca dalla svuotatura) PtrOwner pCrvLink( CreateCurveComposite()) ; if ( CalcBoundedSmootedLink( ptStart, vtStart, ptEnd, vtEnd, 0.5, vOffsFirstCurve, pCrvLink)) { pRCrv->AddCurve( Release( pCrvLink)) ; @@ -2123,7 +2151,7 @@ CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nSt return false ; nStat = 1 ; // 0 -> no overlap | 1 -> overlap - // controllo se una sottocurva della composita è abbastanza vicina a tutti i punti trovati + // controllo se una sottocurva della composita è abbastanza vicina a tutti i punti trovati const double nMAX = 10.0 ; for ( int i = 0 ; i <= nMAX ; ++i) { double dPar = i / nMAX ; @@ -2168,7 +2196,7 @@ CalcZigZagLink( ICurveComposite* pCrv1, ICurveComposite* pCrv2, ICurveComposite* double dAngle, dAngleH ; double dDist = Dist( ptS, ptE) ; - // curve per controllo validità del collegamento + // curve per controllo validità del collegamento PtrOwner pCrvH1( CreateCurveComposite()) ; PtrOwner pCrvH2( CreateCurveComposite()) ; PtrOwner pCrvTempLink( CreateCurveComposite()) ; @@ -2245,7 +2273,7 @@ CalcZigZagLink( ICurveComposite* pCrv1, ICurveComposite* pCrv2, ICurveComposite* pCrv_smoothed->AddCurve( pCrvH2->Clone()) ; ModifyCurveToSmoothed( pCrv_smoothed, dTollLeft, dTollRight, true) ; - // recupero i parametri del nuovo collegamento che si è creato dallo smusso + // recupero i parametri del nuovo collegamento che si è creato dallo smusso pCrvH1->Clear() ; pCrvTempLink->Clear() ; pCrvH2->Clear() ; @@ -2456,7 +2484,7 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, ICRVCOMPOPOVECTOR& vpCrvs, double vLineUnder.emplace_back( Release( pLU)) ; } } - // creo la linea come curva composita, aggiungerò dei Joint per ogni tratto con Feed differente + // creo la linea come curva composita, aggiungerò dei Joint per ogni tratto con Feed differente PtrOwner pLineCompo( CreateCurveComposite()) ; if ( IsNull( pLineCompo)) return false ; @@ -2582,7 +2610,7 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, ICRVCOMPOPOVECTOR& vpCrvs, double BBox3d b3Copy ; if ( ! IsNull( pCopy)) pCopy->GetLocalBBox( b3Copy) ; - if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10 * EPS_SMALL) { // tengo la curva (non ritorno indietro più dello step) + if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10 * EPS_SMALL) { // tengo la curva (non ritorno indietro più dello step) Point3d ptS, ptE ; pCrvLink->Clear() ; pCrvLink->AddCurve( pCopy->Clone()) ; @@ -2686,7 +2714,7 @@ AddSpiralOut( const ISurfFlatRegion* pSrfPock, double dRad, double dStep, bool b if ( pMCrv->GetCurveCount() == 0) break ; // passo al chunk originale successivo - // inverto i percorsi, perchè sono calcolati dall'esterno all'interno (solo nel caso non ottimizzato) + // inverto i percorsi, perchè sono calcolati dall'esterno all'interno (solo nel caso non ottimizzato) pMCrv->Invert() ; pRCrv->Invert() ; @@ -2768,7 +2796,7 @@ OptimizeChunkOneWay( ISurfFlatRegion* pSrfOrig, ISURFFRPOVECTOR& vSrfIdeal) if ( IsNull( pSrfToPock) || pSrfToPock->GetChunkCount() == 0) return false ; - // classifico i chunks in modo da creare delle regioni ideali; una regione ideale è formata da un chunk principale + // classifico i chunks in modo da creare delle regioni ideali; una regione ideale è formata da un chunk principale // con tutti gli altri contenuti in esso ( in questo modo ottimizzo i percorsi per i bordi) INTVECTOR vChunksAvailable( pSrfToPock->GetChunkCount(), 1) ; @@ -2782,11 +2810,11 @@ OptimizeChunkOneWay( ISurfFlatRegion* pSrfOrig, ISURFFRPOVECTOR& vSrfIdeal) PtrOwner pCrvExt( ConvertCurveToComposite( pSrfToPock->GetLoop( c, 0))) ; if ( IsNull( pCrvExt)) return false ; - // inserisco il chunk c-esimo ( curva per curva, così non perdo le temp prop) + // inserisco il chunk c-esimo ( curva per curva, così non perdo le temp prop) pSrfIdeal->AddExtLoop( pCrvExt->Clone()) ; // ... inizio a creare la regione ideale da esso for ( int l = 1 ; l < pSrfToPock->GetLoopCount( c) ; ++ l) pSrfIdeal->AddIntLoop( ConvertCurveToComposite( pSrfToPock->GetLoop( c, l))) ; - // il chunk c-esimo non è più disponibile... + // il chunk c-esimo non è più disponibile... vChunksAvailable[c] = -1 ; // scorro tutti gli altri chunk i-esimi ancora disponibili for ( int i = 0 ; i < int( vChunksAvailable.size()) ; ++ i) { @@ -2795,7 +2823,7 @@ OptimizeChunkOneWay( ISurfFlatRegion* pSrfOrig, ISURFFRPOVECTOR& vSrfIdeal) PtrOwner pCrvExtC( ConvertCurveToComposite( pSrfToPock->GetLoop( i, 0))) ; if ( IsNull( pCrvExtC)) return false ; - // classifico i bordi esterni ( se il bordo del chunk c-esimo contiene o è contenuto nel loop + // classifico i bordi esterni ( se il bordo del chunk c-esimo contiene o è contenuto nel loop // esterno del chunk i-esimo -> sono chunks appartenenti alla stessa superficie ideale) IntersCurveCurve intCC( *pCrvExtC, *pCrvExt) ; CRVCVECTOR ccClass, ccClass1 ; @@ -2803,11 +2831,11 @@ OptimizeChunkOneWay( ISurfFlatRegion* pSrfOrig, ISURFFRPOVECTOR& vSrfIdeal) intCC.GetCurveClassification( 1, EPS_SMALL, ccClass1) ; if (( ccClass.size() == 1 && ccClass[0].nClass == CRVC_IN) || ( ccClass1.size() == 1 && ccClass1[0].nClass == CRVC_IN)) { - // inserisco il chunk i-esimo ( curva per curva, così non perdo le temp prop) + // inserisco il chunk i-esimo ( curva per curva, così non perdo le temp prop) pSrfIdeal->AddExtLoop( ConvertCurveToComposite( pSrfToPock->GetLoop( i, 0))) ; for ( int l = 1 ; l < pSrfToPock->GetLoopCount( i) ; ++ l) pSrfIdeal->AddIntLoop( ConvertCurveToComposite( pSrfToPock->GetLoop( i, l))) ; - vChunksAvailable[i] = -1 ; // chunk j-esimo non più disponibile + vChunksAvailable[i] = -1 ; // chunk j-esimo non più disponibile // NB: Se il chunk i-esimo contiene la pSrfIdeal ( quindi chunk i-esimo unito ad eventuali altri chunk // j-esimi precedenti -> prendo come bordo esterno di riferimento il suo e ricontrollo dall'inizio i // chunk disponibili @@ -2855,7 +2883,7 @@ AddOneWay( const ISurfFlatRegion* pSrfPock, double dRad, double dStep, double dA if ( ! OptimizeChunkOneWay( pSrfToPock, vSrfFlat)) return false ; - // riporto le superfici ideali nel sistema di riferimento globale ( Ogni chunk verrà poi messo nel suo frame) + // riporto le superfici ideali nel sistema di riferimento globale ( Ogni chunk verrà poi messo nel suo frame) for ( int i = 0 ; i < ( int)vSrfFlat.size() ; ++ i) vSrfFlat[i]->ToGlob( frLoc) ; // ------------------------------------------------------------------ @@ -2943,7 +2971,7 @@ CalcPocketing( const ISurfFlatRegion *pSfr, double dRad, double dStep, double dA // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid() || dStep < EPS_SMALL || - ( nType != POCKET_SUB_ZIGZAG && nType != POCKET_SUB_ONEWAY && nType != POCKET_SUB_SPIRALIN && nType != POCKET_SUB_SPIRALOUT)) + ( nType != POCKET_ZIGZAG && nType != POCKET_ONEWAY && nType != POCKET_SPIRALIN && nType != POCKET_SPIRALOUT)) return false ; vCrvCompoRes.clear() ; // pulizia vettore delle curve elementari TYPE = nType ; @@ -2952,19 +2980,19 @@ CalcPocketing( const ISurfFlatRegion *pSfr, double dRad, double dStep, double dA // calcolo delle curve elementari della superficie switch ( nType) { - case POCKET_SUB_ZIGZAG: + case POCKET_ZIGZAG: if ( ! AddZigZag( pSfr, dRad, dStep, dAngle, bSmooth, vCrvCompoRes)) return false ; break ; - case POCKET_SUB_ONEWAY: + case POCKET_ONEWAY: if ( ! AddOneWay( pSfr, dRad, dStep, dAngle, bSmooth, vCrvCompoRes)) return false ; break ; - case POCKET_SUB_SPIRALIN: + case POCKET_SPIRALIN: if ( ! AddSpiralIn( pSfr, dRad, dStep, bSmooth, vCrvCompoRes)) return false ; break ; - case POCKET_SUB_SPIRALOUT: + case POCKET_SPIRALOUT: if ( ! AddSpiralOut( pSfr, dRad, dStep, bSmooth, vCrvCompoRes)) return true ; break ; @@ -3003,9 +3031,9 @@ AdjustZigZagPathTangentLinks( ICurveComposite* pCrvCompo) } if ( ! pCrvLink->IsValid()) return false ; - // se ho più di una curva nel link + // se ho più di una curva nel link if ( pCrvLink->GetCurveCount() > 1) { - // ricavo la curva precendente al Link ( se presente e se prima curva del Link è lineare) + // ricavo la curva precendente al Link ( se presente e se prima curva del Link è lineare) if ( u != 0 && pCrvLink->GetFirstCurve()->GetType() == CRV_LINE) { const ICurve* pCrvSegPrec = pCrvCompo->GetCurve( u - 1) ; if ( pCrvSegPrec == nullptr || pCrvSegPrec->GetType() != CRV_LINE) @@ -3018,7 +3046,7 @@ AdjustZigZagPathTangentLinks( ICurveComposite* pCrvCompo) if ( AreSameVectorApprox( vtZigZagEndDir, vtLinkStartDir)) pCrvCompo->SetCurveTempProp( u, 0, 1) ; } - // ricavo la curva successiva al Link ( se presente e se ultima curva del Link è lineare) + // ricavo la curva successiva al Link ( se presente e se ultima curva del Link è lineare) if ( u + pCrvLink->GetCurveCount() < pCrvCompo->GetCurveCount() && pCrvLink->GetLastCurve()->GetType() == CRV_LINE) { const ICurve* pCrvSegSucc = pCrvCompo->GetCurve( u + pCrvLink->GetCurveCount()) ; if ( pCrvSegSucc == nullptr || pCrvSegSucc->GetType() != CRV_LINE) @@ -3033,7 +3061,7 @@ AdjustZigZagPathTangentLinks( ICurveComposite* pCrvCompo) } } // aggiorno - u += pCrvLink->GetCurveCount() ; // così la successiva è corretta nel ciclo + u += pCrvLink->GetCurveCount() ; // così la successiva è corretta nel ciclo } } @@ -3206,14 +3234,14 @@ AdjustLinkZigZagInfill( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vNewCrv) return false ; } // aggiorno - u += pCrvLink->GetCurveCount() ; // così la successiva è corretta nel ciclo + u += pCrvLink->GetCurveCount() ; // così la successiva è corretta nel ciclo if ( bSplit) { // se dimensione sopra la tolleranza, allora spezzo la curva e rimuovo il link CopyRange CR { 1. * nCrvStartBreak, // dParS 1. * ( u - pCrvLink->GetCurveCount()) // dParE } ; - // se il primo tratto è un link non valido, non considero l'intervallo + // se il primo tratto è un link non valido, non considero l'intervallo if ( ! ( nCrvStartBreak == 0 && abs( CR.dParS - CR.dParE) < 20 * EPS_SMALL)) vIntervals.push_back( CR) ; nCrvStartBreak = u ; @@ -3227,7 +3255,7 @@ AdjustLinkZigZagInfill( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vNewCrv) // per ogni intervallo... for ( int i = 0 ; i < int( vIntervals.size()) ; ++ i) vNewCrv.emplace_back( ConvertCurveToComposite( pCrvCompo->CopyParamRange( vIntervals[i].dParS, vIntervals[i].dParE))) ; - // ultimo intervallo ( se l'ultimo intervallo è un link non valido, non inserisco) + // ultimo intervallo ( se l'ultimo intervallo è un link non valido, non inserisco) if ( abs( vIntervals.back().dParE - pCrvCompo->GetCurveCount()) > 20 * EPS_SMALL) vNewCrv.emplace_back( ConvertCurveToComposite( pCrvCompo->CopyParamRange( nCrvStartBreak, pCrvCompo->GetCurveCount()))) ; } @@ -3237,7 +3265,7 @@ AdjustLinkZigZagInfill( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vNewCrv) //---------------------------------------------------------------------------- bool -CalcZigZagInfill( const ISurfFlatRegion* pSfr, double dStep, bool bSmooth, ICRVCOMPOPOVECTOR& vCrvCompoRes) +CalcZigZagInfill( const ISurfFlatRegion* pSfr, double dStep, bool bSmooth, bool bRemoveOverlapLink, ICRVCOMPOPOVECTOR& vCrvCompoRes) { // controllo dei parametri if ( pSfr == nullptr || ! pSfr->IsValid() || dStep < EPS_SMALL) @@ -3258,35 +3286,31 @@ CalcZigZagInfill( const ISurfFlatRegion* pSfr, double dStep, bool bSmooth, ICRVC // calcolo i percorsi a ZigZag if ( ! CalcZigZag( pSfrChunk, vpCrvs, dStep, true)) return false ; - ICRVCOMPOPOVECTOR vCrvFinal ; - // sistemo le curve ottenute, aggiustando i Links - for ( int u = 0 ; u < int( vpCrvs.size()) ; ++ u) { - ICRVCOMPOPOVECTOR vNewCrv ; - if ( ! AdjustLinkZigZagInfill( vpCrvs[u], vNewCrv)) - return false ; - for ( int uu = 0 ; uu < int( vNewCrv.size()) ; ++ uu) - vCrvFinal.emplace_back( Release( vNewCrv[uu])) ; - vNewCrv.clear() ; - //vCrvFinal.emplace_back( Release( vpCrvs[u])) ; + + if ( bRemoveOverlapLink) { + ICRVCOMPOPOVECTOR vCrvFinal ; + for ( int u = 0 ; u < int( vpCrvs.size()) ; ++ u) + vCrvFinal.emplace_back( Release( vpCrvs[u])) ; + vpCrvs.clear() ; + // sistemo le curve ottenute, aggiustando i Links + for ( int u = 0 ; u < int( vCrvFinal.size()) ; ++ u) { + ICRVCOMPOPOVECTOR vNewCrv ; + if ( ! AdjustLinkZigZagInfill( vCrvFinal[u], vNewCrv)) + return false ; + for ( int uu = 0 ; uu < int( vNewCrv.size()) ; ++ uu) + vpCrvs.emplace_back( Release( vNewCrv[uu])) ; + } } + // inserisco i percorsi da ritornare - for ( int u = 0 ; u < int( vCrvFinal.size()) ; ++ u) { + for ( int u = 0 ; u < int( vpCrvs.size()) ; ++ u) { if ( bSmooth) { SMOOTH = true ; - ModifyCurveToSmoothed( vCrvFinal[u], RAD / 16, RAD / 16, false) ; + ModifyCurveToSmoothed( vpCrvs[u], RAD / 16, RAD / 16, false) ; } - vCrvCompoRes.emplace_back( Release( vCrvFinal[u])) ; + vCrvCompoRes.emplace_back( Release( vpCrvs[u])) ; } - vCrvFinal.clear() ; } return true ; -} - -//---------------------------------------------------------------------------- -bool -CalcSpiralInfill( const ISurfFlatRegion* pSfr, double dStep, bool bSmooth, ICRVCOMPOPOVECTOR& vCrvCompoRes) -{ - return true ; -} - +} \ No newline at end of file diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index 60c1e08..a250754 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -1424,254 +1424,6 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& } } -//---------------------------------------- -bool -SurfFlatRegion::GetZigZagInfill( double dStep, bool bStepCorrection, bool bInvert, ICRVCOMPOPOVECTOR& vpCrvs) const -{ - // ingombro della regione - BBox3d b3Pocket ; - GetLocalBBox( b3Pocket) ; - Point3d ptMin ; double dDimX, dDimY, dDimZ ; - b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ; - - // lunghezza dei contorni - DBLVECTOR vLen( m_vpLoop.size()) ; - for ( size_t i = 0 ; i < vLen.size() ; i++) - m_vpLoop[i]->GetLength( vLen[i]) ; - - // passi in Y - double dYStep = dStep ; - int nYStep = static_cast( floor( dDimY / dStep)) ; - int nRef = 0 ; - if ( bStepCorrection) { - // se permesso, lo modifico per coprire uniformemente la regione - nYStep = static_cast( ceil( ( dDimY - 30 * EPS_SMALL) / dStep)) ; - dYStep = ( nYStep > 0 ? ( dDimY - 30 * EPS_SMALL) / nYStep : 0) ; - nRef = ( ( nYStep + ( bInvert ? 0 : 1)) % 2) ; - } - - // tratto valido - struct Section { - bool bActive ; - Point3d ptS ; - Point3d ptE ; - double dOs ; - double dOe ; - size_t nIdxS ; // indice del loop a cui appartiene ptS - size_t nIdxE ; // indice del loop a cui appartiene ptE - } ; - // raccolta di tratti - typedef vector> VECVECSECT ; - - VECVECSECT vvSec ; - vvSec.resize( nYStep + 1) ; - - // calcolo le linee di svuotatura - int nCount = 0 ; - for ( int i = 0 ; i <= nYStep ; ++ i) { - // determino senso - bool bPlus = (( i % 2) == nRef) ; - // definisco correzione per essere sicura di poter fare primo e ultimo step - double dCorr = 0 ; - if ( i == 0) - dCorr = 10 * EPS_SMALL ; - else if ( i == nYStep) - dCorr = - 10 * EPS_SMALL ; - // definisco la linea - PtrOwner pLine( CreateBasicCurveLine()) ; - const double EXP_LEN = 1.0 ; - Point3d ptStart( ptMin.x - EXP_LEN, ptMin.y + dCorr + i * dYStep, ptMin.z + dDimZ) ; - if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX , dDimX + 2 * EXP_LEN)) { - return false ; - } - - // calcolo la classificazione della curva rispetto alla regione - CRVCVECTOR ccClass ; - if ( ! GetCurveClassification( *pLine, EPS_SMALL, ccClass)) - return false ; - - // determino gli intervalli di curva da conservare - Intervals inOk ; - for ( auto& ccOne : ccClass) { - if ( ccOne.nClass == CRVC_IN || ccOne.nClass == CRVC_ON_P || ccOne.nClass == CRVC_ON_M) - inOk.Add( ccOne.dParS, ccOne.dParE) ; - } - // inserisco i tratti validi (secondo X+ i pari, secondo X- i dispari) - double dParS, dParE ; - bool bFound = ( bPlus ? inOk.GetFirst( dParS, dParE) : inOk.GetLast( dParE, dParS)) ; - while ( bFound) { - // determino i dati della sezione - Section Sect ; - Sect.bActive = true ; - pLine->GetPointD1D2( dParS, ICurve::FROM_PLUS, Sect.ptS) ; - pLine->GetPointD1D2( dParE, ICurve::FROM_MINUS, Sect.ptE) ; - - // porto i punti nel riferimento della curva - if ( ! AreSameFrame( m_frF, GLOB_FRM)) { - Sect.ptS.ToLoc( m_frF) ; - Sect.ptE.ToLoc( m_frF) ; - } - - // cerco la curva della regione che passa per ptS - bool bCrvFound = false ; - for ( size_t k = 0 ; ! bCrvFound && k < m_vpLoop.size() ; k++) { - bCrvFound = m_vpLoop[k]->GetParamAtPoint( Sect.ptS, Sect.dOs, 10 * EPS_SMALL) ; - if ( bCrvFound) - Sect.nIdxS = k ; - } - if ( ! bCrvFound) - return false ; - - // cerco la curva della regione che passa per ptE - bCrvFound = false ; - for ( size_t k = 0 ; ! bCrvFound && k < m_vpLoop.size() ; k++) { - bCrvFound = m_vpLoop[k]->GetParamAtPoint( Sect.ptE, Sect.dOe, 10 * EPS_SMALL) ; - if ( bCrvFound) - Sect.nIdxE = k ; - } - if ( ! bCrvFound) - return false ; - - // inserisco nel contenitore - vvSec[i].emplace_back( Sect) ; - ++ nCount ; - // recupero intervallo successivo - bFound = ( bPlus ? inOk.GetNext( dParS, dParE) : inOk.GetPrev( dParE, dParS)) ; - } - } - - // dominio del contorno - DBLVECTOR vUmax( m_vpLoop.size()) ; - DBLVECTOR vUmin( m_vpLoop.size()) ; - DBLVECTOR vUspan( m_vpLoop.size()) ; - for ( size_t i = 0 ; i < m_vpLoop.size() ; i++) { - m_vpLoop[i]->GetDomain( vUmin[i], vUmax[i]) ; - vUspan[i] = vUmax[i] - vUmin[i] ; - } - - // creo i percorsi di svuotatura - vpCrvs.reserve( nCount) ; - int nI = -1, nJ = -1 ; - while ( true) { - // se sezione non valida - if ( nI < 0 || nJ < 0) { - // ricerco la prima valida - for ( int k = 0 ; k < int( vvSec.size()) && nI < 0 ; ++ k) { - for ( int l = 0 ; l < int( vvSec[k].size()) && nJ < 0 ; ++ l) { - if ( vvSec[k][l].bActive) { - nI = k ; - nJ = l ; - } - } - } - // se trovata, creo nuova curva composita - if ( nI >= 0 && nJ >= 0) { - // creo la curva - vpCrvs.emplace_back( CreateCurveComposite()) ; - // aggiungo punto iniziale - vpCrvs.back()->AddPoint( vvSec[nI][nJ].ptS) ; - } - // altrimenti, esco - else - break ; - } - // determino senso - bool bPlus = (( nI % 2) == nRef) ; - // aggiungo la sezione alla curva - Section& Sec = vvSec[nI][nJ] ; - Sec.bActive = false ; - vpCrvs.back()->AddLine( vvSec[nI][nJ].ptE) ; - // cerco nella stessa fila o in quella successiva sezione successiva raccordabile tramite il contorno - double dUstart = Sec.dOe ; - double dUref = ( bPlus ? INFINITO : - INFINITO) ; - int nNextI = -1 ; - int nNextJ = -1 ; - int li = nJ + 1 ; - for ( int k = nI ; k <= nI + 1 && k < int( vvSec.size()) ; ++ k) { - for ( int l = li ; l < int( vvSec[k].size()) ; ++ l) { - if ( ! vvSec[k][l].bActive) - continue ; - // la nuova sezione deve partire dalla stessa curva su cui ci si è fermati - if ( vvSec[k][l].nIdxS != Sec.nIdxE) - continue ; - double dU = vvSec[k][l].dOs ; - if ( bPlus) { - if ( dU < dUstart) - dU += vUspan[Sec.nIdxE] ; - if ( dU < dUref) { - dUref = dU ; - nNextI = k ; - nNextJ = l ; - } - } - else { - if ( dU > dUstart) - dU -= vUspan[Sec.nIdxE] ; - if ( dU > dUref) { - dUref = dU ; - nNextI = k ; - nNextJ = l ; - } - } - } - li = 0 ; - } - // se trovato, aggiungo il tratto di contorno e continuo - if ( nNextI != -1) { - PtrOwner pCopy ; - size_t idx = vvSec[nNextI][nNextJ].nIdxS ; - if ( bPlus) { - if ( dUref > vUmax[idx]) - dUref -= vUspan[idx] ; - pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUstart, dUref)) ; - if ( ! IsNull( pCopy)) { - double dCLen ; pCopy->GetLength( dCLen) ; - if ( dCLen > 0.5 * vLen[idx]) { - pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUref, dUstart)) ; - if ( ! IsNull( pCopy)) - pCopy->Invert() ; - } - } - } - else { - if ( dUref < vUmin[idx]) - dUref += vUspan[idx] ; - pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUref, dUstart)) ; - if ( ! IsNull( pCopy)) { - pCopy->Invert() ; - double dCLen ; pCopy->GetLength( dCLen) ; - if ( dCLen > 0.5 * vLen[idx]) - pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUstart, dUref)) ; - } - } - BBox3d b3Copy ; - if ( ! IsNull( pCopy)) - pCopy->GetBBox( m_frF, b3Copy) ; - if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10 * EPS_SMALL) { - vpCrvs.back()->AddCurve( Release( pCopy)) ; - nI = nNextI ; - nJ = nNextJ ; - } - else { - nI = -1 ; - nJ = -1 ; - } - } - else { - nI = -1 ; - nJ = -1 ; - } - } - - // porto le curve calcolate nel riferimento globale - if ( ! AreSameFrame( m_frF, GLOB_FRM)) { - for ( int i = 0 ; i < ( int) vpCrvs.size() ; i++) - vpCrvs[i]->ToGlob( m_frF) ; - } - - return true ; -} - //---------------------------------------------------------------------------- bool SurfFlatRegion::CalcVoronoiObject() const diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index d69cbcb..794e755 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -101,7 +101,6 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ; bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ; int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides - bool GetZigZagInfill( double dStep, bool bStepCorrection, bool bInvert, ICRVCOMPOPOVECTOR& vpCrvs) const override ; Voronoi* GetVoronoiObject( void) const override ; bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) const override ; bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ;