diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index c76bb1c..932cba9 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -85,48 +85,10 @@ typedef vector VICRVCOMPOPOVECTOR ; #include "EgtDev/Include/EGkGeoObjSave.h" #include "EgtDev/Include/EGkGeoPoint3d.h" #include "EgtDev/Include/EGkGeoVector3d.h" - string sPockDebug = "C:\\Temp\\PockDebug.nge" ; vector VT ; vector VC ; - //---------------------------------------------------------------------------- - // Debug Functions - //---------------------------------------------------------------------------- - void - DrawObjs( const ISURFFRPOVECTOR& vSfr, bool bSfrUniform, bool bAlphaCoverage, - const ICRVCOMPOPOVECTOR& vCompo, bool bCompoUniform, string sName) - { - // definisco i vettori per geometrie e colori - vector VT ; - vector VC ; - - // disegno le superfici - for ( int nS = 0 ; nS < int( vSfr.size()) ; ++ nS) { - if ( vSfr[nS] == nullptr || ! vSfr[nS]->IsValid()) - return ; - VT.emplace_back( static_cast( vSfr[nS]->Clone())) ; - VC.emplace_back( bAlphaCoverage ? Color( 0., 64., 0., .5) : Color( 0., 255., 0., .5)) ; - for ( int nC = 0 ; nC < vSfr[nS]->GetChunkCount() ; ++ nC) { - for ( int nL = 0 ; nL < vSfr[nS]->GetLoopCount( nC) ; ++ nL) { - PtrOwner pCrvCompo( ConvertCurveToComposite( vSfr[nS]->GetLoop( nC, nL))) ; - for ( int nU = 0 ; nU < pCrvCompo->GetCurveCount() ; ++ nU) { - int nProp0 ; pCrvCompo->GetCurveTempProp( nU, nProp0, 0) ; - VT.emplace_back( static_cast( pCrvCompo->GetCurve( nU)->Clone())) ; - VC.emplace_back( bSfrUniform ? WHITE : ( nProp0 == 0 ? ( bAlphaCoverage ? AQUA : BLUE) : ( bAlphaCoverage ? ORANGE : RED))) ; - } - } - } - } - - // disegno le curve - for ( int nC = 0 ; nC < int( vCompo.size()) ; ++ nC) { - if ( vCompo[nC] == nullptr || ! vCompo[nC]->IsValid()) - continue ; - VT.emplace_back( static_cast( vCompo[nC]->Clone())) ; - VC.emplace_back( Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.)) ; - } - - SaveGeoObj( VT, VC, sName) ; - return ; + inline Color GetRandomColor() { + return Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ; } #endif @@ -5436,7 +5398,7 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con double dMinDist = INFINITO ; // distanza tra questa curva e la successiva Point3d ptStartNext ; // punto iniziale della curva successiva - // tra le curva successive cerco la curva interna e più vicina ad essa + // tra le curve successive cerco la curva interna e più vicina ad essa for ( int j = i + 1 ; j < int( vOffs.size()) ; ++ j) { IntersCurveCurve IntCC( *vOffs[i], *vOffs[j]) ; CRVCVECTOR ccClass ; @@ -5599,7 +5561,7 @@ CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, CRVCVECTOR ccClass ; IntersCurveCurve intCC( *pCrvOffLonger, *pCrvTool) ; intCC.GetCurveClassification( 1, EPS_SMALL, ccClass) ; - if ( int(ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { + if ( int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_OUT) { // centroide bInsert = false ; return true ; @@ -5625,8 +5587,7 @@ CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, double dDimY = bBox.GetDimY() ; // se dimensioni accettabili, inserisco - if ( dDimX < 2 * PockParams.dRad - 100 * EPS_SMALL || - dDimY < 2 * 2 * PockParams.dRad - 100 * EPS_SMALL) { + if ( dDimX < 2 * PockParams.dRad - 100 * EPS_SMALL || dDimY < 4 * PockParams.dRad - 100 * EPS_SMALL) { bInsert = false ; return true ; } @@ -5672,9 +5633,8 @@ IsCompoMadeBy2DifferentHomogeneousParts( const ICurveComposite* pCompo, const Po //---------------------------------------------------------------------------- static bool -CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int& nReg, Point3d& ptStart, - ICRVCOMPOPOVECTOR& vCrvOrigChunkLoops, ICurveComposite* pMCrv, bool& bOptimizedTrap, - bool& bMidOut, Vector3d& vtMidOut) +CalcSpiral( const ISurfFlatRegion* pSfrPock, const PocketParams& PockParams, int& nReg, Point3d& ptStart, + ICRVCOMPOPOVECTOR& vCrvOrigChunkLoops, ICurveComposite* pMCrv, bool& bMidOut, Vector3d& vtMidOut) { // inizializzo il percorso come vuoto pMCrv->Clear() ; @@ -5682,28 +5642,26 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int // Offset corrente ( il primo è definito dal raggio utensile) double dOffs = PockParams.dRad + PockParams.dRadialOffset ; - // recupero il versore normale della superficie, ruotandola nel piano XY - PtrOwner pSrfToWork( pSrfPock->Clone()) ; - if ( IsNull( pSrfToWork) || pSrfToWork->GetChunkCount() == 0) - return false; - // ciclo di offset verso l'interno const int MAX_ITER = 1000 ; int nIter = 0 ; ICRVCOMPOPOVECTOR vOffs ; // vettore delle curve di offset ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset - PtrOwner pSrfAct( CloneSurfFlatRegion( pSrfToWork)) ; // regione attuale + // tengo una copia della regione corrente da svuotare + PtrOwner pSrfAct( CloneSurfFlatRegion( pSfrPock)) ; if ( IsNull( pSrfAct) || pSrfAct->GetChunkCount() == 0) return false ; + // ricavo le regioni progressive double dOffsPrec = 0. ; int nCrvFirstOffs = 0 ; while ( nIter < MAX_ITER) { - // ricavo la regione piana da VRONI + // Offset della regione attuale PtrOwner pSfrOffsVR( pSrfAct->CreateOffsetSurf( - dOffs, ICurve::OFF_FILLET)) ; if ( IsNull( pSfrOffsVR)) return false ; + // se la regione sparisce allora riprovo con un Offset leggermente più piccolo if ( ! pSfrOffsVR->IsValid()) { pSfrOffsVR.Set( pSrfAct->CreateOffsetSurf( - dOffs + 5 * EPS_SMALL, ICurve::OFF_FILLET)) ; if ( IsNull( pSfrOffsVR)) @@ -5756,7 +5714,8 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int nCrvFirstOffs = int( vOffs.size()) ; // controllo se serve un raggio più piccolo di svuotatura - bool bSmallRad = ( nIter == 0 ? dOffs < PockParams.dRad + EPS_ZERO : dOffs - dOffsPrec < PockParams.dRad + EPS_ZERO) ; + bool bSmallRad = ( nIter == 0 ? ( dOffs < PockParams.dRad + EPS_ZERO) : + ( dOffs - dOffsPrec < PockParams.dRad + EPS_ZERO)) ; // se ho trovato dei chunk, allora aggiorno l'Offset per la passata successiva if ( nChunks > 0) { @@ -5791,14 +5750,14 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int // Se ho come lavorazione uno SpiralIn posso poter entrare dalle isole aperte... int nIndexSwap = 0 ; // indice del vettore di curve per identificare la curva su cui entrare if ( PockParams.nType == POCKET_SPIRALIN) { - if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSrfToWork, ptRef, ptStart, + if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSfrPock, ptRef, ptStart, vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops)) vOffsFirstCurve[nIndexSwap]->GetStartPoint( ptNewStart) ; else return false ; } else { - if ( SetPtStartForPath( vOffs[0], PockParams, pSrfToWork, ptRef, ptStart, vtMidOut, bMidOut, + if ( SetPtStartForPath( vOffs[0], PockParams, pSfrPock, ptRef, ptStart, vtMidOut, bMidOut, vCrvOrigChunkLoops[0])) vOffs[0]->GetStartPoint( ptNewStart) ; else @@ -5806,23 +5765,23 @@ CalcSpiral( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, int } // se richiesta inversione - for ( int i = 0 ; i < int( vOffs.size()) && PockParams.bInvert ; ++ i) - vOffs[i]->Invert() ; + if ( PockParams.bInvert) { + for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) + vOffs[i]->Invert() ; + } // smusso le curve di offset ( ad eccezione di quelle di primo Offset) - ICRVCOMPOPOVECTOR vOffsClosedCurves( vOffs.size()) ; // vettore con tutte le curve di Offset Chiuse - double dSmoothPar = PockParams.dRad / 8 ; + double dSmoothPar = PockParams.dRad / 8. ; for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { if ( i >= nCrvFirstOffs) ModifyCurveToSmoothed( vOffs[i], PockParams, dSmoothPar, dSmoothPar, false) ; vOffs[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; - vOffsClosedCurves[i].Set( vOffs[i]->Clone()) ; } // setto il punto iniziale della svuotatura double dNewUS ; if ( nIndexSwap != 0) - swap( vOffs[0], vOffs[nIndexSwap]) ; // se entro da un'isola aperta + swap( vOffs[0], vOffs[nIndexSwap]) ; vOffs[0]->GetParamAtPoint( ptNewStart, dNewUS) ; vOffs[0]->ChangeStartPoint( dNewUS) ; vOffs[0]->SetTempParam( 0., 0) ; // prima iterazione @@ -6394,7 +6353,6 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, int nRegTot = nReg ; Point3d ptStart ; - bool bOptimizedTrap = false ; // cerco le curve originali del chunk cc-esimo ( per casi ottimizzati) ICRVCOMPOPOVECTOR vCrvOrigChunkLoops ; @@ -6404,8 +6362,7 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, // calcolo il percorso di svuotatura bool bSomeOpen ; Vector3d vtMidOut ; - if ( ! CalcSpiral( pSfrChunk, PockParams, nRegTot, ptStart, vCrvOrigChunkLoops, pMCrv, bOptimizedTrap, - bSomeOpen, vtMidOut)) + if ( ! CalcSpiral( pSfrChunk, PockParams, nRegTot, ptStart, vCrvOrigChunkLoops, pMCrv, bSomeOpen, vtMidOut)) return false ; // se terminate le regioni, esco @@ -6413,21 +6370,7 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, break ; // passo al chunk originale successivo bool bIsExtended = false ; - // se caso a trapezio - if ( bOptimizedTrap) { - Vector3d vtRef ; - pMCrv->GetStartDir( vtRef) ; - vtRef.Invert() ; - if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, false, bIsExtended)) - return false ; - pMCrv->GetEndDir( vtRef) ; - if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, true, bIsExtended)) - return false ; - AssignFeedSpiralOpt( 1, PockParams, pMCrv) ; - pMCrv->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ; - } - // se esistenza di lati aperti validi - else if ( bSomeOpen) + if ( bSomeOpen) ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, bIsExtended) ; // inserisco le curve nel vettore @@ -6487,7 +6430,6 @@ AddSpiralOut( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, int nRegTot = nReg ; Point3d ptStart ; - bool bOptimizedTrap = false ; // cerco la curva originale del chunk cc-esimo ( per casi ottimizzati) ICRVCOMPOPOVECTOR vCrvOrig ; @@ -6497,28 +6439,13 @@ AddSpiralOut( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, // calcolo il percorso di svuotatura bool bSomeOpen ; Vector3d vtMidOut ; - if ( ! CalcSpiral( pSfrChunk, PockParams, nRegTot, ptStart, vCrvOrig, pMCrv, bOptimizedTrap, - bSomeOpen, vtMidOut)) + if ( ! CalcSpiral( pSfrChunk, PockParams, nRegTot, ptStart, vCrvOrig, pMCrv, bSomeOpen, vtMidOut)) return false ; // se terminate le regioni, esco if ( pMCrv->GetCurveCount() == 0) break ; // passo al chunk originale successivo - if ( bOptimizedTrap) { // se caso a trapezio - Vector3d vtRef ; - pMCrv->GetStartDir( vtRef) ; - vtRef.Invert() ; - bool bIsExtended = false ; - if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, false, bIsExtended)) - return false ; - pMCrv->GetEndDir( vtRef) ; - if ( ! ExtendPath( pMCrv, pSrfPock, PockParams, vtRef, true, bIsExtended)) - return false ; - AssignFeedSpiralOpt( 1, PockParams, pMCrv) ; - pMCrv->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ; - } - // inverto il percorso, perchè sono calcolati dall'esterno all'interno (solo nel caso non ottimizzato) pMCrv->Invert() ; @@ -7711,7 +7638,7 @@ ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const PocketPara //---------------------------------------------------------------------------- static bool AddLeadInLeadOutToCurveConformalPaths( const ISurfFlatRegion* pSfrOrig, const ISurfFlatRegion* pSfrPock, - const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvPaths) + const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvPaths) { // controllo dei parametri if ( pSfrOrig == nullptr || ! pSfrOrig->IsValid() || @@ -7796,11 +7723,11 @@ AddLeadInLeadOutToCurveConformalPaths( const ISurfFlatRegion* pSfrOrig, const IS // 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)) + bool bOkExtension ; + if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, false, bOkExtension)) return false ; vCrvPaths[i]->GetEndDir( vtTan) ; - if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, true, bOkExtended)) + if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, true, bOkExtension)) return false ; } @@ -8540,6 +8467,101 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, return true ; } +//---------------------------------------------------------------------------- +static bool +SmoothExtensionLinesByIntersection( ICRVCOMPOPOVECTOR& vCrvPaths, const PocketParams& PockParams) +{ + // estendendo i percorsi con tratti in ingresso e in uscita, può capitare che si creino autointersezioni + // se ho meno di due percorsi non faccio nulla + if ( int( vCrvPaths.size()) < 2) + return true ; + + // cerco le autointersezioni tra i percorsi successivi tra loro + double dTol = 50 * EPS_SMALL ; + for ( int i = 0 ; i < int( vCrvPaths.size()) - 1 ; ++ i) { + // se uno dei due percorsi presenta meno di 3 curve, non faccio nulla + if ( ! vCrvPaths[i]->IsValid() || vCrvPaths[i]->GetCurveCount() < 3 || + ! vCrvPaths[i+1]->IsValid() || vCrvPaths[i+1]->GetCurveCount() < 3) + continue ; + // se il percorso i-esimo non presenta una estensione in uscita e il percorso (i+1)-esimo + // non presenta una estensione in entrata, non faccio nulla + if ( vCrvPaths[i]->GetLastCurve()->GetTempProp() != TEMP_PROP_OUT_START || + vCrvPaths[i+1]->GetFirstCurve()->GetTempProp() != TEMP_PROP_OUT_START) + continue ; + // recupero i due tratti lineari del percorso + const ICurveLine* pLineA = GetCurveLine( vCrvPaths[i]->GetLastCurve()) ; + const ICurveLine* pLineB = GetCurveLine( vCrvPaths[i+1]->GetFirstCurve()) ; + if ( pLineA == nullptr || ! pLineA->IsValid() || + pLineB == nullptr || ! pLineB->IsValid()) + continue ; + // se non esistono intersezioni tra i segmenti, non faccio nulla + IntersCurveCurve ICC( *pLineA, *pLineB) ; + if ( ICC.GetIntersCount() == 0) + continue ; + // definisco la curva di collegamento + PtrOwner pCrvLink( CreateCurveComposite()) ; + if ( IsNull( pCrvLink)) + return false ; + Point3d ptS_A ; pLineA->GetStartPoint( ptS_A) ; + pCrvLink->AddPoint( ptS_A) ; + IntCrvCrvInfo aInfo ; + if ( ! ICC.GetIntCrvCrvInfo( 0, aInfo)) + continue ; + pCrvLink->AddLine( aInfo.IciA[0].ptI) ; + if ( aInfo.bOverlap) + pCrvLink->AddLine( aInfo.IciA[1].ptI) ; + Point3d ptE_B ; pLineB->GetEndPoint( ptE_B) ; + pCrvLink->AddLine( ptE_B) ; + // se tutti i punti sono coincidenti, allora non ho bisogno di entrambe le estensioni + if ( ! pCrvLink->IsValid() || pCrvLink->GetCurveCount() == 0) { + delete( vCrvPaths[i]->RemoveFirstOrLastCurve( true)) ; + delete( vCrvPaths[i+1]->RemoveFirstOrLastCurve( false)) ; + vCrvPaths[i]->AddCurve( Release( vCrvPaths[i+1]), dTol) ; + vCrvPaths.erase( vCrvPaths.begin() + i + 1) ; + -- i ; + continue ; + } + // raccordo del Link con percorso attuale e successivo + double dLen ; + double dLenExtension ; + pLineA->GetLength( dLenExtension) ; + if ( vCrvPaths[i]->GetLength( dLen) && ( dLen - dLenExtension) > PockParams.dRad / 2.) { + double dUS, dUE ; + vCrvPaths[i]->GetDomain( dUS, dUE) ; + double dU ; + vCrvPaths[i]->GetParamAtLength( dLen - dLenExtension - ( PockParams.dRad / 2.), dU) ; + pCrvLink->AddCurve( ConvertCurveToComposite( vCrvPaths[i]->CopyParamRange( dU, dUE - 1)), false, dTol) ; ; + } + pLineB->GetLength( dLenExtension) ; + if ( vCrvPaths[i+1]->GetLength( dLen) && ( dLen - dLenExtension) > PockParams.dRad / 2.) { + double dUS, dUE ; + vCrvPaths[i+1]->GetDomain( dUS, dUE) ; + double dU ; + vCrvPaths[i+1]->GetParamAtLength( dLenExtension + ( PockParams.dRad / 2.), dU) ; + pCrvLink->AddCurve( ConvertCurveToComposite( vCrvPaths[i+1]->CopyParamRange( dUS + 1, dU)), true, dTol) ; + } + pCrvLink->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG) ; + ModifyCurveToSmoothed( pCrvLink, PockParams, PockParams.dRad / 8., PockParams.dRad / 8., false) ; + // assegno Feed massima + AssignMaxFeed( pCrvLink, PockParams) ; + // modifico i percorsi + Point3d ptLinkS ; pCrvLink->GetStartPoint( ptLinkS) ; + Point3d ptLinkE ; pCrvLink->GetEndPoint( ptLinkE) ; + double dUE, dUS ; + if ( ! vCrvPaths[i]->GetParamAtPoint( ptLinkS, dUE, dTol) || + ! vCrvPaths[i]->TrimEndAtParam( dUE) || + ! vCrvPaths[i+1]->GetParamAtPoint( ptLinkE, dUS, dTol) || + ! vCrvPaths[i+1]->TrimStartAtParam( dUS)) + continue ; + vCrvPaths[i]->AddCurve( Release( pCrvLink), dTol) ; + vCrvPaths[i]->AddCurve( Release( vCrvPaths[i+1]), dTol) ; + vCrvPaths.erase( vCrvPaths.begin() + i + 1) ; + -- i ; + } + + return true ; +} + //---------------------------------------------------------------------------- bool CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle, @@ -8653,6 +8675,12 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double break ; } + // ------------ intersezione delle estensioni ---------------------------- + if ( ! myParams.bAllClosed) { + if ( ! SmoothExtensionLinesByIntersection( vCrvCompoPock, myParams)) + return false ; + } + // riporto tutte le curve ottenute in globale for ( int i = 0 ; i < int( vCrvCompoPock.size()) ; ++ i) { vCrvCompoPock[i]->ToGlob( myParams.frLocXY) ;