EgtMachKernel :
- in finiture, migliorie varie.
This commit is contained in:
+853
-14
@@ -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
@@ -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 ;
|
||||
|
||||
Reference in New Issue
Block a user