diff --git a/Pocketing.cpp b/Pocketing.cpp index 2a49d96..c86e63e 100644 --- a/Pocketing.cpp +++ b/Pocketing.cpp @@ -741,10 +741,8 @@ Pocketing::Apply( bool bRecalc, bool bPostApply) } // se necessario, eseguo concatenamento ed inserisco i percorsi sotto la geometria ausiliaria - if ( bChain && ! Chain( nAuxId)) { - // m_pMchMgr->SetLastError( 2421, "Error in Pocketing : Chaining failed") ; + if ( bChain && ! Chain( nAuxId)) return false ; - } // lavoro ogni singola catena bool bOk = true ; @@ -2200,6 +2198,8 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId) pStm_PartVolume->ToGlob( frElevation) ; // calcolo l'elevazione massima su ogni faccia del volume con normale circa - vtTool ( il volume è interno) double dElev = 0. ; + // Flat Region per regione di calcolo dell'elevazione + SurfFlatRegionByContours SfrBC ; pStm_PartVolume->Invert() ; // ho curve e normali orientate correttamente for ( int i = 0 ; i < pStm_PartVolume->GetFacetCount() ; ++ i) { Vector3d vtN_f ; @@ -2212,17 +2212,36 @@ Pocketing::ProcessPath( int nPathId, int nPvId, int nClId) if ( ! pStm_PartVolume->GetFacetLoops( i, vPL) || vPL.empty()) return false ; - // ricavo le curve Composite associate e calcolo l'elevazione + // ricavo le curve Composite associate e creo la FlatRegion assocoiata per l'orientamento + // NB. CalcRegionElevation calcola l'elevazione nella regione definita dalle curve, quindi serve che siano orientate for ( int j = 0 ; j < int( vPL.size()) ; ++ j) { PtrOwner pCompo( CreateCurveComposite()) ; - double dCurrElev = 0. ; if ( IsNull( pCompo) || ! pCompo->FromPolyLine( vPL[j]) || ! pCompo->IsValid() || - ! CalcRegionElevation( pCompo, vtTool, 0., 0.5 * ( m_dDiam_Prec > 0 ? m_dDiam_Prec : m_TParams.m_dDiam), + ! SfrBC.AddCurve( Release( pCompo))) + return false ; + } + } + // ricavo la Flat region per il calcolo dell'elevazione + PtrOwner pSfrElevation( SfrBC.GetSurf()) ; + if ( IsNull( pSfrElevation) || ! pSfrElevation->IsValid()) + return false ; + if ( AreOppositeVectorApprox( pSfrElevation->GetNormVersor(), vtTool)) + pSfrElevation->Invert() ; + // calcolo l'elevazione + for ( int c = 0 ; c < pSfrElevation->GetChunkCount() ; ++ c) { + for ( int l = 0 ; l < pSfrElevation->GetLoopCount( c) ; ++ l) { + PtrOwner pCrvLoop( ConvertCurveToComposite( pSfrElevation->GetLoop( c, l))) ; + if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid()) + return false ; + if ( l > 0) + pCrvLoop->Invert() ; + double dCurrElev = 0. ; + if ( ! CalcRegionElevation( pCrvLoop, vtTool, 0., 0.5 * ( m_dDiam_Prec > 0 ? m_dDiam_Prec : m_TParams.m_dDiam), m_dLen_Prec > 0 ? m_dLen_Prec : m_TParams.m_dLen, dCurrElev)) return false ; - dElev = max( dElev, dCurrElev) ; + dElev = max( dElev, dCurrElev) ; // l'elevazione è la massima tra quelle trovate } } pStm_PartVolume->Invert() ; // riporto come in orginale @@ -7822,6 +7841,7 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt PtrOwner pSfrOffsVR( pSrfAct->CreateOffsetSurf( - dOffs, ICurve::OFF_FILLET)) ; if ( IsNull( pSfrOffsVR)) return false ; + // se l'offset della regione la la annulla, allora ritento con una piccola tolleranza if ( ! pSfrOffsVR->IsValid()) { pSfrOffsVR.Set( pSrfAct->CreateOffsetSurf( - dOffs + 5 * EPS_SMALL, ICurve::OFF_FILLET)) ; if ( IsNull( pSfrOffsVR)) @@ -7843,20 +7863,23 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt 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 ; + // assegno come if ( j > 0) // inverto l'orientamento delle curve interne ( offset delle isole trovate) pCrvCompoBorder->Invert() ; + // salvo l'iterazione come primo parametro della curva + pCrvCompoBorder->SetTempParam( nIter * 1., 0) ; // controllo quali regioni di Offset possono essere sostituite bool bInsert = true ; - if ( ! CheckIfOffsetIsNecessary( pCrvCompoBorder, dOffs - dOffsPrec, ( int)vOffs.size(), nIter, vtExtr, bInsert)) + if ( ! CheckIfOffsetIsNecessary( pCrvCompoBorder, dOffs - dOffsPrec, int( vOffs.size()), nIter, vtExtr, bInsert)) return false ; if ( bInsert) vOffs.emplace_back( Release( pCrvCompoBorder)) ; - if ( nIter == 0) { // salvo il bordo per i link (non invertiti) + 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)) ; } @@ -7883,7 +7906,7 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt } // se non ho trovato curve di Offset allora esco - if (( int)vOffs.size() == 0) + if ( vOffs.empty()) return true ; // cambio il punto iniziale della prima Curva di Offset @@ -7891,136 +7914,44 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt Point3d ptNewStart ; if ( SetBetterPtStartForSubChunks( vOffs[0], pSrfToWork, ptRef, frPocket, ptStart, vtMidOut, bMidOut)) vOffs[0]->GetStartPoint( ptNewStart) ; - else + else return false ; // se richiesta inversione - for ( int i = 0 ; i < ( int)vOffs.size() && m_Params.m_bInvert ; ++ i) + for ( int i = 0 ; i < int( vOffs.size()) && m_Params.m_bInvert ; ++ i) vOffs[i]->Invert() ; // smusso le curve di offset ( ad eccezione della prima) ICRVCOMPOPOVECTOR vOffsClosedCurves( vOffs.size()) ; // vettore con tutte le curve di Offset Chiuse double dSmoothPar = m_TParams.m_dDiam / 16 ; - - for ( int i = 0 ; i < int( vOffs.size()) ; ++i ) { + for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { if ( i != 0) ModifyCurveToSmoothed( vOffs[i], dSmoothPar, dSmoothPar, false) ; vOffs[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ; vOffsClosedCurves[i].Set( vOffs[i]->Clone()) ; } - for ( int i = 0 ; i < int( vOffsFirstCurve.size()) ; ++ i) { - if ( i != 0) - ModifyCurveToSmoothed( vOffsFirstCurve[i], dSmoothPar, dSmoothPar, false) ; - vOffsFirstCurve[i]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; - } - // setto il punto iniziale della svuotatura double dNewUS ; vOffs[0]->GetParamAtPoint( ptNewStart, dNewUS) ; vOffs[0]->ChangeStartPoint( dNewUS) ; + vOffs[0]->SetTempParam( 0., 0) ; // prima iterazione - // riordino le curve cambiando il loro punto di inizio e creando poi i collegamenti - int nClosestInd = -1 ; int nFlag ; - double dDist = INFINITO ; - Point3d ptHelp ; + // riordino le curve cambiando e creo i collegamenti ICURVEPOVECTOR vLinks( vOffs.size()) ; - - for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) { - - Point3d ptS ; - if ( ! vOffs[i]->GetStartPoint( ptS)) - return false ; - - // setto i default delle variabili - if ( ! DistPointCurve( ptS, *vOffs[i+1]).GetMinDistPoint( EPS_SMALL, ptHelp, nFlag)) - return false ; - dDist = INFINITO ; - - for ( int j = i + 1 ; j <= int( vOffs.size()) - 1 ; ++ j) { - // cerco il punto più vicino della curva - Point3d ptE ; - - if ( ! DistPointCurve( ptS, *vOffs[j]).GetMinDistPoint( EPS_SMALL, ptE, nFlag)) - return false ; - - if ( dDist > Dist( ptS, ptE) ) { - dDist = Dist( ptS, ptE) ; - nClosestInd = j ; - ptHelp.Set( ptE.x, ptE.y, ptE.z) ; - } - } - // avendo la curva più vicina ... - - // 1) scambio la curva i con la curva nClosestInd - if ( nClosestInd != i + 1) { - PtrOwner ptoCCHelp( Release( vOffs[i + 1])) ; - vOffs[i + 1].Set( vOffs[nClosestInd]) ; - vOffs[nClosestInd].Set( ptoCCHelp) ; - } - - // 2) cambio il suo punto iniziale ... - double dU ; - Point3d ptNE( ptHelp.x, ptHelp.y, ptHelp.z) ; - if ( ! vOffs[i + 1]->GetParamAtPoint( ptNE, dU)) - return false ; - vOffs[i + 1]->ChangeStartPoint( dU) ; - - // 2.1) Accorcio la curva per velocizzare ... - if (( int)vOffs.size() > 1) { // accorcio se ho almeno due Offset - // copio le curve i e i+1 nel caso non riesca a tagliarle ... - double dUNS, dUNE ; - PtrOwner pCrvTest( CreateCurveComposite()) ; // possibile collegamento tra la curva i ed i+1 - PtrOwner pOff_i0( CloneCurveComposite( vOffs[i])) ; - PtrOwner pOff_i1( CloneCurveComposite( vOffs[i + 1])) ; - // cerco di tagliare le curve, ottenendo il collegamento - // NB. se la curva di offset è la prima, non devo tagliarla, accorcio solo le successive ... - if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsClosedCurves, vOffsFirstCurve, pCrvTest, i == 0 ? 0 : 0.01, 0.01, 2)) { - // se non sono riuscito, ritorno alla configurazione iniziale - PtrOwner pCrvLink( CreateCurveComposite()) ; - Vector3d vS, vE ; - vOffs[i].Set( pOff_i0) ; vOffs[i+1].Set( pOff_i1) ; - if ( ! vOffs[i]->GetStartDir( vS) || ! vOffs[i+1]->GetStartDir( vE)) - return false ; - if ( CalcBoundedSmootedLink( ptS, vS, ptNE, vE, 0.5, vOffsFirstCurve, pCrvLink)) - vLinks[i + 1].Set( pCrvLink) ; // aggiorno il collegamento - else { - m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; - return false ; - } - continue ; - } - - if ( ! pCrvTest->GetStartPoint( ptS) || - ! pCrvTest->GetEndPoint( ptNE) || - ! vOffs[i]->GetParamAtPoint( ptS, dUNS) || - ! vOffs[i+1]->GetParamAtPoint( ptNE, dUNE)) - return false ; - - // imposto il nuovo punto inziale della curva successiva - vOffs[i+1]->ChangeStartPoint( dUNE) ; - PtrOwner pCrvNewOffS( CloneCurveComposite( vOffs[i])) ; - if ( dUNS > EPS_SMALL) { // se parametro di trim sufficientemente grande - pCrvNewOffS.Set( GetCurveComposite( vOffs[i]->CopyParamRange( 0, dUNS))) ; - // sostituisco la curva i-esima con quella tagliata - vOffs[i]->Clear() ; - vOffs[i].Set( pCrvNewOffS) ; - } - // aggiorno il collegamento - vLinks[i + 1].Set( pCrvTest) ; - } - } + if ( ! CreateSpiralPocketingPath( vOffs, vLinks, vOffsClosedCurves, vOffsFirstCurve)) + return false ; // copio il vettore degli Offset per settare poi la Feed - ICRVCOMPOPOVECTOR vOffsFeed ; vOffsFeed.reserve(( int)vOffs.size()) ; - for ( int i = 0 ; i < ( int)vOffs.size() ; ++ i) - vOffsFeed.emplace_back( vOffs[i]->Clone()) ; + //ICRVCOMPOPOVECTOR vOffsFeed ; vOffsFeed.reserve(( int)vOffs.size()) ; + //for ( int i = 0 ; i < ( int)vOffs.size() ; ++ i) + // vOffsFeed.emplace_back( vOffs[i]->Clone()) ; - // 3) controllo eventuali parti non svuotate... + // controllo eventuali parti non svuotate... pCrvOEWithFlags->ToLoc( frPocket) ; PtrOwner pSrfToCut( CreateSurfFlatRegion()) ; if ( GetUnclearedRegion( vOffsFirstCurve, vOffs, vLinks, pCrvOEWithFlags, pSrfToCut)) { - // 4) Modifico i percorsi + // Modifico i percorsi if ( ! RemoveExtraParts( pSrfToCut, vOffs, vOffsClosedCurves, vOffsFirstCurve, vLinks)) return false ; } @@ -8067,6 +7998,141 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt return true ; } +//---------------------------------------------------------------------------- +bool +Pocketing::CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, + const ICRVCOMPOPOVECTOR& vOffsClosedCurves, const ICRVCOMPOPOVECTOR& vOffsFirstCurve) +{ + // controllo dei parametri + if ( vOffs.empty() || vOffsFirstCurve.empty()) + return false ; + vLinks.clear() ; + vLinks.resize( int( vOffs.size())) ; + + // 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 ; + + // ricavo l'iterazione corrente + int nCurrIter = int( vOffs[i]->GetTempParam( 0)) ; + + int nNextInd = -1 ; // indice della curva successiva + double dMinDist = INFINITO ; // distanza tra questa curva e la successiva + Point3d ptStartNext ; // punto iniziale della curva successiva + + // tra le curva successive cerco la curva interna e più vicina ad essa + 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) { + // calcolo la distanza minima tra essa + int nFlag ; + Point3d ptClosest ; + if ( DistPointCurve( ptS, *vOffs[j]).GetMinDistPoint( EPS_SMALL, ptClosest, nFlag)) { + double dCurrDist = SqDist( ptS, ptClosest) ; + if ( dCurrDist < dMinDist) { + dMinDist = dCurrDist ; + nNextInd = j ; + ptStartNext = ptClosest ; + } + } + } + } + // 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 ; + Point3d ptClosest ; + if ( DistPointCurve( ptS, *vOffs[j]).GetMinDistPoint( EPS_SMALL, ptClosest, nFlag)) { + double dCurrDist = SqDist( ptS, ptClosest) ; + if ( dCurrDist < dMinDist) { + dMinDist = dCurrDist ; + nNextInd = j ; + ptStartNext = ptClosest ; + } + } + } + } + // 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) ; + + // accorcio la curva per raccordarmi in tangenza con la successiva + if ( int( vOffs.size()) > 1) { + // clono le curve i ed i+1 esime ( nel caso non riuscissi ad accorciarle o raccordarle ) + PtrOwner pCrv_i( CloneCurveComposite( vOffs[i])) ; + PtrOwner pCrv_ii( CloneCurveComposite( vOffs[i+1])) ; + 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 ; + // NB. Le curve di Offset da tagliare non devono essere quelle di primo Offset + if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsClosedCurves, vOffsFirstCurve, pCrvLink, + i == 0 ? 0 : 0.01, 0.01, 2)) { + // se non sono riuscito, cerco una strada più semplice + // ripristino le curve + pCrvLink->Clear() ; + vOffs[i].Set( Release( pCrv_i)) ; // chiuso + vOffs[i+1].Set( Release( pCrv_ii)) ; // chiuso + // recupero i vettori tangente 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 + if ( CalcBoundedSmootedLink( ptS, vtS, ptStartNext, vtE, 0.5, vOffsFirstCurve, pCrvLink)) + vLinks[i + 1].Set( pCrvLink) ; // aggiorno il collegamento + else { + m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; + 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->GetStartPoint( ptS) || + ! 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( Release( pCrvLink)) ; + } + + } + + return true ; +} + //---------------------------------------------------------------------------- bool Pocketing::OptimizedSpiralCirle( const ICurveComposite* pCrvCompo, const double dToll, double& dRad, @@ -8180,7 +8246,7 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl Vector3d vtS, vtE ; if ( ! vCrvStepsToFill[i]->GetEndDir( vtS) || ! vCrvStepsToFill[i+1]->GetStartDir( vtE)) continue ; - if ( AreSameVectorApprox( vtS, vtE)) { + if ( AreSameVectorEpsilon( vtS, vtE, 5 * EPS_SMALL)) { vCrvArcs.emplace_back( CreateCurveComposite()) ; // arco nullo vArcsToJump.push_back( i) ; // da scartare continue ; @@ -8199,7 +8265,9 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl // se valori trattati come parametri... if ( bAsParam) { // ... cerco i parametri corrispondenti sulle due curve - double dU_cm_S = 0 ; double dULast1 = 1 ; double dULast2 = 1 ; + double dU_cm_S = 0 ; + double dULast1 = 1 ; + double dULast2 = 1 ; vCrvStepsToFill[i]->GetDomain( dU_cm_S, dULast1) ; dUE_ref = ( 1 - dRightLen) * dULast1 ; vCrvStepsToFill[i+1]->GetDomain( dU_cm_S, dULast2) ; @@ -8209,10 +8277,12 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl // prendo i punti sulle due curve rispetto a tali parametri Point3d ptS, ptE ; if ( ! vCrvStepsToFill[i]->GetPointD1D2( dUE_ref, ICurve::FROM_PLUS, ptS) || - ! vCrvStepsToFill[i+1]->GetPointD1D2( dUS_ref, ICurve::FROM_MINUS, ptE)) + ! vCrvStepsToFill[i+1]->GetPointD1D2( dUS_ref, ICurve::FROM_MINUS, ptE)) return false ; dRadius = Dist( ptS, ptE) ; // uso come raggio la distanza tra i due punti + // NB. Due curve non è detto che siano raccordabili con una circonferenza ai parametri stabiliti + // -> cerco di stare vicino a tale quantità int nMaxTestForArcs = 3 ; // tentativi per creare l'arco int nIterForArcs = 0 ; @@ -8223,21 +8293,25 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl // controllo che l'arco creato non sia troppo piccolo double dArcLen ; - if ( ! IsNull( pCrvArc) && pCrvArc->IsValid() && (! pCrvArc->GetLength( dArcLen) || dArcLen < 5 * EPS_SMALL)) { + if ( ! IsNull( pCrvArc) && pCrvArc->IsValid() && + ( ! pCrvArc->GetLength( dArcLen) || dArcLen < 5 * EPS_SMALL)) { vCrvArcs.emplace_back( Release( pCrvArc)) ; // arco nullo vArcsToJump.push_back( i) ; // da scartare continue ; } - if ( i != 0 && vArcsToJump[i-1] == -1 && ! IsNull( pCrvArc) && pCrvArc->IsValid()) { // dal secondo arco in poi controllo che non ci siano intersezioni tra essi + // dal secondo arco in poi di raccordo controllo che non ci siano intersezioni tra essi + if ( i != 0 && vArcsToJump[i-1] == -1 && ! IsNull( pCrvArc) && pCrvArc->IsValid()) { IntersCurveCurve intCCH( *pCrvArc, *vCrvArcs[i-1]) ; if ( intCCH.GetIntersCount() > 0 ) IntersBTWArcs = true ; } - // se ho intersezioni tra archi o l'arco creato non è valido, allora provo altre nMaxTestForArcs volte a ricrearlo avvicinando i punti + // se ho intersezioni tra archi o l'arco creato non è valido, allora provo altre + // nMaxTestForArcs volte a ricrearlo avvicinando i punti while (( IsNull( pCrvArc) || IntersBTWArcs) && nIterForArcs < nMaxTestForArcs) { + // aggiorno i parametri di riferimento ( mi avvicino sempre della metà) dUE_ref = ( 1 + dUE_ref ) * 0.5 ; dUS_ref = dUS_ref * 0.5 ; @@ -8248,8 +8322,16 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl dRadius = Dist( ptS, ptE) ; pCrvArc.Set( CreateFillet( *vCrvStepsToFill[i], ptS, *vCrvStepsToFill[i+1], ptE, Z_AX, dRadius, dPar1, dPar2)) ; - nIterForArcs++ ; + ++ nIterForArcs; + // controllo ancora lunghezza ed intersezioni + double dArcLen ; + if ( ! IsNull( pCrvArc) && pCrvArc->IsValid() && + ( ! pCrvArc->GetLength( dArcLen) || dArcLen < 5 * EPS_SMALL)) { + vCrvArcs.emplace_back( Release( pCrvArc)) ; // arco nullo + vArcsToJump.push_back( i) ; // da scartare + continue ; + } IntersBTWArcs = false ; if ( i != 0 && vArcsToJump[i-1] == -1 && ! IsNull( pCrvArc) && pCrvArc->IsValid()) { // dal secondo arco in poi controllo che non ci siano intersezioni tra essi IntersCurveCurve intCCH( *pCrvArc, *vCrvArcs[i-1]) ; @@ -8258,7 +8340,9 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl } } - if ( IsNull( pCrvArc) || ! pCrvArc->IsValid()) { // se ancora non riesco... salto l'arco + + // se ancora non valido... salto l'arco + if ( IsNull( pCrvArc) || ! pCrvArc->IsValid()) { vCrvArcs.emplace_back( CreateCurveArc()) ; // arco nullo vArcsToJump.push_back( i) ; // da scartare continue ; @@ -8360,8 +8444,8 @@ Pocketing::ModifyCurveToSmoothed( ICurveComposite* pCrv, double dRightLen, doubl //---------------------------------------------------------------------------- bool -Pocketing::CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, ICRVCOMPOPOVECTOR& vOffsCL, - ICRVCOMPOPOVECTOR& vFirstOffset, ICurveComposite* pCrvLink, double dLenPercS, +Pocketing::CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOMPOPOVECTOR& vOffsCL, + const ICRVCOMPOPOVECTOR& vFirstOffset, ICurveComposite* pCrvLink, double dLenPercS, double dLenPercE, int nMaxIter) { // controllo i parametri @@ -8373,7 +8457,7 @@ Pocketing::CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, IC if ( IsNull( ptCrvFinal)) return false ; - // Prendo i punti, i vettori tangenti e i parametri di essi per le curve + // Prendo i punti, i vettori tangenti e i parametri di essi per le curve Point3d ptSS, ptSE, ptES, ptEE ; Vector3d vS, vE ; double dUSS, dUSE, dUES, dUEE, dLenS, dLenE ; @@ -9425,7 +9509,8 @@ Pocketing::RemoveExtraPartByMedialAxis( const ISurfFlatRegion* pChunkToCut, ICRV //---------------------------------------------------------------------------- bool -Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) +Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ICRVCOMPOPOVECTOR& vOffIslands, + ICurveComposite* pCrvLink) { pCrvLink->Clear() ; @@ -9491,8 +9576,9 @@ Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCO PtrOwner pCrvA( GetCurve( vOffIslands[i]->CopyParamRange( dOffS, dOffE))) ; PtrOwner pCrvB( GetCurve( vOffIslands[i]->CopyParamRange( dOffE, dOffS))) ; - if ( IsNull( pCrvA) || IsNull( pCrvB) ) + if ( IsNull( pCrvA) || IsNull( pCrvB)) { return false ; + } double dLenA ; pCrvA->GetLength( dLenA) ; double dLenB ; pCrvB->GetLength( dLenB) ; if ( dLenA < dLenB ) { @@ -9525,7 +9611,7 @@ Pocketing::CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCO //------------------------------------------------------------------------------ bool Pocketing::CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, - const Vector3d& vtEnd, double dParMeet, ICRVCOMPOPOVECTOR& vOffIslands, + const Vector3d& vtEnd, const double dParMeet, const ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) { // creo il BiArc che unisce i due punti @@ -9551,7 +9637,14 @@ Pocketing::CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtSta if ( SqDist( ptStart, ptEnd) > 25 * ( GetSideStep() + m_TParams.m_dDiam * m_TParams.m_dDiam)) { Point3d ptS_shift = ptStart + ( m_TParams.m_dDiam / 2) * vtStart ; Point3d ptE_shift = ptEnd - ( m_TParams.m_dDiam / 2) * vtEnd ; - if ( ! CalcBoundedLink( ptS_shift, ptE_shift, vOffIslands, pCrvLink)) + // controllo che tali punti siano effettivamente interni alla regione da svuotare + bool bOk = true ; + for ( int i = 0 ; i < int( vOffIslands.size()) && bOk ; ++ i) { + PolyLine PL ; vOffIslands[i]->ApproxWithLines( EPS_SMALL, EPS_ANG_SMALL, ICurve::APL_STD, PL) ; + bOk = IsPointInsidePolyLine( ptS_shift, PL, EPS_SMALL) || + IsPointInsidePolyLine( ptE_shift, PL, EPS_SMALL) ; + } + if ( ! CalcBoundedLink( bOk ? ptS_shift : ptStart, bOk ? ptE_shift : ptEnd, vOffIslands, pCrvLink)) return false ; pCrvLink->AddLine( ptStart, false) ; pCrvLink->AddLine( ptEnd, true) ; @@ -9601,8 +9694,9 @@ Pocketing::CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtSta PtrOwner pCrvA( GetCurve( vOffIslands[i]->CopyParamRange( dOffS, dOffE))) ; PtrOwner pCrvB( GetCurve( vOffIslands[i]->CopyParamRange( dOffE, dOffS))) ; - if ( IsNull( pCrvA) || IsNull( pCrvB)) + if ( IsNull( pCrvA) || IsNull( pCrvB)) { return CalcBoundedLink( ptStart, ptEnd, vOffIslands, pCrvLink) ; + } double dLenA ; pCrvA->GetLength( dLenA) ; double dLenB ; pCrvB->GetLength( dLenB) ; @@ -10882,7 +10976,7 @@ Pocketing::AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVE // assegno le proprietà di lato Aperto/Chiuso per la curva corrente for ( int u = 0 ; u < vpCrvs[i]->GetCurveCount() ; ++ u) vpCrvs[i]->SetCurveTempProp( u, nCurrTmpProp, 0) ; - // aggiungo la curva ricavata + // aggiungo la curva ricavata ( se chiusa -> la copio, se aperta -> copio l'estesa) if ( ! pCrvCompo_final->AddCurve( vpCrvs[i]->Clone())) { Point3d ptH ; vpCrvs[i]->GetStartPoint( ptH) ; if ( ! pCrvCompo_final->AddLine( ptH) || @@ -10935,11 +11029,10 @@ Pocketing::AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVE ! CreateSurfFrIncidence( pCrvBorder, dRad, pSfrInc)) return false ; - // creo un vettore con tutte le curve che potrebbero cadere in parte nella regione di incidenza + // creo un vettore con tutte le curve che potrebbero cadere, in parte, nella regione di incidenza ICRVCOMPOPOVECTOR vCrvToCheck ; for ( int i = 0 ; i < ( int)vCrvIsland.size() ; ++ i) vCrvToCheck.emplace_back( vCrvIsland[i]->Clone()) ; // aggiungo le isole - // se la curva originale non è tutta Aperta -> devo aggiungere anche essa nelle curve da controllare bool bIsAllOpen = abs( abs( dParE - dParS) - pCrvCompo->GetCurveCount()) < EPS_SMALL ; if ( ! bIsAllOpen) { @@ -10947,45 +11040,50 @@ Pocketing::AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVE PtrOwner pCompoOther( ConvertCurveToComposite( pCrvCompo->CopyParamRange( dParE, dParS))) ; if ( IsNull( pCompoOther) || ! pCompoOther->IsValid()) return false ; - vCrvToCheck.emplace_back( Release( pCompoOther)) ; + vCrvToCheck.emplace_back( Release( pCompoOther)) ; // aggiungo il bordo } // scorro il vettore creato... - for ( int c = 0 ; c < ( int)vCrvToCheck.size() ; ++ c) { + for ( int c = 0 ; c < int( vCrvToCheck.size()) ; ++ c) { // 1) recupero la curva corrente PtrOwner pCrvCurr( CloneCurveComposite( vCrvToCheck[c])) ; if ( IsNull( pCrvCurr) || ! pCrvCurr->IsValid()) return false ; + // 2) ricavo i tratti con proprietà uniformi ( Aperti/Chiusi ) ICRVCOMPOPOVECTOR vpCrvs ; if ( ! GetHomogeneousParts( pCrvCurr, vpCrvs)) return false ; - // 5) considero solo i tratti chiusi + // 3) considero solo i tratti chiusi for ( int cl = 0 ; cl < int( vpCrvs.size()) ; ++ cl) { if ( vpCrvs[cl]->GetTempProp() == 1) continue ; - // 6) effettuo l'Offset della curva di metà dDiamJ + // 4) effettuo l'Offset della curva di metà dDiamJ OffsetCurve OffsCrv ; if ( ! OffsCrv.Make( vpCrvs[cl], - dDiamJ * 0.5, ICurve::OFF_FILLET)) { m_pMchMgr->SetLastError( 2412, "Error in Pocketing : Offset not computable") ; return false ; } - // 7) scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti + // 5) scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; while ( ! IsNull( pOffLongestCrv)) { - // 8) tengo solo le curve che non si chiudono su loro stesse - if ( ! pOffLongestCrv->IsClosed()) { - // 9) creo la regione di incidenza di tale curva ( "Curva a fagiolo") - PtrOwner pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ * 0.5, false, false)) ; - if ( IsNull( pSfrBean) || ! pSfrBean->IsValid()) - return false ; - // inverto se necessario - if ( AreOppositeVectorApprox( pSfrBean->GetNormVersor(), pSfrInc->GetNormVersor())) - pSfrBean->Invert() ; - // 10) aggiorno la regione di incidenza + // 6) creo la regione di incidenza di tale curva ( "Curva a fagiolo") + PtrOwner pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ * 0.5, false, false)) ; + if ( IsNull( pSfrBean) || ! pSfrBean->IsValid()) + return false ; + // inverto se necessario + if ( AreOppositeVectorApprox( pSfrBean->GetNormVersor(), pSfrInc->GetNormVersor())) + pSfrBean->Invert() ; + // 7) se la "Regione a fagiolo" non influenza la regione di incidenza, la transcuro + bool bDiscard = true ; + for ( int cI = 0 ; cI < pSfrInc->GetChunkCount() && bDiscard ; ++ cI) + for ( int cB = 0 ; cB < pSfrBean->GetChunkCount() && bDiscard ; ++ cB) + bDiscard = ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrBean, cB) != REGC_INTERS) ; + if ( ! bDiscard) { + // 8) aggiorno la regione di incidenza if ( ! pSfrInc->Add( *pSfrBean)) return false ; } - pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ; + pOffLongestCrv.Set( OffsCrv.GetLongerCurve()) ; // passo al tratto offsettato successivo } } } @@ -10999,39 +11097,46 @@ Pocketing::AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVE return false ; // può capitare che la regione Limite mi crei più Chunk sulla pSfrInc // I chunk da togliere sono tutti quelli che si sono separati dalla pCrvBorder - if ( pSfrInc->GetChunkCount() > 1) { + // NB. Il mio obiettivo è quello di avere un'unica curva con estremi i due tratti aperti estremanti + if ( pSfrInc->GetChunkCount() > 1) { // se ottengo più chunks PtrOwner pNewSfrInc( CreateSurfFlatRegion()) ; if ( IsNull( pNewSfrInc)) return false ; + // ricavo i punti iniziali e finali della curva di bordo Point3d ptS, ptE ; if ( ! pCrvBorder->GetStartPoint( ptS) || ! pCrvBorder->GetEndPoint( ptE)) return false ; + // per ogni Chunk ( > 1 ) for ( int i = 0 ; i < pSfrInc->GetChunkCount() ; ++ i) { + // bordo esterno PtrOwner pCrvEL( ConvertCurveToComposite( pSfrInc->GetLoop( i, 0))) ; if ( IsNull( pCrvEL) || ! pCrvEL->IsValid()) return false ; + // se estremi in comune, la curva cercata è la seguente if ( pCrvEL->IsPointOn( ptS, 300 * EPS_SMALL) && pCrvEL->IsPointOn( ptE, 300 * EPS_SMALL)) { - if ( ! pNewSfrInc->IsValid()) - pNewSfrInc.Set( pSfrInc->CloneChunk( i)) ; - else - if ( ! pNewSfrInc->Add( * pSfrInc->CloneChunk( i))) + if ( ! pNewSfrInc->IsValid()) // se la nuova regione di incidenza è vuota... + pNewSfrInc.Set( pSfrInc->CloneChunk( i)) ; // aggiorno.... + else // se la nuova regione di incidenza non è vuota... + if ( ! pNewSfrInc->Add( * pSfrInc->CloneChunk( i))) // aggiungo... return false ; } } + // definisco quinfi la nuova regione di incidenza if ( ! pNewSfrInc->IsValid()) return false ; pSfrInc.Set( Release( pNewSfrInc)) ; } } - // controllo se la curva è un'isola + // controllo se la curva è un'isola ( dall'area ) bool bIsIsland = false ; double dArea ; Plane3d plCheck ; if ( ! pCrvCompo->GetArea( plCheck, dArea)) return false ; bIsIsland = AreSameVectorEpsilon( plCheck.GetVersN(), - Z_AX, 10 * EPS_SMALL) ; - // recupero la curva di bordo del lato aperto corrente + // dalla regione di incidenza devo estrarre il tratto di bordo che ha per estremi i lati chiusi + // ( stando al di fuori, quindi estendendomi all'esterno, della regione da svuotare ) PtrOwner pCrvNewBorder( ConvertCurveToComposite( pSfrInc->GetLoop( 0, 0))) ; if ( IsNull( pCrvNewBorder) || ! pCrvNewBorder->IsValid()) return false ; @@ -11039,7 +11144,7 @@ Pocketing::AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVE for ( int u = 0 ; u < pCrvNewBorder->GetCurveCount() ; ++ u) pCrvNewBorder->SetCurveTempProp( u, 1, 0) ; - // se la curva originale era tutta aperta... + // se la curva originale era tutta aperta... ( il nuovo lato è il loop esterno della regione di incidenza) if ( bIsAllOpen) { // pulisco la curva originale pCrvBorder->Clear() ; @@ -11089,14 +11194,16 @@ Pocketing::CreateSurfFrIncidence( const ICurveComposite* pCrv, const double dRad return false ; pSfrInc->CopyFrom( pSfrInc_tmp) ; // pSfrInc ha sempre normale Z_AX ! - // La regione di incidenza non deve avere un bordo distante dRad dagli estremi del tratto aperto - // per questo motivo, creo due FlatRegion a rettangolo che andrò a sottrarre alla pSfrInc_tmp - - if ( pCrv->IsClosed()) { + // se la curva è chiusa, allora tutto il bordo è aperto + if ( pCrv->IsClosed()) { pSfrInc->CopyFrom( pSfrInc_tmp) ; return pSfrInc->IsValid() && pSfrInc->GetChunkCount() > 0 ; } + // La regione di incidenza non deve avere un bordo distante dRad dagli estremi del tratto aperto + // per questo motivo, creo due FlatRegion a rettangolo che andrò a sottrarre alla pSfrInc_tmp + // ( tolgo i semi-dischi agli estremi ) + // Rettangolo all'inizio Vector3d vtTanS ; pCrv->GetStartDir( vtTanS) ; Point3d ptS ; pCrv->GetStartPoint( ptS) ; diff --git a/Pocketing.h b/Pocketing.h index 130297c..ea7d9a8 100644 --- a/Pocketing.h +++ b/Pocketing.h @@ -195,6 +195,8 @@ class Pocketing : public Machining bool vbChangedPrec, bool& bOptimizedTrap) ; bool CheckIfOffsetIsNecessary( const ICurveComposite* pCrvOffs, const double dOffs, const int nIter, const int nOffsCount, const Vector3d& vtN, bool& bInsert) ; + bool CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, + const ICRVCOMPOPOVECTOR& vOffsClosedCurves, const ICRVCOMPOPOVECTOR& vOffsFirstCurve) ; bool GetUnclearedRegion( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR& vCrvs, ICURVEPOVECTOR& vLinks, const ICurveComposite* pCrv_orig, ISurfFlatRegion* pSrfToCut) ; bool GetDynamicClearedRegion( ISurfFlatRegion* pSrfPrec, const ICurveComposite* pCrv) ; @@ -215,14 +217,16 @@ class Pocketing : public Machining ICurveComposite* pPath2, ICRVCOMPOPOVECTOR& vOffsCL) ; bool GetCurveWeightInfo( const ICurveComposite* pCrvCompo, double dMaxLen, double& dToTRot, int& nSmallArcs, int& nSmallLines) ; bool ChoosePath( const ICurveComposite* pCrv1, const ICurveComposite* pCrv2, int nP, double dPerP, double dMaxLen, int& nC) ; - bool CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, ICRVCOMPOPOVECTOR& vOffIslands, + bool CalcBoundedLink( const Point3d& ptStart, const Point3d& ptEnd, const ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) ; - bool CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, const Vector3d& vtEnd, double dParMeet, - ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) ; + bool CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, + const Vector3d& vtEnd, const double dParMeet, + const ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink) ; bool ModifyBiArc( ICurve* pCrvBiArc, double dCutToll, ICurveComposite* pNewCrv) ; bool CutCurveByOffsets( ICurveComposite* pCurve, ICRVCOMPOPOVECTOR& vOffs) ; - bool CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, ICRVCOMPOPOVECTOR& vOffs, ICRVCOMPOPOVECTOR& vOffIslands, - ICurveComposite* pCrvLink, double dLenPercS = 0.01, double dLenPercE = 0.01, int nMaxIter = 2) ; + bool CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOMPOPOVECTOR& vOffs, + const ICRVCOMPOPOVECTOR& vOffIslands, ICurveComposite* pCrvLink, + double dLenPercS = 0.01, double dLenPercE = 0.01, int nMaxIter = 2) ; bool CalcBoundedLinkWithBiArcs( const Point3d& ptStart, const Vector3d& vtStart, const Point3d& ptEnd, const Vector3d& vtEnd, const ICurve* pCrvBound, ICurveComposite* pCrvLink) ; bool CalcCircleSpiral( const Point3d& ptCen, const Vector3d& vtN, double dOutRad, double dIntRad,