From 92d8f4414e0b6445f25627f14da28275fe45aa3d Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 16 Jun 2026 12:42:36 +0200 Subject: [PATCH] EgtGeomKernel : - in CalcPocketing aggiunto algoritmo ordinamento Offset per lavorazioni Spiral. --- CalcPocketing.cpp | 841 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 630 insertions(+), 211 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 1605ea7..6ba5a1e 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -96,10 +96,13 @@ typedef vector VICRVCOMPOPOVECTOR ; //--------------------------------------------------------------------------- // definizione varibaile di debug #define ENABLE_DEBUG 0 -#if ENABLE_DEBUG +#define ENABLE_ORDER_OFFSET_DEBUG 0 +#if ENABLE_DEBUG || ENABLE_ORDER_OFFSET_DEBUG #include "EgtDev/Include/EGkGeoObjSave.h" #include "EgtDev/Include/EGkGeoPoint3d.h" #include "EgtDev/Include/EGkGeoVector3d.h" + #include "EgtDev/Include/EGkExtText.h" + #include "EgtDev/Include/EGnStringUtils.h" // Varibili ausiliarie vector VT ; @@ -110,6 +113,22 @@ typedef vector VICRVCOMPOPOVECTOR ; return Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.) ; } + //--------------------------------------------------------------------------- + inline Color GetRandomLightColor() { + auto rnd = []() { + return 0.5 + ( double( rand()) / RAND_MAX) * 0.5 ; // [0.5, 1] + } ; + return Color( rnd(), rnd(), rnd(), 1.) ; + } + + //--------------------------------------------------------------------------- + inline Color GetRandomDarkColor() { + auto rnd = []() { + return ( double( rand()) / RAND_MAX) * 0.5; // [0.0, 0.5] + } ; + return Color( rnd(), rnd(), rnd(), 1.) ; + } + //--------------------------------------------------------------------------- inline void DrawCurve( const ICurveComposite* pCrvCompo) { if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid()) @@ -640,7 +659,7 @@ AssignFeedSpiral( ICurveComposite* pCompo, const ISurfFlatRegion* pSrfRemoved, b PtrOwner pCompoNew( CreateCurveComposite()) ; if ( IsNull( pCompoNew)) return false ; - for ( int i = 0 ; i < int( ccClass.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( ccClass) ; ++ i) { // recupero il tratto di curva ricavato dalla classificazione PtrOwner pSubCompo( ConvertCurveToComposite( pCompo->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE))) ; if ( IsNull( pSubCompo)) @@ -700,7 +719,7 @@ AssignFeedSpiral( ICurveComposite* pCompo, const ISurfFlatRegion* pSrfRemoved, b for ( int k = j + 1 ; k < int( ceil( dUE)) ; ++ k) { double dLenH = EPS_SMALL ; pCompo->GetCurve( k)->GetLength( dLenH) ; - if ( dLenH < dTol + 5 * EPS_SMALL) + if ( dLenH < dTol + 5. * EPS_SMALL) continue ; // cerco tra le curve successive vicine se ne trovo una con Feed Minima double dParam ; @@ -745,32 +764,32 @@ AssignFeedSpiralOpt( int nOptType, const PocketParams& PockParams, ICurveComposi if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_CONFORMAL_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ONEWAY) { if ( nOptType == 0) { // Spirale dall'Esterno - for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { - if ( u == 0) // prima circonferenza + for ( int nU = 0 ; nU < pCrv->GetCurveCount() ; ++ nU) { + if ( nU == 0) // prima circonferenza pCrv->SetCurveTempParam( 0, GetMinFeed( PockParams), 0) ; else // semi cerchi in tangenza - pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ; + pCrv->SetCurveTempParam( nU, GetMaxFeed( PockParams), 0) ; } } else if ( nOptType == 1) { // Trapezoidi - for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) - pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; + for ( int nU = 0 ; nU < pCrv->GetCurveCount() ; ++ nU) + pCrv->SetCurveTempParam( nU, GetMinFeed( PockParams), 0) ; } } /* NB. Essendo la funzione CalcSpiral richiamata sia per lo SpiralIN che per lo SpiralOUT le curve sono sempre orientate nello stesso modo, solamente alla fine viene invertita la curva finale per la svuotatura... */ else { if ( nOptType == 0) { // Spiral verso l'esterno - for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) { - if ( u > pCrv->GetCurveCount() - 3) // prime semi circonferenze - pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; + for ( int nU = 0 ; nU < pCrv->GetCurveCount() ; ++ nU) { + if ( nU > pCrv->GetCurveCount() - 3) // prime semi circonferenze + pCrv->SetCurveTempParam( nU, GetMinFeed( PockParams), 0) ; else - pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ; + pCrv->SetCurveTempParam( nU, GetMaxFeed( PockParams), 0) ; } } else if ( nOptType == 1) { // Trapezoidi - for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) - pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ; + for ( int nU = 0 ; nU < pCrv->GetCurveCount() ; ++ nU) + pCrv->SetCurveTempParam( nU, GetMinFeed( PockParams), 0) ; } } @@ -787,8 +806,8 @@ ResetCurveTempProps( ICurveComposite* pCrvCompo) // scorro le curve for ( int nU = 0 ; nU < pCrvCompo->GetCurveCount() ; ++ nU) { - pCrvCompo->SetCurveTempProp( nU, 0, 0) ; - pCrvCompo->SetCurveTempProp( nU, 0, 1) ; + pCrvCompo->SetCurveTempProp( nU, TEMP_PROP_CLOSE_EDGE, 0) ; + pCrvCompo->SetCurveTempProp( nU, TEMP_PROP_CLOSE_EDGE, 1) ; } return true ; @@ -5235,14 +5254,14 @@ CalcBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart, const pMyCrvLink.Set( ConvertCurveToComposite( Release( pCrvCir))) ; } } - if ( ! pMyCrvLink->IsValid() || pMyCrvLink->GetCurveCount() == 0) + if ( IsNull( pMyCrvLink) || ! pMyCrvLink->IsValid() || pMyCrvLink->GetCurveCount() == 0) return CalcBoundedLink( ptStart, ptEnd, vCrvBorders, pCrvLink) ; // se il BiArco creato è troppo piccolo, lo approssimo ad un tratto lineare BBox3d bBox3 ; if ( pMyCrvLink->GetLocalBBox( bBox3)) { double dRadBB ; - if ( bBox3.GetRadius( dRadBB) && dRadBB < 500 * EPS_SMALL) + if ( bBox3.GetRadius( dRadBB) && dRadBB < 500. * EPS_SMALL) return CalcBoundedLink( ptStart, ptEnd, vCrvBorders, pCrvLink) ; } @@ -5267,14 +5286,14 @@ CalcBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart, const pCompoHelp->Clear() ; // analizzo le intersezioni - for ( int i = 0 ; i < int( ccClass.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( ccClass) ; ++ i) { // se ho intersezione spezzo il segmento if ( ccClass[i].nClass == CRVC_OUT && int( ccClass.size()) > 1) { // recupero eventuali punti di intersezioni e parametri Point3d ptS ; pCompoTest->GetPointD1D2( ccClass[i].dParS, ICurve::FROM_PLUS, ptS) ; - double dOffS ; pCrvBorder->GetParamAtPoint( ptS, dOffS, 1500 * EPS_SMALL) ; + double dOffS ; pCrvBorder->GetParamAtPoint( ptS, dOffS, 1500. * EPS_SMALL) ; Point3d ptE ; pCompoTest->GetPointD1D2( ccClass[i].dParE, ICurve::FROM_MINUS, ptE) ; - double dOffE ; pCrvBorder->GetParamAtPoint( ptE, dOffE, 1500 * EPS_SMALL) ; + double dOffE ; pCrvBorder->GetParamAtPoint( ptE, dOffE, 1500. * EPS_SMALL) ; // recupero i due possibili percorsi e uso il più corto PtrOwner pCrvA( pCrvBorder->CopyParamRange( dOffS, dOffE)) ; PtrOwner pCrvB( pCrvBorder->CopyParamRange( dOffE, dOffS)) ; @@ -5578,7 +5597,7 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR bool bFirstOffs = false ; } ; vector vOffsPtMinDist( vOffs.size()) ; - for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vOffs) ; ++ i) { // indice dell'Offset vOffsPtMinDist[i].nInd = i ; // nel caso di Conformal, escludo le curve di primo Offset dalla ricerca @@ -5598,11 +5617,11 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR // nel caso Spiral if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_SPIRALOUT) { // InVsOut - vOffsPtMinDist[i].bInVsOut = ( int( vOffs[i]->GetTempParam( 1) != nSide)) ; + vOffsPtMinDist[i].bInVsOut = ( ! PockParams.bInvert ? ( nSide == MDS_LEFT) : ( nSide == MDS_RIGHT)) ; // 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)) { + if ( vOffsFirstCurve[j]->IsPointOn( ptCheck, 100. * EPS_SMALL)) { vOffsPtMinDist[i].bFirstOffs = true ; break ; } @@ -5674,8 +5693,7 @@ RemoveUnclearedRegions( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& int nInd = -1 ; Point3d ptCloser ; bool bFirstOffs = false ; - if ( ! ChooseCurveForRemovingUnclearedRegion( vOffs, vOffsFirstCurve, ptCentroid, PockParams, - nInd, ptCloser, bFirstOffs)) + if ( ! ChooseCurveForRemovingUnclearedRegion( vOffs, vOffsFirstCurve, ptCentroid, PockParams, nInd, ptCloser, bFirstOffs)) return false ; // se nessun indice trovato, salto il chunk if ( nInd == -1) @@ -5956,164 +5974,6 @@ RemoveUnclearedRegions( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR& return true ; } -//---------------------------------------------------------------------------- -static bool -CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, const PocketParams& PockParams, - const ICRVCOMPOPOVECTOR& vOffsFirstCurve) -{ - // controllo dei parametri - if ( vOffs.empty() || vOffsFirstCurve.empty()) - return false ; - 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) { - - // ricavo il punto inziale della curva corrente - 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 - Point3d ptStartNext ; // punto iniziale della curva successiva - bool bMinDistAtSmooth = false ; // se punto a minima distanza su curva di smusso - for ( int j = i + 1 ; j < int( vOffs.size()) ; ++ j) { - IntersCurveCurve IntCC( *vOffs[i], *vOffs[j]) ; - CRVCVECTOR ccClass ; - // se interna - if ( IntCC.GetCurveClassification( 1, EPS_SMALL, ccClass) && - int( ccClass.size()) == 1 && - ( ( 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. ; - Point3d ptClosest ; - DistPointCurve DistPtCrv( ptS, *vOffs[j]) ; - if ( DistPtCrv.GetParamAtMinDistPoint( EPS_SMALL, dPar, nFlag)) { - // controllo se la curva ottenuta è di raccordo, in caso positivo considero come - // punto più vicino il suo punto finale ( per avere poi successivamente Link tra - // Offset in tangenza ) - const ICurve* pCrv = vOffs[j]->GetCurve( static_cast( floor( dPar))) ; - if ( pCrv != nullptr && pCrv->IsValid()) { - if ( pCrv->GetTempProp( 1) == TEMP_PROP_SMOOTH) - pCrv->GetEndPoint( ptClosest) ; - else - DistPtCrv.GetMinDistPoint( EPS_SMALL, ptClosest, nFlag) ; - double dCurrDist = SqDist( ptS, ptClosest) ; - if ( dCurrDist < dMinDist) { - dMinDist = dCurrDist ; - nNextInd = j ; - ptStartNext = ptClosest ; - bMinDistAtSmooth = ( pCrv->GetTempProp( 1) == TEMP_PROP_SMOOTH) ; - } - } - } - } - } - - // se non ho trovato nessuna curva interna... cerco semplicemente la curva più vicina - if ( nNextInd == -1) { - for ( int j = i + 1 ; j < int( vOffs.size()) ; ++ j) { - int nFlag ; - double dPar = 0. ; - Point3d ptClosest ; - DistPointCurve DistPtCrv( ptS, *vOffs[j]) ; - if ( DistPtCrv.GetParamAtMinDistPoint( EPS_SMALL, dPar, nFlag)) { - const ICurve* pCrv = vOffs[j]->GetCurve( static_cast( floor( dPar))) ; - if ( pCrv != nullptr && pCrv->IsValid()) { - if ( pCrv->GetTempProp( 1) == TEMP_PROP_SMOOTH) - pCrv->GetEndPoint( ptClosest) ; - else - DistPtCrv.GetMinDistPoint( EPS_SMALL, ptClosest, nFlag) ; - double dCurrDist = SqDist( ptS, ptClosest) ; - if ( dCurrDist < dMinDist) { - dMinDist = dCurrDist ; - nNextInd = j ; - ptStartNext = ptClosest ; - bMinDistAtSmooth = ( pCrv->GetTempProp( 1) == TEMP_PROP_SMOOTH) ; - } - } - } - } - } - // se non ho trovato nessuna curva, errore - if ( nNextInd == -1) - return false ; - - // 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) ; - - // 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()) ; - PtrOwner pCrv_ii( vOffs[i+1]->Clone()) ; - if ( IsNull( pCrv_i) || IsNull( pCrv_ii) || ! pCrv_i->IsValid() || ! pCrv_ii->IsValid()) - return false ; - // creo la curva che le collegherà - PtrOwner pCrvLink( CreateCurveComposite()) ; - if ( IsNull( pCrvLink)) - return false ; - 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) ; - 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)) - return false ; - // creo il bi-arco tra esse - bool bSpecial = false ; - if ( CalcBoundedSmoothedLink( ptS, vtS, ptStartNext, vtE, 0.5, vOffsFirstCurve, PockParams, pCrvLink, bSpecial)) - vLinks[i + 1].Set( pCrvLink) ; // aggiorno il collegamento - else - return false ; - continue ; // passo alla curva i+1 esima successiva - } - - // per sicurezza aggiorno i nuovi punti e i nuovi parametri - double dUNewS, dUNewE ; - if ( ! pCrvLink->GetEndPoint( ptStartNext) || - ! vOffs[i]->GetParamAtPoint( ptS, dUNewS) || - ! vOffs[i+1]->GetParamAtPoint( ptStartNext, dUNewE)) - return false ; - - // imposto il punto iniziale della curva successiva ( i+1 esima) - vOffs[i+1]->ChangeStartPoint( dUNewE) ; - PtrOwner pCrvNewOffs( CloneCurveComposite( vOffs[i])) ; - if ( dUNewS > EPS_SMALL) { - pCrvNewOffs.Set( ConvertCurveToComposite( vOffs[i]->CopyParamRange( 0, dUNewS))) ; - // sostituisco la curva i esima con quella tagliata - vOffs[i].Set( pCrvNewOffs) ; - } - - // aggiorno il collegamento - vLinks[i+1].Set( pCrvLink) ; - } - - } - - return true ; -} - //---------------------------------------------------------------------------- static bool CheckIfOffsetIsNecessary( const ISurfFlatRegion* pSfrAct, const ICurveComposite* pCrvOffs, @@ -6386,8 +6246,8 @@ CalcBoundedPolishingLink( const Point3d& ptStart, const Vector3d& vtStart, const vtDir2.GetAngleXY( X_AX, dAng2) ; pCompo->AddCurve( GetBiArc( ptStart, -dAngStart, ptMinDist1, -dAng1, 0.5)) ; // primo biarco - pCompo->AddCurve( pCrvBound->CopyParamRange( dPar1, dPar2)) ; // tratto di pCrvBound - pCompo->AddCurve( GetBiArc( ptMinDist2, -dAng2, ptEnd, -dAngEnd, 0.5)) ; // secondo biarco + pCompo->AddCurve( pCrvBound->CopyParamRange( dPar1, dPar2)) ; // tratto di pCrvBound + pCompo->AddCurve( GetBiArc( ptMinDist2, -dAng2, ptEnd, -dAngEnd, 0.5)) ; // secondo biarco pCrvLink->AddCurve( Release( pCompo)) ; } @@ -6465,6 +6325,559 @@ ComputePolishingPath( const PocketParams& PockParam, ICRVCOMPOPOVECTOR& vOffs, I return true ; } +//---------------------------------------------------------------------------- +typedef vector> SPIRALOFFSETINDEXVECTOR ; // vettore di indici +typedef vector SPIRALOFFSETINDEXMATRIX ; // matrice associata (per ogni Offset) + +//---------------------------------------------------------------------------- +static bool +SwapMatOffsInd( const int& nIndA, const int& nIndB, SPIRALOFFSETINDEXMATRIX& matSpiralOffsIndex) +{ + // se Indice A e B sono gli stessi non faccio nulla + if ( nIndA == nIndB) + return true ; + // se non ho una matrice valida, esco + if ( matSpiralOffsIndex.empty()) + return true ; + + // scorro la matrice alla ricerca dell'Indice A e dell'Indice B + INTINT nCelA, nCelB ; + bool bFoundA = false, bFoundB = false ; + for ( int i = 0 ; ( ! bFoundA || ! bFoundB) && i < ssize( matSpiralOffsIndex) ; ++ i) { + for ( int j = 0 ; ( ! bFoundA || ! bFoundB) && j < ssize( matSpiralOffsIndex[i]) ; ++ j) { + bFoundA = ( matSpiralOffsIndex[i][j].first == nIndA) ; + if ( bFoundA) + nCelA = make_pair( i, j) ; + else { + bFoundB = ( matSpiralOffsIndex[i][j].first == nIndB) ; + if ( bFoundB) + nCelB = make_pair( i, j) ; + } + } + } + // se indici validi e trovati, effettuo lo scambio + if ( bFoundA && bFoundB) + swap( matSpiralOffsIndex[nCelA.first][nCelA.second], matSpiralOffsIndex[nCelB.first][nCelB.second]) ; + + return true ; +} + +//---------------------------------------------------------------------------- +// Struttura per informazioni di Gerarchia tra gli Offset +struct SpiralOffsetInfo { + ICurveComposite* pCompoOffs ; // puntatore alla curva in vOffs + INTSET SetIndOrigCrv ; // set di indici di gerarchia + bool bUsed ; // flag per inserimento Offset in un percorso di gerarchia + SpiralOffsetInfo() { + pCompoOffs = nullptr ; + SetIndOrigCrv = INTSET{} ; + bUsed = false ; + } + SpiralOffsetInfo( const SpiralOffsetInfo& SOI) { + pCompoOffs = SOI.pCompoOffs ; + SetIndOrigCrv = SOI.SetIndOrigCrv ; + bUsed = false ; + } +} ; +typedef vector SPIRALOFFSETINFOVECTOR ; // vettore assocato +typedef vector SPIRALOFFSETINFOMATRIX ; // matrice associata. Row : indice di Offset | Col : #Offset ottenuti + +//---------------------------------------------------------------------------- +static bool +UpdateSpiralOffsetInfo( const ICurveComposite* pCompoOffs, int nIter, int nOffs, int nOrigLoops, SPIRALOFFSETINDEXMATRIX& matSpiralOffsIndex) +{ + // verifica validità delle curve + if ( pCompoOffs == nullptr || ! pCompoOffs->IsValid()) + return false ; + // verifica validità della superficie originale + if ( nOrigLoops <= 0) + return false ; + + INTSET setIndOrigCrv ; + + // recupero le curve di Offset + for ( int nCrv = 0 ; nCrv < pCompoOffs->GetCurveCount() ; ++ nCrv) { + const ICurve* pCrv = pCompoOffs->GetCurve( nCrv) ; + if ( pCrv != nullptr && pCrv->IsValid()) { + int nOrigLoop = pCrv->GetTempProp( 1) ; + if ( nOrigLoop >= 0 && nOrigLoop < nOrigLoops) + setIndOrigCrv.insert( nOrigLoop) ; + } + } + + // aggiorno il vettore degli Offset + if ( ssize( matSpiralOffsIndex) <= nIter) + matSpiralOffsIndex.resize( matSpiralOffsIndex.size() + 1) ; // aggiungo una riga + matSpiralOffsIndex.back().resize( matSpiralOffsIndex.back().size() + 1) ; // aggiungo una colonna + matSpiralOffsIndex.back().back().first = nOffs ; // Ind( vOffs) + matSpiralOffsIndex.back().back().second = setIndOrigCrv ; // setInd( Offset da dipendenza) + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +GetDependeceOffsets( const SPIRALOFFSETINFOMATRIX& matSpiralOffsetInfo, const INTVECTOR& vIndRef, const int& nIter, INTINTVECTOR& vIndInd) +{ + vIndInd.clear() ; + // se non ho Offset, non faccio nulla + if ( matSpiralOffsetInfo.empty()) + return true ; + if ( nIter < 0 || nIter >= ssize( matSpiralOffsetInfo)) + return false ; + + // scorro gli Offset + int i = nIter ; + for ( int j = 0 ; j < ssize( matSpiralOffsetInfo[i]) ; ++ j) { + // verifico che la curva sia valida + if ( matSpiralOffsetInfo[i][j].bUsed ) + continue ; + // verifico la dipendenza del Set di Indici + const INTSET& setInds = matSpiralOffsetInfo[i][j].SetIndOrigCrv ; + bool bOk = true ; + for ( INTSET::iterator Iter = setInds.begin() ; bOk && Iter != setInds.end() ; ++ Iter) + bOk = ( find( vIndRef.begin(), vIndRef.end(), ( *Iter)) != vIndRef.end()) ; + if ( bOk) + vIndInd.push_back( make_pair( i, j)) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +GetMinDistPointOffsInfo( const Point3d& ptRef, const ICurveComposite* pCompoOffs, double& dMinDist, Point3d& ptMinDist, bool& bAtSmooth) +{ + // verifico che la curva sia valida + if ( pCompoOffs == nullptr || ! pCompoOffs->IsValid()) + return false ; + dMinDist = 0. ; + ptMinDist = P_INVALID ; + bAtSmooth = false ; + + // calcolo la distanza punto curva + DistPointCurve distPtCrv( ptRef, *pCompoOffs) ; + double dMyDist = INFINITO - 1 ; + double dMyPar = -1. ; + int nFlag = 0 ; + if ( distPtCrv.GetDist( dMyDist) && distPtCrv.GetParamAtMinDistPoint( EPS_SMALL, dMyPar, nFlag)) { + dMinDist = dMyDist ; + // controllo se la curva ottenuta è di raccordo + const ICurve* pCrv = pCompoOffs->GetCurve( static_cast( floor( dMyPar))) ; + if ( pCrv != nullptr && pCrv->IsValid()) { + if ( pCrv->GetTempProp( 1) == TEMP_PROP_SMOOTH) { + pCrv->GetEndPoint( ptMinDist) ; + bAtSmooth = true ; + } + else { + if ( ! distPtCrv.GetMinDistPoint( EPS_SMALL, ptMinDist, nFlag)) + return false ; + } + } + + return true ; + } + + return false ; +} + +//---------------------------------------------------------------------------- +static bool +IsOffsetInside( const ICurveComposite* pCompoClass, const ICurveComposite* pMyCompo) +{ + // verifico la validità della curve + if ( pCompoClass == nullptr || pMyCompo == nullptr || ! pCompoClass->IsValid() || ! pCompoClass->IsValid()) + return false ; + + // classifico le curve in base al risultato della classificazione e al primo TempParam della curva il quale contiene + // l'nSide di classificazione + // NB. Le curve di Offset potrebbero essere invertite per rispettare il verso di percorrenza delle isole + IntersCurveCurve IntCC( *pCompoClass, *pMyCompo) ; + CRVCVECTOR ccClass ; + if ( ! IntCC.GetCurveClassification( 1, EPS_SMALL, ccClass)) + return false ; + if ( ssize( ccClass) != 1) + return false ; + int nTmpPar1 = int( pCompoClass->GetTempParam( 1)) ; + return ( ( ccClass[0].nClass == CRVC_IN && nTmpPar1 == MDS_LEFT) || ( ccClass[0].nClass == CRVC_OUT && nTmpPar1 == MDS_RIGHT)) ; +} + +//---------------------------------------------------------------------------- +static bool +OrderSpiralOffset( const ICRVCOMPOPOVECTOR& vOffsFirstCurve, const PocketParams& PockParams, const SPIRALOFFSETINDEXMATRIX& matOffsIndex, + ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks) +{ + // se non ho curve di Offset non faccio nulla + if ( matOffsIndex.empty() || vOffsFirstCurve.empty()) + return false ; + vLinks.clear() ; vLinks.resize( vOffs.size()) ; + + // se meno di due Offset non faccio nulla + if ( ssize( vOffs) < 2) + return true ; + + // NB. vOffs contiene gli Offset nell'Ordine ricavato dalla progressione di Offset della regione piana originaria. + // NNB. matOffsIndex[0][0].first contiene l'indice del vettore di vOffs per il riferimento alla prima curva di Offset + // NNNB. La dimensione del vettore dei Link e degli Offset deve essere la stessa, con l'accortezza che il primo Link è nullptr + // ( il Link i-esimo collega la curva di Offset (i-1)-esima con la curva di Offset i-esima) + + #if 0 + // inzializzo la matrice degli Offset ( tra la fine di una riga e l'inizio dell'altra vi è un Link Special) + // Ogni riga di questa matrice rappresenta un successione di Offset che possono essere collegati medianti un Link nel piano, + // mentre tra la fine di una riga e l'inizio della successiva il Link potrebbe essere un alzata in ZLocale + vector> matOffs ; matOffs.reserve( vOffs.size()) ; + #endif + + // vettore dei nuovi Offset calcolati ( si sotituiranno a vOffs alla fine dell'ordinamento) + ICRVCOMPOPOVECTOR vecOffs ; vecOffs.reserve( vOffs.size()) ; + int nOffsCnt = ssize( vOffs) - 1 ; + + // estendo la matrice degli indici (matOffsIndex) mediante matOffsInfo. + // MatOffsetIndex è una matrice dove su ogni riga sono contenuti gli Offset calolati all'Iterazione i-esima e ogni colonna è rappresentata + // da un diverso Offset ottenuto all'Iterazione i-esima. + // L'elemento (i,j) di questa matrice è rappresentato da una coppia di valori, dove il primo elemento (.first) è l'indice del vettore + // vOffs per recuperare la curva di Offset correte, come secondo elemento (.second) vi è l'insieme degli indici dei loop che hanno generato + // tale Offset + // -->! NB !<-- Il riferimento ai bordi esterni è da intendersi rispetto alle CURVE DI PRIMO OFFSET, gli indici analizzati NON si + // si riferiscono agli indici dei Loop della regione originaria, ma agli indici dei Loop della pSfrAct dichiarata nella + // funzione "CalcSpiral". Guardare I loop originari è fuorviante in quanto al primo Offset potrei ottenre un numero diverso di + // Chunke e di Loop (oltre al fatto che la curva iniziale di Offset è già determinata matOffsIndex[0][0]) + SPIRALOFFSETINFOMATRIX matOffsInfo ; matOffsInfo.resize( matOffsIndex.size()) ; + for ( int i = 0 ; i < ssize( matOffsIndex) ; ++ i) { + matOffsInfo[i].resize( matOffsIndex[i].size()) ; + for ( int j = 0 ; j < ssize( matOffsIndex[i]) ; ++ j) { + // verifico che gli indici siano coerenti + const int& nIndOffs = matOffsIndex[i][j].first ; + if ( nIndOffs < 0 || nIndOffs >= ssize( vOffs)) + return false ; + matOffsInfo[i][j].pCompoOffs = vOffs[nIndOffs] ; // Curva di Offset Corrispondente + matOffsInfo[i][j].SetIndOrigCrv = matOffsIndex[i][j].second ; // Dipendenze dai Loop originali + matOffsInfo[i][j].bUsed = false ; // Flag per Offset inserito in un percorso + } + } + // verifico che tutti i puntatori siano validi e corretti + for ( int i = 0 ; i < ssize( matOffsInfo) ; ++ i) { + for ( int j = 0 ; j < ssize( matOffsInfo[i]) ; ++ j) { + if ( matOffsInfo[i][j].pCompoOffs == nullptr || ! matOffsInfo[i][j].pCompoOffs->IsValid()) + return false ; + } + } + + #if ENABLE_ORDER_OFFSET_DEBUG + // Offset (i,j), ... Dipendenze ... [Ind( vOffs)] + for ( int i = 0 ; i < ssize( matOffsInfo) ; ++ i) { + Color myColor = ( i == 0 ? FUCHSIA : GetRandomDarkColor()) ; + for ( int j = 0 ; j < ssize( matOffsInfo[i]) ; ++ j) { + VT.emplace_back( CloneCurveComposite( matOffsInfo[i][j].pCompoOffs)) ; + VC.emplace_back( myColor) ; + Point3d ptStart ; matOffsInfo[i][j].pCompoOffs->GetStartPoint( ptStart) ; + const INTSET& setInd = matOffsInfo[i][j].SetIndOrigCrv ; + PtrOwner pText( CreateExtText()) ; + string sText{ ""} ; + sText += ( "(" + ToString( i) + ", " + ToString( j)) + ")" ; + for ( auto Iter = setInd.begin() ; Iter != setInd.end() ; ++ Iter) { + int nInd = ( *Iter) ; + if ( i == 0) + sText += ToString( matOffsIndex[i][j].first) ; + else { + sText += ToString( nInd) ; + auto IterTmp = Iter ; IterTmp ++ ; + if ( IterTmp != setInd.end()) + sText += "-" ; + } + VT.emplace_back( pText->Clone()) ; + VC.emplace_back( myColor) ; + } + sText += "[" + ToString( matOffsIndex[i][j].first) + "]" ; + pText->Set( ptStart + X_AX, 0., sText, PockParams.dSideStep / 2. ) ; + VT.emplace_back( pText->Clone()) ; + VC.emplace_back( i == 0 ? FUCHSIA : RED) ; + } + } + SaveGeoObj( VT, VC, "C:\\Temp\\OffsOrder.nge") ; + #endif + + /* Definizione dell'Algormimo + * La curva di Offset espressa dalla cella [0][0] della Matrice è la prima curva scelta per Effettuare il LeadIn, ha già punto iniziale + * importato nel punto più opportuno. L'algoritmo procede in maniera sequenziale e data la curva (i-1)-esima cerca di ricavare la curva + * i-esima. Di seguito tra queste 2 curve viene creato il collegamento (Link). + * Si procede partendo dall'Interazione corrente (inizialmente a 0) e si cercano le curve di Offset appartenenti all'interazione successiva. + * Tra le curve ricavate si cerca quella all'interno dell'ultimo Offset inserito. + * Si tiene traccia di particolare Split degli Offset, ovvero quando eseguendo un Offset la curva si divide in n-parti. Ognuna di esse viene + * memorizzata all'interno dei un container (vItersSplit) e, quando non si trovano curve all'iterazione successiva all'interno dell'ultimo + * offset inserito, vengono prese in esame tale curve di Split (precisamente quella più vicina al punto corrente del percorso). + * Nel caso non si trovi una curva successiva di Offset allora la ricerca riparte dalla curve di primo Offset. + * NB. Un Offset viene inserito nel percorso se è contenuto all'interno dell'ultimo Offset inserito, se appartiene all'interazione successiva + * e se la dipendenza dalle curve di bordo e sbloccata (ovvero le curve di bordo da cui dipende sono già state inserite nel percorso) + * In caso negativo si ricercano curve di Split e se nemmeno quelle vengono trovate, si procede ad inserire una curva di Primo Offset + * NNB. Questo algoritmo è pensato per funzionare sia in SpiralIn che in SpiralOut (dato che lo SpiralOut è l'Invert del percorso finale + * di SpiralIn) + */ + + // inizializzazione dei parametri per ordinamento a gerarchia degli Offset + #if 0 + matOffs.resize( 1) ; + #endif + ICurveComposite* pCompoPrev = vOffs[0] ; // curva precedente + ICurveComposite* pCompoCurr = nullptr ; // curva corrente di Offset + Point3d ptRef ; vOffs[0]->GetStartPoint( ptRef) ; // punto di riferimento per pCompoCurr + vector> vItersSplit ; // vettore per SplitOffset + int nOffs = 1 ; // numero di Offset utilizzati Offset + INTVECTOR vIndRef = { matOffsIndex[0][0].first } ; // indici dei loop originari in esame + matOffsInfo[0][0].bUsed = true ; // primo Offset automaticamente determinato + vecOffs.emplace_back( CloneCurveComposite( vOffs[matOffsIndex[0][0].first])) ; + + int nIter = 0 ; + bool bFirst = true ; + while ( nOffs <= nOffsCnt) { + + // recupero il punto inziale della curva corrente + Point3d ptS ; + if ( ! vecOffs[nOffs-1]->GetStartPoint( ptS)) + return false ; + + // recupero l'Iterazione successiva + ++ nIter ; + + // flag per nuovo punto inziale su parametro di Smusso + bool bAtSmooth = false ; + + // recupero gli indici delle curve di Offset all'iterazione corrente che dipendono solo dagli indici delle curve + // presenti nel vettore vIndRef + INTINTVECTOR vIndIndIterLoops ; + GetDependeceOffsets( matOffsInfo, vIndRef, nIter, vIndIndIterLoops) ; + // --- tra queste curve devo selezionarne solo una, che sarà la successiva nell'ordinamento --- + bool bFound = false ; + + // 1) tra le curve ricavate tengo solo quelle che sono all'interno della curva precedente + erase_if( vIndIndIterLoops, [&]( const INTINT& Cell) { + return ( ! IsOffsetInside( pCompoPrev, matOffsInfo[Cell.first][Cell.second].pCompoOffs)) ; + }) ; + + // 2.a) tra le curve interne scelgo quella più vicina alla corrente (cambiando il suo punto iniziale) + if ( ! vIndIndIterLoops.empty()) { + double dMinDist = INFINITO ; + int nMinDistCrvInd = 0 ; + for ( int i = 0 ; i < ssize( vIndIndIterLoops) ; ++ i) { + const INTINT& Cell = vIndIndIterLoops[i] ; + ICurveComposite* pMyCompoCurr = matOffsInfo[Cell.first][Cell.second].pCompoOffs ; + double dMyDist = INFINITO - 1 ; + Point3d ptMyDist ; + bool bMyAtSmooth = false ; + if ( ! GetMinDistPointOffsInfo( ptRef, pMyCompoCurr, dMyDist, ptMyDist, bMyAtSmooth)) + return false ; + if ( dMyDist < dMinDist) { + dMinDist = dMyDist ; + nMinDistCrvInd = i ; + bAtSmooth = bMyAtSmooth ; + // cambio il suo punto iniziale nel punto più vicino tovato + double dUS ; + pCompoCurr = pMyCompoCurr ; + if ( ! pCompoCurr->GetParamAtPoint( ptMyDist, dUS, EPS_SMALL)) + return false ; + pCompoCurr->ChangeStartPoint( dUS) ; + } + } + // la curva più vicina diventa la successiva nel percorso e tutte le altre vengono memorizzate come Split + for ( int i = 0 ; i < ssize( vIndIndIterLoops) ; ++ i) { + const INTINT& Cell = vIndIndIterLoops[i] ; + if ( i == nMinDistCrvInd) { + #if 0 + matOffs.back().push_back( pCompoCurr) ; + #endif + vecOffs.emplace_back( CloneCurveComposite( pCompoCurr)) ; + matOffsInfo[Cell.first][Cell.second].bUsed = true ; + bFound = true ; // Offset trovato + nIter = Cell.first ; // Aggiornamento Iterazione + } + else + vItersSplit.push_back( make_pair( nIter, Cell)) ; + } + } + // 2.b) se non ho curve interne, verifico se devo recuperare degli Split precedentemente memorizzati + else { + // se vi sono degli Split, recupero l'ultimo inserito (stack => LIFO) + if ( ! vItersSplit.empty()) { + // recupero la curva più vicina al punto corrente + double dMinDist = INFINITO ; + int nMinDistCrvInd = 0 ; + for ( int i = 0 ; i < ssize( vItersSplit) ; ++ i) { + const INTINT& Cell = vItersSplit[i].second ; + ICurveComposite* pMyCompo = matOffsInfo[Cell.first][Cell.second].pCompoOffs ; + double dMyDist = INFINITO - 1 ; + Point3d ptMyDist ; + bool bMyAtSmooth = false ; + if ( ! GetMinDistPointOffsInfo( ptRef, pMyCompo, dMyDist, ptMyDist, bMyAtSmooth)) + return false ; + if ( dMyDist < dMinDist) { + dMinDist = dMyDist ; + nMinDistCrvInd = i ; + bAtSmooth = bMyAtSmooth ; + // cambio il suo punto inziale nel punto più vicino trovato + double dUS ; + pCompoCurr = pMyCompo ; + if ( ! pCompoCurr->GetParamAtPoint( ptMyDist, dUS, EPS_SMALL)) + return false ; + pCompoCurr->ChangeStartPoint( dUS) ; + } + } + // recupero la curva migliore + const INTINT& Cell = vItersSplit[nMinDistCrvInd].second ; + pCompoCurr = matOffsInfo[Cell.first][Cell.second].pCompoOffs ; + #if 0 + matOffs.back().push_back( pCompoCurr) ; + #endif + vecOffs.emplace_back( CloneCurveComposite( pCompoCurr)) ; + matOffsInfo[Cell.first][Cell.second].bUsed = true ; + bFound = true ; // Offset trovato + nIter = Cell.first ; // Aggiornamento Iterazione + // elimino tale elemento dal vettore + vItersSplit.erase( vItersSplit.begin() + nMinDistCrvInd) ; + } + } + + // se nessuna curva trovata valida, ne scelgo una da un indice dei bordi originali + if ( ! bFound) { + // recupero tutti gli indici non già inseriti + double dMinDist = INFINITO ; + int nNewRefInd = -1 ; + for ( int j = 0 ; j < ssize( matOffsInfo[0]) ; ++ j) { + if ( matOffsInfo[0][j].bUsed) + continue ; + ICurveComposite* pMyCompo = matOffsInfo[0][j].pCompoOffs ; + double dMyDist = INFINITO - 1 ; + Point3d ptMinDist ; + bool bMyAtSmooth = false ; + if ( ! GetMinDistPointOffsInfo( ptRef, pMyCompo, dMyDist, ptMinDist, bMyAtSmooth)) + return false ; + if ( dMyDist < dMinDist) { + dMinDist = dMyDist ; + nNewRefInd = j ; + pCompoCurr = pMyCompo ; + bAtSmooth = bMyAtSmooth ; + // cambio il suo punto iniziale nel punto più vicino tovato + double dUS ; + if ( ! pCompoCurr->GetParamAtPoint( ptMinDist, dUS, EPS_SMALL)) + return false ; + pCompoCurr->ChangeStartPoint( dUS) ; + } + } + // se vuoto + if ( nNewRefInd == -1) { + // cerco tra le curve valide, quella più vicina + INTINT CellMinDist = make_pair( -1, -1) ; + double dMinDist = INFINITO ; + for ( int i = 0 ; i < ssize( matOffsInfo) ; ++ i) { + for ( int j = 0 ; j < ssize( matOffsInfo[i]) ; ++ j) { + if ( ! matOffsInfo[i][j].bUsed) { + ICurveComposite* pMyCompo = matOffsInfo[i][j].pCompoOffs ; + double dMyDist = INFINITO - 1 ; + Point3d ptMyDist ; + bool bMyAtSmooth = false ; + if ( ! GetMinDistPointOffsInfo( ptRef, pMyCompo, dMyDist, ptMyDist, bMyAtSmooth)) + return false ; + if ( dMyDist < dMinDist) { + dMinDist = dMyDist ; + CellMinDist = make_pair( i, j) ; + bAtSmooth = bMyAtSmooth ; + // cambio il suo punto iniziale nel punto più vicino tovato + double dUS ; + pCompoCurr = pMyCompo ; + if ( ! pCompoCurr->GetParamAtPoint( ptMyDist, dUS, EPS_SMALL)) + return false ; + pCompoCurr->ChangeStartPoint( dUS) ; + } + } + } + } + if ( CellMinDist.first == -1 || CellMinDist.second == -1) + return false ; + } + vIndRef.push_back( nNewRefInd) ; // Aggiorno gli indici dei loop originali + #if 0 + matOffs.resize( matOffs.size() + 1) ; + matOffs.back().push_back( pCompoCurr) ; + #endif + vecOffs.emplace_back( CloneCurveComposite( pCompoCurr)) ; + matOffsInfo[0][nNewRefInd].bUsed = true ; + bFound = true ; // Offset trovato + nIter = 0 ; // Aggiornamento Iterazione + } + + // verifica dei parametri utilizzati + if ( pCompoPrev == nullptr || pCompoCurr == nullptr) + return false ; + + // la curva corrente diventa la precedente per la prossima iterazione + pCompoPrev = pCompoCurr ; + + // recupero il punto iniziale del percorso corrente, diventerà il riferimento per il successivo + vecOffs.back()->GetStartPoint( ptRef) ; + + // calcolo il Link tra la curva precedente e la curva corrente calcolata + // clono le curve (nel caso non riuscissi ad accorciarle o raccordarle) + PtrOwner pCompoOffsPrev( CloneCurveComposite( vecOffs[nOffs-1])) ; + PtrOwner pCompoNext( CloneCurveComposite( vecOffs[nOffs])) ; + if ( IsNull( pCompoOffsPrev) || IsNull( pCompoNext) || ! pCompoOffsPrev->IsValid() || ! pCompoNext->IsValid()) + return false ; + // creo la curva che le collegherà + PtrOwner pCrvLink( CreateCurveComposite()) ; + if ( IsNull( pCrvLink)) + return false ; + double dLenPercS = ( bFirst ? 0. : 10. * EPS_SMALL) ; + bFirst = false ; + double dLenPercE = ( bAtSmooth ? 0. : 10. * EPS_SMALL) ; + if ( ! CutCurveToConnect( vecOffs[nOffs-1], vecOffs[nOffs], vOffsFirstCurve, PockParams, dLenPercS, dLenPercE, pCrvLink) || ! pCrvLink->IsValid()) { + // se non sono riuscito, cerco una strada più semplice ripristinando le curve + pCrvLink->Clear() ; + vecOffs[nOffs-1].Set( ::Release( pCompoOffsPrev)) ; + vecOffs[nOffs].Set( ::Release( pCompoNext)) ; + // recupero i vettori tangenti iniziali (le curve sono chiuse) + Vector3d vtS, vtE ; + if ( ! vecOffs[nOffs-1]->GetStartDir( vtS) || ! vecOffs[nOffs]->GetStartDir( vtE)) + return false ; + // creo il bi-arco tra esse + bool bSpecial = false ; + if ( CalcBoundedSmoothedLink( ptS, vtS, ptRef, vtE, 0.5, vOffsFirstCurve, PockParams, pCrvLink, bSpecial)) + vLinks[nOffs].Set( pCrvLink) ; // aggiorno il collegamento + else + return false ; + continue ; // passo alla curva successiva + } + + // per sicurezza aggiorno i nuovi punti e i nuovi parametri + double dUNewS, dUNewE ; + if ( ! pCrvLink->GetEndPoint( ptRef) || ! vecOffs[nOffs-1]->GetParamAtPoint( ptS, dUNewS) || ! vecOffs[nOffs]->GetParamAtPoint( ptRef, dUNewE)) + return false ; + + // imposto il punto iniziale della curva successiva + vecOffs[nOffs]->ChangeStartPoint( dUNewE) ; + PtrOwner pCrvNewOffs( CloneCurveComposite( vecOffs[nOffs-1])) ; + if ( dUNewS > EPS_SMALL) { + pCrvNewOffs.Set( ConvertCurveToComposite( vecOffs[nOffs-1]->CopyParamRange( 0, dUNewS))) ; + // sostituisco la curva i esima con quella tagliata + vecOffs[nOffs-1].Set( pCrvNewOffs) ; + } + + // aggiorno il collegamento + vLinks[nOffs].Set( pCrvLink) ; + #if ENABLE_ORDER_OFFSET_DEBUG + #if 1 + VT.emplace_back( vLinks[nOffs]->Clone()) ; + VC.emplace_back( GetRandomLightColor()) ; + SaveGeoObj( VT, VC, "C:\\Temp\\OffsOrder.nge") ; + #endif + #endif + + // incremento del contatore di Offset inseriti + ++ nOffs ; + } + + // scambio il vettore degli Offset originali con il vettore degli Offset calcolati + swap( vecOffs, vOffs) ; + return true ; +} + //---------------------------------------------------------------------------- static bool CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, int& nReg, Point3d& ptStart, @@ -6495,6 +6908,10 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co if ( nCase == -1) return false ; + // definisco la matrice di relazione degli Offset (la regione ha un solo Chunk) + SPIRALOFFSETINDEXMATRIX matSpiralOffsIndex ; + int nOrigLoops = pSrfAct->GetLoopCount( 0) ; + // ricavo le regioni progressive double dOffsPrec = 0. ; int nCrvFirstOffs = 0 ; @@ -6506,7 +6923,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co 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)) ; + pSfrOffsVR.Set( pSrfAct->CreateOffsetSurf( - dOffs + 5. * EPS_SMALL, ICurve::OFF_FILLET)) ; if ( IsNull( pSfrOffsVR)) return false ; bLastNotValid = true ; @@ -6515,10 +6932,10 @@ 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 ; + int nCurrReg = nReg ; nReg = pSfrOffsVR->GetChunkCount() ; // gli Offset progressivi appartengono al Chunk nReg-esimo - pSrfAct.Set( pSfrOffsVR->CloneChunk( my_nReg)) ; + pSrfAct.Set( pSfrOffsVR->CloneChunk( nCurrReg)) ; // se supero i chunk ottenuti if ( IsNull( pSrfAct)) return true ; @@ -6547,7 +6964,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co bInsert = true ; if ( bInsert) { // imposto come secondo TempParam il Side di classificazione - pCrvCompoBorder->SetTempParam( j == 0 ? MDS_RIGHT : MDS_LEFT, 1) ; + pCrvCompoBorder->SetTempParam( MDS_LEFT, 1) ; // stabilisco l'orientamento della curva if ( ( nCase == 1 && nIter != 0 && j > 0) || ( nCase == 2 && j > 0) || @@ -6557,6 +6974,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co SwapSideBySecondTempParam( pCrvCompoBorder) ; } vOffs.emplace_back( Release( pCrvCompoBorder)) ; + UpdateSpiralOffsetInfo( vOffs.back(), nIter, ssize( vOffs) - 1, nOrigLoops, matSpiralOffsIndex) ; } if ( nIter == 0) { // salvo il bordo per i link ( non invertiti, devo sapere IN/OUT) PtrOwner pCrvCompoExtBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ; @@ -6615,16 +7033,13 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co // Se ho come lavorazione uno SpiralIn posso poter entrare dalle isole aperte... int nIndexSwap = 0 ; if ( PockParams.nType == POCKET_SPIRALIN) { - if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSfrPock, ptRef, ptStart, - vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops)) { + if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSfrPock, ptRef, ptStart, vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops)) vOffsFirstCurve[nIndexSwap]->GetStartPoint( ptNewStart) ; - } else return false ; } else { - if ( SetPtStartForPath( vOffs[0], PockParams, pSfrPock, ptRef, ptStart, vtMidOut, bMidOut, - vCrvOrigChunkLoops[0])) + if ( SetPtStartForPath( vOffs[0], PockParams, pSfrPock, ptRef, ptStart, vtMidOut, bMidOut, vCrvOrigChunkLoops[0])) vOffs[0]->GetStartPoint( ptNewStart) ; else return false ; @@ -6632,7 +7047,7 @@ 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 < ssize( vOffs) ; ++ i) { vOffs[i]->Invert() ; SwapSideBySecondTempParam( vOffs[i]) ; } @@ -6640,24 +7055,29 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co // smusso le curve di offset ( ad eccezione di quelle di primo Offset) double dSmoothPar = PockParams.dSmooth / SQRT2 ; - for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vOffs) ; ++ i) { if ( i >= nCrvFirstOffs) ModifyCurveToSmoothed( vOffs[i], PockParams, dSmoothPar, dSmoothPar, false) ; - vOffs[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; + vOffs[i]->MergeCurves( 10. * EPS_SMALL, 10. * EPS_ANG_SMALL, true, true) ; } // setto il punto iniziale della svuotatura double dNewUS ; if ( nIndexSwap != 0) - swap( vOffs[0], vOffs[nIndexSwap]) ; - vOffs[0]->GetParamAtPoint( ptNewStart, dNewUS) ; - vOffs[0]->ChangeStartPoint( dNewUS) ; - vOffs[0]->SetTempParam( 0., 0) ; // prima iterazione + SwapMatOffsInd( 0, nIndexSwap, matSpiralOffsIndex) ; + vOffs[nIndexSwap]->GetParamAtPoint( ptNewStart, dNewUS) ; + vOffs[nIndexSwap]->ChangeStartPoint( dNewUS) ; + vOffs[nIndexSwap]->SetTempParam( 0., 0) ; // prima iterazione // riordino le curve e creo i collegamenti ICURVEPOVECTOR vLinks( vOffs.size()) ; - if ( ! CreateSpiralPocketingPath( vOffs, vLinks, PockParams, vOffsFirstCurve)) - return false ; + #if ENABLE_ORDER_OFFSET_DEBUG + VT.clear() ; VC.clear() ; + PtrOwner pSfrDebug( CloneSurfFlatRegion( pSfrPock)) ; pSfrDebug->Translate( - Z_AX * 100. * EPS_SMALL) ; + VT.emplace_back( ::Release( pSfrDebug)) ; + VC.emplace_back( WHITE) ; + #endif + OrderSpiralOffset( vOffsFirstCurve, PockParams, matSpiralOffsIndex, vOffs, vLinks) ; // controllo eventuali parti non svuotate ( e setto la Feed degli Offset e dei Link)... PtrOwner pSfrUncleared( CreateSurfFlatRegion()) ; @@ -6668,7 +7088,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co } // creo il percorso di lavoro a partire dalla raccolta degli offset e dei collegamenti - for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { + for ( int i = 0 ; i < ssize( vOffs) ; ++ i) { // se collegamento da aggiungere if ( ! IsNull( vLinks[i])) { // accodo nel percorso di lavorazione @@ -6679,7 +7099,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co } // semplifico la curva ottenuta - SimplifyCurveByFeeds( pMCrv, PockParams, 10 * EPS_SMALL) ; + SimplifyCurveByFeeds( pMCrv, PockParams, 10. * EPS_SMALL) ; // verifico il percorso di lavoro if ( pMCrv->GetCurveCount() == 0) @@ -6687,8 +7107,8 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co // reset delle proprietà temporanee delle curve componenti for ( int i = 0 ; i < pMCrv->GetCurveCount() ; ++ i) { - pMCrv->SetCurveTempProp( i, 0, 0) ; - pMCrv->SetCurveTempProp( i, 0, 1) ; + pMCrv->SetCurveTempProp( i, TEMP_PROP_CLOSE_EDGE, 0) ; + pMCrv->SetCurveTempProp( i, TEMP_PROP_CLOSE_EDGE, 1) ; } // setto estrusione @@ -7185,8 +7605,7 @@ CalcZigZag( const ISurfFlatRegion* pSfrZigZag, const PocketParams& PockParams, I //---------------------------------------------------------------------------- static bool -AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, - PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes) +AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes) { // ricavo il numero di Chunk da svuotare if ( pSrfPock == nullptr) @@ -7225,7 +7644,7 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, int nRegTot = nReg ; Point3d ptStart ; - // cerco le curve originali del chunk cc-esimo ( per casi ottimizzati) + // cerco le curve originali del chunk (per casi ottimizzati) ICRVCOMPOPOVECTOR vCrvOrigChunkLoops ; if ( ! GetOptCrvIndex( pSfrOrig, pSfrChunk, PockParams, nReg, vCrvOrigChunkLoops)) return false ;