From 5841c9cae03b831fc762f90644104d6068beae4e Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Fri, 14 Jun 2024 16:46:56 +0200 Subject: [PATCH] EgtGeomKernel : - migliorie a CalcPocketing. --- CalcPocketing.cpp | 279 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 230 insertions(+), 49 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 6058ced..76369e6 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -584,6 +584,94 @@ ExistOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParam, bool& bExi return true ; } +//---------------------------------------------------- +static bool +ComputeTrapezoidSpiralLeadInLeadOut( ICurveComposite* pCompo, const Vector3d& vtMainDir, bool bLeadIn, + PocketParams PockParams, bool& bIsOutsideRaw) +{ + // inizializzazione come interno al grezzo + bIsOutsideRaw = false ; + Point3d ptP ; + Vector3d vtDir ; + if ( bLeadIn) { + pCompo->GetStartPoint( ptP) ; + pCompo->GetStartDir( vtDir) ; + } + else { + pCompo->GetEndPoint( ptP) ; + pCompo->GetEndDir( vtDir) ; + } + + // recupero estrusione della curva + Vector3d vtExtr ; pCompo->GetExtrusion( vtExtr) ; + + // recupero info sui lati aperti + int nPropOpen = pCompo->GetTempProp( 0) ; + bool bEdgeOpen = (( nPropOpen & ( bLeadIn ? 8 : 2)) > 0) ; + bool bBase0Open = (( nPropOpen & 1) > 0) ; + bool bBase1Open = (( nPropOpen & 4) > 0) ; + + // recupero info per capire se sto considerando un lato aggiuntivo per pulire angoli + int nIdCrv = ( bLeadIn ? 0 : pCompo->GetCurveCount() - 1) ; + int nExtraEdge ; + pCompo->GetCurveTempProp( nIdCrv, nExtraEdge) ; + + // tento con allungamento se lato inclinato è aperto oppure se sto considerando un lato aggiuntivo per pulire angoli + if ( bEdgeOpen || nExtraEdge == 1) { + + Vector3d vtDirP = ( bLeadIn ? -vtDir : vtDir) ; + Point3d ptNewStart = ptP + vtDirP * ( PockParams.dRad + PockParams.dOpenMinSafe) ; + pCompo->AddLine( ptNewStart, ! bLeadIn) ; + pCompo->SetCurveTempProp( bLeadIn ? 0 : pCompo->GetCurveCount() - 1, 2) ; + bIsOutsideRaw = true ; + } + // tento con attacco ruotato di 90° se non sto considerando un tratto aggiuntivo per pulire angoli + else if (( bBase0Open || bBase1Open) && ! bIsOutsideRaw && nExtraEdge == 0) { + + Vector3d vtDirO = bBase0Open ? vtDir : - vtDir ; + vtDirO.Rotate( vtExtr, ( PockParams.bInvert ? -90 : 90)) ; + + // se vicino al bordo del grezzo + Point3d ptNewStart = ptP + vtDirO * ( PockParams.dRad + PockParams.dOpenMinSafe) ; + pCompo->AddLine( ptNewStart, ! bLeadIn) ; + pCompo->SetCurveTempProp( bLeadIn ? 0 : pCompo->GetCurveCount() - 1, 2) ; + bIsOutsideRaw = true ; + } + + return true ; +} + +//---------------------------------------------------- +static bool +AdjustTrapezoidSpiralForLeadInLeadOut( ICurveComposite* pCompo, PocketParams PockParams) +{ + // recupero la direzione principale della svuotatura + Vector3d vtMainDir ; + for ( int i = 0 ; i < pCompo->GetCurveCount() ; i++) { + int nProp ; + if ( pCompo->GetCurveTempProp( i, nProp) && nProp == 0) { + // se non è lato aggiuntivo per la pulitura angoli recupero la sua direzione + pCompo->GetCurve( i)->GetStartDir( vtMainDir) ; + break ; + } + } + + // start point + bool bStartOutside = false ; + ComputeTrapezoidSpiralLeadInLeadOut( pCompo, vtMainDir, true, PockParams, bStartOutside) ; + // end point + bool bEndOutside = false ; + ComputeTrapezoidSpiralLeadInLeadOut( pCompo, vtMainDir, false, PockParams, bEndOutside) ; + + // eventuale inversione della curva per partire sempre dall'esterno del grezzo + if ( bEndOutside && ! bStartOutside) + pCompo->Invert() ; + + return true ; +} + + + //---------------------------------------------------------------------------- static bool ExtendPathOnOpenEdge( ICurveComposite* pCrvPath, const PocketParams& PockParams, const Vector3d& vtN, @@ -1148,13 +1236,17 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI //---------------------------------------------------------------------------- static bool -AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvIsl, const double dDiam, - const double dOffR, const double dStep, const PocketParams& PockParams) +AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvIsl, const PocketParams& PockParams) { // controllo dei parametri if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) return false ; + // recupero i parametri di lavorazione correnti + double dDiam = PockParams.dRad * 2 ; + double dOffR = PockParams.dRadialOffset ; + double dStep = PockParams.dSideStep ; + // raggio di riferimento per offset double dOutEdge = 0.5 * dDiam ; if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_ZIGZAG) @@ -1311,10 +1403,7 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParams) bSomeOpen = true ; if ( bSomeOpen) { // se trovo dei lati aperti // 3.1) sistemo la superificie - if ( ! AdjustContourWithOpenEdges( pCrvEL, vCrvIsl, PockParams.dRad_prec > 0 ? 2 * PockParams.dRadialOffset_prec : 2 * PockParams.dRad, - PockParams.dRadialOffset_prec > 0 ? PockParams.dRadialOffset_prec : PockParams.dRadialOffset, - PockParams.dRad_prec > 0 ? PockParams.dSideStep_prec : PockParams.dSideStep, - PockParams)) + if ( ! AdjustContourWithOpenEdges( pCrvEL, vCrvIsl, PockParams)) return false ; bIsChunkModified = true ; // la curva è stata modificata } @@ -1397,7 +1486,7 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, const PocketParams& PockParams) pSfr->Clear() ; pSfr->CopyFrom( pSrfFinal) ; - return pSrfFinal->IsValid() && pSrfFinal->GetChunkCount() > 0 ; + return ( pSrfFinal->IsValid() && pSrfFinal->GetChunkCount() > 0) ; } @@ -1519,17 +1608,6 @@ GetParamOnOpenSide( const ICurveComposite* pCompo, const ICRVCOMPOPOVECTOR& vOth // ricavo il punto fuori Point3d ptOut = ptStart + vtMidOut * ( PockParams.dRad + PockParams.dRadialOffset + ( PockParams.dRad + PockParams.dOpenMinSafe)) ; - // controllo l'elevazione sopra a quel punto ( qui è un bel mistero...) - // double dElev = 0. ; - // if ( ! GetElevation( m_nPhase, ptOut, frPocket.VersZ(), m_TParams.m_dDiam, m_TParams.m_dLen, - // frPocket.VersZ(), dElev)) - // return false ; - // se non vi è elevazione, il lato aperto trovato è il privilegiato - //if ( dElev < EPS_SMALL) { - // bFound = true ; - // if ( nPriorityOpenEdge > -1) - // return true ; - //} } } dLenPrev = dLen ; @@ -1566,7 +1644,7 @@ SetSpecialPtStartForOpenEdges( const ICurveComposite* pCrvOrig, const Frame3d& f return false ; // cerco il lato aperto più lungo - double dLenRef = ( 2 * PockParams.dRad) - 50 * EPS_SMALL ; + double dLenRef = ( 2 * PockParams.dRad) - 50 * EPS_SMALL ; // almeno di questa lunghezza for ( int u = 0 ; u < pCrvOrig->GetCurveCount() ; ++ u) { if ( pCrvOrig->GetCurve( u)->GetTempProp( 0) == 0) continue ; // escludo le chiuse @@ -1577,12 +1655,38 @@ SetSpecialPtStartForOpenEdges( const ICurveComposite* pCrvOrig, const Frame3d& f // ricavo la lunghezza di tale curva double dLen = 0. ; pCrvOpen->GetLength( dLen) ; - if ( dLen > dLenRef) { + if ( dLen > dLenRef) { // se lunghezza accettabile o maggiore della massima trovata Point3d ptSTmp ; Vector3d vtMidOutTmp ; + // ricavo il punto medio e il versore tangente associato if ( pCrvOpen->GetPointD1D2( 0.5, ICurve::FROM_MINUS, ptSTmp, &vtMidOutTmp)) { int nFlag ; if ( DistPointCurve( ptSTmp, *pCrvCompo).GetMinDistPoint( EPS_SMALL, ptStart, nFlag)) { + // controllo se il punto iniziale sta effettivaente su un lato aperto della curva attuale + // di primo Offset + double dU_check ; + if ( pCrvCompo->GetParamAtPoint( ptStart, dU_check)) { + // se il punto trovato è a cavallo tra due curve... + if ( abs( dU_check - floor( dU_check)) < EPS_PARAM || + abs( dU_check - ceil( dU_check)) < EPS_PARAM) { + const ICurve* pCrvA = pCrvCompo->GetCurve( floor( dU_check)) ; + if ( pCrvA == nullptr) + return false ; + const ICurve* pCrvB = pCrvCompo->GetCurve( ceil( dU_check)) ; + if ( pCrvB == nullptr) + return false ; + if ( pCrvA->GetTempProp( 0) == 0 || pCrvB->GetTempProp( 0) == 1) + continue ; // se una delle due è chiusa, salto tale punto + } + // se invece tocca una sola curva, controllo che sia aperta + else { + const ICurve* pCrvA = pCrvCompo->GetCurve( floor( dU_check)) ; + if ( pCrvA == nullptr) + return false ; + if ( pCrvA->GetTempProp( 0) == 0) + continue ; // se chiusa, salto tale punto + } + } vtMidOutTmp.Normalize() ; vtMidOutTmp.Rotate( Z_AX, - 90) ; vtMidOut = vtMidOutTmp ; @@ -1606,6 +1710,33 @@ SetPtStartForPath( ICurveComposite* pCrvOffsAct, const PocketParams& PockParams, // ( questa superificie ha i flag di lati aperti/chiusi settati nei loops) // ================================================================================================= + /* + 1) 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 mio 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. + + 2) Verifico l'esistenza di lati aperti : + - Se esistono lati aperti -> cerco il lato più sensato su cui entrare + - 2.1) Guardo la curva originale ( senza estensione degli aperti) che delimita la regione di + svuotatura e cerco i lati aperti presenti in essa ; se mi posiziono a metà del lato aperto + e cerco il punto più vicino sulla curva di primo offset. Se quest'ultima è anch'essa aperta + e di lunghezza adeguata, l'entrata è valida + - 2.2) ( se 2.1 non accettabile ) Scorro tutte le curve di lato aperto sulla curva di primo + Offset e per ogni curva di lunghezza accettabile controllo la precedente e la successiva. + Ad ogni curva aperta viene assegnato uno "score", in base alla sua Lenght, alle Lenghts + delle curve adiacenti ( se aperte ) e ai loro angoli di adiacenza. + Se la curva aperta corrente ha uno "score" sufficiente, viene scelta come curva per l'entrata + - 2.3) ( se 2.2 non accettabile ) Considero le curve come tutte chiuse ( vedi sotto ) + - Se non esistono dei lati aperti -> entro presso il lato chiuso più lungo + - 2.4) + */ + // controllo dei parametri if ( pCrvOffsAct == nullptr || ! pCrvOffsAct->IsValid() || pCrvOffsAct->GetCurveCount() == 0 || pSrfToWork == nullptr || ! pSrfToWork->IsValid() || pSrfToWork->GetChunkCount() != 1) @@ -1616,6 +1747,8 @@ SetPtStartForPath( ICurveComposite* pCrvOffsAct, const PocketParams& PockParams, if ( IsNull( pCrv)) return false ; + // 1) ********************************************************************* + bool bSomeOpen = false ; // flag per presenza di lati aperti // creo un vettore di Loops della superificie, ordinati @@ -1683,6 +1816,8 @@ SetPtStartForPath( ICurveComposite* pCrvOffsAct, const PocketParams& PockParams, } } + // ********************************************************************* + // se ho dei lati aperti... double dLenMax = EPS_SMALL ; int nCrvForMax = 0 ; @@ -1736,13 +1871,14 @@ SetPtStartForPath( ICurveComposite* pCrvOffsAct, const PocketParams& PockParams, // cerchiamo un punto valido per l'entrata ... bMidOut = false ; if ( bSomeOpen) { // se ho dei lati aperti, cerco un parametro ideale per entrare + /* ( 2.1 ) */ bool bOK = false ; if ( nOffs == 1 && pCrvOrig != nullptr && pCrvOrig->IsValid()) { // in questo caso le curve a fagiolo dei lati aperti a sinistra e a destra potrebbero // intersecarsi tra loro -> risulta difficile calcolare il versore direzione d'uscita - bOK = SetSpecialPtStartForOpenEdges( pCrvOrig, frPocket, PockParams, pCrvOffsAct, ptStart, vtMidOut, bMidOut) ; + bOK = SetSpecialPtStartForOpenEdges( pCrvOrig, frPocket, PockParams, pCrv, ptStart, vtMidOut, bMidOut) ; } - if ( ! bOK) + if ( ! bOK) /* ( 2.2 ) */ bMidOut = GetParamOnOpenSide( pCrv, vOtherCrv, frPocket, PockParams, ptStart, vtMidOut) ; } if ( bMidOut) { // se ho trovato e valido, allora imposto il punto inziale trovato @@ -1751,6 +1887,8 @@ SetPtStartForPath( ICurveComposite* pCrvOffsAct, const PocketParams& PockParams, bMidOut = ( DistPointCurve( ptStart + LEN_OUT * vtMidOut, *pCrv).GetParamAtMinDistPoint( 0, dPar, nFlag) && pCrv->ChangeStartPoint( dPar)) ; } + + /* ( 2.3 | 2.4 ) */ if ( ! bMidOut) // alla peggio, ordino i lati lunghi per lunghezza e cerco un'entrata valida AdjustContourStart( pCrv, PockParams, vOtherCrv, true, ptEndPrec) ; @@ -1762,42 +1900,83 @@ SetPtStartForPath( ICurveComposite* pCrvOffsAct, const PocketParams& PockParams, return true ; } + // *************************************************************************** //---------------------------- CASI OTTIMIZZATI ------------------------------ // *************************************************************************** //---------------------------------------------------------------------------- static bool -GetOptCrvIndex( const ICRVCOMPOPOVECTOR& vCrvOEWithFlags, ISurfFlatRegion* pSrfChunkFinal, - int& nIndex) +GetOptCrvIndex( const ICRVCOMPOPOVECTOR& vCrvOEWithFlags, const ISurfFlatRegion* pSrfChunkFinal, + const PocketParams& PockParams, int nReg, int& nIndex) { // controllo dei parametri - if ( int( vCrvOEWithFlags.size()) == 0 || pSrfChunkFinal == nullptr || ! pSrfChunkFinal->IsValid()) + if ( vCrvOEWithFlags.empty() || pSrfChunkFinal == nullptr || ! pSrfChunkFinal->IsValid()) + return false ; + nIndex = 0 ; + + // cerco la curva originale del chunk (cc)-esimo ( per casi ottimizzati) + if ( int( vCrvOEWithFlags.size()) == 1) + return true ; + + // vettore di indici delle curve candidate + INTVECTOR vInds ; + + // scorro tutte le curve originali + for ( int k = 0 ; k < int( vCrvOEWithFlags.size()) ; ++ k) { + CRVCVECTOR ccClass ; + if ( pSrfChunkFinal->GetCurveClassification( *vCrvOEWithFlags[k], EPS_SMALL, ccClass)) { + bool bIsThis = true ; + for ( int kk = 0 ; kk < ( int)ccClass.size() && bIsThis ; ++kk) { + if ( ccClass[kk].nClass == CRVC_OUT) + bIsThis = false ; + } + if ( bIsThis) + vInds.push_back( k) ; + } + } + // se ho un solo indice allora ho già identificato la curva + if ( int( vInds.size()) == 1) { + nIndex = vInds[0] ; + return true ; + } + + // IN QUESTO CASO, I LATI APERTI DI CHUNK VICINI SI SONO UNITI RIDUCENDO IL NUMERO DI CHUNK + // COMPLESSIVI DELLA REGIONE DI SVUOTATURA + + // effettuo un Offset del Chunk per simulare la creazione delle nReg + double dOffs = PockParams.dRad + PockParams.dRadialOffset ; + PtrOwner pSfrRefChunk( CloneSurfFlatRegion( pSrfChunkFinal)) ; + if ( IsNull( pSfrRefChunk) || + ! pSfrRefChunk->Offset( - dOffs, ICurve::OFF_FILLET)) return false ; - // cerco la curva originale del chunk (cc)-esimo ( per casi ottimizzati) - if ( int( vCrvOEWithFlags.size()) == 1) - nIndex = 0 ; - else { - for ( int k = 0 ; k < ( int)vCrvOEWithFlags.size() ; ++k) { - CRVCVECTOR ccClass ; - if ( pSrfChunkFinal->GetCurveClassification( *vCrvOEWithFlags[k], EPS_SMALL, ccClass)) { - bool bIsThis = true ; - for ( int kk = 0 ; kk < ( int)ccClass.size() && bIsThis ; ++kk) { - if ( ccClass[kk].nClass == CRVC_OUT) - bIsThis = false ; - } - if ( bIsThis) { - nIndex = k ; - break ; - } - } - } - } + // clono il Chunk nReg-esimo se esiste + pSfrRefChunk.Set( pSfrRefChunk->CloneChunk( nReg)) ; + if ( IsNull( pSfrRefChunk)) + return true ; // bisogna passare al ( pSrfChunkFinal + 1)-esimo + + // scorro tutte le curve originali + for ( int k = 0 ; k < int( vCrvOEWithFlags.size()) ; ++ k) { + CRVCVECTOR ccClass ; + if ( pSfrRefChunk->GetCurveClassification( *vCrvOEWithFlags[k], EPS_SMALL, ccClass)) { + bool bIsThis = true ; + for ( int kk = 0 ; kk < ( int)ccClass.size() && bIsThis ; ++kk) { + if ( ccClass[kk].nClass == CRVC_OUT) + bIsThis = false ; + } + if ( bIsThis) { + nIndex = k ; + return true ; + } + } + } + + return true ; - return true ; } + //---------------------------------------------------------------------------- static bool OptimizedSpiralCirle( const ICurveComposite* pCrvCompo, const double dToll, double& dRad, @@ -5909,9 +6088,9 @@ AddSpiralIn( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, Point3d ptStart ; bool bOptimizedTrap = false ; - // cerco la curva originale del chunk cc-esimo ( per casi ottimizzati) + // cerco la curva originale del chunk cc-esimo ( per casi ottimizzati) int nInd = 0 ; // indice del vettore delle curve esterne relativo al chunk cc-esimo - if ( ! GetOptCrvIndex( vCrvOrig, pSrfChunk, nInd)) + if ( ! GetOptCrvIndex( vCrvOrig, pSrfChunk, PockParams, nReg, nInd)) return false ; // calcolo il percorso di svuotatura @@ -5926,7 +6105,9 @@ AddSpiralIn( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, break ; // passo al chunk originale successivo // se il chunk presenta dei lati aperti, estendo la curva che ho trovato per un LeadIn - if ( bSomeOpen) { + if ( bOptimizedTrap) // se caso a trapezio + AdjustTrapezoidSpiralForLeadInLeadOut( pMCrv, PockParams) ; + else if ( bSomeOpen) { // se presenza di lati aperti if ( ! ExtendPathOnOpenEdge( pMCrv, PockParams, pSrfChunk->GetNormVersor(), vtMidOut, false)) return false ; } @@ -5973,7 +6154,7 @@ AddSpiralOut( const ISurfFlatRegion* pSrfPock, const PocketParams& PockParams, // cerco la curva originale del chunk cc-esimo ( per casi ottimizzati) int nInd = 0 ; // indice del vettore delle curve esterne relativo al chunk cc-esimo - if ( ! GetOptCrvIndex( vCrvOrig, pSrfChunk, nInd)) + if ( ! GetOptCrvIndex( vCrvOrig, pSrfChunk, PockParams, nReg, nInd)) return false ; // calcolo il percorso di svuotatura