EgtMachKernel :

- LeadIn/Out con VORONI e Dijkstra ( cammini minimi).
This commit is contained in:
Riccardo Elitropi
2024-01-09 18:48:31 +01:00
parent 0cbf148bb6
commit d684f6fb82
2 changed files with 369 additions and 126 deletions
+362 -125
View File
@@ -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<ICRVCOMPOPOVECTOR>&
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<ICRVCOMPOPOVECTOR>&
// 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<ICRVCOMPOPOVECTOR>&
//----------------------------------------------------------------------------
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<ICurveComposite> 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<ICurveComposite> pCrvBef( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( 0, dUS))) ;
PtrOwner<ICurveComposite> 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<ICurveComposite> pCrvBef( ConvertCurveToComposite( vCrvCompo[nIndE]->CopyParamRange( 0, dUE))) ;
PtrOwner<ICurveComposite> 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<ICurveComposite> pCrvBef( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( 0, 0.5 * ( dUS + dUE)))) ;
PtrOwner<ICurveComposite> 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<ICurveComposite> pCrvBef( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( 0, dUS))) ;
PtrOwner<ICurveComposite> pCrvAft( ConvertCurveToComposite( vCrvCompo[nIndS]->CopyParamRange( dUE,
vCrvCompo[nIndS]->GetCurveCount()))) ;
PtrOwner<ICurveComposite> 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<Point3d> Nodes ;
vector<Link> 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<double> vdDist ; vdDist.resize( int( Nodes.size())) ;
INTVECTOR vnIndPrec ; vnIndPrec.resize( int( Nodes.size())) ;
set<int> 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<int>::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<INTINT> 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<ICurveComposite> 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 ;
}
+7 -1
View File
@@ -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<ICRVCOMPOPOVECTOR>& 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 ;