EgtExecutor :

- migliorata ExePackPartCluster con algoritmo scan-line.
This commit is contained in:
Dario Sassi
2016-09-03 06:22:31 +00:00
parent c4483ca0d6
commit 43bee5d375
3 changed files with 287 additions and 46 deletions
+250 -46
View File
@@ -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) {