EgtMachKernel :

- in finiture, migliorie varie.
This commit is contained in:
Riccardo Elitropi
2024-12-30 16:14:45 +01:00
parent 89ed5eeb2f
commit 0a56d76535
2 changed files with 878 additions and 15 deletions
+853 -14
View File
@@ -41,6 +41,9 @@
#include "/EgtDev/Include/EGkCurveAux.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointSurfFr.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include <thread>
#include <future>
// per far dimenticare macro di WinUser.h
#undef GetClassName
@@ -74,6 +77,7 @@ using namespace std ;
// 3125 = "Error in SurfFinishing : CalcPocketing failed"
// 3126 = "Error in SurfFinishing : Computing ZConst Curves failed"
// 3127 = "Error in SurfFinishing : Computing ZConst Paths failed"
// 3128 = "Error in SurfFinishing : Curves with different extrusion"
// 3151 = "Warning in SurfFinishing : Skipped entity (xx)"
// 3152 = "Warning in SurfFinishing : No machinable path"
// 3153 = "Warning in SurfFinishing : Tool name changed (xx)"
@@ -1012,6 +1016,7 @@ SurfFinishing::Chain( int nGrpDestId)
}
}
// preparo i dati per il concatenamento
Vector3d vtExtr = Z_AX ;
bool bFirst = true ;
Point3d ptNear = ORIG ;
double dToler = 10 * EPS_SMALL ;
@@ -1032,9 +1037,18 @@ SurfFinishing::Chain( int nGrpDestId)
return false ;
// se prima curva, assegno inizio della ricerca
if ( bFirst) {
pCrv->GetExtrusion( vtExtr) ;
ptNear = ptStart + 10 * EPS_SMALL * vtStart ;
bFirst = false ;
}
// altrimenti
else {
Vector3d vtTmpExtr ; pCrv->GetExtrusion( vtTmpExtr) ;
if ( ! AreSameVectorApprox( vtTmpExtr, vtExtr)) {
m_pMchMgr->SetLastError( 3128, "Error in SurfFinishing : Curves with different extrusion") ;
return false ;
}
}
}
// recupero i percorsi concatenati e definisco la regione piana di svuotatura
SurfFlatRegionByContours SfrByC ;
@@ -1108,6 +1122,9 @@ SurfFinishing::Chain( int nGrpDestId)
int nGroupName = -1 ;
PtrOwner<ISurfFlatRegion> pSfrCurr( SfrByC.GetSurf()) ;
while ( ! IsNull( pSfrCurr) && pSfrCurr->IsValid()) {
// la normale del Chunk deve essere coerente con l'estrusione ricavata
if ( AreOppositeVectorApprox( pSfrCurr->GetNormVersor(), vtExtr))
pSfrCurr->Invert() ;
// per ogni Chunk
for ( int nC = 0 ; nC < pSfrCurr->GetChunkCount() ; ++ nC) {
// creo nuovo gruppo
@@ -1129,7 +1146,7 @@ SurfFinishing::Chain( int nGrpDestId)
PtrOwner<ICurveComposite> pCrvLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, nL))) ;
if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid())
return false ;
// memorizzo le propriet di lato aperto nelle Info del gruppo
// memorizzo le proprietà di lato aperto nelle Info del gruppo
INTVECTOR vIndOpen ;
for ( int nU = 0 ; nU < pCrvLoop->GetCurveCount() ; ++ nU) {
int nTmpProp0 = TEMP_PROP_INVALID ;
@@ -1140,8 +1157,6 @@ SurfFinishing::Chain( int nGrpDestId)
if ( nL == 0) {
double dThick = pCrvLoop->GetTempParam( 1) ;
m_pGeomDB->SetInfo( nNewId, KEY_THICK, dThick) ;
Vector3d vtExtr ;
pCrvLoop->GetExtrusion( vtExtr) ;
m_pGeomDB->SetInfo( nNewId, KEY_EXTR, vtExtr) ;
}
}
@@ -1323,9 +1338,11 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId)
}
// se richiesto, elimino le parti al massimo affondamento
if ( bSkipMaxDown && ( m_Params.m_nSubType != SURFFIN_SUB_Z_CONST)) {
if ( bSkipMaxDown &&
( m_Params.m_nSubType != SURFFIN_SUB_Z_CONST &&
m_Params.m_nSubType != SURFFIN_SUB_OPTIMAL)) {
// calcolo silhouette dell'insieme di superfici
CISURFTMPVECTOR vpStm ; vpStm.reserve( vSurfId.size()) ;
CISURFTMPVECTOR vpStm ; vpStm.reserve( vSurfId.size()) ;
for ( int i = 0 ; i < int( vSrfLoc.size()) ; ++ i)
vpStm.emplace_back( GetSurfTriMesh( vSrfLoc[i].Get())) ;
Frame3d frPocket ;
@@ -1378,7 +1395,7 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId)
pSfrCnt->Clear() ;
pSfrCnt->AddExtLoop( *pCompo) ;
}
// azzero le propriet delle curve semplici dei contorni delle regioni ( se 1 lato aperto)
// azzero le proprietà delle curve semplici dei contorni delle regioni ( se 1 lato aperto)
for ( int nC = 0 ; nC < pSfrCnt->GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < pSfrCnt->GetLoopCount( nC) ; ++ nL) {
for ( int nCrv = 0 ; ; ++ nCrv) {
@@ -1423,10 +1440,13 @@ SurfFinishing::ProcessPath( int nPathId, int nPvId, int nClId)
return false ;
break ;
case SURFFIN_SUB_Z_CONST :
case SURFFIN_SUB_OPTIMAL :
if ( ! AddZConst( pCAvTlStm, vSrfLoc, frSurf, pSfrCnt, vtTool, dDepth, dElev, bSplitArcs))
return false ;
break ;
case SURFFIN_SUB_OPTIMAL :
if ( ! AddOptimal( pCAvTlStm, vSrfLoc, frSurf, pSfrCnt, vtTool, dDepth, dElev, bSplitArcs))
return false ;
break ;
}
}
@@ -2421,7 +2441,7 @@ SurfFinishing::CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECT
for ( ; nCurrRow < int( vCrvCompo.size()) - 1 ; ++ nCurrRow) {
// scorro sulle colonne
for ( int nCurrCol = 0 ; nCurrCol < int( vCrvCompo[nCurrRow].size()) ; ++ nCurrCol) {
// se la curva attuale nulla, passo alla successiva
// se la curva attuale è nulla, passo alla successiva
if ( vCrvCompo[nCurrRow][nCurrCol] == nullptr)
continue ;
// recupero il punto finale della curva corrente
@@ -2477,8 +2497,8 @@ SurfFinishing::CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECT
}
}
}
// se la curva risulta troppo distante o non ho trovato nessuna colonna valida
if ( /*dMinSqDist > m_Params.m_dSideStep * m_Params.m_dSideStep * 1000 ||*/ nNextCol_path == -1) {
// se non ho trovato nessuna colonna valida (potrei controllare anche la distanza...)
if ( nNextCol_path == -1) {
nCurrRow = 0 ; // azzero il contatore delle righe
break ; // interrompo ciclo sulle righe successive di ricerca
}
@@ -2570,8 +2590,9 @@ SurfFinishing::CreateZConstPaths( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECT
if ( ! pCompoLink->IsValid())
return false ;
// porto il link sulla curva attuale di silhouette e lo proietto sulla pStm
pCompoLink->Translate( vtTool * dSfrDistCurr) ;
// porto il link sulla curva attuale di silhouette e lo proietto sulla pStm (sono in locale)
double dSfrDistNext = vCrvCompo[nNextRow][nNextCol_path]->GetTempParam( 0) ;
pCompoLink->Translate( Z_AX * min( dSfrDistCurr, dSfrDistNext)) ;
#if ENABLE_ZCONST_DEBUG
int _d = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCompoLink->Clone()) ;
@@ -2885,12 +2906,830 @@ SurfFinishing::AddZConst( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrf
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFinishing::ApproxSilhouetteClosedPLForOptimal( PolyLine& PL, double dSampleTol, double dMaxLinTol, double dAngTol, double dLinFeaTol,
ICurveComposite* pCompoPL)
{
/* approssimazione di una polyline di Silhouette per rimuovere Spikes di proiezione */
// controllo dei parametri
if ( pCompoPL == nullptr)
return false ;
pCompoPL->Clear() ;
// se aperta errore
Plane3d plPL ;
double dArea ;
if ( ! PL.IsClosedAndFlat( plPL, dArea))
return false ;
// semplifico rimuovendo i punti allineati
PL.RemoveAlignedPoints( dSampleTol + 10 * EPS_SMALL) ;
// essendo chiusa, se presenti meno di 4 punti, non faccio nulla
int nPts = PL.GetPointNbr() ;
if ( nPts < 4)
return true ;
// porto la PolyLine nel frame LocaleXY
Frame3d frLoc ;
if ( ! frLoc.Set( plPL.GetPoint(), plPL.GetVersN()))
return false ;
PL.ToLoc( frLoc) ;
// --------------------------- scelta del punto iniziale ------------------------------
// creo un vettore contenente tutti i punti ( cerco nel mentre il segmento più lungo)
PNTVECTOR vPt ; vPt.reserve( nPts) ;
int nLongEdge = -1 ;
double dMaxSqLen = 0. ;
Point3d myPt ;
if ( ! PL.GetFirstPoint( myPt))
return false ;
vPt.emplace_back( myPt) ;
while ( PL.GetNextPoint( myPt)) {
double dCurrSqDist = SqDist( vPt.back(), myPt) ;
if ( dCurrSqDist > dMaxSqLen) {
dMaxSqLen = dCurrSqDist ;
nLongEdge = int( vPt.size()) - 1 ;
}
vPt.emplace_back( myPt) ;
}
if ( nLongEdge < 0 || nLongEdge > nPts - 2)
return false ;
// calcolo il punto iniziale come punto medio del segmento più lungo
Point3d ptStart = Media( vPt[nLongEdge], vPt[nLongEdge + 1]) ;
ChangePolyLineStart( PL, ptStart, 10 * EPS_SMALL) ;
nPts = PL.GetPointNbr() ;
// ---------------------- modifica dei punti Spike ---------------------------------
// creo un vettore di punti a partire dai punti della PolyLine
PNTVECTOR vPts ; vPts.reserve( nPts) ;
PL.GetFirstPoint( myPt) ;
vPts.emplace_back( myPt) ;
while ( PL.GetNextPoint( myPt))
vPts.emplace_back( myPt) ;
/*ICurveComposite* pCrvOrig = CreateCurveComposite() ;
for ( int i = 0 ; i < int( vPts.size()) ; ++ i) {
if ( i == 0)
pCrvOrig->AddPoint( vPts[i]) ;
else
pCrvOrig->AddLine( vPts[i]) ;
IGeoPoint3d* pt = CreateGeoPoint3d() ;
pt->Set( vPts[i]) ;
int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pt->Clone()) ;
m_pGeomDB->SetMaterial( a, WHITE) ;
}
pCrvOrig->Close() ;
int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrvOrig->Clone()) ;
m_pGeomDB->SetMaterial( a, GREEN) ;
LOG_ERROR( GetEMkLogger(), ("Samp tol -> " + to_string( dSampleTol)).c_str()) ;
LOG_ERROR( GetEMkLogger(), ("Lin tol ( 2*dMaxRad) -> " + to_string( dMaxLinTol)).c_str()) ;
LOG_ERROR( GetEMkLogger(), ("Ang tol -> " + to_string( dAngTol)).c_str()) ;*/
// dichiaro i versori tangenti consecutivi per il percorso della PolyLinea
Vector3d vtTanPrev, vtTan, vtTanAfter ;
// recupero il cosendo della tolleranza angolare
double dCosAngTol = abs( cos( dAngTol * DEGTORAD)) ;
// calcolo il quadrato della tolleranza lineare
double dSqMaxLinTol = dMaxLinTol * dMaxLinTol ;
// ciclo tutti i punti della PolyLine
for ( int i = 2 ; i < int( vPts.size()) - 1 ; ++ i) {
// se distanza tra punto attuale e precedente sopra al tolleranza, passo ai successivi
if ( SqDist( vPts[i], vPts[i-1]) > dSqMaxLinTol)
continue ;
// calcolo il versore tangente del segmento pecedente
vtTanPrev = vPts[i-1] - vPts[i-2] ;
vtTanPrev.Normalize() ;
// calcolo versore tangente attuale
vtTan = vPts[i] - vPts[i-1] ;
vtTan.Normalize() ;
// recupero la direzione successia
vtTanAfter = vPts[i+1] - vPts[i] ;
vtTanAfter.Normalize() ;
// controllo se l'angolo tra la direzione attuale e precedente supera la tolleranza
if ( abs( vtTanPrev * vtTan) > dCosAngTol && abs( vtTan * vtTanAfter) > dCosAngTol)
continue ; // se uno dei due sotto la tolleranza, analizzo segmento successivo
// se Spike individuato, modifico il punto corrente con il punto medio del segmento attuale
vPts[i] = Media( vPts[i], vPts[i-1]) ;
/*IGeoPoint3d* pt = CreateGeoPoint3d() ;
pt->Set( vPts[i]) ;
int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pt->Clone()) ;
m_pGeomDB->SetMaterial( a, YELLOW) ;*/
// il punto precedente diventa uguale all' i-2-esimo
vPts[i-1] = vPts[i-2] ;
}
// a partire da questi punti, creo la PolyLine
double dPar = -1 ;
PolyLine myPL ;
myPL.AddUPoint( ++ dPar, vPts[0]) ; // il primo punto è automaticamente inserito
Point3d myLastPtInPL = vPts[0] ;
for ( int i = 1 ; i < int( vPts.size()) ; ++ i) {
// se il punto corrente è già inserito nella PolyLine, passo al successivo
if ( AreSamePointApprox( vPts[i], myLastPtInPL))
continue ;
// altrimenti inserisco il punto nella Polyline e aggiorno il punto finale
myPL.AddUPoint( ++ dPar, vPts[i]) ;
myLastPtInPL = vPts[i] ;
}
// chiudo la PolyLine per sicurezza
myPL.Close() ;
// swap
swap( PL, myPL) ;
// recupero la curva composita dalla polyLine
if ( ! pCompoPL->FromPolyLine( PL) || ! pCompoPL->IsValid())
return false ;
/*int _b = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCompoPL->Clone()) ;
m_pGeomDB->SetMaterial( _b, ORANGE) ;*/
// approssimo con archi
PolyArc PA ;
double dMyLinFea = dLinFeaTol ;
double dMyAngTol = dAngTol ;
if ( dMaxLinTol > LIN_TOL_STD) {
double dCoeff = ( dMaxLinTol - LIN_TOL_STD) / LIN_TOL_STD ;
dMyLinFea = min( LIN_FEA_STD + 1.0 * dCoeff * LIN_FEA_STD, 400.) ;
dMyAngTol = min( ANG_TOL_STD_DEG + 0.2 * dCoeff * ANG_TOL_STD_DEG, 60.) ;
}
if ( pCompoPL->ApproxWithArcsEx( dMaxLinTol, dMyAngTol, dMyLinFea, PA)) {
PtrOwner<ICurveComposite> pTempCrv( CreateCurveComposite()) ;
if ( ! IsNull( pTempCrv) &&
pTempCrv->FromPolyArc( PA) &&
pTempCrv->RemoveSmallDefects( dMaxLinTol, ANG_TOL_STD_DEG) &&
pTempCrv->MergeCurves( dMaxLinTol, ANG_TOL_STD_DEG)) {
/*int _a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pTempCrv->Clone()) ;
m_pGeomDB->SetMaterial( _a, GREEN) ;*/
pCompoPL->CopyFrom( pTempCrv) ;
}
}
// riporto la curva nel frame di partenza
pCompoPL->ToGlob( frLoc) ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFinishing::GetSfrBySilhouette( ICAvParSilhouettesSurfTm* pCavParSilh, double dDepth,
double dSilTolSamp, double dSilTolLin,
double dSilTolAng, ISurfFlatRegion* pSfrSil)
{
/* funzione per resitutire una regione piana data la classe di calcolo per silhouette */
// controllo dei parametri
if ( pSfrSil == nullptr)
return false ;
pSfrSil->Clear() ;
// recupero il vettore di PolyLine della silhouette
POLYLINEVECTOR vPL ;
if ( ! pCavParSilh->GetSilhouette( - dDepth, vPL))
return false ;
// creo la regione piana dalle PolyLine ricavate dalla Silhouette
SurfFlatRegionByContours SfrMaker ;
for ( auto& PL : vPL) {
// recupero la curva in base alla polyLine
PtrOwner<ICurveComposite> pSilCrv( CreateCurveComposite()) ;
if ( IsNull( pSilCrv))
return false ;
if ( ! ApproxSilhouetteClosedPLForOptimal( PL, dSilTolSamp, dSilTolLin, ANG_TOL_STD_DEG, LIN_FEA_STD, pSilCrv))
return false ;
// aggiungo per regione
if ( ! SfrMaker.AddCurve( Release( pSilCrv)))
return false ;
}
// definisco la reigone piana
PtrOwner<ISurfFlatRegion> pSfrTmp( SfrMaker.GetSurf()) ;
if ( ! IsNull( pSfrTmp) && pSfrTmp->IsValid())
pSfrSil->CopyFrom( pSfrTmp) ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFinishing::SplitStmTrianglesForSpiralAndZConst( const ISurfTriMesh* pStm, const Frame3d& frSurf,
const Vector3d& vtTool, double dClippingAngle, double dTolerAngle,
StmFromTriangleSoup& TriaSoup, double& dMaxFrontTriaRad)
{
/*
funzione per ciclare i triangoli di una TriMesh (*pStm) partendo da nT_start e terminando a nT_end
I triangoli che formano un angolo in valore assoluto con vtTool, maggiore di dClippingAngle
vengono inseriti nella zuppa
dMaxFrontTriaRad è il raggio massimo dei triangoli con normale che si discosta da vtTool per
meno di dTolerAngle (triangoli frontalieri)
*/
// controllo della superficie
if ( pStm == nullptr || ! pStm->IsValid())
return false ;
// porto il versore utensile nel riferimento locale
Vector3d vtToolLoc = vtTool ; vtToolLoc.ToLoc( frSurf) ;
// aggiusto i parametri
dClippingAngle = Clamp( dClippingAngle, 30., 60.) ; // [30°,60°]
dTolerAngle = Clamp( dTolerAngle, 1., 5.) ; // [1°,5°]
// definizione delle costanti
double dCosLimit = cos( dClippingAngle * DEGTORAD) ;
double dCosLimSup = cos( ( dClippingAngle - dTolerAngle) * DEGTORAD) ;
double dCosLimInf = cos( max( 0., ( dClippingAngle + dTolerAngle)) * DEGTORAD) ;
double dAbsCosPerpTol = dTolerAngle * DEGTORAD ; // x->PI/2, cos(x) ~ -x + PI/2
// scorro i triangoli della superficie
for ( int nT = 0 ; nT < pStm->GetTriangleCount() ; ++ nT) {
// recupero il triangolo corrente (controllo la sua validità)
Triangle3d Tria ; pStm->GetTriangle( nT, Tria) ;
if ( ! Tria.IsValid())
continue ;
// recupero la normale del triangolo
Vector3d vtN_tria = Tria.GetN() ;
// se i due versori sono quasi paralleli, passo al triangolo successivo
// ( se faccia piana equiversa a vtToolLoc allora è in Spiral, se opposta non la considero)
if ( AreSameOrOppositeVectorEpsilon( vtN_tria, vtToolLoc, 50 * EPS_SMALL))
continue ;
// recupero il valore coseno dell'angolo
double dCos = vtN_tria * vtToolLoc ;
// se triangolo è forntaliero, lo inserisco nel vettore
if ( dCos < dCosLimSup && dCos > dCosLimInf) {
// recupero il raggio della sfera che contine il triangolo
BBox3d BBoxTria ;
double dRad ;
if ( ! Tria.GetLocalBBox( BBoxTria) || ! BBoxTria.GetRadius( dRad))
continue ;
// se raggio più grande del limite superiore, aggiorno
if ( dRad > dMaxFrontTriaRad)
dMaxFrontTriaRad = dRad ;
}
// se la normale è circa perpendicolare a vtToolLoc, salto il triangolo (crea loop non validi)
if ( abs( dCos) < dAbsCosPerpTol)
continue ;
// se la normale del triangolo è sotto la tolleranza, lo inserisco nella zuppa
// più il prodottoscalare tende a 0, più i versori sono distanti
if ( abs( dCos) < dCosLimit + EPS_ANG_ZERO)
TriaSoup.AddTriangle( Tria.GetP( 0), Tria.GetP( 1), Tria.GetP( 2)) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFinishing::SplitStmInTwoSilSfrByClippingAngle( const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfrCnt,
double dDepth, const Vector3d& vtTool, double dClippingAngle, ISurfFlatRegion* pSfrSpiral,
ISurfFlatRegion* pSfrZConst)
{
// controllo delle regioni piane
if ( pSfrSpiral == nullptr || pSfrZConst == nullptr ||
pSfrCnt == nullptr || ! pSfrCnt->IsValid())
return false ;
pSfrSpiral->Clear() ;
pSfrZConst->Clear() ;
// definisco il piano di taglio alla profondità massima
Point3d ptCenter ; pSfrCnt->GetCentroid( ptCenter) ;
Plane3d plClipping ;
Point3d ptPlCl = GetToLoc( ptCenter, frSurf) ;
Vector3d vtNCl = GetToLoc( vtTool, frSurf) ;
if ( ! plClipping.Set( ptPlCl - vtNCl * dDepth, - vtNCl))
return false ;
// parametri e costanti per il calcolo della regione
double dMaxRad = 100 * EPS_SMALL ; // raggio massimo della sfera che contiene i triangoli frontalieri
const double OFFS_TRIA_ANG_TOL = 2. ; // tolleranza di ricerca dei triangoli frontalieri
const double OFFS_CORR = 0. ; // offset correttivo regione piana ZConst
// creazione della zuppa di triangoli per la Zconst
StmFromTriangleSoup StmSoup ;
StmSoup.Start() ;
// scorro il vettore delle regioni piane
for ( int i = 0 ; i < int( vSrfLoc.size()) ; ++ i) {
// recupero la regione come superficie trimesh (controllo la sua validità)
PtrOwner<ISurfTriMesh> pStm( CloneSurfTriMesh( GetSurfTriMesh( vSrfLoc[i].Get()))) ;
if ( IsNull( pStm) || ! pStm->IsValid())
continue ;
// NB. devo tagliare la supericie con un piano diretto come vtTool a profondità dDepth
// ( altrimenti rischio di calcolare regioni piane inutili )
if ( ! pStm->Cut( plClipping, true))
return false ;
// recupero la zuppa per ZConst
if ( ! SplitStmTrianglesForSpiralAndZConst( pStm, frSurf, vtTool, dClippingAngle, OFFS_TRIA_ANG_TOL, StmSoup, dMaxRad))
return false ;
dMaxRad = Clamp( dMaxRad, 100 * EPS_SMALL, 5.) ; // per sicurezza
}
StmSoup.End() ;
// definisco vettori superfici locali ZConst
CISURFTMPVECTOR vStmLocZConst ;
// recupero le superfici trimesh
PtrOwner<ISurfTriMesh> pStmCurr( StmSoup.GetSurf()) ;
while ( ! IsNull( pStmCurr) && pStmCurr->IsValid() && pStmCurr->GetTriangleCount() > 0) {
// porto la superficie nel sistema di riferimento globale
pStmCurr->ToGlob( frSurf) ;
int _o = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pStmCurr->Clone()) ;
m_pGeomDB->SetMaterial( _o, PURPLE) ;
vStmLocZConst.emplace_back( Release( pStmCurr)) ;
pStmCurr.Set( StmSoup.GetSurf()) ;
} ;
// definisco il frame di calcolo per la superficie in base alla pSfrCnt
Frame3d frLoc ;
if ( ! frLoc.Set( ptCenter, vtTool))
return false ;
// definisco la costante di campionamento per la silhouette
const double SILH_TOL = 1. ;
// construisco la regione piana per ZConst
pSfrSpiral->CopyFrom( pSfrCnt) ; // superficie per spiral uguale all'originale
if ( ! vStmLocZConst.empty()) {
// inizializzo classe di calcolo della Silhoeutte
PtrOwner<ICAvParSilhouettesSurfTm> pCavParSilh( CreateCAvParSilhouettesSurfTm()) ;
if ( IsNull( pCavParSilh) || ! pCavParSilh->SetData( vStmLocZConst, frLoc, SILH_TOL))
return false ;
// recupero la regione piana
if ( ! GetSfrBySilhouette( pCavParSilh, dDepth, SILH_TOL, 2. * dMaxRad, ANG_TOL_STD_DEG, pSfrZConst))
return false ;
// se regione valida, la porto nel sistema di riferimento globale
if ( pSfrZConst->IsValid()) {
// traslo la superficie sopra al grezzo
bool bOK = pSfrZConst->Translate( dDepth * vtTool) ;
// offset di correzione...
bOK = bOK && pSfrZConst->Offset( OFFS_CORR, ICurve::OFF_FILLET) ;
// limito la superficie a ZConst alla regione di contorno
bOK = bOK && pSfrZConst->Intersect( *pSfrCnt) ;
// definizione superficie Spiral per sottrazione
bOK = bOK && pSfrSpiral->Subtract( *pSfrZConst) ;
if ( ! bOK)
return false ;
}
}
int _a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrSpiral->Clone()) ;
m_pGeomDB->SetMaterial( _a, Color( 255., 0., 255., .25)) ;
_a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrZConst->Clone()) ;
m_pGeomDB->SetMaterial( _a, Color( 0., 255., 0., .25)) ;
LOG_ERROR( GetEMkLogger(), ToString( dMaxRad).c_str()) ;
// elimino i piccoli chunk imprecisi
for ( int nC = 0 ; nC < pSfrSpiral->GetChunkCount() ; ++ nC) {
// verifico se l'Offset massimo del chunk è sopra alla tolleranza
double dMaxOffs = EPS_SMALL ;
pSfrSpiral->GetChunkMaxOffset( nC, dMaxOffs) ;
// rimuovo il Chunk c-esimo se l'Offset massimo è minore della tolleranza
if ( dMaxOffs < dMaxRad) {
pSfrSpiral->EraseChunk( nC) ;
-- nC ;
}
}
for ( int nC = 0 ; nC < pSfrZConst->GetChunkCount() ; ++ nC) {
// verifico se l'Offset massimo del chunk è sopra alla tolleranza
double dMaxOffs = EPS_SMALL ;
pSfrZConst->GetChunkMaxOffset( nC, dMaxOffs) ;
// rimuovo il Chunk c-esimo se l'Offset massimo è minore della tolleranza
if ( dMaxOffs < dMaxRad) {
pSfrZConst->EraseChunk( nC) ;
-- nC ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFinishing::OrderOptimalPathsByZLoc( const ISurfFlatRegion* pSfr, VECTORPATHS& vCrvPaths)
{
// controllo dei parametri
if ( pSfr == nullptr || ! pSfr->IsValid())
return false ;
// se ho un solo percorso, non faccio nulla
if ( int( vCrvPaths.size()) == 1)
return true ;
// creo un frame sulla superficie
Frame3d frOrder ;
Point3d ptOrder ; pSfr->GetCentroid( ptOrder) ;
Vector3d vtOrder = pSfr->GetNormVersor() ;
if ( ! frOrder.Set( ptOrder, vtOrder))
return false ;
DBLVECTOR vZorder( vCrvPaths.size()) ;
for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) {
Point3d ptStart ; vCrvPaths[i].pCrvPath->GetStartPoint( ptStart) ;
ptStart.ToLoc( frOrder) ;
vZorder[i] = ptStart.z ;
}
// swap degli indici per ordine delle Z locali
for ( int i = 0 ; i < int( vZorder.size()) - 1 ; ++ i) {
for ( int j = i + 1 ; j < int( vZorder.size()) ; ++ j) {
if ( vZorder[j] > vZorder[i]) {
swap( vZorder[j], vZorder[i]) ;
swap( vCrvPaths[j], vCrvPaths[i]) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFinishing::ChooseFinishingForOptimal( const ISurfFlatRegion* pSfr, int nChunk, bool& bSpiral,
double& dSideAng)
{
// controllo dei parametri
if ( pSfr == nullptr || ! pSfr->IsValid())
return false ;
// controllo valore di nChunk
if ( nChunk < 0 || nChunk >= pSfr->GetChunkCount())
return false ;
// informazioni sul Chunk
int nLines = 0 ; double dMaxLineLen = 0. ; Vector3d vtTanMaxLine ;
int nArcs = 0 ; double dMaxArcLen = 0. ;
BBox3d BBox ; Vector3d vtX ;
for ( int nL = 0 ; nL < pSfr->GetLoopCount( nChunk) ; ++ nL) {
// recupero il loop come curva composita
PtrOwner<ICurveComposite> pCompoLoop( ConvertCurveToComposite( pSfr->GetLoop( nChunk, nL))) ;
if ( IsNull( pCompoLoop) || ! pCompoLoop->IsValid())
return false ;
// se loop esterno calcolo il Box
if ( nL == 0) {
PolyLine PL ;
if ( ! pCompoLoop->ApproxWithLines( 100 * EPS_SMALL, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
Point3d ptCenter ;
double dLen ; double dHeight ;
if ( ! PL.GetMinAreaRectangleXY( ptCenter, vtX, dLen, dHeight))
return false ;
}
// scorro le curve del Loop
for ( int nU = 0 ; nU < pCompoLoop->GetCurveCount() ; ++ nU) {
const ICurve* pCurve = pCompoLoop->GetCurve( nU) ;
if ( pCurve == nullptr || ! pCurve->IsValid())
return false ;
// se arco
if ( pCurve->GetType() == CRV_ARC) {
++ nArcs ;
double dLen ; pCurve->GetLength( dLen) ;
if ( dLen > dMaxArcLen)
dMaxArcLen = dLen ;
}
// se linea
else if ( pCurve->GetType() == CRV_LINE) {
++ nLines ;
double dLen ; pCurve->GetLength( dLen) ;
if ( dLen > dMaxLineLen) {
dMaxLineLen = dLen ;
pCurve->GetStartDir( vtTanMaxLine) ;
}
}
}
}
// di base lavorazione Spiral
bSpiral = true ;
// se l'entità più lunga è la linea
if ( dMaxLineLen > dMaxArcLen) {
// se ci sono in genere più linee che archi (60% linee)
if ( nLines / ( nLines + nArcs + 1) > .6) {
// se la direzione principale della linea concide con la direzione massima del box minimo
if ( AreSameOrOppositeVectorApprox( vtTanMaxLine, vtX)) {
bSpiral = false ; // ZigZag
X_AX.GetAngle( vtX, dSideAng) ;
abs( dSideAng) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFinishing::AddOptimal( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr,
const Vector3d& vtTool, double dDepth, double dElev, bool bSplitArcs)
{
return true ; // per ora (Test)
// controllo che la regione sia definita correttamente
if ( pSfr == nullptr || ! pSfr->IsValid())
return false ;
// recupero distanze di sicurezza
double dSafeZ = GetSafeZ() ;
// lunghezza di approccio/retrazione
double dAppr = m_Params.m_dStartPos ;
// raggio di lavorazione e offset di correzione
double dPockRad = m_Params.m_dSideStep ;
double dPockRadOffs = m_TParams.m_dDiam / 2 - m_Params.m_dSideStep - m_Params.m_dOverlap ;
// vettore dei percorsi da calcolare
VECTORPATHS vPaths ;
// definizione angolo di tolleranza per lavorazioni Spiral e ZConst
double dClippingAngle = ANG_TOL_STD_DEG * 3. ;
PtrOwner<ISurfFlatRegion> pSfrSpiral( CreateSurfFlatRegion()) ;
PtrOwner<ISurfFlatRegion> pSfrZConst( CreateSurfFlatRegion()) ;
if ( ! SplitStmInTwoSilSfrByClippingAngle( vSrfLoc, frSurf, pSfr, dDepth, vtTool, dClippingAngle, pSfrSpiral, pSfrZConst))
return false ;
// ----------------------- Lavorazione Spiral/ZigZag -------------------------------
if ( ! IsNull( pSfrSpiral) && pSfrSpiral->IsValid()) {
// aggiusto la regione a seconda dei parametri (il centro utensile deve stare sul bordo)
PtrOwner<ISurfFlatRegion> pSfrToWork( pSfrSpiral->CreateOffsetSurf( m_TParams.m_dDiam / 2. - m_Params.m_dOverlap, ICurve::OFF_FILLET)) ;
if ( IsNull( pSfrToWork) || ! pSfrToWork->IsValid())
return false ;
// mi assicuro di non uscire dalla superficie originale
pSfrToWork->Intersect( *pSfr) ;
// assegno tutte proprietà di lato chiuso
for ( int nC = 0 ; nC < pSfrToWork->GetChunkCount() ; ++ nC)
for ( int nL = 0 ; nL < pSfrToWork->GetLoopCount( nC) ; ++ nL)
for ( int nU = 0 ; nU < pSfrToWork->GetLoopCurveCount( nC, nL) ; ++ nU)
pSfrToWork->SetCurveTempProp( nC, nL, nU, 0, TEMP_PROP_CLOSE_EDGE) ;
// lavorazione Spiral/ZigZag
ICRVCOMPOPOVECTOR vpCrvs ;
if ( ! CalcPocketing( pSfrToWork, dPockRad, dPockRadOffs, m_Params.m_dSideStep, m_Params.m_dSideAngle,
POCKET_SPIRALIN, false, false, true, false, P_INVALID, nullptr, vpCrvs)) {
m_pMchMgr->SetLastError( 3125, "Error in SurfFinishing : CalcPocketing failed") ;
return false ;
}
// determino il riferimento di base della svuotatura
Frame3d frPocket ;
Point3d ptCen ; pSfr->GetCentroid( ptCen) ;
frPocket.Set( ptCen, vtTool) ;
// ciclo sui percorsi ricavati risultanti
double dProgCoeff = 1. / max( int( vpCrvs.size()), 1) ;
for ( int k = 0 ; k < int( vpCrvs.size()) ; ++ k) {
// definisco un nuovo percorso (in locale)
vPaths.resize( vPaths.size() + 1) ;
vPaths.back().pCrvPath.Set( Release( vpCrvs[k])) ;
vPaths.back().pCrvPath->ToLoc( frPocket) ;
vPaths.back().nType = SURFFIN_SUB_SPIRALIN ;
// li correggo per non interferire con le superfici
if ( pCAvTlStm != nullptr) {
// approssimo la curva con una polilinea
PolyLine PL ;
if ( ! vPaths.back().pCrvPath->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
return false ;
// eventuale aggiunta di punti per garantire max distanza
const double MIN_DIST = 1. ;
const double MAX_DIST = 50. ;
double dDist = Clamp( m_TParams.m_dDiam / 2, MIN_DIST, MAX_DIST) ;
if ( ! PL.AdjustForMaxSegmentLen( dDist))
return false ;
// porto nel riferimento delle superfici
PL.LocToLoc( frPocket, frSurf) ;
// porto i dati geometrici in locale alle superfici
Vector3d vtAxL = vtTool ;
vtAxL.ToLoc( frSurf) ;
Vector3d vtMoveL = vtAxL ;
// 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, ( k + 1) * dProgCoeff))
return false ;
// contro-traslo della lunghezza utensile
PL.Translate( - vtAxL * m_TParams.m_dLen) ;
// riporto la polilinea nel riferimento della curva
PL.LocToLoc( frSurf, frPocket) ;
// elimino i punti allineati
PL.RemoveAlignedPoints( 0.8 * m_Params.m_dApprox) ;
// creo una curva composita a partire dalla polilinea
PtrOwner< ICurveComposite> pCompo( CreateCurveComposite()) ;
if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL))
return false ;
// sostituisco la vecchia curva con la nuova
vPaths.back().pCrvPath.Set( pCompo) ;
}
}
// porto tutti i percorsi nel frame globale
for ( int i = 0 ; i < int( vPaths.size()) ; ++ i)
vPaths[i].pCrvPath->ToGlob( frPocket) ;
}
// disegno i percorsi per controllo
int ___a = int( vPaths.size()) ;
for ( int i = 0 ; i < int( vPaths.size()) ; ++ i) {
int _n = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vPaths[i].pCrvPath->Clone()) ;
m_pGeomDB->SetMaterial( _n, RED) ;
}
// ----------------------- Lavorazione Zconst -------------------------------
if ( ! IsNull( pSfrZConst) && pSfrZConst->IsValid()) {
// aggiusto la regione a seconda dei parametri (il centro utensile deve stare sul bordo)
PtrOwner<ISurfFlatRegion> pSfrToWork( pSfrZConst->CreateOffsetSurf( 0., ICurve::OFF_FILLET)) ;
if ( IsNull( pSfrToWork) || ! pSfrToWork->IsValid())
return false ;
// mi assicuro di non uscire dalla superficie originale
pSfrToWork->Intersect( *pSfr) ;
// assegno tutte proprietà di lato chiuso
for ( int nC = 0 ; nC < pSfrToWork->GetChunkCount() ; ++ nC)
for ( int nL = 0 ; nL < pSfrToWork->GetLoopCount( nC) ; ++ nL)
for ( int nU = 0 ; nU < pSfrToWork->GetLoopCurveCount( nC, nL) ; ++ nU)
pSfrToWork->SetCurveTempProp( nC, nL, nU, 0, TEMP_PROP_CLOSE_EDGE) ;
// inizializzo la classe di calcolo delle silhouette nei piani come sopra
PtrOwner<ICAvParSilhouettesSurfTm> pCavParSilh( GetParSilhouettesForZConst( vSrfLoc, frSurf, pSfrToWork)) ;
if ( IsNull( pCavParSilh))
return false ;
// recupero le curve singole definite dal bordo della Silhouette
vector<ICRVCOMPOPOVECTOR> vCrvCompo ;
if ( ! CalcZConstSilCrv( pCavParSilh, vSrfLoc, frSurf, pSfrToWork, vtTool, dDepth, vCrvCompo)) {
m_pMchMgr->SetLastError( 3126, "Error in SurfFinishing : Computing ZConst Curves failed") ;
return false ;
}
// se ho delle curve, allora unisco i percorsi trovati
if ( ! vCrvCompo.empty()) {
// collego tra loro le curve trovate
ICRVCOMPOPOVECTOR vCrv ;
if ( ! CreateZConstPaths( pCAvTlStm, vSrfLoc, frSurf, vCrvCompo, vtTool, pSfrToWork, dDepth, vCrv)) {
m_pMchMgr->SetLastError( 3127, "Error in SurfFinishing : Computing ZConst Paths failed") ;
return false ;
}
// aggiungo i percorsi trovati
for ( int i = 0 ; i < int( vCrv.size()) ; ++ i) {
vPaths.resize( vPaths.size() + 1) ;
vPaths.back().pCrvPath.Set( Release( vCrv[i])) ;
vPaths.back().nType = SURFFIN_SUB_ZIGZAG ;
}
}
}
// disegno i percorsi per controllo
for ( int i = ___a ; i < int( vPaths.size()) ; ++ i) {
int _n = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vPaths[i].pCrvPath->Clone()) ;
m_pGeomDB->SetMaterial( _n, GREEN) ;
}
// ordino i percorsi in base alla Zlocale
if ( ! OrderOptimalPathsByZLoc( pSfr, vPaths))
return false ;
// aggiusto la regione a seconda dei parametri
PtrOwner<ISurfFlatRegion> pSfrClass( pSfr->CreateOffsetSurf( - m_TParams.m_dDiam / 2. + m_Params.m_dOverlap, ICurve::OFF_FILLET)) ;
if ( IsNull( pSfrClass) || ! pSfrClass->IsValid())
return false ;
// inserisco i percorsi
bool bStart = true ;
// ciclo sulle curve risultanti
for ( int k = 0 ; k < int( vPaths.size()) ; ++ k) {
// se la curva non è valida, passo alla successiva
if ( IsNull( vPaths[k].pCrvPath) || ! vPaths[k].pCrvPath->IsValid())
continue ;
// determino in che piano di partenza e il piano di arrivo se ZConst
int nStartPlane = 0 ;
int nEndPlane = 0 ;
if ( vPaths[k].nType == SURFFIN_SUB_Z_CONST) {
nStartPlane = vPaths[k].pCrvPath->GetTempProp( 0) ;
nEndPlane = vPaths[k].pCrvPath->GetTempProp( 1) ;
}
// ciclo sulle curve elementari
int nMaxInd = vPaths[k].pCrvPath->GetCurveCount() - 1 ;
for ( int i = 0 ; i <= nMaxInd ; ++ i) {
// curva corrente
const ICurve* pCrvC = vPaths[k].pCrvPath->GetCurve( i) ;
// copio la curva
PtrOwner<ICurve> pCurve( pCrvC->Clone()) ;
if ( IsNull( pCurve))
return false ;
// se prima entità
if ( i == 0) {
// dati inizio entità
Point3d ptStart ; pCurve->GetStartPoint( ptStart) ;
Vector3d vtStart ; pCurve->GetStartDir( vtStart) ;
// vettore tangente iniziale non deve salire rispetto a estrusione (poi si prende opposto)
double dStartOnExtr = vtStart * vtTool ;
if ( dStartOnExtr > 0) {
vtStart -= dStartOnExtr * vtTool ;
vtStart.Normalize() ;
}
// determino normale della superficie sul punto iniziale
Vector3d vtNorm ;
if ( ! GetSurfaceNormalAtPoint( pCAvTlStm, frSurf, ptStart, vtTool, vtNorm)) {
Point3d ptEnd ;
pCurve->GetEndPoint( ptEnd) ;
if ( ! GetSurfaceNormalAtPoint( pCAvTlStm, frSurf, ptEnd, vtTool, vtNorm))
vtNorm = V_NULL ;
}
// determino inizio attacco
Point3d ptP1 ;
if ( ! CalcLeadInStart( ptStart, vtStart, vtTool, vtNorm, ptP1))
return false ;
// eventuale correzione inizio attacco per evitare interferenze
if ( ! GetLastGoodPoint( pCAvTlStm, frSurf, ptStart, ptP1, vtTool, ptP1))
return false ;
// se ZConst, controllo che tale punto sia al di fuori della regione piana
if ( vPaths[k].nType == SURFFIN_SUB_Z_CONST) {
bool bIsInside = false ;
if ( IsPointInsideSurfFr( ptP1 + vtTool * ( m_Params.m_dSideStep * nStartPlane), pSfrClass, EPS_SMALL, bIsInside))
ptP1 = ptStart ;
}
// determino elevazione su inizio attacco
double dStElev ;
if ( ! GetElevation( m_nPhase, ptStart - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dStElev))
dStElev = dElev ;
dStElev -= ( ptP1 - ptStart) * vtTool ;
// se inizio, approccio globale al punto iniziale
if ( bStart) {
if ( ! AddApproach( ptP1, vtTool, dSafeZ, dStElev, dAppr)) {
m_pMchMgr->SetLastError( 3111, "Error in SurfFinishing : Approach not computable") ;
return false ;
}
bStart = false ;
}
// altrimenti, approccio di collegamento
else {
if ( ! AddLinkApproach( ptP1, vtTool, dSafeZ, dStElev, dAppr)) {
m_pMchMgr->SetLastError( 3112, "Error in SurfFinishing : Link not computable") ;
return false ;
}
}
// aggiungo attacco
SetFeed( GetStartFeed()) ;
if ( ! AddLeadIn( ptP1, ptStart, vtStart, vtTool, bSplitArcs)) {
m_pMchMgr->SetLastError( 3113, "Error in SurfFinishing : LeadIn not computable") ;
return false ;
}
}
// elaborazioni sulla curva corrente (sempre un segmento di retta)
if ( pCurve->GetType() == CRV_LINE) {
ICurveLine* pLine = GetCurveLine( pCurve) ;
Point3d ptP3 = pLine->GetEnd() ;
Vector3d vtMove ; pLine->GetStartDir( vtMove) ;
SetFeed( GetRightFeed( vtMove, vtTool)) ;
if ( AddLinearMove( ptP3) == GDB_ID_NULL)
return false ;
}
else if ( pCurve->GetType() == CRV_ARC) {
ICurveArc* pArc = GetCurveArc( pCurve) ;
Point3d ptCen = pArc->GetCenter() ;
double dAngCen = pArc->GetAngCenter() ;
Vector3d vtN = pArc->GetNormVersor() ;
Point3d ptP3 ; pArc->GetEndPoint( ptP3) ;
SetFeed( GetFeed()) ;
if ( AddArcMove( ptP3, ptCen, dAngCen, vtN) == GDB_ID_NULL)
return false ;
}
// se ultima entità
if ( i == nMaxInd) {
// dati fine entità
Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ;
Vector3d vtEnd ; pCurve->GetEndDir( vtEnd) ;
// vettore tangente finale non deve scendere rispetto a estrusione
double dEndOnExtr = vtEnd * vtTool ;
if ( dEndOnExtr < 0) {
vtEnd -= dEndOnExtr * vtTool ;
vtEnd.Normalize() ;
}
// determino normale della superficie sul punto finale
Vector3d vtNorm ;
if ( ! GetSurfaceNormalAtPoint( pCAvTlStm, frSurf, ptEnd, vtTool, vtNorm)) {
Point3d ptStart ;
pCurve->GetStartPoint( ptStart) ;
if ( ! GetSurfaceNormalAtPoint( pCAvTlStm, frSurf, ptStart, vtTool, vtNorm))
vtNorm = V_NULL ;
}
// determino fine uscita
Point3d ptP1 ;
if ( ! CalcLeadOutEnd( ptEnd, vtEnd, vtTool, vtNorm, ptP1))
return false ;
// eventuale correzione fine uscita per evitare interferenze
if ( ! GetLastGoodPoint( pCAvTlStm, frSurf, ptEnd, ptP1, vtTool, ptP1))
return false ;
// controllo che tale punto sia al di fuori della regione piana
bool bIsInside = false ;
if ( IsPointInsideSurfFr( ptP1 + vtTool * ( m_Params.m_dSideStep * nStartPlane), pSfrClass, EPS_SMALL, bIsInside))
ptP1 = ptEnd ;
// se ultima uscita globale del percorso
if ( k == int( vPaths.size()) - 1) {
// aggiungo LeadOut
SetFeed( GetEndFeed()) ;
if ( ! AddLeadOut( ptEnd, vtEnd, ptP1, vtTool, bSplitArcs)) {
m_pMchMgr->SetLastError( 3114, "Error in SurfFinishing : LeadOut not computable") ;
return false ;
}
// aggiungo retroazione finale
if ( ! AddRetract( ptP1, vtTool, dSafeZ, nEndPlane * m_Params.m_dSideStep, dAppr)) {
m_pMchMgr->SetLastError( 3115, "Error in SurfFinishing : Retract not computable") ;
return false ;
}
}
// altrimenti
else {
// determino elevazione su fine uscita
double dEndElev ;
if ( ! GetElevation( m_nPhase, ptEnd - 10 * EPS_SMALL * vtTool, vtTool, GetRadiusForStartEndElevation(), vtTool, dEndElev))
dEndElev = dElev ;
dEndElev -= ( ptP1 - ptEnd) * vtTool ;
if ( ! AddRetract( ptP1, vtTool, dSafeZ, dEndElev, dAppr)) {
m_pMchMgr->SetLastError( 3115, "Error in SurfFinishing : Retract not computable") ;
return false ;
}
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfFinishing::AddApproach( const Point3d& ptP, const Vector3d& vtTool, double dSafeZ, double dElev, double dAppr)
{
SetFlag( 1) ;
// se sopra attacco c' spazio per sicurezza o approccio
// se sopra attacco c'è spazio per sicurezza o approccio
double dSafeDist = dSafeZ ;
if ( dElev + max( dSafeDist, dAppr) > 10 * EPS_SMALL) {
// se distanza di sicurezza minore di distanza di inizio
@@ -3223,7 +4062,7 @@ SurfFinishing::GetRightFeed( const Vector3d& vtMove, const Vector3d& vtTool) con
// Se l'utensile non ha movimento significativo di punta, si restituisce la feed standard
if ( dCosMove > - COS_ORTO_ANG_SMALL)
return GetFeed() ;
// Altrimenti non si deve superare la massima velocit di punta prevista
// Altrimenti non si deve superare la massima velocità di punta prevista
return min( GetFeed(), GetTipFeed() / abs( dCosMove)) ;
}
+25 -1
View File
@@ -24,7 +24,17 @@
class ICAvToolSurfTm ;
class ISurfFlatRegion ;
class ISurfTriMesh ;
class ICAvParSilhouettesSurfTm ;
class StmFromTriangleSoup ;
// vettore dei percorsi da calcolare per finiture ottimizzate
struct PATH {
PtrOwner<ICurveComposite> pCrvPath ;
int nType ;
double dSideAng ;
} ;
typedef std::vector<PATH> VECTORPATHS ;
//----------------------------------------------------------------------------
class SurfFinishing : public Machining
@@ -90,7 +100,21 @@ class SurfFinishing : public Machining
const Vector3d& vtTool, double dDepth, double dElev, bool bSplitArcs, bool bInVsOut) ;
bool AddZConst( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr,
const Vector3d& vtTool, double dDepth, double dElev, bool bSliptArcs) ;
bool GetZConstFacesInsideSfr( const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr,
bool AddOptimal( ICAvToolSurfTm* pCAvTlStm, const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf, const ISurfFlatRegion* pSfr,
const Vector3d& vtTool, double dDepth, double dElev, bool bSliptArcs) ;
bool ChooseFinishingForOptimal( const ISurfFlatRegion* pSfr, int nChunk, bool& bSpiral, double& dSideAng) ;
bool OrderOptimalPathsByZLoc( const ISurfFlatRegion* pSfr, VECTORPATHS& vCrvPaths) ;
bool SplitStmTrianglesForSpiralAndZConst( const ISurfTriMesh* pStm, const Frame3d& frSurf,
const Vector3d& vtTool, double dClippingAngle, double dTolerAngle,
StmFromTriangleSoup& TriaSoup, double& dMaxFrontTriaRad) ;
bool GetSfrBySilhouette( ICAvParSilhouettesSurfTm* pCavParSilh, double dDepth, double dSilTolSamp,
double dSilTolLin, double dSilTolAng, ISurfFlatRegion* pSfrSil) ;
bool ApproxSilhouetteClosedPLForOptimal( PolyLine& PL, double dSampleTol, double dMaxLinTol, double dAngTol, double dLinFeaTol, ICurveComposite* pCompoPL) ;
bool SplitStmInTwoSilSfrByClippingAngle( const SURFLOCALVECTOR&, const Frame3d& frSurf, const ISurfFlatRegion* pSfrCnt,
double dDepth, const Vector3d& vtTool, double dClippingAngle, ISurfFlatRegion* pSfrSpiral, ISurfFlatRegion* pSfrZConst) ;
bool GetZConstFacesInsideSfr( const SURFLOCALVECTOR&
, const Frame3d& frSurf, const ISurfFlatRegion* pSfr,
const Vector3d& vtTool, std::set<double>& setZAmbiguos) ;
ICAvParSilhouettesSurfTm* GetParSilhouettesForZConst( const SURFLOCALVECTOR& vSrfLoc, const Frame3d& frSurf,
const ISurfFlatRegion* pSfr) const ;