EgtMachKernel 3.1a2 :

- In Sgrossature aggiunti controlli con Tavola e Ventose.
This commit is contained in:
Riccardo Elitropi
2026-01-13 15:21:01 +01:00
parent 04bb4165c9
commit 0c9575f754
3 changed files with 501 additions and 24 deletions
BIN
View File
Binary file not shown.
+492 -21
View File
@@ -93,6 +93,7 @@ using namespace std ;
// 3054 = "Warning in SurfRoughing : Tool data changed (xx)"
// 3055 = "Warning in SurfRoughing : CalcPocketing failed with substep (xx)"
// 3056 = "Warning in SurfRoughing : invalid Conformal ZigZag at substep (xx)"
// 3057 = "Warning in SurfRoughing : Depth reduced at (xx)"
//----------------------------------------------------------------------------
static string KEY_SURF_POCK = "SurfPock_" ;
@@ -107,15 +108,20 @@ static string KEY_SUBSTEP = "SUBSTEP" ;
#define ENABLE_DEBUG_SFR 0
#define ENABLE_DEBUG_STM_NORMAL_SHADER 0
#define ENABLE_DEBUG_REMOVED_REGION 0
#define ENABLE_DEBUG_FEEDS 0
#define ENABLE_DEBUG_SFR_BOOLEANS 0
#define ENABLE_DEBUG_SFR_COLLISION 0
#define ENABLE_DEBUG_ZPLANE 0
#define ENBALE_DEBUG_LINK 0
#define ENABLE_DEBUG_ORDER_ZCHUNK 0
#if ENABLE_DEBUG_SFR_BOOLEANS || ENBALE_DEBUG_LINK
#if ENABLE_DEBUG_SFR || ENABLE_DEBUG_STM_NORMAL_SHADER || ENABLE_DEBUG_REMOVED_REGION || \
ENABLE_DEBUG_FEEDS || ENABLE_DEBUG_SFR_BOOLEANS || ENABLE_DEBUG_SFR_COLLISION || ENABLE_DEBUG_ZPLANE || \
ENBALE_DEBUG_LINK || ENABLE_DEBUG_ORDER_ZCHUNK
#include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkGeoVector3d.h"
#include "/EgtDev/Include/EgtPerfCounter.h"
#include "/EgtDev/Include/EGkExtText.h"
string sPathSrfBool = "C:\\Temp\\" ;
#endif
@@ -123,6 +129,8 @@ const double STEP_TOL = 10. * EPS_SMALL ;
const double SIL_DEPTH_TOL = 100. * EPS_SMALL ;
const double OFFS_CORR_OPEN_EDGES = 25. * EPS_SMALL ;
const double SUPP_SURF_RADIAL_OFFS = 5. ;
const double TOL_OFFS_CORNER_COLL = 50. * EPS_SMALL ;
const double DIST_TABLE = 5. * EPS_SMALL ;
//----------------------------------------------------------------------------
USEROBJ_REGISTER( GetOperationClass( OPER_SURFROUGHING), SurfRoughing) ;
@@ -893,7 +901,7 @@ SurfRoughing::GetToolData( void) const
//----------------------------------------------------------------------------
bool
SurfRoughing::UpdateToolData( void)
SurfRoughing::UpdateToolData()
{
// recupero il gestore DB utensili della macchina corrente
ToolsMgr* pTMgr = m_pMchMgr->GetCurrToolsMgr() ;
@@ -1523,6 +1531,14 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
if ( IsNull( pStmLimit))
return false ;
// determino la regione piana di tavola e ventose per evitare collisioni
// NB. creo una regione piana perchè questa è statica per ogni step, non si adatta
PtrOwner<ISurfFlatRegion> pSfrColl( CreateSurfFlatRegion()) ;
PtrOwner<ISurfFlatRegion> pSfrSearchCorners( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrColl) || IsNull( pSfrSearchCorners) ||
! GetToolCollisionRegion( pSfrSgro, dDepth, pSfrColl, pSfrSearchCorners))
return false ;
// inizializzo la classe di intersezione tra la superficie trimesh limite e piani paralleli ( quelli di lavoro)
IntersParPlanesSurfTm IPPStm1( frSfr, *pStmLimit) ;
@@ -1644,12 +1660,12 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
// inserimento degli step ( ed eventuali PlaneZ se SubSteps non presenti)
for ( int i = 0 ; i < nStep ; ++ i) {
vStepInfo.emplace_back( -1, - ( i + 1) * dStep, false, false, 1., nullptr, nullptr) ;
vStepInfo.emplace_back( -1, - ( i + 1) * dStep, false, false, 1., nullptr, nullptr, nullptr) ;
// se non ho SubStep ma PlaneZ, inserisco i PlaneZ
if ( nSubStep == -1) {
for ( int j = 0 ; j < int( vPlaneZ.size()) ; ++ j) {
if ( vPlaneZ[j].second > - ( i + 1) * dStep + STEP_TOL && vPlaneZ[j].second < - i * dStep - STEP_TOL) {
vStepInfo.emplace_back( i, vPlaneZ[j].second, false, true, -1., nullptr, nullptr) ;
vStepInfo.emplace_back( i, vPlaneZ[j].second, false, true, -1., nullptr, nullptr, nullptr) ;
vStepInfo.back().pSfrPlaneZ = Release( vPlaneZ[j].first) ;
}
}
@@ -1676,7 +1692,7 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
int nMyInd = ( j == i - 1 ? nIndRef : int( vStepInfo.size()) - 1) ;
bool bSS = ( vExtraStep[j].first == -1) ;
vStepInfo.emplace_back( nMyInd, vExtraStep[j].second, bSS, ! bSS,
-1. , nullptr, nullptr) ;
-1. , nullptr, nullptr, nullptr) ;
if ( ! bSS)
vStepInfo.back().pSfrPlaneZ = Release( vPlaneZ[vExtraStep[j].first].first) ;
}
@@ -1685,7 +1701,7 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
}
}
// definisco il vettore per salvataggio delle regione e dei loro parametri nel GromDB
// definisco il vettore per salvataggio delle regione e dei loro parametri nel GeomDB
SFRGEODBINFOVECTOR vInfoSfrGeomDB ;
vInfoSfrGeomDB.reserve( vStepInfo.size()) ;
@@ -1733,6 +1749,8 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
return false ;
/* ***************** Regione piana esterna ai contorni ****************** */
// regione definita dalla parte di grezzo al di fuori della curva di sgrossatura
// unita ad eventuale regione di collisione
PtrOwner<ISurfFlatRegion> pSfrOutCompo( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrOutCompo))
return false ;
@@ -1743,9 +1761,19 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
return false ;
}
}
if ( ! IsNull( pSfrColl) && pSfrColl->IsValid()) {
PtrOwner<ISurfFlatRegion> pSfrCollTransl( CloneSurfFlatRegion( pSfrColl)) ;
if ( IsNull( pSfrCollTransl) || ! pSfrCollTransl->IsValid())
return false ;
pSfrCollTransl->Translate( ( dSfrDepth + GetOffsL()) * vtTool) ;
if ( IsNull( pSfrOutCompo) || ! pSfrOutCompo->IsValid())
pSfrOutCompo.Set( CloneSurfFlatRegion( pSfrCollTransl)) ;
else
pSfrOutCompo->Add( *pSfrCollTransl) ;
}
/* *************************** Silhouette **************************** */
// determino la regione da non lavorare e la sottraggo
// determino la regione da non lavorare ( dalle geometrie selezionate) e la sottraggo
double dSilDepth = dSfrDepth - ( it->bPlaneZStep ? SIL_DEPTH_TOL : 0.) ;
bool bOkSil = false ;
PtrOwner<ISurfFlatRegion> pSfrSil_Hypothetical( CreateSurfFlatRegion()) ;
@@ -1782,6 +1810,7 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
continue ; // passo allo step successivo ( la silhouette coincide con il grezzo )
/* ************************** Superfici di supporto ************************ */
// sottraggo i contributi dovuti a regioni di supporto ( mediante Offset in 2d)
if ( ! vSurfL_supp.empty()) {
bool bOkSil_supp = false ;
PtrOwner<ISurfFlatRegion> pSfrSil_supp( GetSfrSilhouette( pCavParSilh_supp, dSilDepth, SILH_TOL, bOkSil_supp)) ;
@@ -1819,7 +1848,6 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
return false ;
/* *************************** Gestione StepExtra **************************** */
// piccolo Offset di correzione per booleane SurfFlatRegion
if ( it->bSubStep) {
// recupero l'indice nel vettore dello step di riferimento
int nIndRef = it->nIndRef ;
@@ -1829,18 +1857,34 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
}
// recupero la superficie progressiva dello step di riferimento
PtrOwner<ISurfFlatRegion> pSfrRef( CloneSurfFlatRegion( vStepInfo[nIndRef].pSfrRemoved)) ;
if ( ! IsNull( pSfrRef) && pSfrRef->IsValid()) { // se valida
pSfrRef->Offset( OFFS_CORR_OPEN_EDGES, ICurve::OFF_FILLET) ; // correzione
if ( ! pSfr->Subtract( *pSfrRef)) { // sottraggo la regione svuotata in precedenza
PtrOwner<ISurfFlatRegion> pSfrRemovedRef( CloneSurfFlatRegion( vStepInfo[nIndRef].pSfrRemoved)) ;
if ( ! IsNull( pSfrRemovedRef) && pSfrRemovedRef->IsValid()) { // se valida
pSfrRemovedRef->Offset( OFFS_CORR_OPEN_EDGES, ICurve::OFF_FILLET) ; // correzione per booleane
if ( ! pSfr->Subtract( *pSfrRemovedRef)) { // sottraggo la regione svuotata in precedenza
#if ENABLE_DEBUG_SFR_BOOLEANS
SaveSfrBooleans( pSfr, pSfrRef, sPathSrfBool + "Sub_" + to_string( it->dDepth) + ".nge") ;
#endif
// NB. In attesa di una versione più robusta per le booleane tra regioni piane, il substep viene scartato
continue ;
}// aggiorno Regione piana per gestione lati aperti
pSfrOpenClose->Subtract( *pSfrRef) ;
}
// aggiorno Regione piana per gestione lati aperti
pSfrOpenClose->Subtract( *pSfrRemovedRef) ;
}
/* ******************** Regione di Corner ******************************** */
// se presente una regione di Corner la aggiungo alla regione attuale da lavorare
// ( estendo quindi la regione )
if ( vStepInfo[nIndRef].pSfrCorn != nullptr && vStepInfo[nIndRef].pSfrCorn->IsValid()) {
pSfr->Add( *vStepInfo[nIndRef].pSfrCorn) ;
// verifico sempre di non rovinare la regione di Silhouette e la regione al di fuori
// della curva di bordo di sgrossatura
if ( ! IsNull( pSfrOutCompo) && pSfrOutCompo->IsValid())
pSfr->Subtract( *pSfrOutCompo) ;
if ( ! IsNull( pSfrSil) && pSfrSil->IsValid())
pSfr->Subtract( *pSfrSil) ;
}
}
else if ( it->bPlaneZStep && ! IsNull( pSfrSil) && pSfrSil->IsValid()) {
PtrOwner<ISurfFlatRegion> pSfrRef( CloneSurfFlatRegion( it->pSfrRemoved)) ;
@@ -1905,10 +1949,11 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
pSfrOpenClose->Subtract( *pSfrRef) ;
}
// se regione risultante non vuota
// se regione risultante non vuota
if ( pSfr->IsValid() && pSfr->GetChunkCount() > 0) {
// *************************** Regione Limite ***************************
// la regione limite definisce le aree dove l'utensile non deve passare
PtrOwner<ISurfFlatRegion> pSfrLimit( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrLimit))
return false ;
@@ -1921,7 +1966,7 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
pSfrLimit.Set( pSfrSil) ;
}
// se si tratta di un SottoStep, rimuovo tutti i chunk troppo snelli
// rimuovo tutti i chunk troppo snelli
if ( it->bSubStep) {
if ( ! RemoveChunksUnderTolerance( pSfr, m_dSubStepToler, pSfrLimit, it->pSfrRemoved)) {
m_pMchMgr->SetLastError( 3029, "Error in SurfRoughing : Simplify Chunks for SubSteps failed") ;
@@ -1940,7 +1985,8 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
m_pMchMgr->SetLastError( 3026, "Error in SurfRoughing : Detecting open edges failed") ;
return false ;
}
// se step base
// se step base, rimuovo i Chunk sotto una certa tolleranza
if ( ! it->bSubStep && ! it->bPlaneZStep) {
RemoveChunksUnderTolerance( pSfr, m_dStepToler, pSfrLimit) ;
// se dopo la semplificazione non rimane nulla, allora passo allo step successivo
@@ -1955,7 +2001,9 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
if ( ! CloseOpenEdgesUnderTolerance( pSfr, m_TParams.m_dDiam - 200 * EPS_SMALL)) {
m_pMchMgr->SetLastError( 3029, "Error in SurfRoughing : Simplify Chunks for SubSteps failed") ;
return false ;
}
}
// rimuovo i Chunk troppo snelli ( la regione è cambiata rispetto a prima)
if ( it->bSubStep) {
// rimuovo tutti i Chunk snelli
RemoveChunksUnderTolerance( pSfr, m_dSubStepToler, pSfrLimit) ;
@@ -1967,6 +2015,17 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
}
}
// se rischiesto, calcolo la regione di Corner allo/al Step/SubStep corrente
bool bSfrCorner = ( ! IsNull( pSfrColl) && pSfrColl->IsValid() &&
! IsNull( pSfrSearchCorners) && pSfrSearchCorners->IsValid()) ;
if ( bSfrCorner) {
PtrOwner<ISurfFlatRegion> pSfrCorner( GetSfrCornerColl( pSfr, pSfrLimit, pSfrColl, pSfrSearchCorners)) ;
if ( ! IsNull( pSfrCorner) && pSfrCorner->IsValid()) {
it->pSfrCorn = CreateSurfFlatRegion() ;
it->pSfrCorn->CopyFrom( pSfrCorner) ;
}
}
#if ENABLE_DEBUG_SFR
DrawLoopsSurf( pSfr, false, Color( .0, 1., 0., .5), it->bSubStep, ToString( it->dDepth)) ;
#endif
@@ -2035,7 +2094,7 @@ SurfRoughing::ProcessPath( int nPathId, int nPvId, int nClId)
int nNew_SfrLimit_Id = GDB_ID_NULL ;
if ( ! IsNull( vInfoSfrGeomDB[i].pSfrLimit) && vInfoSfrGeomDB[i].pSfrLimit->IsValid()) {
#if ENABLE_DEBUG_SFR
DrawLoopsSurf( vInfoSfrGeomDB[i].pSfrLimit, true, Color( .5, .5, .5, .5), vInfoSfrGeomDB[i].bSubStep, ToString( dDepth)) ;
DrawLoopsSurf( vInfoSfrGeomDB[i].pSfrLimit, true, Color( .5, .5, .5, .5), vInfoSfrGeomDB[i].bSubStep, ToString( vInfoSfrGeomDB[i].dDepth)) ;
#endif
nNew_SfrLimit_Id = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nTempId, Release( vInfoSfrGeomDB[i].pSfrLimit)) ;
if ( nNew_SfrLimit_Id == GDB_ID_NULL) {
@@ -2260,6 +2319,278 @@ SurfRoughing::GetStmOutSideSfr( const ISurfFlatRegion* pSfr, double dDepth, cons
return ( bOk ? Release( pStmLimit) : nullptr) ;
}
//----------------------------------------------------------------------------
bool
SurfRoughing::GetToolCollisionRegion( const ISurfFlatRegion* pSfrSgro, double& dDepth,
ISurfFlatRegion* pSfrColl, ISurfFlatRegion* pSfrSearchCorners) const
{
// la collisione viene calcolata mediante tavola e ventose
// se la superficie di sgrossatura non è valida, non faccio nulla
if ( pSfrSgro == nullptr || ! pSfrSgro->IsValid())
return false ;
// le supercici risultante deve essere vuota
if ( pSfrColl == nullptr || pSfrSearchCorners == nullptr)
return false ;
pSfrColl->Clear() ;
pSfrSearchCorners->Clear() ;
// dalla superficie definisco il riferimento locale ( vista come ZTool)
Frame3d frLoc ;
Point3d ptCen ; pSfrSgro->GetCentroid( ptCen) ;
if ( ! frLoc.Set( ptCen, pSfrSgro->GetNormVersor()))
return false ;
// definisco la distanza di sicurezza
double const SAFE_TOL = 5. * EPS_SMALL ;
// --- tavola
BBox3d b3Area ; // z = 0
if ( m_pMchMgr->GetTableArea( 1, b3Area) && ! b3Area.IsEmpty()) {
// caso sgrossatura in Z
if ( AreSameVectorApprox( pSfrSgro->GetNormVersor(), Z_AX)) {
// controllo se limitare la Depth della tavola
double dTabDist = abs( ( ptCen - b3Area.GetMax()) * pSfrSgro->GetNormVersor()) ;
if ( dDepth > dTabDist - DIST_TABLE) {
dDepth = dTabDist - DIST_TABLE ;
string sWarn = "Warning in SurfRoughing : Depth reduced at " + ToString( dDepth, 3) ;
m_pMchMgr->SetWarning( 3057, sWarn) ;
}
}
// se orientamento diverso dalla tavola
else {
// recupero la TriMesh di espansione per evitare collisioni
double dTmpTabThick = 0.1 * ( min( b3Area.GetDimX(), b3Area.GetDimY())) ;
b3Area.Expand( SAFE_TOL, SAFE_TOL, 0.) ;
PtrOwner<ICurveComposite> pCompoTab( CreateCurveComposite()) ;
if ( IsNull( pCompoTab))
return false ;
pCompoTab->AddPoint( b3Area.GetMin()) ;
pCompoTab->AddLine( b3Area.GetMin() + X_AX * b3Area.GetDimX()) ;
pCompoTab->AddLine( b3Area.GetMax() - Z_AX * b3Area.GetDimZ()) ;
pCompoTab->AddLine( b3Area.GetMin() + Y_AX * b3Area.GetDimY()) ;
pCompoTab->Close() ;
pCompoTab->Translate( - Z_AX * ( dTmpTabThick + SAFE_TOL)) ;
#if ENABLE_DEBUG_SFR_COLLISION
ICurveComposite* _pCompoBox = CloneCurveComposite( pCompoTab) ;
_pCompoBox->SetExtrusion( Z_AX) ;
_pCompoBox->SetThickness( dTmpTabThick + 2. * SAFE_TOL) ;
int _nTbId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, _pCompoBox) ;
m_pGeomDB->SetMaterial( _nTbId, RED) ;
#endif
CICURVEPVECTOR vpCrvs ;
vpCrvs.emplace_back( pCompoTab) ;
PtrOwner<ISurfTriMesh> pStmCollTab( GetSurfTriMeshByRegionExtrusion( vpCrvs, Z_AX * ( dTmpTabThick + 2. * SAFE_TOL))) ;
if ( IsNull( pStmCollTab) || ! pStmCollTab->IsValid() || pStmCollTab->GetTriangleCount() == 0)
return false ;
// recupero la sua proiezione nel piano di sgrossatura come regione piana
Plane3d plProj ;
if ( ! plProj.Set( frLoc.Orig() - dDepth * frLoc.VersZ(), frLoc.VersZ()))
return false ;
POLYLINEVECTOR vPL ;
if ( ! pStmCollTab->GetSilhouette( plProj, EPS_SMALL, vPL)) // proiezione di 6 triangoli, veloce
return false ;
// se completamente dietro al piano, non influenza la sgrossatura attuale
if ( ! vPL.empty()) {
SurfFlatRegionByContours SfrByC ;
for ( const PolyLine& PL : vPL) {
PtrOwner<ICurveComposite> pCompoLoop( CreateCurveComposite()) ;
if ( IsNull( pCompoLoop) || ! pCompoLoop->FromPolyLine( PL) ||
! SfrByC.AddCurve( Release( pCompoLoop)))
return false ;
}
PtrOwner<ISurfFlatRegion> pSfrTabColl( SfrByC.GetSurf()) ;
if ( IsNull( pSfrTabColl) || ! pSfrTabColl->IsValid())
return false ;
// aggiorno la regione di collissione per l'utensile
if ( ! pSfrColl->CopyFrom( pSfrTabColl))
return false ;
if ( AreOppositeVectorApprox( pSfrColl->GetNormVersor(), frLoc.VersZ()))
pSfrColl->Invert() ;
#if ENABLE_DEBUG_SFR_COLLISION
ISurfFlatRegion* _pSfrTab = CreateSurfFlatRegion() ;
_pSfrTab->CopyFrom( pSfrColl) ;
int _nSrfTbId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, _pSfrTab) ;
m_pGeomDB->SetMaterial( _nSrfTbId, Color( 255, 0, 0, 50)) ;
#endif
}
}
}
// --- ventose
INTVECTOR vFxtId ;
int nFxtId = m_pMchMgr->GetFirstFixture() ;
while ( nFxtId != GDB_ID_NULL) {
vFxtId.emplace_back( nFxtId) ;
nFxtId = m_pMchMgr->GetNextFixture( nFxtId) ;
}
for ( const int& nFxtId : vFxtId) {
// recupero il Box della ventosa
BBox3d bFxtBox ;
if ( m_pGeomDB->GetGlobalBBox( nFxtId, bFxtBox) && ! bFxtBox.IsEmpty()) {
// espando il Box per evitare la collisione con l'utensile
bFxtBox.Expand( SAFE_TOL) ;
#if ENABLE_DEBUG_SFR_COLLISION
ICurveComposite* _pCompoFxt = CreateCurveComposite() ;
_pCompoFxt->AddPoint( bFxtBox.GetMin()) ;
_pCompoFxt->AddLine( bFxtBox.GetMin() + X_AX * bFxtBox.GetDimX()) ;
_pCompoFxt->AddLine( bFxtBox.GetMax() - Z_AX * bFxtBox.GetDimZ()) ;
_pCompoFxt->AddLine( bFxtBox.GetMin() + Y_AX * bFxtBox.GetDimY()) ;
_pCompoFxt->Close() ;
_pCompoFxt->SetExtrusion( Z_AX) ;
_pCompoFxt->SetThickness( bFxtBox.GetDimZ()) ;
int nFxtId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, _pCompoFxt) ;
m_pGeomDB->SetMaterial( nFxtId, YELLOW) ;
#endif
// recupero la TriMesh del Box
PtrOwner<ICurveComposite> pCompoFxt( CreateCurveComposite()) ;
if ( IsNull( pCompoFxt))
return false ;
pCompoFxt->AddPoint( bFxtBox.GetMin()) ;
pCompoFxt->AddLine( bFxtBox.GetMin() + X_AX * bFxtBox.GetDimX()) ;
pCompoFxt->AddLine( bFxtBox.GetMax() - Z_AX * bFxtBox.GetDimZ()) ;
pCompoFxt->AddLine( bFxtBox.GetMin() + Y_AX * bFxtBox.GetDimY()) ;
pCompoFxt->Close() ;
CICURVEPVECTOR vpCrvs ;
vpCrvs.emplace_back( pCompoFxt) ;
PtrOwner<ISurfTriMesh> pStmCollFxt( GetSurfTriMeshByRegionExtrusion( vpCrvs, Z_AX * bFxtBox.GetDimZ())) ;
if ( IsNull( pStmCollFxt) || ! pStmCollFxt->IsValid() || pStmCollFxt->GetTriangleCount() == 0)
return false ;
// recupero la sua proiezione nel piano di sgrossatura come regione piana
Plane3d plProj ;
if ( ! plProj.Set( frLoc.Orig() - dDepth * frLoc.VersZ(), frLoc.VersZ()))
return false ;
POLYLINEVECTOR vPL ;
if ( ! pStmCollFxt->GetSilhouette( plProj, EPS_SMALL, vPL)) // proiezione di 6 triangoli, veloce
return false ;
// se completamente dietro al piano, non influenza la sgrossatura attuale
if ( vPL.empty())
continue ;
SurfFlatRegionByContours SfrByC ;
for ( const PolyLine& PL : vPL) {
PtrOwner<ICurveComposite> pCompoLoop( CreateCurveComposite()) ;
if ( IsNull( pCompoLoop) || ! pCompoLoop->FromPolyLine( PL) ||
! SfrByC.AddCurve( Release( pCompoLoop)))
return false ;
}
PtrOwner<ISurfFlatRegion> pSfrFxtColl( SfrByC.GetSurf()) ;
if ( IsNull( pSfrFxtColl) || ! pSfrFxtColl->IsValid())
return false ;
if ( AreOppositeVectorApprox( pSfrFxtColl->GetNormVersor(), frLoc.VersZ()))
pSfrFxtColl->Invert() ;
// aggiorno la regione di collissione per l'utensile
if ( ! pSfrColl->IsValid()) {
if ( ! pSfrColl->CopyFrom( pSfrFxtColl))
return false ;
}
else {
if ( ! pSfrColl->Add( *pSfrFxtColl))
return false ;
}
#if ENABLE_DEBUG_SFR_COLLISION
ISurfFlatRegion* _pSfrFxt = CreateSurfFlatRegion() ;
_pSfrFxt->CopyFrom( pSfrFxtColl) ;
int _nSfrFxtId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, _pSfrFxt) ;
m_pGeomDB->SetMaterial( _nSfrFxtId, Color( 255, 255, 0, 50)) ;
#endif
}
}
// se ho una regione di collisione valida
if ( pSfrColl->IsValid()) {
PtrOwner<ISurfFlatRegion> pSfrBlock( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrBlock))
return false ;
// scorro le curve della regione di sgrossatura e definisco delle superfici di blocco
for ( int nC = 0 ; nC < pSfrSgro->GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < pSfrSgro->GetLoopCount( nC) ; ++ nL) {
PtrOwner<ICurveComposite> pCompoLoop( ConvertCurveToComposite( pSfrSgro->GetLoop( nC, nL))) ;
if ( ! IsNull( pCompoLoop) && pCompoLoop->IsValid()) {
pCompoLoop->Translate( - pSfrSgro->GetNormVersor() * dDepth) ;
for ( int nU = 0 ; nU < pCompoLoop->GetCurveCount() ; ++ nU) {
const ICurve* pSubCrvLoop = pCompoLoop->GetCurve( nU) ;
if ( pSubCrvLoop == nullptr || ! pSubCrvLoop->IsValid())
return false ;
CRVCVECTOR ccClass ;
if ( ! pSfrColl->GetCurveClassification( *pSubCrvLoop, EPS_SMALL, ccClass))
return false ;
bool bBlock = false ;
for ( int i = 0 ; ! bBlock && i < ssize( ccClass) ; ++ i) {
if ( ccClass[i].nClass == CRVC_OUT)
continue ;
PtrOwner<ICurve> pCrvColl( pSubCrvLoop->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE)) ;
if ( IsNull( pCrvColl) || ! pCrvColl->IsValid())
continue ;
double dLen = 0. ;
pCrvColl->GetLength( dLen) ;
bBlock = ( dLen > 2. * SAFE_TOL) ;
}
if ( bBlock) {
PtrOwner<ICurveComposite> pCompoBlock( CreateCurveComposite()) ;
if ( IsNull( pCompoBlock))
return false ;
pCompoBlock->AddCurve( pSubCrvLoop->Clone()) ;
pCompoBlock->SetExtrusion( pSfrSgro->GetNormVersor()) ;
OffsetCurve OffsCrv ; // ... rappresentativo
OffsCrv.Make( pCompoBlock, m_TParams.m_dDiam, ICurve::OFF_FILLET) ;
PtrOwner<ICurve> pCrvOffs( OffsCrv.GetLongerCurve()) ;
if ( IsNull( pCrvOffs) || ! pCrvOffs->IsValid())
return false ;
pCompoBlock->Invert() ;
Point3d ptA ; pCrvOffs->GetStartPoint( ptA) ;
Point3d ptC ; pCompoBlock->GetStartPoint( ptC) ;
pCompoBlock->AddLine( ptA) ;
pCompoBlock->AddCurve( Release( pCrvOffs)) ;
pCompoBlock->AddLine( ptC) ;
#if ENABLE_DEBUG_SFR_COLLISION
int _nCrvId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCompoBlock->Clone()) ;
m_pGeomDB->SetMaterial( _nCrvId, PURPLE) ;
#endif
PtrOwner<ISurfFlatRegion> pSfrCurrBlock( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrCurrBlock))
return false ;
if ( ! pSfrCurrBlock->AddExtLoop( Release( pCompoBlock)))
return false ;
if ( ! pSfrBlock->IsValid()) {
if ( ! pSfrBlock.Set( Release( pSfrCurrBlock)))
return false ;
}
else {
if ( ! pSfrBlock->Add( *pSfrCurrBlock))
return false ;
}
}
}
}
}
}
// determino la superficie di collisione
pSfrColl->Clear() ;
pSfrColl->CopyFrom( pSfrBlock) ;
// per essere sufficientemente distanti
pSfrColl->Offset( 50. * EPS_SMALL, ICurve::OFF_FILLET) ;
// riporto la superficie alla stessa quota della regione di sgrossatura
pSfrColl->Translate( pSfrSgro->GetNormVersor() * dDepth) ;
// determino la superficie di ricerca per la pulizia dei corners
pSfrSearchCorners->Clear() ;
pSfrSearchCorners->CopyFrom( pSfrColl) ;
pSfrSearchCorners->Offset( m_TParams.m_dDiam + TOL_OFFS_CORNER_COLL, ICurve::OFF_FILLET) ;
if ( ! pSfrSearchCorners->Intersect( *pSfrSgro))
return false ;
}
#if ENABLE_DEBUG_SFR_COLLISION
int _nSfrId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrColl->Clone()) ;
m_pGeomDB->SetMaterial( _nSfrId, Color( 128, 0, 128, 50)) ;
_nSfrId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrSearchCorners->Clone()) ;
m_pGeomDB->SetMaterial( _nSfrId, Color( 128, 128, 0, 50)) ;
#endif
return true ;
}
//----------------------------------------------------------------------------
ISurfFlatRegion*
SurfRoughing::GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs) const
@@ -2381,6 +2712,146 @@ SurfRoughing::GetSfrSilhouette( ICAvParSilhouettesSurfTm* pCavParSilh, double dD
return ( SfrMaker.GetSurf()) ;
}
//----------------------------------------------------------------------------
ISurfFlatRegion*
SurfRoughing::GetSfrCornerColl( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrLimit,
const ISurfFlatRegion* pSfrColl, const ISurfFlatRegion* pSfrSearchCorners) const
{
/*
se ho la presenza di tavole o ventose, la superficie di collissione ricavata genera dei nuovi
lati chiusi nella geometria attuale ( pSfr deve già avere impostati i lati OPEN/CLOSE)
i nuovi lati chiusi possono generare regioni i cui spigoli non si possono svuotare ( nei punti
di unione dei lati aperti originali con i nuovi chiusi).
questa funzione aggiunge delle piccole parti di regione in questi punti, evitando quindi la presenza
di colonne di materiale non rimosso
NB. questa parti non riguardano nè le regioni nons vuotate, nè le regioni si silhouette ipotetica
*/
// se la superficie di collissione non è valida non faccio nulla
if ( pSfrColl == nullptr || ! pSfrColl->IsValid() ||
pSfrSearchCorners == nullptr || ! pSfrSearchCorners->IsValid())
return nullptr ;
if ( pSfr == nullptr)
return nullptr ;
#if ENABLE_DEBUG_REMOVED_REGION
int _nIdSfrSearch = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrSearchCorners->Clone()) ;
m_pGeomDB->SetMaterial( _nIdSfrSearch, YELLOW) ;
int _nIdSfrLimit = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrLimit->Clone()) ;
m_pGeomDB->SetMaterial( _nIdSfrLimit, GRAY) ;
DrawLoopsSurf( pSfr, false, Color( 0., 1., 0.), false, "") ;
#endif
// recupero tutti i lati aperti della superficie attuale
ICURVEPOVECTOR vCrvOpenInSearch ;
for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) {
PtrOwner<ICurveComposite> pCompoLoop( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ;
if ( IsNull( pCompoLoop) || ! pCompoLoop->IsValid())
return nullptr ;
ICRVCOMPOPOVECTOR vpCrvs ;
GetHomogeneousParts( pCompoLoop, vpCrvs) ;
for ( int i = 0 ; i < ssize( vpCrvs) ; ++ i) {
if ( vpCrvs[i]->GetTempProp( 0) == TEMP_PROP_OPEN_EDGE) {
CRVCVECTOR ccClass ;
if ( ! pSfrSearchCorners->GetCurveClassification( *vpCrvs[i], EPS_SMALL, ccClass))
return nullptr ;
for ( int j = 0 ; j < ssize( ccClass) ; ++ j) {
if ( ccClass[j].nClass != CRVC_OUT) {
PtrOwner<ICurve> pCrvIn( vpCrvs[i]->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE)) ;
if ( ! IsNull( pCrvIn) && pCrvIn->IsValid()) {
if ( ! vCrvOpenInSearch.emplace_back( Release( pCrvIn)))
return nullptr ;
}
}
}
}
}
}
}
#if ENABLE_DEBUG_REMOVED_REGION
for ( int _i = 0 ; _i < ssize( vCrvOpenInSearch) ; ++ _i) {
int _nIdCrvOpen = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, vCrvOpenInSearch[_i]->Clone()) ;
m_pGeomDB->SetMaterial( _nIdCrvOpen, ORANGE) ;
}
#endif
// determino la regione complessiva di ricerca
PtrOwner<ISurfFlatRegion> pSfrExtra( CreateSurfFlatRegion()) ;
if ( IsNull( pSfrExtra))
return nullptr ;
double dOffs = m_TParams.m_dDiam + 50. * EPS_SMALL ; // deve passare l'utensile per tale regione
for ( int i = 0 ; i < ssize( vCrvOpenInSearch) ; ++ i) {
// recupero la curva come composita
PtrOwner<ICurveComposite> pCrvCompo( ConvertCurveToComposite( vCrvOpenInSearch[i]->Clone())) ;
if ( IsNull( pCrvCompo) || ! pCrvCompo->IsValid())
return nullptr ;
// calcolo il semi-offset
pCrvCompo->SetExtrusion( pSfr->GetNormVersor()) ;
OffsetCurve OffsCrv ;
if ( ! OffsCrv.Make( pCrvCompo, dOffs / 2., ICurve::OFF_FILLET))
return nullptr ;
PtrOwner<ICurve> pCrvOffs( OffsCrv.GetLongerCurve()) ;
if ( IsNull( pCrvOffs) || ! pCrvOffs->IsValid())
return nullptr ;
// determino la regione da aggiungere
if ( IsNull( pSfrExtra) || ! pSfrExtra->IsValid())
pSfrExtra.Set( GetSurfFlatRegionFromFatCurve( pCrvOffs->Clone(), dOffs / 2. + 50. * EPS_SMALL, false, false)) ;
else {
PtrOwner<ISurfFlatRegion> pSfrToAdd( GetSurfFlatRegionFromFatCurve( pCrvOffs->Clone(), dOffs / 2 + 50. * EPS_SMALL, false, false)) ;
if ( IsNull( pSfrToAdd) || ! pSfrToAdd->IsValid())
return nullptr ;
pSfrExtra->Add( *pSfrToAdd) ;
}
if ( IsNull( pSfrExtra) || ! pSfrExtra->IsValid())
return nullptr ;
}
if ( IsNull( pSfrExtra) || ! pSfrExtra->IsValid())
return nullptr ;
if ( ! pSfrExtra->Intersect( *pSfrSearchCorners))
return nullptr ;
// rimuovo i Chunk che non sono attaccati alle curve aperte ricavate
for ( int nC = 0 ; nC < pSfrExtra->GetChunkCount() ; ++ nC) {
PtrOwner<ISurfFlatRegion> pSfrExtraChunk( pSfrExtra->CloneChunk( nC)) ;
if ( IsNull( pSfrExtraChunk) || ! pSfrExtraChunk->IsValid())
return nullptr ;
bool bSave = false ;
for ( int i = 0 ; ! bSave && i < ssize( vCrvOpenInSearch) ; ++ i) {
CRVCVECTOR ccClass ;
if ( pSfrExtraChunk->GetCurveClassification( *vCrvOpenInSearch[i], 10. * EPS_SMALL, ccClass)) {
for ( int j = 0 ; ! bSave && j < ssize( ccClass) ; ++ j)
bSave = ( ccClass[j].nClass != CRVC_OUT) ;
}
}
if ( ! bSave) {
pSfrExtra->EraseChunk( nC) ;
-- nC ;
}
}
// se superficie non valida, ho finito
if ( IsNull( pSfrExtra) || ! pSfrExtra->IsValid())
return nullptr ;
// rimuovo la regione da non rovinare, ho esteso i lati aperti mediante Offset semplice,
// devo controllare di non rovinare altre regioni
// regolarizzo la superficie
pSfrExtra->Offset( - m_TParams.m_dDiam / 8., ICurve::OFF_FILLET) ;
pSfrExtra->Offset( m_TParams.m_dDiam / 8., ICurve::OFF_FILLET) ;
if ( ! pSfrExtra->Subtract( *pSfrLimit))
return nullptr ;
#if ENABLE_DEBUG_REMOVED_REGION
int _nIdExtraSfr = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrExtra->Clone()) ;
m_pGeomDB->SetMaterial( _nIdExtraSfr, FUCHSIA) ;
#endif
// bisogna ricalcolare i lati aperti/chiusi in base alle nuove modifica della superficie
return ( Release( pSfrExtra)) ;
}
//----------------------------------------------------------------------------
bool
SurfRoughing::GetActiveSurfaces( INTVECTOR& vSurfId, INTVECTOR& vSurfSuppId) const
@@ -3933,7 +4404,7 @@ SurfRoughing::RemoveChunksUnderTolerance( ISurfFlatRegion* pSfr, double dTol,
if ( pSfrToUpdate != nullptr && pSfrToUpdate->IsValid()) {
PtrOwner<ISurfFlatRegion> pSfrChunk( pSfr->CloneChunk( nC)) ;
if ( ! IsNull( pSfrChunk) || pSfrChunk->IsValid()) {
pSfrChunk->Offset( 50 * EPS_SMALL, ICurve::OFF_FILLET) ; // si prova...
pSfrChunk->Offset( 50. * EPS_SMALL, ICurve::OFF_FILLET) ; // si prova...
pSfrToUpdate->Subtract( *pSfrChunk) ; // si prova...
}
}
@@ -4218,7 +4689,7 @@ SurfRoughing::GetRadiusForStartEndElevation( void) const
}
//----------------------------------------------------------------------------
bool
bool
SurfRoughing::CheckSafetyLinearLink( const Point3d& ptCurr, const Point3d& ptDest, const ISurfFlatRegion* pSfrCheck, const Vector3d& vtTool,
bool& bSafe) const
{
+9 -3
View File
@@ -41,13 +41,14 @@ typedef std::vector<PathInfoSR> PATHINFOSRVECTOR ;
struct StepInfoSRTmp {
StepInfoSRTmp( void)
: nIndRef( -1), dDepth( 0), bSubStep( false), bPlaneZStep( false), dPercFeed( 0.),
pSfrRemoved( nullptr), pSfrPlaneZ( nullptr) {}
StepInfoSRTmp( int nIR, double dD, bool bSS, bool bPZ, double dPF, ISurfFlatRegion* pSR, ISurfFlatRegion* pSPZ)
pSfrRemoved( nullptr), pSfrPlaneZ( nullptr), pSfrCorn( nullptr) {}
StepInfoSRTmp( int nIR, double dD, bool bSS, bool bPZ, double dPF, ISurfFlatRegion* pSR, ISurfFlatRegion* pSPZ, ISurfFlatRegion* pSC)
: nIndRef( nIR), dDepth( dD), bSubStep( bSS), bPlaneZStep( bPZ), dPercFeed( dPF),
pSfrRemoved( pSR), pSfrPlaneZ( pSPZ) {}
pSfrRemoved( pSR), pSfrPlaneZ( pSPZ), pSfrCorn( pSC) {}
~StepInfoSRTmp() {
delete( pSfrRemoved) ;
delete( pSfrPlaneZ) ;
delete( pSfrCorn) ;
}
int nIndRef ; // ( usato solo per step intermedi ) posizione step precedente
double dDepth ; // profondità posizione piano di svuotatura ( in negativo)
@@ -56,6 +57,7 @@ struct StepInfoSRTmp {
double dPercFeed ; // percentuale degli extra steps relativa agli step base ( per Feed ZLoc)
ISurfFlatRegion* pSfrRemoved ; // regione PROGRESSIVA rimossa attuale
ISurfFlatRegion* pSfrPlaneZ ; // regione individuata da PlaneZDetection
ISurfFlatRegion* pSfrCorn ; // regione non svutata per presenza di lati chiusi definiti da tavola/ventose
} ;
// vettore associato
typedef std::vector<StepInfoSRTmp> STEPINFOTMPSRVECTOR ;
@@ -209,6 +211,10 @@ class SurfRoughing : public Machining
ISurfTriMesh* GetStmOutSideSfr( const ISurfFlatRegion* pSfr, double dDepth, const ISurfTriMesh* pStmRaw, const Vector3d& vtExtr) const ;
ISurfFlatRegion* GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs = 0) const ;
ISurfFlatRegion* GetSfrSilhouette( ICAvParSilhouettesSurfTm* pCavParSilh, double dDepth, double Sil_tol, bool& bOk) const ;
ISurfFlatRegion* GetSfrCornerColl( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrLimit,
const ISurfFlatRegion* pSfrColl, const ISurfFlatRegion* pSfrSearchCorners) const ;
bool GetToolCollisionRegion( const ISurfFlatRegion* pSfrSgro, double& dDepth, ISurfFlatRegion* pSfrColl,
ISurfFlatRegion* pSfrSearchCorners) const ;
bool GetActiveSurfaces( INTVECTOR& vSurfId, INTVECTOR& vSurfSuppId) const ;
double GetRightFeed( const Vector3d& vtMove, const Vector3d& vtTool) const ;
double GetRadiusForStartEndElevation( void) const ;