From 3b5c34cb05902ea9c70ada9725cd3ee5d10c74ba Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Fri, 11 Jul 2025 15:38:55 +0200 Subject: [PATCH] EgtGeomKernel : - in CalcPocketing migliorati i collegamenti per lavorazioni Conformal e migliorato l'orientamento delle curve per lavorazioni Spiral. --- CalcPocketing.cpp | 293 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 203 insertions(+), 90 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 318eca3..5c3c3b7 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -398,6 +398,16 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV return true ; } +//---------------------------------------------------------------------------- +static bool +SwapSideBySecondTempParam( ICurveComposite* pCompo) +{ + if ( pCompo == nullptr || ! pCompo->IsValid()) + return false ; + pCompo->SetTempParam( int( pCompo->GetTempParam( 1)) == MDS_LEFT ? MDS_RIGHT : MDS_LEFT, 1) ; + return true ; +} + //---------------------------------------------------------------------------- static bool CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nStat, double dToll) @@ -462,7 +472,7 @@ AssignFeedForOpenEdge( ICurveComposite* pCrv, const ISurfFlatRegion* pSfrOpenEdg pNewCrv->SetTempProp( pCrv->GetTempProp( 0), 0) ; pNewCrv->SetTempProp( pCrv->GetTempProp( 1), 1) ; pNewCrv->SetTempParam( pCrv->GetTempParam( 0), 0) ; - pNewCrv->SetTempParam( pCrv->GetTempParam( 0), 0) ; + pNewCrv->SetTempParam( pCrv->GetTempParam( 1), 1) ; double dThick ; pCrv->GetThickness( dThick) ; pNewCrv->SetThickness( dThick) ; Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ; @@ -4784,7 +4794,7 @@ CalcSpecialBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart, pZigZagLink->AddLine( ptNew) ; } - // questa composita contiene al massimo 5 curve e, in generale, quella una curva molto più lunga + // questa composita contiene al massimo 5 curve e, in generale, una curva molto più lunga // delle altre ( quella che collega le due estensioni calcolate). Spezzo la composita ottenuta in curve // la cui lunghezza massima è circa il raggio utensile PolyLine PL ; @@ -4965,12 +4975,14 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOM double dLenS ; pCrvS->GetLength( dLenS) ; double dLenE ; pCrvE->GetLength( dLenE) ; - // se ho una curva di primo Offset allora non devo accorciarla ( sia per bordi esterni che per isole) + // azzero i parametri per curve di primo Offset 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. ; + #if 0 + if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE)) + dLenPercE = 0. ; + #endif } #if 0 // nel caso volessi estendere anche prima del punto finale double dLStepS = ( dLenPercS < EPS_SMALL ? 0. : PockParams.dRad) ; @@ -5081,6 +5093,9 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& // recupero le proprietà temporanee int nProp0 = vOffs[i]->GetTempProp( 0) ; int nProp1 = vOffs[i]->GetTempProp( 1) ; + // il primo TempParam viene settato in proporzione alla Feed + // il secondo TempParam contiene l'nSide della curva + double dTempPar1 = vOffs[i]->GetTempParam( 1) ; // Feed bool bFirstOffs = false ; @@ -5104,6 +5119,7 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& } vOffs[i]->SetTempProp( nProp0, 0) ; vOffs[i]->SetTempProp( nProp1, 1) ; + vOffs[i]->SetTempParam( dTempPar1, 1) ; // ================= LINK ================================ int nLink_Ind = ( bFollowOrder ? i + 1 : i) ; @@ -5150,12 +5166,13 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR const Point3d& ptToGo, const PocketParams& PockParams, int& nInd, Point3d& ptCloser, bool& bFirstOffs) { - /* - E' richiesto che le curve di Offset presentino le seguenti TempProps : - - TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter) [per CONFORMAL] - - TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_LEFT) [per CONFORMAL] - [per SPIRAL le proprietà sono ricavate automaticamente] - */ + // E' richiesto che le curve di Offset presentino le seguenti proprietà : + // - CONFORMAL + // * TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter) + // * TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT) + // - SPIRAL + // * vOffsFirstCurve -> per capire se l'Offset corrente è di primo Offset o meno + // * TempParam1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT) // controllo dei parametri nInd = -1 ; @@ -5177,10 +5194,8 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR vOffsPtMinDist[i].nInd = i ; // nel caso di Conformal, escludo le curve di primo Offset dalla ricerca if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ONEWAY) { - bool bSkip = false ; - for ( int j = 0 ; j < int( vOffsFirstCurve.size()) && ! bSkip ; ++ j) - bSkip = ( vOffs[i]->GetTempProp( 0) == 0) ; // prima iterazione - if ( bSkip) { + // prima iterazione + if ( vOffs[i]->GetTempProp( 0) == 0) { vOffsPtMinDist[i].bFirstOffs = true ; continue ; } @@ -5190,26 +5205,16 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR // in questo modo riesco a creare le curve a ricciolo int nSide ; DistPointCurve DistPtCrv( ptToGo, *vOffs[i]) ; - bool bFirstBorderIsland = false ; if ( DistPtCrv.GetSideAtMinDistPoint( EPS_SMALL, Z_AX, nSide)) { // nel caso Spiral if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_SPIRALOUT) { // InVsOut - vOffsPtMinDist[i].bInVsOut = ( ( ! PockParams.bInvert && nSide == MDS_LEFT) || - ( PockParams.bInvert && nSide == MDS_RIGHT)) ; + vOffsPtMinDist[i].bInVsOut = ( int( vOffs[i]->GetTempParam( 1) != nSide)) ; // controllo se la curva in questione è di primo Offset Point3d ptCheck ; vOffs[i]->GetStartPoint( ptCheck) ; for ( int j = 0 ; j < int( vOffsFirstCurve.size()) ; ++ j) { if ( vOffsFirstCurve[j]->IsPointOn( ptCheck, 100 * EPS_SMALL)) { vOffsPtMinDist[i].bFirstOffs = true ; - // controllo se Isola o di bordo - double dArea = 0. ; - vOffs[i]->GetAreaXY( dArea) ; - bFirstBorderIsland = ( ( ! PockParams.bInvert && dArea < 0.) || - ( PockParams.bInvert && dArea > 0.)) ; - // se isola di primo Offset, InVsOut va invertito - if ( bFirstBorderIsland) - vOffsPtMinDist[i].bInVsOut = ( ! vOffsPtMinDist[i].bInVsOut) ; break ; } } @@ -5228,7 +5233,7 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR PockParams.dSideStep + PockParams.dSideStep ; } // se curva di bordo esterno, aggiungo un'altra penalità ( euristica) - if ( vOffsPtMinDist[i].bFirstOffs && ! bFirstBorderIsland) + if ( vOffsPtMinDist[i].bFirstOffs) vOffsPtMinDist[i].dSqDist *= 2. ; } } @@ -5252,7 +5257,7 @@ RemoveUnclearedRegions( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& /* E' richiesto che le curve di Offset presentino le seguenti TempProps : - TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter) [per CONFORMAL] - - TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_LEFT) [per CONFORMAL] + - TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT) [per CONFORMAL] [per SPIRAL le proprietà sono ricavate automaticamente] */ @@ -5267,12 +5272,10 @@ RemoveUnclearedRegions( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& for ( int nC = 0 ; nC < pSfrUncleared->GetChunkCount() ; ++ nC) { // recupero il centroide del Chunk da rimuovere Point3d ptCentroid ; pSfrUncleared->GetChunkCentroid( nC, ptCentroid) ; - /* - Tra tutte le curve di Offset escludo le curve che : - - Sono di primo Offset - - Non contengono il centroide ( condizione già verificata per quelle di primo Offset) - ... cerco la più vicina tra le rimanenti - */ + // Tra tutte le curve di Offset escludo le curve che : + // - Sono di primo Offset + // - Non contengono il centroide ( condizione già verificata per quelle di primo Offset) + // ... cerco la più vicina tra le rimanenti // recupero la curva migliore int nInd = -1 ; Point3d ptCloser ; @@ -5570,6 +5573,9 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con vLinks.clear() ; vLinks.resize( int( vOffs.size())) ; + // NB. Dato che le curve di Offset sono invertite a seconda di dove si trova il materiale, + // Utilizzo il secondo TempParam per evere l'nSide + // scorro tutte le curva di Offset for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) { @@ -5577,6 +5583,7 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con Point3d ptS ; if ( ! vOffs[i]->GetStartPoint( ptS)) return false ; + // tra le curve successive cerco la curva interna e più vicina ad essa int nNextInd = -1 ; // indice della curva successiva double dMinDist = INFINITO ; // distanza tra questa curva e la successiva @@ -5588,8 +5595,8 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con // se interna if ( IntCC.GetCurveClassification( 1, EPS_SMALL, ccClass) && int( ccClass.size()) == 1 && - ( ( ! PockParams.bInvert && ccClass[0].nClass == CRVC_IN) || - ( PockParams.bInvert && ccClass[0].nClass == CRVC_OUT))) { + ( ( ccClass[0].nClass == CRVC_IN && int( vOffs[i]->GetTempParam( 1)) == MDS_RIGHT) || + ( ccClass[0].nClass == CRVC_OUT && int( vOffs[i]->GetTempParam( 1)) == MDS_LEFT))) { // calcolo la distanza minima tra essa int nFlag ; double dPar = 0. ; @@ -5649,13 +5656,14 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con // scambio la curva i+1 esima con la j-esima ( se non sono già in ordine) if ( nNextInd != i + 1) swap( vOffs[nNextInd], vOffs[i+1]) ; + // cambio il suo punto iniziale nel punto più vicino tovato double dUS ; if ( ! vOffs[i+1]->GetParamAtPoint( ptStartNext, dUS, EPS_SMALL)) return false ; vOffs[i+1]->ChangeStartPoint( dUS) ; - // accorcio la curva per raccordarmi in tangenza con la successiva + // se ho più di una curva di Offset if ( int( vOffs.size()) > 1) { // clono le curve i ed i+1 esime ( nel caso non riuscissi ad accorciarle o raccordarle ) PtrOwner pCrv_i( vOffs[i]->Clone()) ; @@ -5666,15 +5674,14 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con PtrOwner pCrvLink( CreateCurveComposite()) ; if ( IsNull( pCrvLink)) return false ; - // NB. Le curve di Offset da tagliare non devono essere quelle di primo Offset double dLenPercS = ( i == 0 ? 0. : 10 * EPS_SMALL) ; double dLenPercE = ( bMinDistAtSmooth ? 0. : 10 * EPS_SMALL) ; if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsFirstCurve, PockParams, dLenPercS, dLenPercE, pCrvLink) || ! pCrvLink->IsValid()) { // se non sono riuscito, cerco una strada più semplice ripristinando le curve pCrvLink->Clear() ; - vOffs[i].Set( pCrv_i) ; // chiuso - vOffs[i+1].Set( pCrv_ii) ; // chiuso + vOffs[i].Set( pCrv_i) ; + vOffs[i+1].Set( pCrv_ii) ; // recupero i vettori tangenti iniziali ( le curve sono chiuse ) Vector3d vtS, vtE ; if ( ! vOffs[i]->GetStartDir( vtS) || ! vOffs[i+1]->GetStartDir( vtE)) @@ -5823,6 +5830,55 @@ IsCompoMadeBy2DifferentHomogeneousParts( const ICurveComposite* pCompo, const Po return true ; } +//---------------------------------------------------------------------------- +static int +CalcInversionForSpiralOffset( const ISurfFlatRegion* pSfrChunk) +{ + // controllo validità della regione + if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid()) + return -1 ; + + // Caso 0 : Non esistono isole + // Caso 1 : Loop Esterno Chiuso e, se esiste, Isola Chiusa + // Caso 2 : Loop Esterno Chiuso e, se esiste, Isola Aperta + // Caso 3 : Loop Esterno Aperto e, se esiste, Isola Chiusa + // Caso 4 : Loop Esterno Aperto e, se esiste, Isola Aperta + + // se non esistono isole, allora Caso 0 + if ( pSfrChunk->GetLoopCount( 0) == 1) + return 0 ; + + // Il Loop esterno è considerato chiuso <=> esiste almeno una curva chiusa + bool bExtClosed = false ; + for ( int nU = 0 ; nU < pSfrChunk->GetLoopCurveCount( 0, 0) && ! bExtClosed ; ++ nU) { + int nTempProp = TEMP_PROP_INVALID ; + bExtClosed = ( pSfrChunk->GetCurveTempProp( 0, 0, nU, nTempProp) && + nTempProp == TEMP_PROP_CLOSE_EDGE) ; + } + + // Le isole vengono classificate come tutte chiuse <=> esiste almeno un isola chiusa + bool bIntClosed = false ; + for ( int nLoop = 1 ; nLoop < pSfrChunk->GetLoopCount( 0) && ! bIntClosed ; ++ nLoop) { + for ( int nU = 0 ; nU < pSfrChunk->GetLoopCurveCount( 0, nLoop) && ! bIntClosed ; ++ nU) { + int nTempProp = TEMP_PROP_INVALID ; + bIntClosed = ( pSfrChunk->GetCurveTempProp( 0, nLoop, nU, nTempProp) && + nTempProp == TEMP_PROP_CLOSE_EDGE) ; + } + } + + // restituisco il caso corrente + if ( bExtClosed && bIntClosed) + return 1 ; + if ( bExtClosed && ! bIntClosed) + return 2 ; + if ( ! bExtClosed && bIntClosed) + return 3 ; + if ( ! bExtClosed && ! bIntClosed) + return 4 ; + + return -1 ; +} + //---------------------------------------------------------------------------- static bool CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, int& nReg, Point3d& ptStart, @@ -5837,14 +5893,19 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co // 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 + ICRVCOMPOPOVECTOR vOffs ; // vettore delle curve di offset + ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset // tengo una copia della regione corrente da svuotare PtrOwner pSrfAct( CloneSurfFlatRegion( pSfrPock)) ; if ( IsNull( pSrfAct) || pSrfAct->GetChunkCount() == 0) return false ; + // ricavo il tipo di relazione descritta tra Open/Close di bordo esterno e/o isole + int nCase = CalcInversionForSpiralOffset( pSrfAct) ; + if ( nCase == -1) + return false ; + // ricavo le regioni progressive double dOffsPrec = 0. ; int nCrvFirstOffs = 0 ; @@ -5862,12 +5923,15 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co // se primo Offset if ( nIter == 0) { + // aggiorno il nuovo valore delle regioni totali di primo Offset int my_nReg = nReg ; - nReg = pSfrOffsVR->GetChunkCount() ; // aggiorno il nuovo valore delle regioni totali di primo Offset + nReg = pSfrOffsVR->GetChunkCount() ; // gli Offset progressivi appartengono al Chunk nReg-esimo pSrfAct.Set( pSfrOffsVR->CloneChunk( my_nReg)) ; - if ( IsNull( pSrfAct)) // se supero i chunk ottenuti + // se supero i chunk ottenuti + if ( IsNull( pSrfAct)) return true ; + // imposto la regione id svuotatura corrente pSfrOffsVR.Set( pSrfAct->Clone()) ; } @@ -5877,24 +5941,41 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co for ( int i = 0 ; i < nChunks ; ++ i) { // per ogni chunk... int nLoops = pSfrOffsVR->GetLoopCount( i) ; - for ( int j = 0 ; j < nLoops ; ++ j) { + for ( int j = 0 ; j < nLoops ; ++ j) { // per ogni loop... PtrOwner pCrvCompoBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ; if ( IsNull( pCrvCompoBorder) || ! pCrvCompoBorder->IsValid()) return false ; - /* - Il materiale deve sempre trovarsi alla destra ( se bInvert -> alla sinistra) del tool - soltanto sul primo bordo; Nel caso di isole aperte o nelle passate di Offset intermedio - l'orientamente non ha importanza. - */ - if ( nIter != 0 && j > 0) // inverto l'orientamento delle curve interne ( offset delle isole trovate) - pCrvCompoBorder->Invert() ; // controllo quali regioni di Offset possono essere sostituite bool bInsert = true ; if ( ! CheckIfOffsetIsNecessary( pSrfAct, pCrvCompoBorder, dOffs, dOffsPrec, nIter, PockParams, bInsert)) return false ; - if ( bInsert) + if ( bInsert) { + // imposto come secondo TempParam il Side di classificazione + pCrvCompoBorder->SetTempParam( j == 0 ? MDS_RIGHT : MDS_LEFT, 1) ; + // stabilisco l'orientamento della curva + // --- Loop esterno chiuso e isole chiuse + if ( nCase == 1 && nIter != 0 && j > 0) { + pCrvCompoBorder->Invert() ; + SwapSideBySecondTempParam( pCrvCompoBorder) ; + } + // --- Loop esterno chiuso e isole aperte + else if ( nCase == 2 && j > 0) { + pCrvCompoBorder->Invert() ; + SwapSideBySecondTempParam( pCrvCompoBorder) ; + } + // --- Loop esterno aperto e isole chiuse + else if ( nCase == 3 && j == 0) { + pCrvCompoBorder->Invert() ; + SwapSideBySecondTempParam( pCrvCompoBorder) ; + } + // --- Loop esterno aperto e isole aperte + else if ( nCase == 4 && j > 0) { + pCrvCompoBorder->Invert() ; + SwapSideBySecondTempParam( pCrvCompoBorder) ; + } vOffs.emplace_back( Release( pCrvCompoBorder)) ; + } if ( nIter == 0) { // salvo il bordo per i link ( non invertiti, devo sapere IN/OUT) PtrOwner pCrvCompoExtBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ; vOffsFirstCurve.emplace_back( Release( pCrvCompoExtBorder)) ; @@ -5940,11 +6021,12 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co Point3d ptNewStart ; // 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 + int nIndexSwap = 0 ; if ( PockParams.nType == POCKET_SPIRALIN) { if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSfrPock, ptRef, ptStart, - vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops)) + vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops)) { vOffsFirstCurve[nIndexSwap]->GetStartPoint( ptNewStart) ; + } else return false ; } @@ -5958,8 +6040,10 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co // se richiesta inversione if ( PockParams.bInvert) { - for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) + for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { vOffs[i]->Invert() ; + SwapSideBySecondTempParam( vOffs[i]) ; + } } // smusso le curve di offset ( ad eccezione di quelle di primo Offset) @@ -5979,10 +6063,6 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co vOffs[0]->SetTempParam( 0., 0) ; // prima iterazione // riordino le curve e creo i collegamenti - /* - Se richiesto parametro di smusso, tutti gli Offset ( ad eccezione di quelli generati alla - prima iterazione vengono tagliati, quindi diventano aperti - */ ICURVEPOVECTOR vLinks( vOffs.size()) ; if ( ! CreateSpiralPocketingPath( vOffs, vLinks, PockParams, vOffsFirstCurve)) return false ; @@ -7067,8 +7147,8 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar //---------------------------------------------------------------------------- static bool -SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink, - const PocketParams& PockParams, bool bFirstOffs0, bool bFirstOffs1, double dSmoothPar, double dTol) +SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink, + const PocketParams& PockParams, bool bFirstOffs0, bool bFirstOffs1, double dSmoothPar, double dTol) { // controllo dei parametri @@ -7077,53 +7157,79 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve pCrvLink == nullptr || ! pCrvLink->IsValid()) return false ; - // curva precedente + // definisco la lunghezza del segmento iniziale e finale sulle due curve di Offset + double dRefLenSeg = 2. * dSmoothPar ; + + // --- Curva precedente --- + // recupero la lunghezza e il dominio del primo Offset + double dLen ; + pCrvOffs0->GetLength( dLen) ; + double dUStart, dUEnd ; + pCrvOffs0->GetDomain( dUStart, dUEnd) ; + // inizializzo la curva PtrOwner pCrvBef( CreateCurveComposite()) ; if ( IsNull( pCrvBef)) return false ; + // se primo Offset di bordo o chiuso... if ( bFirstOffs0 && pCrvOffs0->IsClosed()) { - const ICurve* pCrvFirst = pCrvOffs0->GetFirstCurve() ; - if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid()) - return false ; - PtrOwner pMyCrv( pCrvFirst->Clone()) ; + double dU = dUEnd ; + if ( dLen > dRefLenSeg - EPS_SMALL) + pCrvOffs0->GetParamAtLength( dRefLenSeg, dU) ; + PtrOwner pMyCrv( pCrvOffs0->CopyParamRange( dUStart, dU)) ; if ( IsNull( pMyCrv) || ! pMyCrv->IsValid()) return false ; pCrvBef->AddCurve( Release( pMyCrv)) ; } + // altrimenti... else { - const ICurve* pCrvLast = pCrvOffs0->GetLastCurve() ; - if ( pCrvLast == nullptr || ! pCrvLast->IsValid()) - return false ; - PtrOwner pMyCrv( pCrvLast->Clone()) ; + double dU = dUStart ; + if ( dLen > dRefLenSeg) + pCrvOffs0->GetParamAtLength( dLen - dRefLenSeg, dU) ; + PtrOwner pMyCrv( pCrvOffs0->CopyParamRange( dU, dUEnd)) ; if ( IsNull( pMyCrv) || ! pMyCrv->IsValid()) return false ; pCrvBef->AddCurve( Release( pMyCrv)) ; } + // se non valida, errore + if ( ! pCrvBef->IsValid()) + return false ; - // curva successiva + // --- Curva successiva --- + // recupero la lunghezza e il dominio del primo Offset + pCrvOffs1->GetLength( dLen) ; + pCrvOffs1->GetDomain( dUStart, dUEnd) ; + // inizializzo la curva PtrOwner pCrvAft( CreateCurveComposite()) ; if ( IsNull( pCrvAft)) return false ; - const ICurve* pCrvFirst = pCrvOffs1->GetFirstCurve() ; - if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid()) - return false ; - PtrOwner pMyCrv( pCrvFirst->Clone()) ; + // calcolo il parametro di taglio + double dU = dUEnd ; + if ( dLen > dRefLenSeg - EPS_SMALL) + pCrvOffs1->GetParamAtLength( dRefLenSeg, dU) ; + PtrOwner pMyCrv( pCrvOffs1->CopyParamRange( dUStart, dU)) ; if ( IsNull( pMyCrv) || ! pMyCrv->IsValid()) return false ; pCrvAft->AddCurve( Release( pMyCrv)) ; + // se non valida, errore + if ( ! pCrvAft->IsValid()) + return false ; - // controllo la validità delle curve precedenti e successive ricavate - if ( IsNull( pCrvBef) || IsNull( pCrvAft) || ! pCrvBef->IsValid() || ! pCrvAft->IsValid()) - return false ; - // estendo il Link + // estendo il Link ( linea di ingresso, segmento Link, linea d'uscita) pCrvLink->AddCurve( Release( pCrvBef), false, dTol) ; pCrvLink->AddCurve( Release( pCrvAft), true, dTol) ; - // smusso + + // miglioro la curva + pCrvLink->MergeCurves( 100 * EPS_SMALL, ANG_TOL_STD_DEG) ; + + // smusso la curva ModifyCurveToSmoothed( pCrvLink, PockParams, dSmoothPar, dSmoothPar, false) ; - // toglo gli estremi + + // toglo gli estremi, il Link è in tangenza e le linee di ingresso e d'uscita sono più + // estese dell'arco di smusso creato delete( pCrvLink->RemoveFirstOrLastCurve( false)) ; delete( pCrvLink->RemoveFirstOrLastCurve( true)) ; - // modifico Offset0 per raccordarlo al nuovo Link + + // modifico il primo Offset per raccordarlo al nuovo Link if ( bFirstOffs0 && pCrvOffs0->IsClosed()) { const ICurve* pCrvFirst = pCrvLink->GetFirstCurve() ; if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid()) @@ -7139,7 +7245,8 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve double dUE ; pCrvOffs0->GetParamAtPoint( ptS, dUE, dTol) ; pCrvOffs0->TrimEndAtParam( dUE) ; } - // modifico Offset1 per raccordarlo al nuovo Link + + // modifico il secondo Offset per raccordarlo al nuovo Link Point3d ptE ; pCrvLink->GetEndPoint( ptE) ; double dUS ; pCrvOffs1->GetParamAtPoint( ptE, dUS, dTol) ; if ( bFirstOffs1 && pCrvOffs1->IsClosed()) @@ -7199,8 +7306,8 @@ GetConformalLinkForOpenCrv( const ICurveComposite* pCrvOffs0, const ICurveCompos //---------------------------------------------------------------------------- static bool -GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams, - const ICRVCOMPOPOVECTOR& vCrvClassBorder, ICurveComposite* pCrvLink) +CalcConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams, + const ICRVCOMPOPOVECTOR& vCrvClassBorder, ICurveComposite* pCrvLink) { // controllo validità delle due curve di Offset if ( pCrvOffs0 == nullptr || ! pCrvOffs0->IsValid() || @@ -7252,10 +7359,16 @@ GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocket ICRVCOMPOPOVECTOR vCrvChunk ; for ( int i = 0 ; i < int( vIndOffs0.size()) ; ++ i) vCrvChunk.emplace_back( vCrvClassBorder[vIndOffs0[i]]->Clone()) ; + // se la curva successiva è chiusa, aggiorno il suo punto iniziale a quello a minima distanza + if ( ! bOpen1) { + Point3d ptS ; pCrvOffs0->GetStartPoint( ptS) ; + double dPar ; + int nFlag ; + if ( DistPointCurve( ptS, *pCrvOffs1).GetParamAtMinDistPoint( 0., dPar, nFlag)) + pCrvOffs1->ChangeStartPoint( dPar) ; + } if ( ! CutCurveToConnect( pCrvOffs0, pCrvOffs1, vCrvChunk, PockParams, - ( ( bOpen0 || bFirstIterOffs0) ? 0. : 10 * EPS_SMALL), - ( ( bOpen1 || bFirstIterOffs1) ? 0. : 10 * EPS_SMALL), - pCrvLink) || + bOpen0 ? 0. : 10 * EPS_SMALL, bOpen1 ? 0. : 10 * EPS_SMALL, pCrvLink) || ! pCrvLink->IsValid()) { // se curva di Link non valida, cerco una strada più semplice pCrvLink->Clear() ; @@ -7782,7 +7895,7 @@ CalcConformalOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatRegion* if ( IsNull( pCrvLink)) return false ; // se non calcolabile, allora retroazione, altrimenti lo memorizzo - if ( ! GetConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, pCrvLink) || + if ( ! CalcConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, pCrvLink) || IsNull( pCrvLink) || ! pCrvLink->IsValid() || pCrvLink->GetCurveCount() == 0) vCrvLink.resize( int( vCrvLink.size()) + 1) ; else