diff --git a/Pocketing.cpp b/Pocketing.cpp index fce132b..dc9d7bd 100644 --- a/Pocketing.cpp +++ b/Pocketing.cpp @@ -105,6 +105,7 @@ static string KEY_TOOL = "VTTOOL" ; static int LINK_CURVE_PROP = -3 ; static double FEED_DIVISOR = 1000.0 ; static double TOLL_TRAPEZOID = 50 * EPS_SMALL ; +static double SAFE_Z_RET = 5. ; //---------------------------------------------------------------------------- USEROBJ_REGISTER( GetOperationClass( OPER_POCKETING), Pocketing) ; @@ -1573,7 +1574,6 @@ Pocketing::ChainCurveArray( ICURVEPOVECTOR& vpCrvs, ICRVCOMPOPOVECTOR& vCrvCompo } return true ; - } //---------------------------------------------------------------------------- @@ -6010,7 +6010,7 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& Point3d ptDest ; vMCrv[i]->GetStartPoint( ptDest) ; // calcolo il percorso di ritorno del percorso attuale if ( IsNull( pRCrv) || - ! CalcLinkOnStep( ptCurr, ptDest, dSafeZ, vSfr[j-2], pRCrv)) { + ! CalcLinkOnStep( ptCurr, ptDest, vSfr[j-2], pRCrv)) { m_pMchMgr->SetLastError( 2413, "Error in Pocketing : Toolpath not computable") ; return false ; } @@ -6024,12 +6024,7 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& // ricavo la posizione attuale Point3d ptAbove ; GetCurrPos( ptAbove) ; double dStElev = Dist( ptAbove, ptStart) ; - // approccio al punto iniziale - //if ( ! AddApproach( ptAbove, vtTool, dSafeZ, dSafeAggrBottZ, dStElev, dAppr, vbOut[i])) { - // m_pMchMgr->SetLastError( 2414, "Error in Pocketing : Approach not computable") ; - // return false ; - //} - // aggiungo attacco + // aggiungo attacco ( solo collegamento ) SetFeed( GetStartFeed()) ; if ( ! AddLeadIn( ptAbove, ptStart, vtStart, vtExtr, pSrfLeanInOut, vRCrv[i], !m_Params.m_bInvert, bSplitArcs, vbOut[i])) { m_pMchMgr->SetLastError( 2415, "Error in Pocketing : LeadIn not computable") ; @@ -6092,7 +6087,7 @@ Pocketing::AddSpiralIn( ISURFFRPOVECTOR& vSfr, const vector& //---------------------------------------------------------------------------- bool -Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const double& dSafeZ, const ISurfFlatRegion* pSfr, +Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const ISurfFlatRegion* pSfr, ICurveComposite* pCrvStepLink) { // ptS -> punto finale del percorso attuale di pocketing @@ -6144,10 +6139,8 @@ Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const double& if ( int( ccClass.size()) == 1 && ccClass[0].nClass == CRVC_IN) // creo il tratto lineare leggermente rialzato return pCrvStepLink->AddPoint( ORIG) && - pCrvStepLink->AddLine( ORIG + dSafeZ * Z_AX) && - pCrvStepLink->SetCurveTempProp( 0, FEED_DIVISOR * GetEndFeed(), 0) && - pCrvStepLink->AddLine( ptEProj + dSafeZ * Z_AX) && - pCrvStepLink->SetCurveTempProp( 1, FEED_DIVISOR * GetEndFeed(), 0) && + pCrvStepLink->AddLine( ORIG + SAFE_Z_RET * Z_AX) && + pCrvStepLink->AddLine( ptEProj + SAFE_Z_RET * Z_AX) && pCrvStepLink->IsValid() && pCrvStepLink->ToGlob( frCurr) ; @@ -6172,10 +6165,8 @@ Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const double& // se l'elevazione massima è nulla, allora sono sempre fuori dal grezzo ( quindi passo per i lati aperti) if ( dMAxElev < EPS_SMALL) return pCrvStepLink->AddPoint( ORIG) && - pCrvStepLink->AddLine( ORIG + dSafeZ * Z_AX) && - pCrvStepLink->SetCurveTempProp( 0, FEED_DIVISOR * GetEndFeed(), 0) && - pCrvStepLink->AddLine( ptEProj + dSafeZ * Z_AX) && - pCrvStepLink->SetCurveTempProp( 1, FEED_DIVISOR * GetEndFeed(), 0) && + pCrvStepLink->AddLine( ORIG + SAFE_Z_RET * Z_AX) && + pCrvStepLink->AddLine( ptEProj + SAFE_Z_RET * Z_AX) && pCrvStepLink->IsValid() && pCrvStepLink->ToGlob( frCurr) ; @@ -6187,15 +6178,92 @@ Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const double& vCrvBisectors.empty()) return false ; - // porto i bisettori nel riferimento corrente e cerco le due curve più vicine a ORIG ( pts) e ptEProj + // porto i bisettori nel riferimento + for ( int i = 0 ; i < ( int)vCrvBisectors.size() ; ++ i) + vCrvBisectors[i]->ToLoc( frCurr) ; + // trasformo in composite concatenando le curve ( bloccandomi alle biforcazioni) + ICRVCOMPOPOVECTOR vCompoBisChain ; + if ( ! ChainBisectors( vCrvBisectors, vCompoBisChain)) + return false ; + // pulisco + vCrvBisectors.clear() ; + // calcolo il percorso ottimale + PtrOwner pCrvPath( CreateCurveComposite()) ; + if ( IsNull( pCrvPath) || + ! ChooseBestBisectorPath( vCompoBisChain, ORIG, ptEProj, pCrvPath)) + return false ; + // controllo che la curva si effettivamente distante dal percorso, altrimenti scarico + bool bSkip = false ; + for ( int j = 1 ; j < int( pCrvPath->GetCurveCount()) -1 && ! bSkip ; ++ j) + bSkip = pCrvPath->GetCurve( j)->GetTempParam( 0) < m_TParams.m_dDiam * 0.5 || + pCrvPath->GetCurve( j)->GetTempParam( 1) < m_TParams.m_dDiam * 0.5 ; + if ( bSkip) + return pCrvStepLink->AddPoint( ORIG) && + pCrvStepLink->AddLine( ORIG + ( SAFE_Z_RET + dMAxElev) * Z_AX) && + pCrvStepLink->AddLine( ptEProj + ( SAFE_Z_RET + dMAxElev) * Z_AX) && + ( dMAxElev - SAFE_Z_RET > 0 ? pCrvStepLink->AddLine( ptEProj + SAFE_Z_RET * Z_AX) : true) && + pCrvStepLink->IsValid() && + pCrvStepLink->ToGlob( frCurr) ; + + // aggiungo un tratto lineare per avere il percorso completo + pCrvPath->AddLine( ORIG, false) ; + pCrvPath->AddLine( ptEProj, true) ; + + // calcolo la sua lunghezza + double dCurrLen ; + if ( ! pCrvPath->GetLength( dCurrLen)) + return false ; + + // merge delle curve e smusso il miglior percorso trovato + pCrvPath->MergeCurves( 100 * EPS_SMALL, 100 * EPS_ANG_SMALL) ; + // approssimo con PolyArc + PolyArc PA ; + if ( ! pCrvPath->ApproxWithArcsEx( 500 * EPS_SMALL, ANG_TOL_STD_DEG, LIN_FEA_STD, PA)) + return false ; + pCrvPath->Clear() ; + pCrvPath->FromPolyArc( PA) ; + ModifyCurveToSmoothed( pCrvPath, m_TParams.m_dDiam / 16, m_TParams.m_dDiam / 16, + false) ; + + // valuto se invece è più conveniente scaricare ( quindi alzandomi di dMaxElev) + // la lunghezza del tratto in salita e in discesa è dMaxElev + // la lunghezza del tratto orizzontale è data dalla distanza tra ORIG e ptEProj + if ( dCurrLen < 2 * dMAxElev + Dist( ORIG, ptEProj)) + // privilegio il percorso + return pCrvStepLink->AddPoint( ORIG) && + pCrvStepLink->AddLine( ORIG + SAFE_Z_RET * Z_AX) && + pCrvPath->Translate( SAFE_Z_RET * Z_AX) && + pCrvStepLink->AddCurve( Release( pCrvPath)) && + pCrvStepLink->IsValid() && + pCrvStepLink->ToGlob( frCurr) ; + + // privilegio lo scarico + return pCrvStepLink->AddPoint( ORIG) && + pCrvStepLink->AddLine( ORIG + ( SAFE_Z_RET + dMAxElev) * Z_AX) && + pCrvStepLink->AddLine( ptEProj + ( SAFE_Z_RET + dMAxElev) * Z_AX) && + ( dMAxElev - SAFE_Z_RET > 0 ? pCrvStepLink->AddLine( ptEProj + SAFE_Z_RET * Z_AX) : true) && + pCrvStepLink->IsValid() && + pCrvStepLink->ToGlob( frCurr) ; + +} + +//---------------------------------------------------------------------------- +bool +Pocketing::ChooseBestBisectorPath( ICRVCOMPOPOVECTOR& vCrvCompo, const Point3d& ptS, + const Point3d& ptE, ICurveComposite* pCrvPath) +{ + // controllo dei parametri + if ( vCrvCompo.empty() || ! ptS.IsValid() || ! ptE.IsValid()) + return false ; + pCrvPath->Clear() ; + + // cerco gli indici delle curve più vicine a ptS e ptE double dMinDistORIG = INFINITO, dMinDistEnd = INFINITO ; int nIndS, nIndE ; - Point3d ptCheck ; // punto sulla curva finale più vicina a ptEProj - for ( int i = 0 ; i < ( int)vCrvBisectors.size() ; ++ i) { - vCrvBisectors[i]->ToLoc( frCurr) ; + for ( int i = 0 ; i < ( int)vCrvCompo.size() ; ++ i) { double dCurrDistORIG, dCurrDistEND ; - if ( ! DistPointCurve( ORIG, *vCrvBisectors[i]).GetDist( dCurrDistORIG) || - ! DistPointCurve( ptEProj, *vCrvBisectors[i]).GetDist( dCurrDistEND)) + if ( ! DistPointCurve( ptS, *vCrvCompo[i]).GetDist( dCurrDistORIG) || + ! DistPointCurve( ptE, *vCrvCompo[i]).GetDist( dCurrDistEND)) return false ; if ( dCurrDistORIG < dMinDistORIG) { dMinDistORIG = dCurrDistORIG ; @@ -6204,114 +6272,283 @@ Pocketing::CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const double& if ( dCurrDistEND < dMinDistEnd) { dMinDistEnd = dCurrDistEND ; nIndE = i ; - if ( ! vCrvBisectors[i]->GetMidPoint( ptCheck)) - return false ; } } - // porto la curva più vicina a ORIG ( ptS) in prima posizione - swap( vCrvBisectors[0], vCrvBisectors[nIndS]) ; - // concateno le curve per cercare dei percorsi ammissibili - ICRVCOMPOPOVECTOR vCompoBisChain ; - if ( ! ChainCurveArray( vCrvBisectors, vCompoBisChain)) + // cerco il punto più vicino al bisettore + double dUS, dUE ; + Point3d ptBisS, ptBisE ; + int nFlag ; + if ( ! DistPointCurve( ptS, *vCrvCompo[nIndS]).GetMinDistPoint( EPS_SMALL, ptBisS, nFlag) || + ! DistPointCurve( ptE, *vCrvCompo[nIndE]).GetMinDistPoint( EPS_SMALL, ptBisE, nFlag) || + ! vCrvCompo[nIndS]->GetParamAtPoint( ptBisS, dUS, 10 * EPS_SMALL) || + ! vCrvCompo[nIndE]->GetParamAtPoint( ptBisE, dUE, 10 * EPS_SMALL)) return false ; - // per ogni percorso trovato - int nIndBestPath = -1 ; - double dLenBestPath = INFINITO ; - for ( int i = 0 ; i < int( vCompoBisChain.size()) ; ++ i) { - // non considero il percorso se esso non contiene ptCheck - if ( ! vCompoBisChain[i]->IsPointOn( ptCheck, 10 * EPS_SMALL)) - continue ; - // Spezzo nei punti più vicini a - // ORIG ( ptS) e ptEProj e raccordo linearmente l'inizio e la fine a tali punti ( se necessario) - // NB. Non è esclusa la possibilità che ORIG ( ptS) e ptEProj siano già sul bisettore - double dUS = 0, dUE = vCompoBisChain[i]->GetCurveCount() ; - // cerco il punto più vicino al bosettore - Point3d ptBisS, ptBisE ; - int nFlag ; - if ( ! DistPointCurve( ORIG, *vCompoBisChain[i]).GetMinDistPoint( EPS_SMALL, ptBisS, nFlag) || - ! DistPointCurve( ptEProj, *vCompoBisChain[i]).GetMinDistPoint( EPS_SMALL, ptBisE, nFlag)) - return false ; - - if ( ! vCompoBisChain[i]->GetParamAtPoint( ptBisS, dUS, 10 * EPS_SMALL) || - ! vCompoBisChain[i]->GetParamAtPoint( ptBisE, dUE, 10 * EPS_SMALL)) - return false ; - if ( dUS > dUE) // potrebbe succedere... - swap( dUS, dUE) ; - if ( ! vCompoBisChain[i]->TrimStartEndAtParam( dUS, dUE)) - return false ; - - // controllo che tutte curve non estremanti del percorso siano sufficientemente distanti - // dai bordi della pSfrSafe - bool bSkip = false ; - for ( int j = 1 ; j < int( vCompoBisChain[i]->GetCurveCount()) -1 && ! bSkip ; ++ j) - bSkip = vCompoBisChain[i]->GetCurve( j)->GetTempParam( 0) < m_TParams.m_dDiam * 0.5 || - vCompoBisChain[i]->GetCurve( j)->GetTempParam( 1) < m_TParams.m_dDiam * 0.5 ; - - m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vCompoBisChain[i]->Clone()) ; - vCompoBisChain[i]->AddLine( ORIG, false) ; - vCompoBisChain[i]->AddLine( ptEProj, true) ; - m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vCompoBisChain[i]->Clone()) ; - - // calcolo l'elevazione sopra all'ultimo tratto lineare - Point3d ptCS ; vCompoBisChain[i]->GetLastCurve()->GetStartPoint( ptCS) ; - Point3d ptCE ; vCompoBisChain[i]->GetLastCurve()->GetEndPoint( ptCE) ; - double dElevCheck = 0. ; - if ( ! GetElevation( m_nPhase, ptCS, ptCE, pSfr->GetNormVersor(), m_TParams.m_dDiam * 0.5, m_TParams.m_dLen, - pSfr->GetNormVersor(), dElevCheck)) - return false ; - // se non nulla, allora non considero valido il percorso - if ( dElevCheck > EPS_SMALL) - continue ; - - // calcolo la sua lunghezza - double dCurrLen ; - if ( ! vCompoBisChain[i]->GetLength( dCurrLen)) - return false ; - // aggiorno i parametri se di lunghezza inferiore - if ( dCurrLen < dLenBestPath) { - dLenBestPath = dCurrLen ; - nIndBestPath = i ; + // splitto le curve più vicine sui rispettivi punti ( se non coincidenti a degli estremi) + if ( nIndS != nIndE) { + // se le curve sono distinte + if ( dUS > 2 * EPS_SMALL && dUS < vCrvCompo[nIndS]->GetCurveCount() - 2 * EPS_SMALL) { + PtrOwner pCrvBef( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( 0, dUS))) ; + PtrOwner pCrvAft( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( dUS, + vCrvCompo[nIndS]->GetCurveCount()))) ; + if ( IsNull( pCrvBef) || ! pCrvBef->IsValid() || IsNull( pCrvAft) || ! pCrvAft->IsValid()) + return false ; + vCrvCompo[nIndS].Set( Release( pCrvBef)) ; + vCrvCompo.emplace_back( Release( pCrvAft)) ; + } + if ( dUE > 2 * EPS_SMALL && dUE < vCrvCompo[nIndE]->GetCurveCount() - 2 * EPS_SMALL) { + PtrOwner pCrvBef( ConvertCurveToComposite( vCrvCompo[nIndE]->CopyParamRange( 0, dUE))) ; + PtrOwner pCrvAft( ConvertCurveToComposite( vCrvCompo[nIndE]->CopyParamRange( dUE, + vCrvCompo[nIndE]->GetCurveCount()))) ; + if ( IsNull( pCrvBef) || ! pCrvBef->IsValid() || IsNull( pCrvAft) || ! pCrvAft->IsValid()) + return false ; + vCrvCompo[nIndE].Set( Release( pCrvBef)) ; + vCrvCompo.emplace_back( Release( pCrvAft)) ; + } + } + else { + // se la curva è la stessa + if ( abs( dUS - dUE) < 5 * EPS_SMALL) { + // se coincidenti + PtrOwner pCrvBef( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( 0, 0.5 * ( dUS + dUE)))) ; + PtrOwner pCrvAft( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( 0.5 * ( dUS + dUE), + vCrvCompo[nIndS]->GetCurveCount()))) ; + if ( IsNull( pCrvBef) || ! pCrvBef->IsValid() || IsNull( pCrvAft) || ! pCrvAft->IsValid()) + return false ; + vCrvCompo[nIndS].Set( Release( pCrvBef)) ; + vCrvCompo.emplace_back( Release( pCrvAft)) ; + } + else { + // se distinti... + if ( dUS > dUE) + swap( dUS, dUE) ; + PtrOwner pCrvBef( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( 0, dUS))) ; + PtrOwner pCrvAft( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( dUE, + vCrvCompo[nIndS]->GetCurveCount()))) ; + PtrOwner pCrvBet( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( dUS, dUE))) ; + if ( IsNull( pCrvBef) || ! pCrvBef->IsValid() || IsNull( pCrvAft) || ! pCrvAft->IsValid() || + IsNull( pCrvBet) || ! pCrvBef->IsValid()) + return false ; + vCrvCompo[nIndS].Set( Release( pCrvBef)) ; + vCrvCompo.emplace_back( Release( pCrvBet)) ; + vCrvCompo.emplace_back( Release( pCrvAft)) ; } } - // se non ho trovato un percorso valido , privilegio lo scarico ed esco - if ( nIndBestPath < 0) - return pCrvStepLink->AddPoint( ORIG) && - pCrvStepLink->AddLine( ORIG + ( dSafeZ + dMAxElev) * Z_AX) && - pCrvStepLink->AddLine( ptEProj + ( dSafeZ + dMAxElev) * Z_AX) && - pCrvStepLink->IsValid() && - pCrvStepLink->ToGlob( frCurr) ; - // smusso il miglior percorso trovato - ModifyCurveToSmoothed( vCompoBisChain[nIndBestPath], m_TParams.m_dDiam / 16, m_TParams.m_dDiam / 16, - false) ; + for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) { + int b = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vCrvCompo[i]->Clone()) ; + m_pGeomDB->SetMaterial( b, BLUE) ; + } - // assegno la Feed al percorso - for ( int i = 0 ; i < vCompoBisChain[nIndBestPath]->GetCurveCount() ; ++ i) - vCompoBisChain[nIndBestPath]->SetCurveTempProp( i, FEED_DIVISOR * GetEndFeed(), 0) ; + // definizioni per l'albero su cui calcolare i percorsi minimi + struct Link { + int nIndNodA ; + int nIndNodB ; + double dWeight ; + int nCrvIndex ; + } ; + vector Nodes ; + vector Links ; - // valuto se invece è più conveniente scaricare ( quindi alzandomi di dMaxElev) - // la lunghezza del tratto in salita e in discesa è dMaxElev - // la lunghezza del tratto orizzontale è data dalla distanza tra ORIG e ptEProj - if ( dLenBestPath > 2 * dMAxElev + Dist( ORIG, ptEProj)) - // privilegio il percorso - return pCrvStepLink->AddPoint( ORIG) && - pCrvStepLink->AddLine( ORIG + dSafeZ * Z_AX) && - pCrvStepLink->SetCurveTempProp( 0, FEED_DIVISOR * GetEndFeed(), 0) && - vCompoBisChain[nIndBestPath]->Translate( dSafeZ * Z_AX) && - pCrvStepLink->AddCurve( Release( vCompoBisChain[nIndBestPath])) && - pCrvStepLink->IsValid() && - pCrvStepLink->ToGlob( frCurr) ; + // inserisco il nodo sorgente nel vettore dei nodi in posizione 0 + Nodes.push_back( ptBisS) ; - // privilegio lo scarico - return pCrvStepLink->AddPoint( ORIG) && - pCrvStepLink->AddLine( ORIG + ( dSafeZ + dMAxElev) * Z_AX) && - pCrvStepLink->SetCurveTempProp( 0, FEED_DIVISOR * GetEndFeed(), 0) && - pCrvStepLink->AddLine( ptEProj + ( dSafeZ + dMAxElev) * Z_AX) && - pCrvStepLink->SetCurveTempProp( 1, FEED_DIVISOR * GetEndFeed(), 0) && - pCrvStepLink->IsValid() && - pCrvStepLink->ToGlob( frCurr) ; + // il nodo destinazione sarà all'indice nDestInd + int nDestInd = - 1 ; + + // creo il vettore di nodi e di Archi + for ( int i = 0 ; i < int( vCrvCompo.size()) ; ++ i) { + Point3d ptA, ptB ; + double dLen = 0.; + if ( ! vCrvCompo[i]->GetStartPoint( ptA) || ! vCrvCompo[i]->GetEndPoint( ptB) || + ! vCrvCompo[i]->GetLength( dLen)) + return false ; + // inserisco i due possibili nodi se non già presenti rispettivamente + bool bInsertA = true ; + bool bInsertB = true ; + for ( int j = 0 ; j < int( Nodes.size()) ; ++ j) { + if ( AreSamePointEpsilon( ptA, Nodes[j], 5 * EPS_SMALL)) + bInsertA = false ; + if ( AreSamePointEpsilon( ptB, Nodes[j], 5 * EPS_SMALL)) + bInsertB = false ; + if ( nDestInd == -1) + if ( AreSamePointEpsilon( ptBisE, Nodes[j], 5 * EPS_SMALL)) + nDestInd = j ; + } + if ( bInsertA) + Nodes.push_back( ptA) ; + if ( bInsertB) + Nodes.push_back( ptB) ; + + // inserisco l'Arco + int nIndA = -1 ; int nIndB = -1 ; + for ( int j = 0 ; j < int( Nodes.size()) ; ++ j) { + if ( AreSamePointEpsilon( ptA, Nodes[j], 5 * EPS_SMALL)) + nIndA = j ; + if ( AreSamePointEpsilon( ptB, Nodes[j], 5 * EPS_SMALL)) + nIndB = j ; + } + if ( nIndA == -1 || nIndB == -1) // controllo... + return false ; + Link CurrLink ; + CurrLink.dWeight = dLen ; + CurrLink.nIndNodA = nIndA ; + CurrLink.nIndNodB = nIndB ; + CurrLink.nCrvIndex = i ; + Links.push_back( CurrLink) ; + } + if ( nDestInd == -1) + return false ; + + // calcolo il percorso minimo (Dijkstra) + vector vdDist ; vdDist.resize( int( Nodes.size())) ; + INTVECTOR vnIndPrec ; vnIndPrec.resize( int( Nodes.size())) ; + set SetNode_to_check ; + + for ( int i = 0 ; i < int( Nodes.size()) ; ++ i) { + vdDist[i] = INFINITO ; + vnIndPrec[i] = -1 ; + SetNode_to_check.insert( i) ; + } + + vdDist[0] = 0. ; + + while ( ! SetNode_to_check.empty()) { + // cerco il vertice in SetNode_to_check con distanza minima associata + int nMinInd = -1 ; + double dDistRef = INFINITO - 1 ; + for ( int j = 0 ; j < int( Nodes.size()) ; ++ j) { + set::iterator iter = SetNode_to_check.find( j) ; + if ( iter == SetNode_to_check.end()) + continue ; + if ( vdDist[j] < dDistRef) { + dDistRef = vdDist[j] ; + nMinInd = j ; + } + } + if ( nMinInd == -1 || nMinInd == nDestInd) + break ; + + SetNode_to_check.erase( nMinInd) ; + + // cerco i nodi collegati al nodo in esame + vector NeightBourInfo ; + for ( int j = 0 ; j < int( Links.size()) ; ++ j) { + if ( Links[j].nIndNodA == nMinInd || Links[j].nIndNodB == nMinInd) { + INTINT Info ; + Info.first = j ; // indice del link + Info.second = Links[j].nIndNodA == nMinInd ? Links[j].nIndNodB : Links[j].nIndNodA ; // indice dell'altro nodo + NeightBourInfo.push_back( Info) ; + } + } + + for ( int j = 0 ; j < int( NeightBourInfo.size()) ; ++ j) { + double dCurrWeight = vdDist[nMinInd] + Links[NeightBourInfo[j].first].dWeight ; + if ( dCurrWeight < vdDist[NeightBourInfo[j].second]) { + vdDist[NeightBourInfo[j].second] = dCurrWeight ; + vnIndPrec[NeightBourInfo[j].second] = nMinInd ; + } + } + } + + // inserisco il punto iniziale alla curva da restituire + pCrvPath->AddPoint( ptBisE) ; + + // percorro a ritroso i Nodi indivisuati + int nIndCurrNode = nDestInd ; + int nIndPrecNode = -1 ; + while ( vnIndPrec[nIndCurrNode] != -1) { + nIndPrecNode = vnIndPrec[nIndCurrNode] ; + // cerco l'arco con estremanti tali nodi + for ( int i = 0 ; i < int( Links.size()) ; ++ i) { + if (( Links[i].nIndNodA == nIndCurrNode && Links[i].nIndNodB == nIndPrecNode) || + ( Links[i].nIndNodA == nIndPrecNode && Links[i].nIndNodB == nIndCurrNode)) { + if ( ! pCrvPath->AddCurve( vCrvCompo[i]->Clone())) { + vCrvCompo[i]->Invert() ; + if ( ! pCrvPath->AddCurve( vCrvCompo[i]->Clone())) + return false ; + } + break ; + } + } + nIndCurrNode = nIndPrecNode ; + } + + // controllo se il percorso trovato è ammissibile e che il punto iniziale e finale che coincidano + // a quelli ricavati + Point3d ptSCheck, ptECheck ; + return pCrvPath->IsValid() && + pCrvPath->Invert() && + pCrvPath->GetStartPoint( ptSCheck) && + AreSamePointEpsilon( ptBisS, ptSCheck, 5 * EPS_SMALL) && + pCrvPath->GetEndPoint( ptECheck) && + AreSamePointEpsilon( ptBisE, ptECheck, 5 * EPS_SMALL) ; +} + +//---------------------------------------------------------------------------- +bool +Pocketing::ChainBisectors( ICURVEPOVECTOR& vpCrvs, ICRVCOMPOPOVECTOR& vCrvCompo) +{ + // controllo dei parametri + if ( int( vpCrvs.size()) == 0) + return false ; + vCrvCompo.clear() ; + + // preparo i dati per il concatenamento + bool bFirst = true ; + Point3d ptNear = ORIG ; + double dToler = 10 * EPS_SMALL ; + ChainCurves chainC ; + chainC.Init( true, dToler, int( vpCrvs.size())) ; + for ( size_t i = 0 ; i < vpCrvs.size() ; ++ i) { + // recupero la curva e il suo riferimento + ICurve* pCrv = vpCrvs[i] ; + if ( pCrv == nullptr) + continue ; + // recupero i dati della curva necessari al concatenamento e li assegno + Point3d ptStart, ptEnd ; + Vector3d vtStart, vtEnd ; + if ( ! pCrv->GetStartPoint( ptStart) || ! pCrv->GetStartDir( vtStart) || + ! pCrv->GetEndPoint( ptEnd) || ! pCrv->GetEndDir( vtEnd)) + return false ; + if ( ! chainC.AddCurve( int( i + 1), ptStart, vtStart, ptEnd, vtEnd)) + return false ; + // se prima curva, assegno inizio della ricerca + if ( bFirst) { + ptNear = ptStart + 10 * EPS_SMALL * vtStart ; + bFirst = false ; + } + } + // recupero i percorsi concatenati + int nCount = 0 ; + INTVECTOR vnId2 ; + while ( chainC.GetChainFromNear( ptNear, true, vnId2)) { + // creo una curva composita + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( IsNull( pCrvCompo)) + return false ; + // recupero le curve semplici e le inserisco nella curva composita + for ( size_t i = 0 ; i < vnId2.size() ; ++ i) { + int nId = abs( vnId2[i]) - 1 ; + bool bInvert = ( vnId2[i] < 0) ; + // recupero la curva + ICurve* pCrv = vpCrvs[nId] ; + // se necessario, la inverto + if ( bInvert) + pCrv->Invert() ; + // la aggiungo alla curva composta + if ( ! pCrvCompo->AddCurve( ::Release( vpCrvs[nId]), true, dToler)) + return false ; + } + // se non sono state inserite curve, vado oltre + if ( pCrvCompo->GetCurveCount() == 0) + continue ; + // aggiungo la curva al vettore di curve composite concatenate + vCrvCompo.emplace_back( Release( pCrvCompo)) ; + } + + return true ; } @@ -6953,7 +7190,7 @@ Pocketing::CalcSpiral( const ISurfFlatRegion* pSrfPock, int& nReg, Point3d& ptSt for ( int j = nCrvsCount0 ; j < pMCrv->GetCurveCount() ; ++ j) pMCrv->SetCurveTempProp( j, LINK_CURVE_PROP) ; } - } + } pMCrv->AddCurve( vOffs[i]->Clone()) ; } @@ -8388,14 +8625,14 @@ Pocketing::CalcBoundedSmootedLink( const Point3d& ptStart, const Vector3d& vtSta return CalcBoundedLink( ptStart, ptEnd, vOffIslands, pCrvLink) ; // controllo la distanza tra i due punti ( utilizzo raccordo lineare se grande) - if ( SqDist( ptStart, ptEnd) > 3 * ( 4 * GetSideStep() + m_TParams.m_dDiam * m_TParams.m_dDiam)) { - Point3d ptS_shift = ptStart + ( m_TParams.m_dDiam / 6) * vtStart ; - Point3d ptE_shift = ptEnd - ( m_TParams.m_dDiam / 6) * vtEnd ; + 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)) return false ; pCrvLink->AddLine( ptStart, false) ; pCrvLink->AddLine( ptEnd, true) ; - ModifyCurveToSmoothed( pCrvLink, m_TParams.m_dDiam / 16, m_TParams.m_dDiam / 16, false) ; + ModifyCurveToSmoothed( pCrvLink, 2.5, 2.5, false) ; return true ; } diff --git a/Pocketing.h b/Pocketing.h index 2e1bff2..d3d1f32 100644 --- a/Pocketing.h +++ b/Pocketing.h @@ -89,6 +89,12 @@ class Pocketing : public Machining bool SetPocketingVolume( const Point3d& ptInside, ISurfTriMesh* pStm) ; bool AdjustPocketingSideForVolumePart( ISurfTriMesh* pStmVolPart, const Vector3d& vtTool) ; bool SewingMissingFacesOnPlanes( ISurfTriMesh* pStm, const Plane3d& plPlane) ; + bool ChainBisectors( ICURVEPOVECTOR& vpCrvs, ICRVCOMPOPOVECTOR& vCrvCompo) ; + + // Dijkstra + bool ChooseBestBisectorPath( ICRVCOMPOPOVECTOR& vCrvCompo, const Point3d& ptS, + const Point3d& ptE, ICurveComposite* pCrvPath) ; + bool SliceVolume( const ISurfTriMesh* pStmVol, const ISurfTriMesh* pStm_Part, ISURFFRPOVECTOR& vSrfSliced, std::vector& vCrvOEWithFlags, BOOLVECTOR& vbChangedPrec, VCT3DVECTOR& vVtTrasl, int& nStep, const Vector3d vtTool, @@ -257,7 +263,7 @@ class Pocketing : public Machining bool AddLeadOut( const Point3d& ptEnd, const Vector3d& vtEnd, const Vector3d& vtN, const ICurveComposite* pRCrv, bool bSplitArcs, bool bNoneForced, Point3d& ptP1, double& dElev, bool& bOppositeHome, bool bRecalcElev = true) ; - bool CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const double& dSafeZ, const ISurfFlatRegion* pSfr, + bool CalcLinkOnStep( const Point3d& ptS, const Point3d& ptE, const ISurfFlatRegion* pSfr, ICurveComposite* pCrvStepLink) ; double GetRadiusForStartEndElevation( void) const ;