From 4ffb7087bdb5add6a7be8aaa3911245fb231b492 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 26 Sep 2024 12:22:51 +0200 Subject: [PATCH] EgtGeomKernel : - In CalcPocketing, migliorati i percorsi Conformal. --- CalcPocketing.cpp | 332 +++++++++++++++++++++++++++++++--------------- 1 file changed, 224 insertions(+), 108 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 61ec038..6c75003 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -6750,7 +6750,7 @@ GetSfrByOpenEdgeExtension( const ISurfFlatRegion* pSfrOrig, PocketParams& PockPa //---------------------------------------------------------------------------- static bool SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink, - const PocketParams& PockParams, bool bSmoothLeft, bool bSmoothRight, double dSmoothPar, double dTol) + const PocketParams& PockParams, bool bFirstOffs0, bool bFirstOffs1, double dSmoothPar, double dTol) { // controllo dei parametri @@ -6758,17 +6758,12 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve pCrvOffs1 == nullptr || ! pCrvOffs1->IsValid() || pCrvLink == nullptr || ! pCrvLink->IsValid()) return false ; - - /* - - Data la curva di Link, come prima cosa aggiungo l'ultima curva dell'Offset precedente - e la prima curva dell'Offset successivo. - - Effettuo lo Smusso del Link - - Rimvuovo la prima e l'ultima curva del Link smussato ( Gli estremi del link non vengono - modificati durante l'operazione di smusso - */ - // curva precedente e successiva - PtrOwner pCrvBef( pCrvOffs0->GetLastCurve()->Clone()) ; + PtrOwner pCrvBef ; + if ( bFirstOffs0 && pCrvOffs0->IsClosed()) + pCrvBef.Set( pCrvOffs0->GetFirstCurve()->Clone()) ; + else + pCrvBef.Set( pCrvOffs0->GetLastCurve()->Clone()) ; PtrOwner pCrvAft( pCrvOffs1->GetFirstCurve()->Clone()) ; if ( IsNull( pCrvBef) || IsNull( pCrvAft) || ! pCrvBef->IsValid() || ! pCrvAft->IsValid()) @@ -6782,16 +6777,19 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve pCrvLink->RemoveFirstOrLastCurve( false) ; pCrvLink->RemoveFirstOrLastCurve( true) ; // modifico Offset0 per raccordarlo al nuovo Link - Point3d ptS ; pCrvLink->GetStartPoint( ptS) ; - double dUE ; pCrvOffs0->GetParamAtPoint( ptS, dUE, dTol) ; - if ( ! bSmoothLeft && pCrvOffs0->IsClosed()) - pCrvOffs0->ChangeStartPoint( dUE) ; - else + if ( bFirstOffs0 && pCrvOffs0->IsClosed()) { + pCrvOffs0->AddCurve( pCrvLink->GetFirstCurve()->Clone()) ; + pCrvLink->RemoveFirstOrLastCurve( false) ; + } + else { + Point3d ptS ; pCrvLink->GetStartPoint( ptS) ; + double dUE ; pCrvOffs0->GetParamAtPoint( ptS, dUE, dTol) ; pCrvOffs0->TrimEndAtParam( dUE) ; + } // modifico Offset1 per raccordarlo al nuovo Link Point3d ptE ; pCrvLink->GetEndPoint( ptE) ; double dUS ; pCrvOffs1->GetParamAtPoint( ptE, dUS, dTol) ; - if ( ! bSmoothRight && pCrvOffs1->IsClosed()) + if ( bFirstOffs1 && pCrvOffs1->IsClosed()) pCrvOffs1->ChangeStartPoint( dUS) ; else pCrvOffs1->TrimStartAtParam( dUS) ; @@ -6849,7 +6847,7 @@ GetConformalLinkForOpenCrv( const ICurveComposite* pCrvOffs0, const ICurveCompos //---------------------------------------------------------------------------- static bool GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams, - const ICRVCOMPOPOVECTOR& vCrvClassBorder, const ICRVCOMPOPOVECTOR& vCrvExtendedBorders, + const ICRVCOMPOPOVECTOR& vCrvClassBorder, const ICRVCOMPOPOVECTOR& vCrvExtendedBorders, ICurveComposite* pCrvLink) { // controllo validità delle due curve di Offset @@ -6870,7 +6868,7 @@ GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocket return false ; // smusso il Link raccordandolo if ( pCrvLink->IsValid()) - SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, true, true, PockParams.dRad / 8., TOL) ; + SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, false, false, PockParams.dRad / 8., TOL) ; } else { // clono le due curve di Offset @@ -6905,7 +6903,7 @@ GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocket return false ; } PockParams.bSmooth = bSmooth ; - SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, ! bFirstIterOffs0, ! bFirstIterOffs1, + SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, bFirstIterOffs0, bFirstIterOffs1, PockParams.dRad / 16., TOL) ; // per sicurezza aggiorno i nuovi punti e i nuovi parametri double dUNewE ; @@ -7302,47 +7300,9 @@ ModifyConformalStartPoint( ICurveComposite* pCrvFirst, const PocketParams& PockP //---------------------------------------------------------------------------- static bool -CalcConformalOneWayOffs( VICRVCOMPOPOVECTOR& vvCrvOffs, const PocketParams& PockParams, - const ISurfFlatRegion* pSfrPock, ICRVCOMPOPOVECTOR& vCrvOffs) -{ - // pulizia del vettore degli Offset - vCrvOffs.clear() ; - - // inverto il vettore degli Offset, in modo da partire dalle curve più distanti dai chiusi - reverse( vvCrvOffs.begin(), vvCrvOffs.end()) ; - - // determino il punto iniziale della prima curva di Offset - if ( ! ModifyConformalStartPoint( vvCrvOffs[0][0], PockParams, pSfrPock)) - return false ; - - // le curve di Offset vengono riodinate in base alla loro iterazione nel vettore - for ( int i = 0 ; i < int( vvCrvOffs.size()) ; ++ i) { - for ( int j = 0 ; j < int( vvCrvOffs[i].size()) ; ++ j) { - // se la curva corrente è chiusa, cambio il punto iniziale rispetto alla curva precedente - if ( vvCrvOffs[i][j]->IsClosed()) { - if ( ! vCrvOffs.empty()) { - // ricavo il punto finale della curva precedente - Point3d ptEndPrec ; vCrvOffs.back()->GetEndPoint( ptEndPrec) ; - DistPointCurve DistPtCrv( ptEndPrec, *vvCrvOffs[i][j]) ; - double dParS ; - int nFlag ; - // cambio il punto inziale della curva corrente - if ( DistPtCrv.GetParamAtMinDistPoint( 0, dParS, nFlag)) - vvCrvOffs[i][j]->ChangeStartPoint( dParS) ; - } - } - vCrvOffs.emplace_back( Release( vvCrvOffs[i][j])) ; - } - } - - return true ; -} - -//---------------------------------------------------------------------------- -static bool -CalcConformalZigZagOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatRegion* pSfrChunk, - const ISurfFlatRegion* pSfrClass, PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvOffs, - ICURVEPOVECTOR& vCrvLink) +CalcConformalOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatRegion* pSfrChunk, + const ISurfFlatRegion* pSfrClass, PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvOffs, + ICURVEPOVECTOR& vCrvLink) { // controllo dei parametri if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid() || @@ -7373,21 +7333,21 @@ CalcConformalZigZagOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatR if ( ! ModifyConformalStartPoint( vvCrvOffs[0][0], PockParams, pSfrChunk)) return false ; - /* NB. - I link che collegano due curve di Offset aperte devono partire dalla prima e, seguendo il - bordo della regione di classificazione ( pSfrClass) arrivano alla seconda. - */ - ICRVCOMPOPOVECTOR vCrvSfrClass ; - if ( ! GetSfrCrvCompoLoops( pSfrClass, vCrvSfrClass)) - return false ; - /* NB. - I link che collegano due curve di Offset chiuse tra di loro vengono calcolati esattamente - come per i percorsi SPIRAL, pertanto devo definire un insieme di curve di primo Offset sui - quali smussare i Link per evitare di uscire dalla regione di svuotatura - */ - ICRVCOMPOPOVECTOR vCrvSfrExtended ; - if ( ! GetConformalBordersCrvs( pSfrChunk, PockParams, vCrvSfrExtended)) - return false ; + /* NB. + I link che collegano due curve di Offset aperte devono partire dalla prima e, seguendo il + bordo della regione di classificazione ( pSfrClass) arrivano alla seconda. + */ + ICRVCOMPOPOVECTOR vCrvSfrClass ; + if ( ! GetSfrCrvCompoLoops( pSfrClass, vCrvSfrClass)) + return false ; + /* NB. + I link che collegano due curve di Offset chiuse tra di loro vengono calcolati esattamente + come per i percorsi SPIRAL, pertanto devo definire un insieme di curve di primo Offset sui + quali smussare i Link per evitare di uscire dalla regione di svuotatura + */ + ICRVCOMPOPOVECTOR vCrvSfrExtended ; + if ( ! GetConformalBordersCrvs( pSfrChunk, PockParams, vCrvSfrExtended)) + return false ; /* NB. Se POCKET_CONFORMAL_ZIGZAG : - vCrvCompoOffs contiene gli Offset ordinati @@ -7425,25 +7385,29 @@ CalcConformalZigZagOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatR return true ; // ------------ Definisco i Link ------------ - // per definizione il primo Link è nullo - vCrvLink.resize( 1) ; - // scorro le curve di Offset a coppie - for ( int i = 0 ; i < int( vCrvOffs.size()) - 1 ; ++ i) { - // controllo se bisogna calcolare il Link tra i due Offset - bool bCalcLink = true ; - if ( ! CheckConformalRetractLink( vCrvOffs[i], vCrvOffs[i+1], vCrvSfrClass, PockParams, bCalcLink)) - return false ; - if ( bCalcLink) { - // se link da calcolare, lo ricavo - PtrOwner pCrvLink( CreateCurveComposite()) ; - if ( IsNull( pCrvLink) || - ! GetConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, vCrvSfrExtended, pCrvLink)) - return false ; - // lo salvo nel vettore dei Link - vCrvLink.emplace_back( Release( pCrvLink)) ; + if ( PockParams.nType == POCKET_CONFORMAL_ONEWAY) + vCrvLink.resize( vCrvOffs.size()) ; + else { + // per definizione il primo Link è nullo + vCrvLink.resize( 1) ; + // scorro le curve di Offset a coppie + for ( int i = 0 ; i < int( vCrvOffs.size()) - 1 ; ++ i) { + // controllo se bisogna calcolare il Link tra i due Offset + bool bCalcLink = true ; + if ( ! CheckConformalRetractLink( vCrvOffs[i], vCrvOffs[i+1], vCrvSfrClass, PockParams, bCalcLink)) + return false ; + if ( bCalcLink) { + // se link da calcolare, lo ricavo + PtrOwner pCrvLink( CreateCurveComposite()) ; + if ( IsNull( pCrvLink) || + ! GetConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, vCrvSfrExtended, pCrvLink)) + return false ; + // lo salvo nel vettore dei Link + vCrvLink.emplace_back( Release( pCrvLink)) ; + } + else + vCrvLink.resize( int( vCrvLink.size()) + 1) ; } - else - vCrvLink.resize( int( vCrvLink.size()) + 1) ; } return true ; @@ -7590,6 +7554,166 @@ AddLeadInToCurveConformalPaths( const ISurfFlatRegion* pSfrOrig, const ISurfFlat return true ; } +//---------------------------------------------------------------------------- +static bool +OrderConformalPaths( ICRVCOMPOPOVECTOR& vCrvPaths, const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pSfrOrig, + PocketParams& PockParams) +{ + // controllo dei parametri + if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid() || + pSfrOrig == nullptr || ! pSfrOrig->IsValid()) + return false ; + if ( int( vCrvPaths.size()) < 2) + return true ; + + // superficie di controllo per parti isolate + PtrOwner pSfrToRemove( CloneSurfFlatRegion( pSfrChunk)) ; + if ( IsNull( pSfrToRemove) || ! pSfrToRemove->IsValid() || + ! pSfrToRemove->Intersect( *pSfrOrig)) + return false ; + + // creo le regioni piane di svuotatura dei percorsi + ISURFFRPOVECTOR vSfrRemoved ; vSfrRemoved.resize( vCrvPaths.size()) ; + for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) { + // creo la regione di svuotatura di tale percorso + vSfrRemoved[i].Set( GetSurfFlatRegionFromFatCurve( CloneCurveComposite( vCrvPaths[i]), PockParams.dRad, false, false)) ; + if ( IsNull( vSfrRemoved[i]) || ! vSfrRemoved[i]->IsValid()) + return false ; + } + + // scorro i percorsi ricavati + INTVECTOR vInds ; vInds.resize( vCrvPaths.size(), -1) ; + int nChunkRef = pSfrToRemove->GetChunkCount() ; + for ( int i = 0 ; i < int( vInds.size()) ; ++ i) { + int j = 0 ; + INTVECTOR vTempInds ; + for ( ; j < int( vCrvPaths.size()) ; ++ j) { + // se indice già presente + if ( find( vInds.begin(), vInds.end(), j) != vInds.end()) + continue ; + // se sottraendo questa regione a quella originale ottengo più isole, allora non è il percorso ideale + PtrOwner pSfrRemain( CloneSurfFlatRegion( pSfrToRemove)) ; + if ( IsNull( pSfrRemain) || ! pSfrRemain->IsValid()) + continue ; + pSfrRemain->Subtract( *vSfrRemoved[j]) ; + // se aumento il numero di Chunk, allora non è il percorso ideale + if ( pSfrRemain->GetChunkCount() > nChunkRef) + continue ; + vTempInds.push_back( j) ; + } + if ( vTempInds.empty()) { + // se non ho trovato curva candidate, prendo l'indice disponibile più basso + for ( int k = 0 ; k < int( vInds.size()) ; ++ k) { + if ( find( vInds.begin(), vInds.end(), k) != vInds.end()) + continue ; + vInds[i] = k ; + break ; + } + } + else if ( int( vTempInds.size()) == 1) { + // se la candidata è singola, allora è lei + vInds[i] = vTempInds[0] ; + if ( PockParams.nType == POCKET_CONFORMAL_ONEWAY) { + if ( vCrvPaths[vInds[i]]->IsClosed() && i > 0) { + Point3d ptS ; vCrvPaths[vInds[i-1]]->GetStartPoint( ptS) ; + DistPointCurve DistCalculator( ptS, *vCrvPaths[vInds[i]]) ; + int nFlag ; double dUS ; + DistCalculator.GetParamAtMinDistPoint( 0, dUS, nFlag) ; + vCrvPaths[vInds[i]]->ChangeStartPoint( dUS) ; + } + } + } + else { + // se lavorazione conformal ZigZag + if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) { + // se ne ho trovate di più, allora euristicamente prendo la più corta + double dMinLen = INFINITO ; + for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) { + // privilegio le aperte + if ( vCrvPaths[vTempInds[k]]->IsClosed()) + continue ; + double dLen ; vCrvPaths[vTempInds[k]]->GetLength( dLen) ; + if ( dLen < dMinLen) { + dMinLen = dLen ; + vInds[i] = vTempInds[k] ; + } + } + // cerco solo tra le chiuse se non ho aperte + if ( dMinLen > INFINITO - 1) { + for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) { + if ( vCrvPaths[vTempInds[k]]->IsClosed()) { + double dLen ; vCrvPaths[vTempInds[k]]->GetLength( dLen) ; + if ( dLen < dMinLen) { + dMinLen = dLen ; + vInds[i] = vTempInds[k] ; + } + } + } + } + } + // se lavorazione conformal OneWay + else { + // se ne ho trovate di più, cerco euristicamente la più vicina al punto iniziale della curva + // se prima in assoluto, allora prendo la più corta + if ( i == 0) { + double dMinLen = INFINITO ; + for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) { + double dLen ; vCrvPaths[vTempInds[k]]->GetLength( dLen) ; + if ( dLen < dMinLen) { + dMinLen = dLen ; + vInds[i] = vTempInds[k] ; + } + } + } + // altrimenti + else { + double dSqMinDist = INFINITO ; + Point3d ptS ; vCrvPaths[vInds[i-1]]->GetStartPoint( ptS) ; + Point3d ptTmpS ; + for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) { + if ( vCrvPaths[vTempInds[k]]->IsClosed()) + continue ; + vCrvPaths[vTempInds[k]]->GetStartPoint( ptTmpS) ; + double dMyDist = SqDist( ptS, ptTmpS) ; + if ( dMyDist < dSqMinDist) { + dSqMinDist = dMyDist ; + vInds[i] = vTempInds[k] ; + } + } + if ( dSqMinDist > INFINITO - 1) { + for ( int k = 0 ; k < int( vTempInds.size()) ; ++ k) { + if ( vCrvPaths[vTempInds[k]]->IsClosed()) { + DistPointCurve DistCalculator( ptS, *vCrvPaths[vTempInds[k]]) ; + double dMySqDist ; + DistCalculator.GetSqDist( dMySqDist) ; + if ( dMySqDist < dSqMinDist) { + dSqMinDist = dMySqDist ; + vInds[i] = vTempInds[k] ; + double dUS ; + int nFlag ; + DistCalculator.GetParamAtMinDistPoint( 0, dUS, nFlag) ; + vCrvPaths[vTempInds[k]]->ChangeStartPoint( dUS) ; + } + } + } + } + } + } + } + // aggiorno la regione da svuotare e il numero di Chunk che si sono formati + pSfrToRemove->Subtract( *vSfrRemoved[vInds[i]]) ; + nChunkRef = pSfrToRemove->GetChunkCount() ; + } + + // riordino i percorsi trovati + ICRVCOMPOPOVECTOR vCrvOrderedPaths ; vCrvOrderedPaths.resize( vCrvPaths.size()) ; + for ( int i = 0 ; i < int( vInds.size()) ; ++ i) + vCrvOrderedPaths[i].Set( vCrvPaths[vInds[i]]) ; + swap( vCrvOrderedPaths, vCrvPaths) ; + + return true ; +} + //---------------------------------------------------------------------------- static bool ChainConformalOffsWithLinks( ICRVCOMPOPOVECTOR& vCrvOffs, ICURVEPOVECTOR& vCrvLink, @@ -8053,20 +8177,9 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, // definisco vettore degli Offset e dei Link ICRVCOMPOPOVECTOR vCrvOffs ; ICURVEPOVECTOR vCrvLink ; - // se lavorazione CONFORMAL_ZIGZAG - if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) { - // ordino le curve di Offset e raccordo - if ( ! CalcConformalZigZagOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrClassChunk, PockParams, vCrvOffs, vCrvLink)) - return false ; - } - // se lavorazione CONFORMAL_ONEWAY - else if ( PockParams.nType == POCKET_CONFORMAL_ONEWAY) { - // ordino le curve di Offset - if ( ! CalcConformalOneWayOffs( vvCrvOffs, PockParams, pSfrChunk, vCrvOffs)) - return false ; - // i Link non esistono - vCrvLink.resize( int( vCrvOffs.size())) ; - } + // ordino le curve di Offset e raccordo + if ( ! CalcConformalOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrClassChunk, PockParams, vCrvOffs, vCrvLink)) + return false ; // estendo i percorsi per eventuali regioni non svuotate e calcolo le Feed if ( ! ExtendConformalOffsAndSetFeed( pSfrPock, PockParams, vCrvOffs, vCrvLink)) return false ; @@ -8077,6 +8190,9 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, // estendo i percorsi per entrate/uscite dai lati aperti if ( ! AddLeadInToCurveConformalPaths( pSfrOrig, pSfrChunk, PockParams, vCrvPaths)) return false ; + // ordino i percorsi trovati + if ( ! OrderConformalPaths( vCrvPaths, pSfrChunk, pSfrOrig, PockParams)) + return false ; // aggiungo i percorsi ricavati for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) vCrvCompoRes.emplace_back( Release( vCrvPaths[i])) ;