Merge commit '1a15584126c1eb401c6bed1eabc35f314db92834'

This commit is contained in:
Dario Sassi
2025-05-21 17:33:58 +02:00
2 changed files with 188 additions and 139 deletions
+185 -138
View File
@@ -54,6 +54,7 @@ static string KEY_OPEN = "OPEN" ;
static string KEY_THICK = "THICK" ;
static int LINK_CURVE_PROP = -3 ;
static double EXTRA_ELEV = 5. ;
static double EXTRA_DEPTH = 5. ;
static double SAFETY_LINK_COS = cos( - ( 175 * DEGTORAD)) ;
static double TOOL_RAD_PTSTART = 20. ;
// Parametri avanzati da UserNotes
@@ -1576,6 +1577,7 @@ PocketingNT::Chain( int nGrpDestId)
return false ;
}
// scorro le regioni piane ricavate dalle curve
int nGroupName = -1 ;
PtrOwner<ISurfFlatRegion> pSfrCurr( SfrByC.GetSurf()) ;
@@ -1839,6 +1841,60 @@ PocketingNT::GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, doubl
return ( ( ! IsNull( pSfrFromCrvs) && pSfrFromCrvs->IsValid()) ? Release( pSfrFromCrvs) : nullptr) ;
}
//----------------------------------------------------------------------------
ISurfFlatRegion*
PocketingNT::GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRegion* pSfr,
const Vector3d& vtTool)
{
// controllo dei parametri
if ( pStmRaw == nullptr || ! pStmRaw->IsValid() ||
pSfr == nullptr || ! pSfr->IsValid())
return nullptr ;
// recupero il piano di taglio dalla regione piana
Point3d ptCen ; pSfr->GetCentroid( ptCen) ;
Plane3d plProj ;
if ( ! plProj.Set( ptCen, vtTool))
return nullptr ;
/*int a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfr->Clone()) ;
m_pGeomDB->SetMaterial( a, Color( 0., 1., 0., .5)) ;
a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pStmRaw->Clone()) ;
m_pGeomDB->SetMaterial( a, Color( 5., 1., 0., .5)) ;
PtrOwner<IGeoFrame3d> fr( CreateGeoFrame3d()) ;
Frame3d frr ; frr.Set( ptCen, vtTool) ;
fr->Set( frr) ;
m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, fr->Clone()) ;*/
// recupero la Silhouette al piano trovato
POLYLINEVECTOR vPL ;
if ( ! pStmRaw->GetSilhouette( plProj, EPS_SMALL, vPL))
return nullptr ;
// se non trovo nessun contorno sono fuori dal grezzo, la superficie è vuota
if ( vPL.empty())
return ( CreateSurfFlatRegion()) ;
// costruisco la regione piana
SurfFlatRegionByContours SfrByC ;
for ( const PolyLine& PL : vPL) {
PtrOwner<ICurveComposite> pCrvLoop( CreateCurveComposite()) ;
if ( IsNull( pCrvLoop) || ! pCrvLoop->FromPolyLine( PL))
return nullptr ;
/*a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pCrvLoop->Clone()) ;
m_pGeomDB->SetMaterial( a, RED) ;*/
SfrByC.AddCurve( Release( pCrvLoop)) ;
}
PtrOwner<ISurfFlatRegion> pSfrRaw( SfrByC.GetSurf()) ;
if ( IsNull( pSfrRaw) || ! pSfrRaw->IsValid())
return nullptr ;
if ( AreOppositeVectorApprox( pSfrRaw->GetNormVersor(), vtTool))
pSfrRaw->Invert() ;
/* a = m_pGeomDB->AddGeoObj( GDB_ID_NULL, GDB_ID_ROOT, pSfrRaw->Clone()) ;
m_pGeomDB->SetMaterial( a, ORANGE) ;*/
return Release( pSfrRaw) ;
}
//----------------------------------------------------------------------------
bool
PocketingNT::GetHomogeneousParts( const ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCrvs) const
@@ -2723,32 +2779,6 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId)
// assegno il versore fresa
Vector3d vtTool = vtExtr ;
// calcolo l'elevazione massima (tra tutti i Loop di tutti i Chunk della regione)
double dElev = 0. ;
for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) {
// recupero la curva
PtrOwner<ICurveComposite> pCrvLoop( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ;
if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid())
return false ;
// se isola inverto
if ( nL > 0)
pCrvLoop->Invert() ;
// determino l'elevazione
double dCurrElev ;
if ( ! CalcRegionElevation( pCrvLoop, vtTool, dDepth, 0.5 * m_TParams.m_dDiam, m_TParams.m_dLen, dCurrElev)) {
m_pMchMgr->SetLastError( 2433, "Error in PocketingNT : Calc Region Elevation failed") ;
return false ;
}
// aggiorno l'elevazione
dElev = max( dElev, dCurrElev) ;
}
}
// eventuale imposizione massima elevazione da note utente
double dMaxElev ;
if ( GetValInNotes( m_Params.m_sUserNotes, UN_MAXELEV, dMaxElev) && dElev > dMaxElev)
dElev = dMaxElev ;
// verifico che lo step dell'utensile sia sensato
double dOkStep = ( m_Params.m_dStep > EPS_SMALL ? m_Params.m_dStep + EPS_SMALL : 0) ;
const double MIN_ZSTEP = 1.0 ;
@@ -2759,6 +2789,27 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId)
m_pMchMgr->SetWarning( 2456, sInfo) ;
}
// calcolo l'elevazione inversa per definire la Depth massima
double dInvElev = 0. ;
pSfr->Invert() ;
if ( ! CalcRegionElevation( pSfr, vtTool, 0., m_TParams.m_dDiam / 2., m_TParams.m_dLen, dInvElev)) {
m_pMchMgr->SetLastError( 2433, "Error in PocketingNT : Calc Region Elevation failed") ;
return false ;
}
pSfr->Invert() ;
double dExtraDepth = ( dOkStep < EXTRA_DEPTH ? dOkStep / 2. : EXTRA_DEPTH) ;
dDepth = min( dDepth, dInvElev + dExtraDepth) ;
// calcolo l'elevazione massima
double dElev = 0. ;
if ( ! CalcRegionElevation( pSfr, vtTool, dDepth, m_TParams.m_dDiam / 2., m_TParams.m_dLen, dElev)) {
m_pMchMgr->SetLastError( 2433, "Error in PocketingNT : Calc Region Elevation failed") ;
return false ;
}
double dMaxElev ;
if ( GetValInNotes( m_Params.m_sUserNotes, UN_MAXELEV, dMaxElev) && dElev > dMaxElev)
dElev = dMaxElev ;
// verifico che il massimo materiale dell'utensile sia sensato
const double MIN_MAXMAT = 1.0 ;
if ( m_TParams.m_dMaxMat < dElev && m_TParams.m_dMaxMat < MIN_MAXMAT) {
@@ -2782,22 +2833,10 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId)
m_pMchMgr->SetLastError( 3025, "Error in PocketingNT : RawPart not computable") ;
return false ;
}
// inizializzo la classe di intersezione tra grezzo e piani paralleli ( quelli di lavoro)
Frame3d frSfr ;
Point3d ptCen ; pSfr->GetCentroid( ptCen) ;
Frame3d frPocket ;
if ( ! frPocket.Set( ptCen, vtTool) || ! frPocket.IsValid())
return false ;
IntersParPlanesSurfTm IPPStm( frPocket, *pStmRaw) ;
#if DEBUG_SFR_RAW
int nGrpSR = m_pGeomDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ;
int nLaySR = m_pGeomDB->AddGroup( GDB_ID_NULL, nGrpSR, GLOB_FRM) ;
m_pGeomDB->SetName( nLaySR, "Sfr_Raw_Position") ;
PtrOwner<IGeoFrame3d> pFr( CreateGeoFrame3d()) ;
pFr->Set( frPocket) ;
int _nFr = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySR, pFr->Clone()) ;
int _nSfr = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySR, pSfr->Clone()) ;
m_pGeomDB->SetMaterial( _nSfr, Color( 0., 1., 0., .75)) ;
int _nRaw = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySR, pStmRaw->Clone()) ;
m_pGeomDB->SetMaterial( _nRaw, Color( .35, .46, .78, .1)) ;
#endif
@@ -2839,6 +2878,12 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId)
double dMaxDepth = m_TParams.m_dLen - ( m_TParams.m_dDiam > m_dTHoldDiam ? m_dTHoldBase : m_dTHoldLen) - dSafe ;
if ( dElev > dMaxDepth + EPS_SMALL) {
// controllo se posso evitare il controllo
Frame3d frSfr ;
Point3d ptCen ; pSfr->GetCentroid( ptCen) ;
Frame3d frPocket ;
if ( ! frPocket.Set( ptCen, vtTool) || ! frPocket.IsValid())
return false ;
IntersParPlanesSurfTm IPPStm( frPocket, *pStmRaw) ;
bool bSkipMaxDepth = false ;
if ( ! CheckMaxDepth( pSfr, dDepth, vtTool, pStmRaw, pStmExtrusion, IPPStm, bSkipMaxDepth))
return false ;
@@ -2925,12 +2970,11 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId)
m_pGeomDB->SetInfo( nPxId, KEY_ELEV, dElev) ;
// determino numero e affondamento degli step
int nStep = 1 ;
nStep = max( 1, static_cast<int>( ceil( dElev / dOkStep))) ;
int nStep = max( 1, static_cast<int>( ceil( dElev / dOkStep))) ;
double dStep = dElev / nStep ;
// step per progressBar
int nProgressBarStep = 0 ;
int nProgressBarStep = 0 ;
// vettore per gli step
STEPINFOPOVECTOR vStepInfo ;
@@ -2946,36 +2990,21 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId)
return false ;
// adatto la regione piana alla geometria del grezzo
PtrOwner<ISurfFlatRegion> pSfrRaw( GetSfrByStmIntersection( IPPStm, - ( dDepth - dElev + j * dStep), 0)) ;
PtrOwner<ISurfFlatRegion> pSfrRaw( GetSfrRawProjection( pStmRaw, pSfrPock, vtTool)) ;
if ( IsNull( pSfrRaw)) {
m_pMchMgr->SetLastError( 3027, "Error in PocketingNT : Slicing Raw failed") ;
return false ;
}
if ( pSfrRaw->IsValid() && pSfrRaw->GetChunkCount() > 0)
if ( pSfrRaw->IsValid() && pSfrRaw->GetChunkCount() > 0) {
// se valida, limito la superficie di svuotatura alla proiezione del grezzo
#if DEBUG_SFR_RAW
int _nSfr = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySR, pSfrRaw->Clone()) ;
m_pGeomDB->SetMaterial( _nSfr, Color( 0., 1., 0., .75)) ;
#endif
pSfrPock->Intersect( *pSfrRaw) ;
else {
// potrebbe essere una tasca passante, in questo caso provo a traslare il grezzo
double MAX_DEPTH_EXTRA = 5. + 50 * EPS_SMALL ;
pStmRaw->Translate( - vtTool * MAX_DEPTH_EXTRA) ;
IntersParPlanesSurfTm IPPStm1( frPocket, *pStmRaw) ;
pSfrRaw.Set( GetSfrByStmIntersection( IPPStm1, - ( dDepth - dElev + j * dStep), 0)) ;
if ( IsNull( pSfrRaw)) {
m_pMchMgr->SetLastError( 3027, "Error in PocketingNT : Slicing Raw failed") ;
return false ;
}
if ( pSfrRaw->IsValid() && pSfrRaw->GetChunkCount() > 0) {
pSfrPock->Intersect( *pSfrRaw) ;
pStmExtrusion->Translate( - vtTool * MAX_DEPTH_EXTRA) ;
}
else {
m_pMchMgr->SetWarning( 2459, "Warning in PocketingNT : Steps too far away from Raw") ;
continue ;
}
}
#if DEBUG_SFR_RAW
int _nPlane = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nLaySR, pSfrRaw->Clone()) ;
m_pGeomDB->SetMaterial( _nPlane, Color( .35, .46, .78, 1.)) ;
#endif
else
continue ; // svuotatura fuori dalla proiezione del grezzo, passo al prossimo step
// se regione risultante non vuota
if ( pSfrPock->IsValid() && pSfrPock->GetChunkCount() > 0) {
@@ -3031,84 +3060,102 @@ PocketingNT::ProcessPath( int nPathId, int nPvId, int nClId)
//----------------------------------------------------------------------------
bool
PocketingNT::CalcRegionElevation( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dRad, double dLen,
double& dElev)
PocketingNT::CalcRegionElevation( const ISurfFlatRegion* pSfr, const Vector3d& vtTool, double dDepth,
double dRad, double dLen, double& dElev)
{
// controllo dei parametri
if ( pSfr == nullptr || ! pSfr->IsValid())
return false ;
// inizializzo l'elevazione
dElev = 0 ;
dElev = 0. ;
// approssimo la curva con una polilinea che uso per creare il poligono equivalente
PolyLine PL ;
if ( ! pCompo->ApproxWithLines( LIN_TOL_RAW, ANG_TOL_MAX_DEG, ICurve::APL_SPECIAL, PL))
return false ;
Polygon3d pgFacet ;
if ( ! pgFacet.FromPolyLine( PL))
return false ;
// aggiungo l'affondamento
pgFacet.Translate( - dDepth * vtTool) ;
// recupero tutti i loop della regione
for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < pSfr->GetLoopCount( nC) ; ++ nL) {
// recupero la curva
PtrOwner<ICurveComposite> pCrvLoop( ConvertCurveToComposite( pSfr->GetLoop( nC, nL))) ;
if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid())
return false ;
// se isola inverto
if ( nL > 0)
pCrvLoop->Invert() ;
// approssimo la curva con una polilinea che uso per creare il poligono equivalente
PolyLine PL ;
if ( ! pCrvLoop->ApproxWithLines( LIN_TOL_RAW, ANG_TOL_MAX_DEG, ICurve::APL_SPECIAL, PL))
return false ;
Polygon3d pgFacet ;
if ( ! pgFacet.FromPolyLine( PL))
return false ;
// aggiungo l'affondamento
pgFacet.Translate( - dDepth * vtTool) ;
// inizializzo l'elevazione corrente
double dMyElev = 0. ;
// inizializzo elevazioni per ogni grezzo
INTDBLVECTOR vRawElev ;
// ciclo sui grezzi della fase
int nRawId = m_pMchMgr->GetFirstRawPart() ;
while ( nRawId != GDB_ID_NULL) {
// verifico che il grezzo compaia nella fase
if ( m_pMchMgr->VerifyRawPartPhase( nRawId, m_nPhase)) {
// recupero la trimesh del grezzo
int nStmId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
const ISurfTriMesh* pStm = GetSurfTriMesh( m_pGeomDB->GetGeoObj( nStmId)) ;
if ( pStm != nullptr) {
// recupero il riferimento della trimesh
Frame3d frStm ;
m_pGeomDB->GetGlobFrame( nStmId, frStm) ;
// porto il poligono in questo riferimento
Polygon3d pgFacetL = pgFacet ;
pgFacetL.ToLoc( frStm) ;
// calcolo l'elevazione
double dCurrElev ;
if ( ! PolygonElevationInClosedSurfTm( pgFacetL, *pStm, true, dCurrElev))
return false ;
if ( dCurrElev > EPS_SMALL)
vRawElev.emplace_back( nStmId, dCurrElev) ;
// inizializzo elevazioni per ogni grezzo
INTDBLVECTOR vRawElev ;
// ciclo sui grezzi della fase
int nRawId = m_pMchMgr->GetFirstRawPart() ;
while ( nRawId != GDB_ID_NULL) {
// verifico che il grezzo compaia nella fase
if ( m_pMchMgr->VerifyRawPartPhase( nRawId, m_nPhase)) {
// recupero la trimesh del grezzo
int nStmId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
const ISurfTriMesh* pStm = GetSurfTriMesh( m_pGeomDB->GetGeoObj( nStmId)) ;
if ( pStm != nullptr) {
// recupero il riferimento della trimesh
Frame3d frStm ;
m_pGeomDB->GetGlobFrame( nStmId, frStm) ;
// porto il poligono in questo riferimento
Polygon3d pgFacetL = pgFacet ;
pgFacetL.ToLoc( frStm) ;
// calcolo l'elevazione
double dCurrElev ;
if ( ! PolygonElevationInClosedSurfTm( pgFacetL, *pStm, true, dCurrElev))
return false ;
if ( dCurrElev > EPS_SMALL)
vRawElev.emplace_back( nStmId, dCurrElev) ;
}
}
// passo al grezzo successivo
nRawId = m_pMchMgr->GetNextRawPart( nRawId) ;
}
}
// passo al grezzo successivo
nRawId = m_pMchMgr->GetNextRawPart( nRawId) ;
}
// se trovate elevazioni
if ( ! vRawElev.empty()) {
// ordino il vettore secondo l'elevazione crescente
sort( vRawElev.begin(), vRawElev.end(), []( const INTDBL& a, const INTDBL& b)
{ return a.second < b.second ; }) ;
// box dell'insieme delle posizioni utensile all'inizioe
const double MAX_DIST_RAW = 200.0 ;
BBox3d b3Tool ;
pgFacet.GetLocalBBox( b3Tool) ;
b3Tool.Add( b3Tool.GetMin() + dLen * vtTool) ;
b3Tool.Add( b3Tool.GetMax() + dLen * vtTool) ;
if ( vtTool.IsX())
b3Tool.Expand( 0, dRad, dRad) ;
else if ( vtTool.IsY())
b3Tool.Expand( dRad, 0, dRad) ;
else if ( vtTool.IsZ())
b3Tool.Expand( dRad, dRad, 0) ;
else {
double dExpandX = dRad * sqrt( 1 - vtTool.x * vtTool.x) ;
double dExpandY = dRad * sqrt( 1 - vtTool.y * vtTool.y) ;
double dExpandZ = dRad * sqrt( 1 - vtTool.z * vtTool.z) ;
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
}
b3Tool.Expand( MAX_DIST_RAW) ;
// verifico la reale interferenza dell'utensile con i diversi grezzi
for ( int i = 0 ; i < int( vRawElev.size()) ; ++ i) {
// box del grezzo
BBox3d b3Raw ;
m_pGeomDB->GetGlobalBBox( vRawElev[i].first, b3Raw) ;
// confronto con il box dell'utensile nella posizione precedente
BBox3d b3CurrTool = b3Tool ;
b3CurrTool.Translate( dElev * vtTool) ;
if ( b3Raw.Overlaps( b3CurrTool))
dElev = vRawElev[i].second ;
// se trovate elevazioni
if ( ! vRawElev.empty()) {
// ordino il vettore secondo l'elevazione crescente
sort( vRawElev.begin(), vRawElev.end(), []( const INTDBL& a, const INTDBL& b)
{ return a.second < b.second ; }) ;
// box dell'insieme delle posizioni utensile all'inizioe
const double MAX_DIST_RAW = 200.0 ;
BBox3d b3Tool ;
pgFacet.GetLocalBBox( b3Tool) ;
b3Tool.Add( b3Tool.GetMin() + dLen * vtTool) ;
b3Tool.Add( b3Tool.GetMax() + dLen * vtTool) ;
if ( vtTool.IsX())
b3Tool.Expand( 0, dRad, dRad) ;
else if ( vtTool.IsY())
b3Tool.Expand( dRad, 0, dRad) ;
else if ( vtTool.IsZ())
b3Tool.Expand( dRad, dRad, 0) ;
else {
double dExpandX = dRad * sqrt( 1 - vtTool.x * vtTool.x) ;
double dExpandY = dRad * sqrt( 1 - vtTool.y * vtTool.y) ;
double dExpandZ = dRad * sqrt( 1 - vtTool.z * vtTool.z) ;
b3Tool.Expand( dExpandX, dExpandY, dExpandZ) ;
}
b3Tool.Expand( MAX_DIST_RAW) ;
// verifico la reale interferenza dell'utensile con i diversi grezzi
for ( int i = 0 ; i < int( vRawElev.size()) ; ++ i) {
// box del grezzo
BBox3d b3Raw ;
m_pGeomDB->GetGlobalBBox( vRawElev[i].first, b3Raw) ;
// confronto con il box dell'utensile nella posizione precedente
BBox3d b3CurrTool = b3Tool ;
b3CurrTool.Translate( dMyElev * vtTool) ;
if ( b3Raw.Overlaps( b3CurrTool))
dMyElev = vRawElev[i].second ;
}
}
dElev = max( dElev, dMyElev) ;
}
}
+3 -1
View File
@@ -109,6 +109,7 @@ class PocketingNT : public Machining
ISurfTriMesh* GetRaw( void) ;
ISurfTriMesh* GetExtrusionStm( const ISurfFlatRegion* pSfr, const Vector3d& vtExtr) ;
ISurfFlatRegion* GetSfrByStmIntersection( const IntersParPlanesSurfTm& IPPStm, double dDist, double dSmallOffs = 0) ;
ISurfFlatRegion* GetSfrRawProjection( const ISurfTriMesh* pStmRaw, const ISurfFlatRegion* pSfr, const Vector3d& vtTool) ;
bool ManageOpenEdges( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStmPart) ;
bool GetHomogeneousParts( const ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCrvs) const ;
bool ExtendOpenEdges( ISurfFlatRegion* pSfr, const ISurfTriMesh* pStm) ;
@@ -117,7 +118,8 @@ class PocketingNT : public Machining
const ISurfTriMesh* pStmRaw, const ISurfTriMesh* pStmExtrusion,
const IntersParPlanesSurfTm& IPPStm, bool& bSkipMaxDepth) ;
bool ProcessPath( int nPathId, int nPvId, int nClId) ;
bool CalcRegionElevation( const ICurveComposite* pCompo, const Vector3d& vtTool, double dDepth, double dRad, double dLen, double& dElev) ;
bool CalcRegionElevation( const ISurfFlatRegion* pSfr, const Vector3d& vtTool, double dDepth,
double dRad, double dLen, double& dElev) ;
bool VerifyPathFromBottom( const ICurveComposite* pCompo, const Vector3d& vtTool) ;
bool GeneratePocketingPv( int nPathId, const ICurveComposite* pCompo) ;
bool CalcLimitRegion( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrRaw, ISurfFlatRegion* pSfrLimit) ;