EgtMachKernel :
- In finiture aggiunte considerazioni per invesione utensile, migliorate e corrette finiture Optimal - in PocketingNT aggiunta gestione di isole aperte all'interno del grezzo.
This commit is contained in:
+437
-262
@@ -1997,9 +1997,11 @@ SurfFinishing::ProcessSfr( int nPathId, int nPvId, int nClId)
|
||||
return true ;
|
||||
|
||||
// tengo una copia della regione attuale, nel caso di finitura Optimal
|
||||
PtrOwner<ISurfFlatRegion> pSfrCntOrig( CloneSurfFlatRegion( pSfrCnt)) ;
|
||||
if ( IsNull( pSfrCntOrig) || ! pSfrCntOrig->IsValid())
|
||||
return false ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrCntOrig( nullptr) ;
|
||||
if ( m_Params.m_nSubType == SURFFIN_SUB_OPTIMAL) {
|
||||
if ( ! pSfrCntOrig.Set( CloneSurfFlatRegion( pSfrCnt)) || ! pSfrCntOrig->IsValid())
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se richiesto, elimino le parti al massimo affondamento
|
||||
bool bSkipMaxDown = true ;
|
||||
@@ -2275,7 +2277,7 @@ SurfFinishing::AddZigZag( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons
|
||||
// calcolo lo ZigZag
|
||||
ICRVCOMPOPOVECTOR vpCrvs ;
|
||||
if ( ! CalcPocketing( pSfrCnt, m_TParams.m_dDiam / 2., 0., m_Params.m_dSideStep, m_Params.m_dSideAngle, 5.,
|
||||
POCKET_ZIGZAG, false, false, false, true, true, false, false, P_INVALID, nullptr, true, m_Params.m_dSideStep,
|
||||
POCKET_ZIGZAG, false, false, m_Params.m_bInvert, true, true, false, false, P_INVALID, nullptr, true, m_Params.m_dSideStep,
|
||||
GetLeadInType(), m_Params.m_dLiTang, 0., GetLeadOutType(), m_Params.m_dLoTang, false, 0., 0., false, vpCrvs)) {
|
||||
m_pMchMgr->SetLastError( 3125, "Error in SurfFinishing : CalcPocketing failed") ;
|
||||
return false ;
|
||||
@@ -2303,7 +2305,7 @@ SurfFinishing::AddOneWay( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons
|
||||
// calcolo OneWay
|
||||
ICRVCOMPOPOVECTOR vpCrvs ;
|
||||
if ( ! CalcPocketing( pSfrCnt, m_TParams.m_dDiam / 2., 0., m_Params.m_dSideStep, m_Params.m_dSideAngle, 5.,
|
||||
POCKET_ONEWAY, false, false, false, true, true, false, false, P_INVALID, nullptr, true, m_Params.m_dSideStep,
|
||||
POCKET_ONEWAY, false, false, m_Params.m_bInvert, true, true, false, false, P_INVALID, nullptr, true, m_Params.m_dSideStep,
|
||||
GetLeadInType(), m_Params.m_dLiTang, 0., GetLeadOutType(), m_Params.m_dLoTang, false, 0., 0., false, vpCrvs)) {
|
||||
m_pMchMgr->SetLastError( 3125, "Error in SurfFinishing : CalcPocketing failed") ;
|
||||
return false ;
|
||||
@@ -2331,7 +2333,7 @@ SurfFinishing::AddSpiral( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSurf, cons
|
||||
int nType = ( bInVsOut ? POCKET_SPIRALIN : POCKET_SPIRALOUT) ;
|
||||
ICRVCOMPOPOVECTOR vpCrvs ;
|
||||
if ( ! CalcPocketing( pSfrCnt, m_TParams.m_dDiam / 2., 0., m_Params.m_dSideStep, m_Params.m_dSideAngle, 5.,
|
||||
nType, false, false, false, true, true, false, false, P_INVALID, nullptr, true, m_Params.m_dSideStep,
|
||||
nType, false, false, m_Params.m_bInvert, true, true, false, false, P_INVALID, nullptr, true, m_Params.m_dSideStep,
|
||||
GetLeadInType(), m_Params.m_dLiTang, 0., GetLeadOutType(), m_Params.m_dLoTang, false, 0., 0., false, vpCrvs)) {
|
||||
m_pMchMgr->SetLastError( 3125, "Error in SurfFinishing : CalcPocketing failed") ;
|
||||
return false ;
|
||||
@@ -2933,7 +2935,7 @@ SurfFinishing::CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSu
|
||||
|
||||
// --- se ho una sola curva, allora controllo se posso cambiare il suo punto d'inizio
|
||||
// nel caso non sia la prima in assoluto [ -> controllo ptRef]
|
||||
if ( int( vIndependentCurveGroup[nPath].size()) == 1) {
|
||||
if ( ssize( vIndependentCurveGroup[nPath]) == 1) {
|
||||
if ( ptRef.IsValid()) {
|
||||
// --- se la curva di bordo singola è aperta
|
||||
if ( ! vIndependentCurveGroup[nPath][0]->IsClosed()) {
|
||||
@@ -3031,6 +3033,7 @@ SurfFinishing::CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSu
|
||||
PtrOwner<ICurve> pLineLinkProj( ProjectCurveOnPlane( *pLineLink, plProjection)) ;
|
||||
if ( IsNull( pLineLinkProj) || ! pLineLinkProj->IsValid())
|
||||
return false ;
|
||||
|
||||
// effettuo la classificazione
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ! pSfrClass->GetCurveClassification( *pLineLinkProj, EPS_SMALL, ccClass))
|
||||
@@ -3082,7 +3085,7 @@ SurfFinishing::CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSu
|
||||
if ( ! vCompoLink[nCompo + 1]->IsValid())
|
||||
continue ; // il link rimane inizializzato e non valido ( 0 curve)
|
||||
|
||||
// porto il link sul piano della curva più in alto tra le due
|
||||
// porto il link sul piano della curva più in basso tra le due
|
||||
Point3d ptCheck ;
|
||||
vIndependentCurveGroup[nPath][nCompo + 1]->GetStartPoint( ptCheck) ;
|
||||
double dSfrDistNext = DistPointPlane( ptCheck, plProjection) ;
|
||||
@@ -3101,7 +3104,7 @@ SurfFinishing::CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSu
|
||||
int nLay = GDB_ID_NULL ;
|
||||
Color myCol = INVISIBLE ;
|
||||
#endif
|
||||
for ( int nCompo = 0 ; nCompo < ssize( vIndependentCurveGroup[nPath]) - 1 ; ++ nCompo) {
|
||||
for ( int nCompo = 0 ; nCompo < ssize( vIndependentCurveGroup[nPath]) ; ++ nCompo) {
|
||||
if ( IsNull( vCompoLink[nCompo]) || ! vCompoLink[nCompo]->IsValid()) {
|
||||
#if ENABLE_ZCONST_PATH_DEBUG
|
||||
nLay = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ;
|
||||
@@ -3134,10 +3137,8 @@ SurfFinishing::CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frSu
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFinishing::CalcZConstProjectedLink( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frPocket,
|
||||
const Frame3d& frSurf, const Vector3d& vtTool, double dDepth,
|
||||
const Point3d ptStart_forced, const Point3d ptEnd_forced,
|
||||
ICurveComposite* pCrv) const
|
||||
SurfFinishing::CalcZConstProjectedLink( ICAvToolSurfTm* pCAvTlStm, const Frame3d& frPocket, const Frame3d& frSurf, const Vector3d& vtTool,
|
||||
double dDepth, const Point3d ptStart_forced, const Point3d ptEnd_forced, ICurveComposite* pCrv) const
|
||||
{
|
||||
// funzione per proiettare una curva su una supericie trimesh passando per la silhouette
|
||||
// controllo dei parametri
|
||||
@@ -5416,25 +5417,9 @@ SurfFinishing::AddPencil( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrf
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFinishing::CalcOptimalZigZagCurves( const ISurfFlatRegion* pSfrLoc, const Frame3d& frSurf, const Vector3d& vtTool,
|
||||
SurfFinishing::CalcOptimalZigZagCurves( ISURFFRPOVECTOR& vSfrZigZagProj, const Frame3d& frSurf, const Vector3d& vtTool,
|
||||
double dDepth, ICAvToolSurfTm* pCAvTlStm, VECTORPATHS& vPaths) const
|
||||
{
|
||||
// se la superficie non è valida, non restituisco nulla
|
||||
if ( pSfrLoc == nullptr || ! pSfrLoc->IsValid())
|
||||
return true ;
|
||||
|
||||
// mi assicuro di non uscire dalla superficie originale
|
||||
PtrOwner<ISurfFlatRegion> pMySfrZigZag( CloneSurfFlatRegion( pSfrLoc)) ;
|
||||
if ( IsNull( pMySfrZigZag) || ! pMySfrZigZag->IsValid())
|
||||
return false ;
|
||||
// imposto i lati chiusi
|
||||
for ( int nC = 0 ; nC < pMySfrZigZag->GetChunkCount() ; ++ nC) {
|
||||
for ( int nL = 0 ; nL < pMySfrZigZag->GetLoopCount( nC) ; ++ nL) {
|
||||
for ( int nU = 0 ; nU < pMySfrZigZag->GetLoopCurveCount( nC, nL) ; ++ nU)
|
||||
pMySfrZigZag->SetCurveTempProp( nC, nL, nU, 0, TEMP_PROP_CLOSE_EDGE) ;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_OPTIMAL_DEBUG
|
||||
int nGrp = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ;
|
||||
m_pGeomDB->SetName( nGrp, "ZigZag") ;
|
||||
@@ -5444,94 +5429,103 @@ SurfFinishing::CalcOptimalZigZagCurves( const ISurfFlatRegion* pSfrLoc, const Fr
|
||||
int nLaySfrProj = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrp, GLOB_FRM) ;
|
||||
m_pGeomDB->SetName( nLaySfrProj, "SfrProj") ;
|
||||
m_pGeomDB->SetStatus( nLaySfrProj, GDB_ST_OFF) ;
|
||||
int nSfrProjId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySfrProj, pMySfrZigZag->Clone()) ;
|
||||
m_pGeomDB->SetMaterial( nSfrProjId, Color( 1., 0., 0., .5)) ;
|
||||
#endif
|
||||
|
||||
// controllo se richiesto altro tipo di lavorazione
|
||||
int nSubType = POCKET_ZIGZAG ;
|
||||
if ( GetValInNotes( m_Params.m_sUserNotes, UN_OPTIMALTYPE, nSubType)) {
|
||||
// ammessi ZIG_ZAG, SPIRAL_IN, SPIRAL_OUT
|
||||
if ( nSubType != POCKET_ZIGZAG && nSubType != POCKET_SPIRALIN && nSubType != POCKET_SPIRALOUT)
|
||||
nSubType = POCKET_ZIGZAG ;
|
||||
}
|
||||
|
||||
// per ogni Chunk della superficie a ZigZag, calcolo le curve di lavoro
|
||||
ICRVCOMPOPOVECTOR vCrvCompoZigZag ;
|
||||
for ( int nC = 0 ; nC < pMySfrZigZag->GetChunkCount() ; ++ nC) {
|
||||
// recupero il Chunk corrente
|
||||
PtrOwner<ISurfFlatRegion> pSfrChunk( pMySfrZigZag->CloneChunk( nC)) ;
|
||||
if ( IsNull( pSfrChunk) || ! pMySfrZigZag->IsValid())
|
||||
return false ;
|
||||
// recupero la miglior direzione di orientamento per le curve a ZigZag
|
||||
// --- approssimo il Loop esterno con una PolyLine
|
||||
PolyLine PL ;
|
||||
pSfrChunk->ApproxLoopWithLines( 0, 0, EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) ;
|
||||
// --- porto la PolyLine sul piano locale XY
|
||||
Point3d ptC ; pSfrChunk->GetCentroid( ptC) ;
|
||||
Frame3d frXY ;
|
||||
if ( ! frXY.Set( ptC, pSfrChunk->GetNormVersor()))
|
||||
return false ;
|
||||
PL.ToLoc( frXY) ;
|
||||
pSfrChunk->ToGlob( frSurf) ;
|
||||
// eseguo il calcolo della lavorazione ZigZag
|
||||
ICRVCOMPOPOVECTOR vpCrvs ;
|
||||
if ( ! CalcPocketing( pSfrChunk, m_TParams.m_dDiam / 2., 0., m_Params.m_dSideStep, m_Params.m_dSideAngle, 5.,
|
||||
nSubType, false, false, false, true, true, false, false, P_INVALID, nullptr, true, m_Params.m_dSideStep,
|
||||
GetLeadInType(), m_Params.m_dLiTang, 0., GetLeadOutType(), m_Params.m_dLoTang, false, 0., 0., false, vpCrvs)) {
|
||||
m_pMchMgr->SetLastError( 3125, "Error in SurfFinishing : CalcPocketing failed") ;
|
||||
return false ;
|
||||
}
|
||||
// memorizzo le curve ricavate
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i)
|
||||
vCrvCompoZigZag.emplace_back( Release( vpCrvs[i])) ;
|
||||
}
|
||||
|
||||
// porto i dati geometrici in locale alle superfici ( proeittando)
|
||||
Vector3d vtAxL = vtTool ;
|
||||
vtAxL.ToLoc( frSurf) ;
|
||||
Vector3d vtMoveL = vtAxL ;
|
||||
const double MIN_DIST = 1. ;
|
||||
const double MAX_DIST = 50. ;
|
||||
double dDist = Clamp( m_Params.m_dApprox, MIN_DIST, MAX_DIST) ;
|
||||
|
||||
// ciclo sui percorsi ricavati
|
||||
double dProgCoeff = 1. / max( int( vCrvCompoZigZag.size()), 1) ;
|
||||
for ( int i = 0 ; i < int( vCrvCompoZigZag.size()) ; ++ i) {
|
||||
// se non valida, passo alla successiva
|
||||
if ( IsNull( vCrvCompoZigZag[i]) || ! vCrvCompoZigZag[i]->IsValid())
|
||||
// Scorro le superfici presenti
|
||||
for ( ISurfFlatRegion* pSfrZigZag : vSfrZigZagProj) {
|
||||
if ( pSfrZigZag == nullptr || ! pSfrZigZag->IsValid())
|
||||
continue ;
|
||||
// correggo il percorso per non interferire con le superfici
|
||||
if ( pCAvTlStm != nullptr) {
|
||||
// approssimo la curva con una polilinea
|
||||
PolyLine PL ;
|
||||
if ( ! vCrvCompoZigZag[i]->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.AdjustForMaxSegmentLen( dDist))
|
||||
return false ;
|
||||
PL.ToLoc( frSurf) ;
|
||||
// traslo della lunghezza utensile diminuita dell'affondamento
|
||||
PL.Translate( vtAxL * ( m_TParams.m_dLen - dDepth)) ;
|
||||
// eseguo CAv
|
||||
if ( ! pCAvTlStm->TestPath( PL.GetUPointList(), vtAxL, vtMoveL, m_Params.m_dApprox, ( i + 1) * dProgCoeff))
|
||||
return false ;
|
||||
// contro-traslo della lunghezza utensile
|
||||
PL.Translate( - vtAxL * m_TParams.m_dLen) ;
|
||||
// elimino i punti allineati
|
||||
PL.RemoveAlignedPoints( 0.8 * m_Params.m_dApprox) ;
|
||||
// creo una curva composita a partire dalla polilinea
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( PL))
|
||||
return false ;
|
||||
|
||||
#if ENABLE_OPTIMAL_DEBUG
|
||||
int nCrvId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLayCrv, CloneCurveComposite( pCrvCompo)) ;
|
||||
m_pGeomDB->SetMaterial( nCrvId, RED) ;
|
||||
#endif
|
||||
// tutti i lati della superficie vengono considerati come chiusi, quindi per portare l'utensile lungo
|
||||
// i bordi estendo la superficie del raggio utensile
|
||||
if ( ! pSfrZigZag->Offset( m_TParams.m_dDiam / 2. - 5. * EPS_SMALL, ICurve::OFF_FILLET))
|
||||
return false ;
|
||||
for ( int nC = 0 ; nC < pSfrZigZag->GetChunkCount() ; ++ nC) {
|
||||
for ( int nL = 0 ; nL < pSfrZigZag->GetLoopCount( nC) ; ++ nL) {
|
||||
for ( int nU = 0 ; nU < pSfrZigZag->GetLoopCurveCount( nC, nL) ; ++ nU)
|
||||
pSfrZigZag->SetCurveTempProp( nC, nL, nU, 0, TEMP_PROP_CLOSE_EDGE) ;
|
||||
}
|
||||
}
|
||||
|
||||
// definisco un nuovo percorso
|
||||
vPaths.resize( vPaths.size() + 1) ;
|
||||
vPaths.back().nType = SURFFIN_SUB_ZIGZAG ;
|
||||
vPaths.back().pCrvPath.Set( pCrvCompo) ;
|
||||
#if ENABLE_OPTIMAL_DEBUG
|
||||
int nSfrProjId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySfrProj, pSfrZigZag->Clone()) ;
|
||||
m_pGeomDB->SetMaterial( nSfrProjId, Color( 1., 0., 0., .5)) ;
|
||||
#endif
|
||||
|
||||
// controllo se richiesto altro tipo di lavorazione
|
||||
int nSubType = POCKET_ZIGZAG ;
|
||||
if ( GetValInNotes( m_Params.m_sUserNotes, UN_OPTIMALTYPE, nSubType)) {
|
||||
// ammessi ZIG_ZAG, SPIRAL_IN, SPIRAL_OUT
|
||||
if ( nSubType != POCKET_ZIGZAG && nSubType != POCKET_SPIRALIN && nSubType != POCKET_SPIRALOUT)
|
||||
nSubType = POCKET_ZIGZAG ;
|
||||
}
|
||||
|
||||
// per ogni Chunk della superficie a ZigZag, calcolo le curve di lavoro
|
||||
ICRVCOMPOPOVECTOR vCrvCompoZigZag ;
|
||||
for ( int nC = 0 ; nC < pSfrZigZag->GetChunkCount() ; ++ nC) {
|
||||
// recupero il Chunk corrente
|
||||
PtrOwner<ISurfFlatRegion> pSfrChunk( pSfrZigZag->CloneChunk( nC)) ;
|
||||
if ( IsNull( pSfrChunk) || ! pSfrZigZag->IsValid())
|
||||
return false ;
|
||||
// porto il Chunk in Globale
|
||||
pSfrChunk->ToGlob( frSurf) ;
|
||||
// eseguo il calcolo della lavorazione ZigZag
|
||||
ICRVCOMPOPOVECTOR vpCrvs ;
|
||||
if ( ! CalcPocketing( pSfrChunk, m_TParams.m_dDiam / 2., 0., m_Params.m_dSideStep, m_Params.m_dSideAngle, 5.,
|
||||
nSubType, false, false, false, true, true, false, false, P_INVALID, nullptr, true, m_Params.m_dSideStep,
|
||||
GetLeadInType(), m_Params.m_dLiTang, 0., GetLeadOutType(), m_Params.m_dLoTang, false, 0., 0., false, vpCrvs)) {
|
||||
m_pMchMgr->SetLastError( 3125, "Error in SurfFinishing : CalcPocketing failed") ;
|
||||
return false ;
|
||||
}
|
||||
// memorizzo le curve ricavate
|
||||
for ( int i = 0 ; i < ssize( vpCrvs) ; ++ i)
|
||||
vCrvCompoZigZag.emplace_back( Release( vpCrvs[i])) ;
|
||||
}
|
||||
|
||||
// porto i dati geometrici in locale alle superfici ( proeittando)
|
||||
Vector3d vtAxL = vtTool ;
|
||||
vtAxL.ToLoc( frSurf) ;
|
||||
Vector3d vtMoveL = vtAxL ;
|
||||
const double MIN_DIST = 1. ;
|
||||
const double MAX_DIST = 50. ;
|
||||
double dDist = Clamp( m_Params.m_dApprox, MIN_DIST, MAX_DIST) ;
|
||||
|
||||
// ciclo sui percorsi ricavati
|
||||
double dProgCoeff = 1. / max( static_cast<int>( ssize( vCrvCompoZigZag)), 1) ;
|
||||
for ( int i = 0 ; i < ssize( vCrvCompoZigZag) ; ++ i) {
|
||||
// se non valida, passo alla successiva
|
||||
if ( IsNull( vCrvCompoZigZag[i]) || ! vCrvCompoZigZag[i]->IsValid())
|
||||
continue ;
|
||||
// correggo il percorso per non interferire con le superfici
|
||||
if ( pCAvTlStm != nullptr) {
|
||||
// approssimo la curva con una polilinea
|
||||
PolyLine PL ;
|
||||
if ( ! vCrvCompoZigZag[i]->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL) ||
|
||||
! PL.AdjustForMaxSegmentLen( dDist))
|
||||
return false ;
|
||||
PL.ToLoc( frSurf) ;
|
||||
// traslo della lunghezza utensile diminuita dell'affondamento
|
||||
PL.Translate( vtAxL * ( m_TParams.m_dLen - dDepth)) ;
|
||||
// eseguo CAv
|
||||
if ( ! pCAvTlStm->TestPath( PL.GetUPointList(), vtAxL, vtMoveL, m_Params.m_dApprox, ( i + 1) * dProgCoeff))
|
||||
return false ;
|
||||
// contro-traslo della lunghezza utensile
|
||||
PL.Translate( - vtAxL * m_TParams.m_dLen) ;
|
||||
// elimino i punti allineati
|
||||
PL.RemoveAlignedPoints( 0.8 * m_Params.m_dApprox) ;
|
||||
// creo una curva composita a partire dalla polilinea
|
||||
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( PL))
|
||||
return false ;
|
||||
#if ENABLE_OPTIMAL_DEBUG
|
||||
int nCrvId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLayCrv, CloneCurveComposite( pCrvCompo)) ;
|
||||
m_pGeomDB->SetMaterial( nCrvId, RED) ;
|
||||
#endif
|
||||
// definisco un nuovo percorso
|
||||
vPaths.resize( vPaths.size() + 1) ;
|
||||
vPaths.back().nType = SURFFIN_SUB_ZIGZAG ;
|
||||
vPaths.back().pCrvPath.Set( pCrvCompo) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5540,15 +5534,13 @@ SurfFinishing::CalcOptimalZigZagCurves( const ISurfFlatRegion* pSfrLoc, const Fr
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SURFLOCALVECTOR& vSrfLoc,
|
||||
const Frame3d& frSurf, const Vector3d& vtTool, double dAngDegSplit,
|
||||
double dAngDegTol, double dDepth, ICAvToolSurfTm* pCAvTlStm,
|
||||
VECTORPATHS& vPaths, ISurfFlatRegion* pSfrProj) const
|
||||
SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf,
|
||||
const Vector3d& vtTool, double dAngDegSplit, double dAngDegTol, double dDepth,
|
||||
ICAvToolSurfTm* pCAvTlStm, VECTORPATHS& vPaths) const
|
||||
{
|
||||
// se la superficie non è valida, non restituisco nulla
|
||||
if ( pSfrLoc == nullptr || ! pSfrLoc->IsValid())
|
||||
return true ;
|
||||
pSfrProj->Clear() ;
|
||||
|
||||
// mi assicuro di non uscire dalla superficie originale
|
||||
PtrOwner<ISurfFlatRegion> pMySfrZConst( CloneSurfFlatRegion( pSfrLoc)) ;
|
||||
@@ -5564,7 +5556,7 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
// inizializzo la classe di calcolo delle silhouette
|
||||
CISURFTMPVECTOR vpStm ; vpStm.reserve( vSrfLoc.size()) ;
|
||||
// scorro le superfici
|
||||
for ( int i = 0 ; i < int( vSrfLoc.size()) ; ++ i) {
|
||||
for ( int i = 0 ; i < ssize( vSrfLoc) ; ++ i) {
|
||||
// recupero la superficie
|
||||
const ISurf* pSurf = GetSurf( vSrfLoc[i].Get()) ;
|
||||
if ( pSurf == nullptr || ! pSurf->IsValid())
|
||||
@@ -5599,8 +5591,8 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
// inizializzo classe di calcolo per le curve a ZConst con utensile corrente
|
||||
PtrOwner<ICAvParSilhouettesSurfTm> pCavParSilh( CreateCAvParSilhouettesSurfTm()) ;
|
||||
if ( IsNull( pCavParSilh) ||
|
||||
! pCavParSilh->SetData( vpStm, frSfr, SILH_SAMPLING, m_TParams.m_dSideAng, m_TParams.m_dDiam,
|
||||
m_TParams.m_dCornRad, m_TParams.m_dMaxMat, GetOffsR(), dDepth))
|
||||
! pCavParSilh->SetData( vpStm, frSfr, SILH_SAMPLING, m_TParams.m_dSideAng, m_TParams.m_dDiam, m_TParams.m_dCornRad,
|
||||
m_TParams.m_dMaxMat, GetOffsR(), dDepth))
|
||||
return false ;
|
||||
|
||||
// recupero le curve singole definite dal bordo della Silhouette
|
||||
@@ -5617,7 +5609,6 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
// --- versore direzione utensile e versore direzione movimento
|
||||
Vector3d vtAxL = vtTool ;
|
||||
vtAxL.ToLoc( frSurf) ;
|
||||
Vector3d vtMoveL = vtAxL ;
|
||||
// --- tolleranza di campionamento per punti della PolyLine
|
||||
const double MIN_DIST = 1. ;
|
||||
const double MAX_DIST = 50. ;
|
||||
@@ -5657,7 +5648,7 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
#endif
|
||||
|
||||
// scorro i piani di ZConst ricavati...
|
||||
for ( int i = 0 ; i < int( vvCrvCompo.size()) ; ++ i) {
|
||||
for ( int i = 0 ; i < ssize( vvCrvCompo) ; ++ i) {
|
||||
// Dalle curve si ricavano le PolyLine corrispondeti e vengono suddivise in 3 categorie :
|
||||
// - PolyLine valide : definite da punti di campionamento consecutivi dove esiste una normale di
|
||||
// di collisione con angolo rispetto a vtTool > dSplitAngDeg
|
||||
@@ -5671,8 +5662,8 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
// la distanza dalla Sfr è memorizzata nel primo TempParam [*]
|
||||
double dSfrDist = 0. ;
|
||||
|
||||
// per il piano corrente scorro le curve di Silhouette ricavate...
|
||||
for ( int j = 0 ; j < int( vvCrvCompo[i].size()) ; ++ j) {
|
||||
// per il piano corrente scorro le curve di Silhouette ricavate
|
||||
for ( int j = 0 ; j < ssize( vvCrvCompo[i]) ; ++ j) {
|
||||
// se curva non valida, passo alla successiva
|
||||
if ( IsNull( vvCrvCompo[i][j]) || ! vvCrvCompo[i][j]->IsValid())
|
||||
continue ;
|
||||
@@ -5690,44 +5681,39 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
return false ;
|
||||
|
||||
// scorro i punti della PolyLine e li calssifico
|
||||
for ( POINTU& ptU : PL.GetUPointList()) {
|
||||
for ( const POINTU& ptU : PL.GetUPointList()) {
|
||||
// La curva di Silhouette, una volta approssimata, può presentare alcuni punti quel poco
|
||||
// che basta più lontani dalla superficie per non ricavare alcuna collisione.
|
||||
// NB. le curve ricavate sono approssimate, mergiate e leggermente smussate.
|
||||
// --> In questo caso sposto leggermente il punto verso la superficie
|
||||
// NB. Le curve di Silhoette per definizione sono orientate lasciando le vStm alla loro destra
|
||||
// NB. Le curve ricavate sono approssimate, mergiate e leggermente smussate.
|
||||
// --> In questo caso sposto leggermente il punto verso la superficie ( algoritmo iterativo fino a collisione individuata)
|
||||
// NB. Le curve di Silhouette per definizione sono orientate lasciando le vStm alla loro destra
|
||||
int nPointType = DISCARD ;
|
||||
double dPar ;
|
||||
Point3d ptShift ;
|
||||
Vector3d vtIn ;
|
||||
VCT3DVECTOR vVtN ;
|
||||
if ( vvCrvCompo[i][j]->GetParamAtPoint( ptU.first, dPar, 10 * EPS_SMALL) &&
|
||||
vvCrvCompo[i][j]->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptShift, &vtIn)) {
|
||||
ptShift.Translate( - vtAxL * m_TParams.m_dLen) ; // per ricavare la colisione
|
||||
vtIn.Normalize() ;
|
||||
vtIn.Rotate( vtAxL, ! m_Params.m_bInvert ? ANG_RIGHT : - ANG_RIGHT) ;
|
||||
const double MAXSHIFT = SILH_SAMPLING ;
|
||||
const int SAMPLETOL = 10 ;
|
||||
double dShift = MAXSHIFT / ( 1. * SAMPLETOL) ;
|
||||
for ( int i = 1 ; i < SAMPLETOL && vVtN.empty() ; ++ i) {
|
||||
ptShift.Translate( vtIn * ( i * dShift)) ; // leggero spostamento del punto
|
||||
double dToTDist = 0. ;
|
||||
// calcolo la collisione
|
||||
if ( ! pCAvTlStm->TestPositionAdv( ptShift, vtAxL, vtMoveL, dToTDist, vVtN))
|
||||
return false ;
|
||||
// classificazione del punto
|
||||
if ( ! vVtN.empty()) {
|
||||
for ( Vector3d& vtN : vVtN) {
|
||||
if ( abs( vtN * vtAxL) < dCosLimit) {
|
||||
nPointType = VALID ;
|
||||
break ;
|
||||
}
|
||||
else if ( abs( vtN * vtAxL) < dCosUpperBound)
|
||||
nPointType = AMBIGUOUS ;
|
||||
}
|
||||
VCT3DLIST vvtN ;
|
||||
double dMinDist = INFINITO - 1 ;
|
||||
for ( int nSurf = 0 ; nSurf < ssize( vpStm) ; ++ nSurf) {
|
||||
DistPointSurfTm distPtSurfTm( ptU.first, *vpStm[nSurf]) ;
|
||||
double dMyDist = INFINITO - 2 ;
|
||||
if ( distPtSurfTm.GetDist( dMyDist) && dMyDist < dMinDist) {
|
||||
dMinDist = dMyDist ;
|
||||
INTVECTOR vTriaMinDist ; distPtSurfTm.GetMinDistTriaIndices( vTriaMinDist) ;
|
||||
Triangle3d Tria ;
|
||||
for ( const int& nTria : vTriaMinDist) {
|
||||
vpStm[nSurf]->GetTriangle( nTria, Tria) ;
|
||||
vvtN.push_back( Tria.GetN()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// classificazione del punto
|
||||
if ( ! vvtN.empty()) {
|
||||
for ( const Vector3d& vtN : vvtN) {
|
||||
if ( abs( vtN * vtAxL) < dCosLimit) {
|
||||
nPointType = VALID ;
|
||||
break ;
|
||||
}
|
||||
else if ( abs( vtN * vtAxL) < dCosUpperBound)
|
||||
nPointType = AMBIGUOUS ;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_OPTIMAL_DEBUG
|
||||
PtrOwner<IGeoPoint3d> pt( CreateGeoPoint3d()) ;
|
||||
@@ -5735,7 +5721,7 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLayPt, Release( pt)) ;
|
||||
m_pGeomDB->SetMaterial( a, nPointType == VALID ? GREEN :
|
||||
nPointType == AMBIGUOUS ? LIME : BLACK) ;
|
||||
for ( Vector3d& vtN : vVtN) {
|
||||
for ( Vector3d& vtN : vvtN) {
|
||||
PtrOwner<IGeoVector3d> vt( CreateGeoVector3d()) ;
|
||||
vt->Set( vtN) ;
|
||||
vt->Translate( ptU.first - ORIG) ;
|
||||
@@ -5762,7 +5748,7 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
|
||||
// costruisco le PolyLine definitive
|
||||
bool bFirst = true ;
|
||||
int nPL = int( vTypePL.size()) ;
|
||||
int nPL = ssize( vTypePL) ;
|
||||
for ( int nInd = 0 ; nInd < nPL ; ++ nInd) {
|
||||
// se tratto valido
|
||||
if ( vTypePL[nInd].first == VALID) {
|
||||
@@ -5775,29 +5761,28 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
bFirst = false ;
|
||||
}
|
||||
// se tratto precedente ambiguo, lo aggiungo al tratto corrente e lo rendo invalido
|
||||
if ( nPL > 1 &&
|
||||
( vTypePL[nPrevInd].first == AMBIGUOUS || vTypePL[nPrevInd].first == VALID)) {
|
||||
// controllo che i punti siano sufficientemente vicini ( sqrt(2) * dDist))
|
||||
if ( nPL > 1 && ( vTypePL[nPrevInd].first == AMBIGUOUS || vTypePL[nPrevInd].first == VALID)) {
|
||||
// controllo che i punti siano sufficientemente vicini ( sqrt( 2) * dDist))
|
||||
Point3d ptBack, ptCurr ;
|
||||
vTypePL[nPrevInd].second.GetLastPoint( ptBack) ;
|
||||
vTypePL[nInd].second.GetFirstPoint( ptCurr) ;
|
||||
if ( AreSamePointEpsilon( ptBack, ptCurr, 2 * dDist * dDist)) {
|
||||
for ( auto& ptU : vTypePL[nPrevInd].second.GetUPointList())
|
||||
if ( AreSamePointEpsilon( ptBack, ptCurr, SQRT2 * dDist)) {
|
||||
for ( const POINTU& ptU : vTypePL[nPrevInd].second.GetUPointList())
|
||||
vPL.back().AddUPoint( 0., ptU.first) ;
|
||||
vTypePL[nPrevInd].first = DISCARD ;
|
||||
}
|
||||
}
|
||||
// aggiungo il tratto corrente e lo rendo invalido
|
||||
for ( auto& ptU : vTypePL[nInd].second.GetUPointList())
|
||||
for ( const POINTU& ptU : vTypePL[nInd].second.GetUPointList())
|
||||
vPL.back().AddUPoint( 0., ptU.first) ;
|
||||
vTypePL[nInd].first = DISCARD ;
|
||||
// se tratto successivo ambiguo, lo aggiungo al tratto corrente e lo rendo invalido
|
||||
if ( vTypePL[nAfterInd].first == AMBIGUOUS) {
|
||||
// controllo che i punti siano sufficientemente vicini ( sqrt(2) * dDist))
|
||||
// controllo che i punti siano sufficientemente vicini ( sqrt( 2) * dDist))
|
||||
Point3d ptForward, ptCurr ;
|
||||
vTypePL[nAfterInd].second.GetFirstPoint( ptForward) ;
|
||||
vTypePL[nInd].second.GetLastPoint( ptCurr) ;
|
||||
if ( AreSamePointEpsilon( ptForward, ptCurr, 2 * dDist * dDist)) {
|
||||
if ( AreSamePointEpsilon( ptForward, ptCurr, SQRT2 * dDist)) {
|
||||
for ( auto& ptU : vTypePL[nAfterInd].second.GetUPointList())
|
||||
vPL.back().AddUPoint( 0., ptU.first) ;
|
||||
vTypePL[nAfterInd].first = DISCARD ;
|
||||
@@ -5810,14 +5795,46 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
bFirst = true ;
|
||||
}
|
||||
|
||||
// verifico se inizio e fine delle PolyLine sono sufficientemente vicine, in caso positivo unisco in una PolyLine unica
|
||||
if ( ssize( vPL) == 1 && vPL[0].GetPointNbr() > 1 && ! vPL[0].IsClosed()) {
|
||||
Point3d ptStart ; vPL[0].GetFirstPoint( ptStart) ;
|
||||
Point3d ptEnd ; vPL[0].GetLastPoint( ptEnd) ;
|
||||
if ( AreSamePointEpsilon( ptStart, ptEnd, SQRT2 * dDist))
|
||||
vPL[0].Close() ;
|
||||
}
|
||||
else if ( ssize( vPL) > 1) {
|
||||
BOOLVECTOR vbSkipIndex ; vbSkipIndex.resize( vPL.size()) ;
|
||||
for ( int i = 0 ; i < ssize( vPL) ; ++ i)
|
||||
vbSkipIndex[i] = ( vPL[i].IsClosed()) ;
|
||||
for ( int i = 0 ; i < ssize( vPL) ; ++ i) {
|
||||
if ( ! vbSkipIndex[i]) {
|
||||
Point3d ptEnd ; vPL[i].GetLastPoint( ptEnd) ;
|
||||
for ( int j = 0 ; j < ssize( vPL) ; ++ j) {
|
||||
if ( j != i && ! vbSkipIndex[j]) {
|
||||
Point3d ptStart ; vPL[j].GetFirstPoint( ptStart) ;
|
||||
if ( AreSamePointEpsilon( ptStart, ptEnd, SQRT2 * dDist)) {
|
||||
for ( POINTU& ptU : vPL[j].GetUPointList())
|
||||
vPL[i].AddUPoint( 0., ptU.first) ;
|
||||
vbSkipIndex[j] = true ;
|
||||
vPL[j].Clear() ;
|
||||
-- i ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dalle PolyLine recupero le curve
|
||||
vvCrvCompo[i].clear() ;
|
||||
for ( PolyLine& PL : vPL) {
|
||||
for ( const PolyLine& PL : vPL) {
|
||||
// se vuota, non faccio nulla
|
||||
if ( PL.GetPointNbr() < 2)
|
||||
continue ;
|
||||
// se PolyLine troppo corta, non la memorizzo ( < 1/4 circonferenza utensile)
|
||||
double dLen = 0. ;
|
||||
PL.GetLength( dLen) ;
|
||||
double dLen = 0. ; PL.GetLength( dLen) ;
|
||||
if ( dLen < ( PIGRECO / 2.) * ( m_TParams.m_dDiam / 2.))
|
||||
continue ;
|
||||
// definisco la curva e la abbellisco
|
||||
@@ -5830,46 +5847,11 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
vvCrvCompo[i].back()->SetTempParam( dSfrDist, 0) ;
|
||||
#if ENABLE_OPTIMAL_DEBUG
|
||||
int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLayCrv, vvCrvCompo[i].back()->Clone()) ;
|
||||
m_pGeomDB->SetMaterial( a, GREEN) ;
|
||||
m_pGeomDB->SetMaterial( a, FUCHSIA) ;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// NB. per determinare la regione da lavavorare a ZigZag, devo prima determinare la regione
|
||||
// definita dalle curve ZConst.
|
||||
// --- determino il piano di proiezione dalla regione originale
|
||||
Plane3d plProj ;
|
||||
if ( ! plProj.Set( ptC, vtAxL))
|
||||
return false ;
|
||||
// --- per ogni curva valida, definisco una regione piana Fat sul piano calcolato
|
||||
for ( auto& vCrvCompo : vvCrvCompo) {
|
||||
for ( auto& pCrvCompo : vCrvCompo) {
|
||||
// se curva non valida, passo alla successiva
|
||||
if ( IsNull( pCrvCompo) || ! pCrvCompo->IsValid())
|
||||
continue ;
|
||||
// proeitto la curva sul piano
|
||||
PtrOwner<ICurve> pCrvProj( ProjectCurveOnPlane( *pCrvCompo, plProj)) ;
|
||||
if ( IsNull( pCrvProj) || ! pCrvProj->IsValid())
|
||||
continue ;
|
||||
// determino la sua FatRegion
|
||||
pCrvProj->SetExtrusion( vtAxL) ; // per coprire eventuali regioni fini
|
||||
PtrOwner<ISurfFlatRegion> pSfrFat( GetSurfFlatRegionFromFatCurve( pCrvProj->Clone(), m_Params.m_dSideStep / dCosLimit, false, false)) ;
|
||||
if ( IsNull( pSfrFat) || ! pSfrFat->IsValid())
|
||||
continue ;
|
||||
if ( AreOppositeVectorApprox( pSfrFat->GetNormVersor(), vtAxL))
|
||||
pSfrFat->Invert() ;
|
||||
// aggiungo questa regione a quella complessiva
|
||||
if ( pSfrProj->IsValid() && pSfrProj->GetChunkCount() > 0)
|
||||
pSfrProj->Add( *pSfrFat) ;
|
||||
else
|
||||
pSfrProj->CopyFrom( pSfrFat) ;
|
||||
}
|
||||
}
|
||||
#if ENABLE_OPTIMAL_DEBUG
|
||||
int nSfrId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySfrProj, pSfrProj->Clone()) ;
|
||||
m_pGeomDB->SetMaterial( nSfrId, Color( 0., 1., 0., .5)) ;
|
||||
#endif
|
||||
|
||||
// collego tra loro le curve trovate definendo quindi un percorso
|
||||
ICRVCOMPOPOVECTOR vCrv ;
|
||||
if ( ! CreateZConstPaths( pCAvTlStm, frSurf, vvCrvCompo, vtTool, pMySfrZConst, dDepth, vCrv)) {
|
||||
@@ -5878,7 +5860,7 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
}
|
||||
|
||||
// restituisco i percorsi trovati
|
||||
for ( int i = 0 ; i < int( vCrv.size()) ; ++ i) {
|
||||
for ( int i = 0 ; i < ssize( vCrv) ; ++ i) {
|
||||
vPaths.resize( vPaths.size() + 1) ;
|
||||
vPaths.back().pCrvPath.Set( Release( vCrv[i])) ;
|
||||
vPaths.back().nType = SURFFIN_SUB_Z_CONST ;
|
||||
@@ -5887,74 +5869,267 @@ SurfFinishing::CalcOptimalZConstCurves( const ISurfFlatRegion* pSfrLoc, const SU
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFinishing::AreSameSfrChunkEpsilon( const ISurfFlatRegion* pSfrChunkA, const ISurfFlatRegion* pSfrChunkB, double dMaxDist) const
|
||||
{
|
||||
// se esiste una superficie non valida, sicuro le superfici non sono sovrapposte
|
||||
if ( pSfrChunkA == nullptr || pSfrChunkB == nullptr || ! pSfrChunkA->IsValid() || ! pSfrChunkB->IsValid())
|
||||
return false ;
|
||||
|
||||
// Verifico che le sueprfici siano orientate correntamente
|
||||
if ( ! AreSameVectorApprox( pSfrChunkA->GetNormVersor(), pSfrChunkB->GetNormVersor()))
|
||||
return false ;
|
||||
|
||||
double dMyMaxDist = max( 10. * EPS_SMALL, dMaxDist) ;
|
||||
|
||||
// verifico mediate FatCurves dei bordi se in tolleranza
|
||||
PtrOwner<ICurve> pCrvExtBorderA( pSfrChunkA->GetLoop( 0, 0)) ;
|
||||
PtrOwner<ICurve> pCrvExtBorderB( pSfrChunkB->GetLoop( 0, 0)) ;
|
||||
if ( IsNull( pCrvExtBorderA) || IsNull( pCrvExtBorderB) || ! pCrvExtBorderA->IsValid() || ! pCrvExtBorderB->IsValid())
|
||||
return false ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrFatExtA( GetSurfFlatRegionFromFatCurve( pCrvExtBorderA->Clone(), dMyMaxDist, false, false)) ;
|
||||
if ( IsNull( pSfrFatExtA) || ! pSfrFatExtA->IsValid())
|
||||
return false ;
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ! pSfrFatExtA->GetCurveClassification( *pCrvExtBorderB, EPS_SMALL, ccClass) ||
|
||||
! ( ssize( ccClass) == 1 && ccClass[0].nClass == CRVC_IN))
|
||||
return false ;
|
||||
|
||||
// Recupero la superficie con più isole
|
||||
int nIslA = pSfrFatExtA->GetLoopCount( 0) - 1 ;
|
||||
int nIslB = pSfrChunkB->GetLoopCount( 0) - 1 ;
|
||||
if ( nIslA == 0 && nIslB == 0)
|
||||
return true ;
|
||||
|
||||
const ISurfFlatRegion* pSfrA = ( nIslA >= nIslB ? pSfrChunkA : pSfrChunkB) ;
|
||||
const ISurfFlatRegion* pSfrB = ( nIslA < nIslB ? pSfrChunkA : pSfrChunkB) ;
|
||||
if ( pSfrA == nullptr || pSfrB == nullptr)
|
||||
return false ;
|
||||
|
||||
// Regioni di Controllo
|
||||
ISURFFRPOVECTOR vFatSurfA ; vFatSurfA.reserve( nIslA) ;
|
||||
for ( int nIsl = 0 ; nIsl < nIslA ; ++ nIsl) {
|
||||
PtrOwner<ICurve> pCrvIsl( pSfrA->GetLoop( 0, nIsl + 1)) ;
|
||||
if ( ! IsNull( pCrvIsl) && pCrvIsl->IsValid()) {
|
||||
PtrOwner<ISurfFlatRegion> pSfrFat( GetSurfFlatRegionFromFatCurve( pCrvIsl->Clone(), dMaxDist, false, false)) ;
|
||||
if ( ! IsNull( pSfrFat) && pSfrFat->IsValid()) {
|
||||
if ( ! vFatSurfA.emplace_back( Release( pSfrFat)))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Loop dell'altra regione
|
||||
for ( int nIsl = 0 ; nIsl < nIslB ; ++ nIsl) {
|
||||
PtrOwner<ICurve> pCrvIsl( pSfrB->GetLoop( 0, nIsl + 1)) ;
|
||||
if ( ! IsNull( pCrvIsl) && pCrvIsl->IsValid()) {
|
||||
// Se curva troppo stretta, non la considero
|
||||
OffsetCurve OffsCrv ;
|
||||
if ( OffsCrv.Make( pCrvIsl, dMaxDist, ICurve::OFF_FILLET)) {
|
||||
PtrOwner<ICurve> pCrv( OffsCrv.GetLongerCurve()) ;
|
||||
if ( IsNull( pCrv) || ! pCrv->IsValid())
|
||||
continue ;
|
||||
}
|
||||
// verifico che esista una regione Fat che la contenga
|
||||
bool bOk = true ;
|
||||
for ( const ISurfFlatRegion* pSfrFat : vFatSurfA) {
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( pSfrFat->GetCurveClassification( *pCrvExtBorderB, EPS_SMALL, ccClass) &&
|
||||
ssize( ccClass) == 1 && ccClass[0].nClass == CRVC_IN) {
|
||||
bOk = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( ! bOk)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFinishing::CalcOptimalZigZagRegion( const ISurfFlatRegion* pSfrCntLoc, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf,
|
||||
const Vector3d& vtToolLoc, double dDepth, double dSplitAngDeg, ISURFFRPOVECTOR& vpSfrZigZagProj) const
|
||||
{
|
||||
// verifico validità dei parametri
|
||||
if ( pSfrCntLoc == nullptr || ! pSfrCntLoc->IsValid())
|
||||
return false ;
|
||||
vpSfrZigZagProj.clear() ;
|
||||
|
||||
const double COS_SPLIT_ANG = cos( dSplitAngDeg * DEGTORAD) ;
|
||||
|
||||
// scorro tutte le facce delle superfici presenti
|
||||
CISURFTMPVECTOR vpStm ; vpStm.reserve( vSrfLoc.size()) ;
|
||||
for ( const SurfLocal& SurfL : vSrfLoc) {
|
||||
// recupero la superficie
|
||||
const ISurf* pSurf = GetSurf( SurfL.Get()) ;
|
||||
if ( pSurf == nullptr || ! pSurf->IsValid())
|
||||
continue ;
|
||||
int nType = pSurf->GetType() ;
|
||||
// se TriMesh
|
||||
if ( nType == SRF_TRIMESH) {
|
||||
const ISurfTriMesh* pStm = GetSurfTriMesh( pSurf) ;
|
||||
if ( pStm != nullptr && pStm->IsValid() && pStm->GetTriangleCount() > 0)
|
||||
vpStm.emplace_back( pStm) ;
|
||||
}
|
||||
// se Bezier
|
||||
else if ( nType == SRF_BEZIER) {
|
||||
const ISurfBezier* pSBz = GetSurfBezier( pSurf) ;
|
||||
if ( pSBz != nullptr && pSBz->IsValid()) {
|
||||
double dOldTol = GetSurfBezierAuxSurfRefinedTol() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( 5. * EPS_SMALL) ;
|
||||
const ISurfTriMesh* pStm = pSBz->GetAuxSurfRefined() ;
|
||||
SetSurfBezierAuxSurfRefinedTol( dOldTol) ;
|
||||
if ( pStm != nullptr && pStm->IsValid() && pStm->GetTriangleCount() > 0)
|
||||
vpStm.emplace_back( pStm) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Definisco una Zuppa di Triangoli per le facce entro la tolleranza
|
||||
StmFromTriangleSoup StmSoup ;
|
||||
StmSoup.Start() ;
|
||||
for ( const ISurfTriMesh* pStm : vpStm) {
|
||||
if ( pStm == nullptr || ! pStm->IsValid())
|
||||
continue ;
|
||||
// scorro le faccie della superficie e controllo l'angolo presente
|
||||
for ( int nF = 0 ; nF < pStm->GetFacetCount() ; ++ nF) {
|
||||
Vector3d vtFaceN ; pStm->GetFacetNormal( nF, vtFaceN) ;
|
||||
if ( vtFaceN * vtToolLoc > COS_SPLIT_ANG) {
|
||||
INTVECTOR vnTria ; pStm->GetAllTriaInFacet( nF, vnTria) ;
|
||||
for ( const int& nT : vnTria) {
|
||||
Triangle3d Tria ; pStm->GetTriangle( nT, Tria) ;
|
||||
StmSoup.AddTriangle( Tria) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
StmSoup.End() ;
|
||||
|
||||
// recupero i parametri per il calcolo delle regioni piane a ZigZag
|
||||
Point3d ptTop ; pSfrCntLoc->GetCentroid( ptTop) ;
|
||||
Frame3d frPlanes ;
|
||||
if ( ! frPlanes.Set( ptTop, vtToolLoc))
|
||||
return false ;
|
||||
const double TOL_SIL = 1.0 ;
|
||||
INTDBLVECTOR vSfrDistInd ;
|
||||
|
||||
// Recupero le Superfici TriMesh
|
||||
PtrOwner<ISurfTriMesh> pStmZigZag( StmSoup.GetSurf()) ;
|
||||
while ( ! IsNull( pStmZigZag)) {
|
||||
if ( pStmZigZag->IsValid() && pStmZigZag->GetTriangleCount() > 0) {
|
||||
// ogni Part della TriMesh a ZigZag diventa una FlatRegion
|
||||
for ( int nP = 0 ; nP < pStmZigZag->GetPartCount() ; ++ nP) {
|
||||
PtrOwner<ISurfTriMesh> pStmZigZagPart( pStmZigZag->ClonePart( nP)) ;
|
||||
if ( ! IsNull( pStmZigZagPart) && pStmZigZagPart->IsValid()) {
|
||||
// recupero il Box della Parte corrente e determino la quota media ( controllo basilare, migliorabile)
|
||||
BBox3d BBoxPart ;
|
||||
pStmZigZagPart->GetLocalBBox( BBoxPart) ;
|
||||
Point3d ptMid ; BBoxPart.GetCenter( ptMid) ;
|
||||
// recupero le PolyLine di proiezione per la definizione del bordo
|
||||
PtrOwner<ICAvParSilhouettesSurfTm> pCavParSilh( CreateCAvParSilhouettesSurfTm()) ;
|
||||
if ( IsNull( pCavParSilh) || ! pCavParSilh->SetData( {pStmZigZagPart}, frPlanes, TOL_SIL))
|
||||
return false ;
|
||||
POLYLINEVECTOR vPL ;
|
||||
if ( ! pCavParSilh->GetSilhouette( - dDepth, vPL))
|
||||
return false ;
|
||||
// inizializzo classe di calcolo per regione piana corrente mediante le PolyLine ricavate
|
||||
SurfFlatRegionByContours SfrByC ;
|
||||
for ( const PolyLine& PL : vPL) {
|
||||
PtrOwner<ICurveComposite> pCompoPL( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCompoPL) || ! pCompoPL->FromPolyLine( PL) || ! SfrByC.AddCurve( pCompoPL->Clone()))
|
||||
return false ;
|
||||
}
|
||||
// Recupero le superfici piane e le memorizzo
|
||||
PtrOwner<ISurfFlatRegion> pSfrProj( SfrByC.GetSurf()) ;
|
||||
while ( ! IsNull( pSfrProj)) {
|
||||
if ( pSfrProj->IsValid()) {
|
||||
// porto la superficie in Globale
|
||||
if ( AreOppositeVectorEpsilon( pSfrProj->GetNormVersor(), vtToolLoc, 20. * EPS_SMALL))
|
||||
pSfrProj->Invert() ;
|
||||
// limito questa regione all'intersezione con la superficie di Contorno
|
||||
if ( ! pSfrProj->Intersect( *pSfrCntLoc))
|
||||
return false ;
|
||||
if ( pSfrProj->IsValid()) {
|
||||
// verifico che non ci siano delle superfici duplicate
|
||||
bool bDuplicate = false ;
|
||||
for ( int i = 0 ; ! bDuplicate && i < ssize( vpSfrZigZagProj) ; ++ i)
|
||||
bDuplicate = AreSameSfrChunkEpsilon( pSfrProj, vpSfrZigZagProj[i], m_TParams.m_dDiam / 4.) ;
|
||||
if ( ! bDuplicate) {
|
||||
vpSfrZigZagProj.emplace_back( Release( pSfrProj)) ;
|
||||
vSfrDistInd.emplace_back( make_pair( ssize( vpSfrZigZagProj) - 1, abs( ( ptMid - ptTop) * vtToolLoc))) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
pSfrProj.Set( SfrByC.GetSurf()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pStmZigZag.Set( StmSoup.GetSurf()) ;
|
||||
}
|
||||
if ( ssize( vpSfrZigZagProj) < 2)
|
||||
return true ;
|
||||
|
||||
// ordino le superfici ottenute in base alla distanza con la Superficie di contorno ( riferita alla Part di TriMesh)
|
||||
ranges::sort( vSfrDistInd, {}, &pair<int, double>::second) ;
|
||||
for ( int i = 0 ; i < ssize( vSfrDistInd) ; ++ i) {
|
||||
int nCurrI = i ;
|
||||
while ( vSfrDistInd[nCurrI].first != nCurrI) {
|
||||
int nNextI = vSfrDistInd[nCurrI].first ;
|
||||
swap( vpSfrZigZagProj[nCurrI], vpSfrZigZagProj[nNextI]) ;
|
||||
swap( vSfrDistInd[nCurrI], vSfrDistInd[nNextI]) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFinishing::AddOptimal( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf,
|
||||
const ISurfFlatRegion* pSfrCntZigZag, const ISurfFlatRegion* pSfrCntZConst,
|
||||
const ISurfFlatRegion* pSfrCnt, const ISurfFlatRegion* pSfrCntExt,
|
||||
const Vector3d& vtTool, double dDepth, double dElev, bool bSplitArcs)
|
||||
{
|
||||
// vettore dei percorsi da calcolare
|
||||
VECTORPATHS vPaths ;
|
||||
|
||||
// se entrambe le regioni non sono valide, non faccio nulla
|
||||
if ( ( pSfrCntZigZag == nullptr || ! pSfrCntZigZag->IsValid()) &&
|
||||
( pSfrCntZConst == nullptr || ! pSfrCntZConst->IsValid()))
|
||||
if ( ( pSfrCnt == nullptr || ! pSfrCnt->IsValid()) && ( pSfrCntExt == nullptr || ! pSfrCntExt->IsValid()))
|
||||
return false ;
|
||||
|
||||
// recupero l'angolo di Split e la rispettiva tolleranza
|
||||
double dAngDegSplit = 45 ;
|
||||
GetValInNotes( m_Params.m_sUserNotes, UN_SPLITANGLE, dAngDegSplit) ;
|
||||
double dAngDegTol = 5 ;
|
||||
GetValInNotes( m_Params.m_sUserNotes, UN_ANGLETOL, dAngDegTol) ;
|
||||
double dAngDegSplit = 45. ; GetValInNotes( m_Params.m_sUserNotes, UN_SPLITANGLE, dAngDegSplit) ;
|
||||
double dAngDegTol = 5. ; GetValInNotes( m_Params.m_sUserNotes, UN_ANGLETOL, dAngDegTol) ;
|
||||
|
||||
// inizializzo l'area di lavoro determinata dalle curve ZigZag
|
||||
PtrOwner<ISurfFlatRegion> pSfrZigZagProjLoc ;
|
||||
if ( pSfrCntZigZag != nullptr && pSfrCntZigZag->IsValid()) {
|
||||
if ( ! pSfrZigZagProjLoc.Set( CloneSurfFlatRegion( pSfrCntZigZag)) ||
|
||||
! pSfrCntZigZag->IsValid())
|
||||
return false ;
|
||||
pSfrZigZagProjLoc->ToLoc( frSurf) ;
|
||||
}
|
||||
else {
|
||||
if ( ! pSfrZigZagProjLoc.Set( CreateSurfFlatRegion()))
|
||||
return false ;
|
||||
// tengo una copia della regione di contorno in locale alle superfici
|
||||
PtrOwner<ISurfFlatRegion> pSfrCntLoc( CloneSurfFlatRegion( pSfrCnt)) ;
|
||||
if ( IsNull( pSfrCntLoc) || ! pSfrCntLoc->IsValid() || ! pSfrCntLoc->ToLoc( frSurf))
|
||||
return false ;
|
||||
|
||||
// --- [1°] calcolo delle curve ZLevel e [2°] definizione della regione di proiezione per Zlevel ---
|
||||
PtrOwner<ISurfFlatRegion> pSfrCntZLevel( pSfrCntLoc->CreateOffsetSurf( - m_TParams.m_dDiam / 2. + EPS_SMALL, ICurve::OFF_FILLET)) ;
|
||||
if ( IsNull( pSfrCntZLevel))
|
||||
return false ;
|
||||
// calcolo tutte le curve a ZLevel e determino la regione rimossa da queste curve
|
||||
if ( ! CalcOptimalZConstCurves( pSfrCntZLevel, vSrfLoc, frSurf, vtTool, dAngDegSplit, dAngDegTol, dDepth, pCAvTlStm, vPaths)) {
|
||||
m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se ho una superficie di contorno per ZConst valida
|
||||
if ( pSfrCntZConst != nullptr && pSfrCntZConst->IsValid()) {
|
||||
|
||||
// definizione regione piana di lavoro per curve ZConst
|
||||
PtrOwner<ISurfFlatRegion> pSfrZConstLoc( CloneSurfFlatRegion( pSfrCntZConst)) ;
|
||||
if ( IsNull( pSfrZConstLoc) || ! pSfrZConstLoc->IsValid() || ! pSfrZConstLoc->ToLoc( frSurf))
|
||||
return false ;
|
||||
|
||||
// recupero le curve dalla regione ZConst
|
||||
PtrOwner<ISurfFlatRegion> pSfrZConstProj( CreateSurfFlatRegion()) ;
|
||||
if ( IsNull( pSfrZConstProj) ||
|
||||
! CalcOptimalZConstCurves( pSfrZConstLoc, vSrfLoc, frSurf, vtTool, dAngDegSplit, dAngDegTol, dDepth, pCAvTlStm, vPaths, pSfrZConstProj)) {
|
||||
m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// recupero le curve dalla regione Spiral
|
||||
if ( pSfrZConstProj->IsValid() && pSfrZConstProj->GetChunkCount() > 0 &&
|
||||
pSfrZigZagProjLoc->IsValid()) {
|
||||
PtrOwner<ISurfFlatRegion> pSfrZigZagProjLocClone( CloneSurfFlatRegion( pSfrZigZagProjLoc)) ;
|
||||
if ( IsNull( pSfrZigZagProjLocClone) || ! pSfrZigZagProjLocClone->IsValid())
|
||||
return false ;
|
||||
// alla superficie ZigZag tolgo la regione ZConst
|
||||
pSfrZigZagProjLoc->Subtract( *pSfrZConstProj) ;
|
||||
// nei pressi dei tratti in comune lo ZigZag deve lavorare a SideStep
|
||||
// NB. pSfrZConstProj è ingrandita di SideStep
|
||||
pSfrZigZagProjLoc->Offset( m_Params.m_dSideStep + m_TParams.m_dDiam / 2., ICurve::OFF_FILLET) ;
|
||||
// la supercicie ZigZag deve comunque essere sempre contenuta in quella definita in originale
|
||||
pSfrZigZagProjLoc->Intersect( *pSfrZigZagProjLocClone) ;
|
||||
}
|
||||
// [3°] calcolo della regione di proiezione ZigZag ---
|
||||
ISURFFRPOVECTOR vSfrZigZagProj ;
|
||||
if ( ! CalcOptimalZigZagRegion( pSfrCntZLevel, vSrfLoc, frSurf, GetToLoc( vtTool, frSurf), dDepth, dAngDegSplit, vSfrZigZagProj)) {
|
||||
m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se ho una superficie di contorno per ZigZag valida
|
||||
if ( ! IsNull( pSfrZigZagProjLoc) && pSfrZigZagProjLoc->IsValid()) {
|
||||
if ( ! CalcOptimalZigZagCurves( pSfrZigZagProjLoc, frSurf, vtTool, dDepth, pCAvTlStm, vPaths)) {
|
||||
// [4°] calcolo delle curve ZigZag ---
|
||||
if ( ! vSfrZigZagProj.empty()) {
|
||||
if ( ! CalcOptimalZigZagCurves( vSfrZigZagProj, frSurf, vtTool, dDepth, pCAvTlStm, vPaths)) {
|
||||
m_pMchMgr->SetLastError( 3124, "Error in SurfFinishing : region not computable") ;
|
||||
return false ;
|
||||
}
|
||||
@@ -5965,14 +6140,14 @@ SurfFinishing::AddOptimal( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSr
|
||||
return true ;
|
||||
|
||||
// porto tutte le curve in globale
|
||||
for ( auto& path : vPaths) {
|
||||
for ( PATH& path : vPaths) {
|
||||
if ( IsNull( path.pCrvPath) || ! path.pCrvPath->IsValid())
|
||||
continue ;
|
||||
path.pCrvPath->ToGlob( frSurf) ;
|
||||
}
|
||||
|
||||
// ordino i percorsi ricavati
|
||||
if ( ! OrderOptimalPathsByZLoc( pSfrCntZConst, pSfrCntZigZag, vPaths))
|
||||
if ( ! OrderOptimalPathsByZLoc( pSfrCntExt, pSfrCnt, vPaths))
|
||||
return false ;
|
||||
|
||||
#if ENABLE_OPTIMAL_FINAL_CURVES_DEBUG
|
||||
@@ -5998,9 +6173,9 @@ SurfFinishing::AddOptimal( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSr
|
||||
|
||||
// aggiungo i percorsi di finitura calcolati
|
||||
ICRVCOMPOPOVECTOR vCrvCompo ; vCrvCompo.resize( vPaths.size()) ;
|
||||
for ( int i = 0 ; i < int( vPaths.size()) ; ++ i)
|
||||
for ( int i = 0 ; i < ssize( vPaths) ; ++ i)
|
||||
vCrvCompo[i].Set( Release( vPaths[i].pCrvPath)) ;
|
||||
if ( ! AddFinishing( ( pSfrCntZConst == nullptr || ! pSfrCntZConst->IsValid()) ? pSfrCntZigZag : pSfrCntZConst,
|
||||
if ( ! AddFinishing( ( pSfrCntExt == nullptr || ! pSfrCntExt->IsValid()) ? pSfrCnt : pSfrCntExt,
|
||||
pCAvTlStm, frSurf, vCrvCompo, vtTool, dElev, dDepth, bSplitArcs))
|
||||
return false ;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user