EgtExecutor :
- migliorata ExePackPartCluster con algoritmo scan-line.
This commit is contained in:
+250
-46
@@ -26,6 +26,7 @@
|
||||
#include "/EgtDev/Include/EGkSimpleCDSurfFrMove.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EMkMachiningGeoConst.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
@@ -160,8 +161,6 @@ ExeCreateOutRegion( int nParentId, int nOutCrvId)
|
||||
if ( ! pOutCrv->IsClosed())
|
||||
return false ;
|
||||
// la approssimo con linee
|
||||
const double LIN_TOL_STD = 0.1 ;
|
||||
const double ANG_TOL_STD_DEG = 15 ;
|
||||
PolyLine PL ;
|
||||
if ( ! pOutCrv->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return false ;
|
||||
@@ -194,8 +193,10 @@ ExeCreateOutRegion( int nParentId, int nOutCrvId)
|
||||
if ( ! distPC.GetParamAtMinDistPoint( 0, dU, nFlag) ||
|
||||
! pCompo->ChangeStartPoint( dU))
|
||||
return false ;
|
||||
// accorcio inizio
|
||||
// accorcio inizio e fine
|
||||
pCompo->TrimStartAtLen( 5 * EPS_SMALL) ;
|
||||
double dCrvLen ;
|
||||
pCompo->GetLength( dCrvLen) && pCompo->TrimEndAtLen( dCrvLen - 5 * EPS_SMALL) ;
|
||||
// creo curva della parte esterna
|
||||
Point3d ptStart ;
|
||||
pCompo->GetStartPoint( ptStart) ;
|
||||
@@ -203,11 +204,11 @@ ExeCreateOutRegion( int nParentId, int nOutCrvId)
|
||||
pCompo->GetEndPoint( ptEnd) ;
|
||||
PolyLine PL2 ;
|
||||
PL2.AddUPoint( 0, ptEnd) ;
|
||||
PL2.AddUPoint( 1, Point3d( ptEnd.x, b3Box.GetMax().y, b3Box.GetMin().z)) ;
|
||||
PL2.AddUPoint( 1, Point3d( b3Box.GetMax().x - 5 * EPS_SMALL, b3Box.GetMax().y, b3Box.GetMin().z)) ;
|
||||
PL2.AddUPoint( 2, Point3d( b3Box.GetMin().x, b3Box.GetMax().y, b3Box.GetMin().z)) ;
|
||||
PL2.AddUPoint( 3, b3Box.GetMin()) ;
|
||||
PL2.AddUPoint( 4, Point3d( b3Box.GetMax().x, b3Box.GetMin().y, b3Box.GetMin().z)) ;
|
||||
PL2.AddUPoint( 5, Point3d( b3Box.GetMax().x, ptStart.y, b3Box.GetMin().z)) ;
|
||||
PL2.AddUPoint( 5, Point3d( b3Box.GetMax().x, b3Box.GetMax().y - 5 * EPS_SMALL, b3Box.GetMin().z)) ;
|
||||
PL2.AddUPoint( 6, ptStart) ;
|
||||
// la converto in curva composita
|
||||
PtrOwner<ICurveComposite> pCompo2( CreateCurveComposite()) ;
|
||||
@@ -263,8 +264,6 @@ ExeCreateDamagedRegion( int nParentId, int nDmgCrvId)
|
||||
if ( pCrv == nullptr || ! pCrv->IsClosed())
|
||||
return false ;
|
||||
// la approssimo con linee
|
||||
const double LIN_TOL_STD = 0.1 ;
|
||||
const double ANG_TOL_STD_DEG = 15 ;
|
||||
PolyLine PL ;
|
||||
if ( ! pCrv->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
return GDB_ID_NULL ;
|
||||
@@ -345,6 +344,171 @@ UpdateToolOffset( IGeomDB* pGeomDB, const INTVECTOR& vIds, bool bReducedCut, dou
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class TrimLine {
|
||||
public :
|
||||
bool Init( IGeomDB* pGeomDB, const INTVECTOR& vTrueIds, bool bReducedCut) ;
|
||||
bool Verify( double dLineY, Intervals& inOk) ;
|
||||
|
||||
private :
|
||||
bool TrimLineWithRegion( const ICurveLine* pLine, int nRegId, bool bOn, Intervals& inOut) ;
|
||||
|
||||
private :
|
||||
IGeomDB* m_pGeomDB ;
|
||||
int m_nBoxId ;
|
||||
BBox3d m_b3Box ;
|
||||
INTVECTOR m_vDmgReg ;
|
||||
INTVECTOR m_vOthReg ;
|
||||
INTVECTOR m_vOthDwnReg ;
|
||||
INTVECTOR m_vOthCutReg ;
|
||||
INTVECTOR m_vOthDwnCutReg ;
|
||||
} ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
TrimLine::Init( IGeomDB* pGeomDB, const INTVECTOR& vTrueIds, bool bReducedCut)
|
||||
{
|
||||
// Assegno e verifico gestore DB geometrico
|
||||
m_pGeomDB = pGeomDB ;
|
||||
if ( m_pGeomDB == nullptr)
|
||||
return false ;
|
||||
|
||||
// Verifico se pezzi sotto la radice o pezzi in altro gruppo
|
||||
int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ;
|
||||
bool bInRoot = ( nGroupId == GDB_ID_ROOT) ;
|
||||
|
||||
// Recupero box della regione valida
|
||||
m_nBoxId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_SHEET_OUTREG) ;
|
||||
if ( m_nBoxId == GDB_ID_NULL || ! pGeomDB->GetGlobalBBox( m_nBoxId, m_b3Box))
|
||||
return false ;
|
||||
// Recupero le aree danneggiate
|
||||
int nId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_DAMAGED_REG) ;
|
||||
while ( nId != GDB_ID_NULL) {
|
||||
m_vDmgReg.emplace_back( nId) ;
|
||||
nId = pGeomDB->GetNextName( nId, NST_DAMAGED_REG) ;
|
||||
}
|
||||
// Determino le regioni di tutti gli altri pezzi compresi nella regione di interesse
|
||||
const int BBF_PART_MY_FLAG = BBF_ONLY_VISIBLE | BBF_IGNORE_TEXT | BBF_IGNORE_DIM ;
|
||||
int nId2 = ( bInRoot ? ExeGetFirstPart( true) : ExeGetFirstGroupInGroup( nGroupId)) ;
|
||||
while ( nId2 != GDB_ID_NULL) {
|
||||
if ( find( vTrueIds.begin(), vTrueIds.end(), nId2) == vTrueIds.end()) {
|
||||
BBox3d b3Part2 ;
|
||||
if ( pGeomDB->GetGlobalBBox( nId2, b3Part2, BBF_PART_MY_FLAG) &&
|
||||
m_b3Box.OverlapsXY( b3Part2)) {
|
||||
// recupero regione del pezzo
|
||||
int nRegId = GetFlatPartRegion( pGeomDB, nId2) ;
|
||||
if ( nRegId != GDB_ID_NULL)
|
||||
m_vOthReg.emplace_back( nRegId) ;
|
||||
else
|
||||
return false ;
|
||||
// recupero eventuale regione in basso del pezzo
|
||||
int nDwnRegId = GetFlatPartDownRegion( pGeomDB, nId2) ;
|
||||
m_vOthDwnReg.emplace_back( nDwnRegId) ;
|
||||
// recupero regioni dei tagli del pezzo
|
||||
if ( ! GetFlatPartCutRegions( pGeomDB, nId2, bReducedCut, m_vOthCutReg))
|
||||
return false ;
|
||||
// recupero regioni in basso dei tagli del pezzo
|
||||
GetFlatPartDownCutRegions( pGeomDB, nId2, bReducedCut, m_vOthDwnCutReg) ;
|
||||
}
|
||||
}
|
||||
nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
TrimLine::Verify( double dLineY, Intervals& inOk)
|
||||
{
|
||||
// Verifico se correttamente inizializzato
|
||||
if ( m_pGeomDB == nullptr || m_nBoxId == GDB_ID_NULL)
|
||||
return false ;
|
||||
|
||||
// Limito la linea alla regione valida
|
||||
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
||||
if ( IsNull( pLine) || ! pLine->Set( Point3d( m_b3Box.GetMin().x + 10 * EPS_SMALL, dLineY, 0),
|
||||
Point3d( m_b3Box.GetMax().x - 10 * EPS_SMALL, dLineY, 0)))
|
||||
return false ;
|
||||
if ( ! TrimLineWithRegion( pLine, m_nBoxId, true, inOk))
|
||||
return false ;
|
||||
|
||||
// Verifico con le eventuali aree danneggiate
|
||||
for ( int nDmgRegId : m_vDmgReg) {
|
||||
Intervals inOut ;
|
||||
if ( ! TrimLineWithRegion( pLine, nDmgRegId, true, inOut))
|
||||
return false ;
|
||||
inOk.Intersect( inOut) ;
|
||||
}
|
||||
|
||||
// Verifico con le regioni degli altri pezzi
|
||||
for ( int nOthRegId : m_vOthReg) {
|
||||
Intervals inOut ;
|
||||
if ( ! TrimLineWithRegion( pLine, nOthRegId, false, inOut))
|
||||
return false ;
|
||||
inOk.Intersect( inOut) ;
|
||||
}
|
||||
// e con le regioni dei tagli degli altri pezzi
|
||||
for ( int nOthCutRegId : m_vOthCutReg) {
|
||||
Intervals inOut ;
|
||||
if ( ! TrimLineWithRegion( pLine, nOthCutRegId, true, inOut))
|
||||
return false ;
|
||||
inOk.Intersect( inOut) ;
|
||||
}
|
||||
// Verifico con le regioni sotto degli altri pezzi
|
||||
for ( int nOthDwnRegId : m_vOthDwnReg) {
|
||||
if ( nOthDwnRegId != GDB_ID_NULL) {
|
||||
Intervals inOut ;
|
||||
if ( ! TrimLineWithRegion( pLine, nOthDwnRegId, false, inOut))
|
||||
return false ;
|
||||
inOk.Intersect( inOut) ;
|
||||
}
|
||||
}
|
||||
// e con le regioni sotto dei tagli degli altri pezzi
|
||||
for ( int nOthDwnCutRegId : m_vOthDwnCutReg) {
|
||||
if ( nOthDwnCutRegId != GDB_ID_NULL) {
|
||||
Intervals inOut ;
|
||||
if ( ! TrimLineWithRegion( pLine, nOthDwnCutRegId, true, inOut))
|
||||
return false ;
|
||||
inOk.Intersect( inOut) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
TrimLine::TrimLineWithRegion( const ICurveLine* pLine, int nRegId, bool bOn, Intervals& inOut)
|
||||
{
|
||||
// recupero la regione
|
||||
const ISurfFlatRegion* pSFR = GetSurfFlatRegion( m_pGeomDB->GetGeoObj( nRegId)) ;
|
||||
if ( pSFR == nullptr)
|
||||
return false ;
|
||||
// recupero il riferimento della regione
|
||||
Frame3d frSFR ;
|
||||
if ( ! m_pGeomDB->GetGlobFrame( nRegId, frSFR))
|
||||
return false ;
|
||||
// creo una copia della linea espressa nel riferimento della regione
|
||||
PtrOwner<ICurve>pLocCrv( pLine->Clone()) ;
|
||||
if ( IsNull( pLocCrv) || ! pLocCrv->ToLoc( frSFR))
|
||||
return false ;
|
||||
// calcolo la classificazione della curva rispetto alla regione
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ! pSFR->GetCurveClassification( *pLocCrv, ccClass))
|
||||
return false ;
|
||||
// determino gli intervalli di curva esterni alla regione
|
||||
inOut.Reset() ;
|
||||
for ( auto& ccOne : ccClass) {
|
||||
if ( ccOne.nClass == CRVC_OUT ||
|
||||
( bOn && ( ccOne.nClass == CRVC_ON_P || ccOne.nClass == CRVC_ON_M))) {
|
||||
double dXmin = pLine->GetStart().x + ccOne.dParS * ( pLine->GetEnd().x - pLine->GetStart().x) ;
|
||||
double dXmax = pLine->GetStart().x + ccOne.dParE * ( pLine->GetEnd().x - pLine->GetStart().x) ;
|
||||
inOut.Add( dXmin, dXmax) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
MyVerifyPartCluster( IGeomDB* pGeomDB, const INTVECTOR& vTrueIds, const BBox3d& b3Cluster, bool bReducedCut)
|
||||
@@ -687,48 +851,88 @@ ExePackPartCluster( const INTVECTOR& vIds, bool bReducedCut, bool bBottomUp)
|
||||
}
|
||||
double dRegClDimX = b3RegCluster.GetMax().x - b3RegCluster.GetMin().x ;
|
||||
double dRegClDimY = b3RegCluster.GetMax().y - b3RegCluster.GetMin().y ;
|
||||
|
||||
// Determino lo step per i tentativi di inserimento
|
||||
const double STEP_STD = 50 ;
|
||||
double dStepX = STEP_STD ;
|
||||
double dStepY = STEP_STD ;
|
||||
double dBoxDimX = b3Box.GetMax().x - b3Box.GetMin().x ;
|
||||
double dRegCluDimX = b3RegCluster.GetMax().x - b3RegCluster.GetMin().x ;
|
||||
if ( dBoxDimX - dRegCluDimX < 5 * STEP_STD)
|
||||
dStepX = STEP_STD / 5 ;
|
||||
double dBoxDimY = b3Box.GetMax().y - b3Box.GetMin().y ;
|
||||
double dRegCluDimY = b3RegCluster.GetMax().y - b3RegCluster.GetMin().y ;
|
||||
if ( dBoxDimY - dRegCluDimY < 5 * STEP_STD)
|
||||
dStepY = STEP_STD / 5 ;
|
||||
|
||||
// Procedo per tentativi
|
||||
bool bFit = false ;
|
||||
Point3d ptOrig = b3RegCluster.GetMin() ;
|
||||
Point3d ptLineStart = ( bBottomUp ? b3Box.GetMin() : b3Box.GetMax() - Vector3d(0, -dRegClDimY, 0)) ;
|
||||
Point3d ptIns = ptLineStart ;
|
||||
while ( true) {
|
||||
// porto nella posizione di prova
|
||||
Vector3d vtMove = ptIns - b3RegCluster.GetMin() ;
|
||||
vtMove.z = 0 ;
|
||||
for ( auto nId : vTrueIds)
|
||||
pGeomDB->TranslateGlob( nId, vtMove) ;
|
||||
b3Cluster.Translate( vtMove) ;
|
||||
b3RegCluster.Translate( vtMove) ;
|
||||
// verifico
|
||||
if ( MyVerifyPartCluster( pGeomDB, vTrueIds, b3Cluster, bReducedCut)) {
|
||||
bFit = true ;
|
||||
break ;
|
||||
}
|
||||
// nuova posizione di inserimento (incrementando X)
|
||||
ptIns += Vector3d( dStepX, 0, 0) ;
|
||||
// se esco dal box torno all'inizio e incremento Y
|
||||
if ( ! b3Box.EnclosesXY( ptIns + Vector3d( dRegClDimX, 0, 0))) {
|
||||
ptLineStart += Vector3d( 0, ( bBottomUp ? dStepY : - dStepY), 0) ;
|
||||
if ( ( ! b3Box.EnclosesXY( ptLineStart + Vector3d( 0, dRegClDimY, 0))))
|
||||
break ;
|
||||
ptIns = ptLineStart ;
|
||||
|
||||
// Determino punto più in basso a sinistra del cluster
|
||||
Point3d ptBL = b3RegCluster.GetMax() ;
|
||||
double dDimBottom = 0 ;
|
||||
for ( int nId : vTrueIds) {
|
||||
// recupero l'approssimazione lineare del contorno del pezzo ( in globale)
|
||||
PolyLine PL ;
|
||||
if ( GetFlatPartApproxContour( pGeomDB, nId, PL)) {
|
||||
// cerco il punto più in basso a sinistra
|
||||
Point3d ptP ;
|
||||
bool bFound = PL.GetFirstPoint( ptP) ;
|
||||
while ( bFound) {
|
||||
if ( abs( ptP.y - ptBL.y) < EPS_SMALL) {
|
||||
ptBL.x = min( ptBL.x, ptP.x) ;
|
||||
dDimBottom = max( dDimBottom, abs( ptBL.x - ptP.x)) ;
|
||||
}
|
||||
else if ( ptP.y < ptBL.y) {
|
||||
ptBL = ptP ;
|
||||
dDimBottom = 0 ;
|
||||
}
|
||||
bFound = PL.GetNextPoint( ptP) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
double dRegCLDeltaX = ptBL.x - ptOrig.x ;
|
||||
|
||||
// Assegno gli step per i tentativi di inserimento e la minima lughezza utile
|
||||
const double STEP_X = 20 ;
|
||||
const double STEP_Y = 20 ;
|
||||
double dMinRange = max( dDimBottom, 20.) ;
|
||||
|
||||
// Inserimento per tentativi con metodo delle linee
|
||||
TrimLine tlObj ;
|
||||
tlObj.Init( pGeomDB, vTrueIds, bReducedCut) ;
|
||||
bool bFit = false ;
|
||||
double dYmin = b3Box.GetMin().y ;
|
||||
double dYmax = b3Box.GetMax().y - dRegClDimY ;
|
||||
double dRangeY = dYmax - dYmin ;
|
||||
int nStepY = ( dRangeY > - EPS_SMALL ? int( ceil( dRangeY / STEP_Y)) : -1) ;
|
||||
double dStepY = ( nStepY > 0 ? ( dRangeY / nStepY) : 0) ;
|
||||
for ( int j = 0 ; j <= nStepY ; ++j) {
|
||||
double dLineY = ( bBottomUp ? dYmin + j * dStepY : dYmax - j * dStepY) ;
|
||||
// recupero la prossima linea valida
|
||||
Intervals inOk ;
|
||||
if ( tlObj.Verify( dLineY, inOk)) {
|
||||
// ciclo sugli intervalli validi della linea
|
||||
double dXmin, dXmax ;
|
||||
bool bOk = inOk.GetFirst( dXmin, dXmax) ;
|
||||
while ( bOk && ! bFit) {
|
||||
// limito minimo per box cluster a sinistra del box lastra
|
||||
dXmin = max( dXmin, b3Box.GetMin().x + dRegCLDeltaX) ;
|
||||
// limito massimo per min range e per box cluster a destra del box lastra
|
||||
dXmax = min( dXmax - dMinRange, b3Box.GetMax().x - ( dRegClDimX - dRegCLDeltaX)) ;
|
||||
// ciclo sui punti
|
||||
double dRangeX = dXmax - dXmin ;
|
||||
int nStepX = ( dRangeX > - EPS_SMALL ? int( ceil( dRangeX / STEP_X)) : -1) ;
|
||||
double dStepX = ( nStepX > 0 ? (dRangeX / nStepX) : 0) ;
|
||||
for ( int j = 0 ; j <= nStepX ; ++j) {
|
||||
// posizione di prova
|
||||
Point3d ptIns = Point3d( dXmin + j * dStepX, dLineY, b3Box.GetMin().z) ;
|
||||
// porto nella posizione di prova
|
||||
Vector3d vtMove = ptIns - ( b3RegCluster.GetMin() + Vector3d( dRegCLDeltaX, 0, 0)) ;
|
||||
vtMove.z = 0 ;
|
||||
for ( auto nId : vTrueIds)
|
||||
pGeomDB->TranslateGlob( nId, vtMove) ;
|
||||
b3Cluster.Translate( vtMove) ;
|
||||
b3RegCluster.Translate( vtMove) ;
|
||||
// verifico
|
||||
if ( MyVerifyPartCluster( pGeomDB, vTrueIds, b3Cluster, bReducedCut)) {
|
||||
bFit = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
// passo all'intervallo successivo sulla linea
|
||||
bOk = inOk.GetNext( dXmin, dXmax) ;
|
||||
}
|
||||
}
|
||||
// se trovato, esco
|
||||
if ( bFit)
|
||||
break ;
|
||||
}
|
||||
|
||||
// Se inserimento non riuscito
|
||||
if ( ! bFit) {
|
||||
|
||||
Reference in New Issue
Block a user