5333f6415e
- adattamenti per modifiche libreria GeomKernel.
2234 lines
88 KiB
C++
2234 lines
88 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2015
|
|
//----------------------------------------------------------------------------
|
|
// File : EXE_NstPartNesting.cpp Data : 30.12.15 Versione : 1.6l5
|
|
// Contenuto : Funzioni Nesting di Pezzi per EXE.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 30.12.15 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "EXE.h"
|
|
#include "EXE_Const.h"
|
|
#include "EXE_Macro.h"
|
|
#include "EXE_Nst.h"
|
|
#include "/EgtDev/Include/EXeExecutor.h"
|
|
#include "/EgtDev/Include/EXeConst.h"
|
|
#include "/EgtDev/Include/EGkCurveLine.h"
|
|
#include "/EgtDev/Include/EGkCurveComposite.h"
|
|
#include "/EgtDev/Include/EgkDistPointCurve.h"
|
|
#include "/EgtDev/Include/EGkSfrCreate.h"
|
|
#include "/EgtDev/Include/EGkCAvSimpleSurfFrMove.h"
|
|
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
|
#include "/EgtDev/Include/EMkMachiningGeoConst.h"
|
|
#include "/EgtDev/Include/EGkIntervals.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
struct SCollInfoEx : public SCollInfo
|
|
{
|
|
int nIdM ; // identificativo della regione mobile
|
|
bool bIsCutM ; // flag di regione di pezzo o di taglio
|
|
int nIdF ; // identificativo della regione fissa
|
|
bool bIsCutF ; // flag di regione di pezzo o di taglio
|
|
// costruttori
|
|
SCollInfoEx() : SCollInfo(), nIdM( GDB_ID_NULL), bIsCutM( false),
|
|
nIdF( GDB_ID_NULL), bIsCutF( false) {}
|
|
SCollInfoEx( const SCollInfo& Sou) : SCollInfo( Sou), nIdM( GDB_ID_NULL), bIsCutM( false),
|
|
nIdF( GDB_ID_NULL), bIsCutF( false) {}
|
|
} ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static const double SPESS = 100 ;
|
|
static const int BBF_PART_MY_FLAG = BBF_ONLY_VISIBLE | BBF_IGNORE_TEXT | BBF_IGNORE_DIM ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool MyMovePartCluster( IGeomDB* pGeomDB, const INTVECTOR& vTrueIds, BBox3d b3Cluster, bool bReducedCut, Vector3d& vtMove) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
AdjustClusterObjIds( IGeomDB* pGeomDB, const INTVECTOR& vIds, INTVECTOR& vTrueIds, BBox3d& b3Cluster)
|
|
{
|
|
if ( pGeomDB == nullptr)
|
|
return false ;
|
|
// Risolvo eventuali riferimenti a oggetti selezionati
|
|
vTrueIds.clear() ;
|
|
vTrueIds.reserve( vIds.size()) ;
|
|
b3Cluster.Reset() ;
|
|
for ( auto nId : vIds) {
|
|
int nTrueId = (( nId != GDB_ID_SEL) ? nId : pGeomDB->GetFirstSelectedObj()) ;
|
|
while ( nTrueId != GDB_ID_NULL) {
|
|
BBox3d b3Part ;
|
|
if ( pGeomDB->GetGlobalBBox( nTrueId, b3Part, BBF_PART_MY_FLAG)) {
|
|
// inserisco l'identificativo nel vettore dei validi
|
|
vTrueIds.push_back( nTrueId) ;
|
|
// aggiorno il box del cluster
|
|
b3Cluster.Add( b3Part) ;
|
|
}
|
|
// passo al successivo
|
|
nTrueId = (( nId != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeCreateOutRegion( int nParentId, double dXmin, double dYmin, double dXmax, double dYmax, double dZ)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// Verifiche sui parametri
|
|
const double GAP = 5 * EPS_SMALL ;
|
|
if ( dXmax < dXmin + GAP + 2 * EPS_SMALL ||
|
|
dYmax < dYmin + GAP + 2 * EPS_SMALL)
|
|
return false ;
|
|
|
|
// se già esiste, posso uscire
|
|
int nBoxId = pGeomDB->GetFirstNameInGroup( nParentId, NST_SHEET_OUTREG) ;
|
|
if ( nBoxId != GDB_ID_NULL)
|
|
return true ;
|
|
|
|
// gap per garantire simile risoluzione tra spazio parametrico e spazio geometrico
|
|
double dGap = GAP * max( 1.0, ( 4 * ( dXmax - dXmin) + 4 * ( dYmax - dYmin)) * EPS_PARAM / EPS_SMALL) ;
|
|
|
|
// creo polilinea attorno al box (avvolta a serpente)
|
|
PolyLine PL ;
|
|
PL.AddUPoint( 0, Point3d( dXmax, dYmax - dGap, dZ)) ;
|
|
PL.AddUPoint( 1, Point3d( dXmax, dYmin, dZ)) ;
|
|
PL.AddUPoint( 2, Point3d( dXmin, dYmin, dZ)) ;
|
|
PL.AddUPoint( 3, Point3d( dXmin, dYmax, dZ)) ;
|
|
PL.AddUPoint( 4, Point3d( dXmax - dGap, dYmax, dZ)) ;
|
|
PL.AddUPoint( 5, Point3d( dXmax - dGap + SPESS, dYmax + SPESS, dZ)) ;
|
|
PL.AddUPoint( 6, Point3d( dXmin - SPESS, dYmax + SPESS, dZ)) ;
|
|
PL.AddUPoint( 7, Point3d( dXmin - SPESS, dYmin - SPESS, dZ)) ;
|
|
PL.AddUPoint( 8, Point3d( dXmax + SPESS, dYmin - SPESS, dZ)) ;
|
|
PL.AddUPoint( 9, Point3d( dXmax + SPESS, dYmax - dGap + SPESS, dZ)) ;
|
|
PL.Close() ;
|
|
// la converto in curva composita
|
|
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
|
|
if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL))
|
|
return false ;
|
|
// costruisco la regione piana
|
|
SurfFlatRegionByContours SfrCntr ;
|
|
SfrCntr.AddCurve( Release( pCompo)) ;
|
|
ISurfFlatRegion* pSfr = SfrCntr.GetSurf() ;
|
|
if ( pSfr == nullptr)
|
|
return false ;
|
|
// recupero il riferimento del gruppo di inserimento
|
|
Frame3d frLoc ;
|
|
if ( ! pGeomDB->GetGroupGlobFrame( nParentId, frLoc))
|
|
return false ;
|
|
// porto la regione nel riferimento
|
|
pSfr->ToLoc( frLoc) ;
|
|
// inserisco la superficie nel DB
|
|
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, pSfr) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
// assegno nome e la dichiaro di sistema e invisibile
|
|
pGeomDB->SetName( nId, NST_SHEET_OUTREG) ;
|
|
pGeomDB->SetLevel( nId, GDB_LV_SYSTEM) ;
|
|
pGeomDB->SetStatus( nId, GDB_ST_OFF) ;
|
|
pGeomDB->SetMaterial( nId, INVISIBLE) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeCreateOutRegion( int nParentId, int nOutCrvId)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// se già esiste, posso uscire
|
|
int nBoxId = pGeomDB->GetFirstNameInGroup( nParentId, NST_SHEET_OUTREG) ;
|
|
if ( nBoxId != GDB_ID_NULL)
|
|
return true ;
|
|
|
|
// recupero la curva
|
|
ICurve* pOutCrv = GetCurve( pGeomDB->GetGeoObj( nOutCrvId)) ;
|
|
if ( pOutCrv == nullptr)
|
|
return false ;
|
|
// verifico sia chiusa
|
|
if ( ! pOutCrv->IsClosed())
|
|
return false ;
|
|
// la approssimo con linee
|
|
PolyLine PL ;
|
|
if ( ! pOutCrv->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
|
return false ;
|
|
// porto la polilinea in globale
|
|
Frame3d frOutCrv ;
|
|
pGeomDB->GetGlobFrame( nOutCrvId, frOutCrv) ;
|
|
PL.ToGlob( frOutCrv) ;
|
|
// se antioraria la inverto
|
|
double dArea ;
|
|
if ( ! PL.GetAreaXY( dArea))
|
|
return false ;
|
|
if ( dArea > 0)
|
|
PL.Invert() ;
|
|
// la appiattisco sulla Z iniziale
|
|
Point3d ptP ;
|
|
PL.GetFirstPoint( ptP) ;
|
|
PL.Flatten( ptP.z) ;
|
|
// la converto in curva composita
|
|
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
|
|
if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL))
|
|
return false ;
|
|
// ne ricavo il bbox e lo ingrandisco
|
|
BBox3d b3Box ;
|
|
pCompo->GetLocalBBox( b3Box) ;
|
|
b3Box.Expand( SPESS, SPESS, 0) ;
|
|
// determino il punto più vicino al massimo del box e lo faccio diventare il nuovo inizio
|
|
int nFlag ;
|
|
double dU ;
|
|
DistPointCurve distPC( b3Box.GetMax(), *pCompo) ;
|
|
if ( ! distPC.GetParamAtMinDistPoint( 0, dU, nFlag) ||
|
|
! pCompo->ChangeStartPoint( dU))
|
|
return false ;
|
|
// 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) ;
|
|
Point3d ptEnd ;
|
|
pCompo->GetEndPoint( ptEnd) ;
|
|
PolyLine PL2 ;
|
|
PL2.AddUPoint( 0, ptEnd) ;
|
|
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, b3Box.GetMax().y - 5 * EPS_SMALL, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 6, ptStart) ;
|
|
// la converto in curva composita
|
|
PtrOwner<ICurveComposite> pCompo2( CreateCurveComposite()) ;
|
|
if ( IsNull( pCompo2) || ! pCompo2->FromPolyLine( PL2))
|
|
return false ;
|
|
// unisco le due curve composite
|
|
if ( ! pCompo->AddCurve( Release( pCompo2)))
|
|
return false ;
|
|
// costruisco la regione piana
|
|
SurfFlatRegionByContours SfrCntr ;
|
|
SfrCntr.AddCurve( Release( pCompo)) ;
|
|
ISurfFlatRegion* pSfr = SfrCntr.GetSurf() ;
|
|
if ( pSfr == nullptr)
|
|
return false ;
|
|
// recupero il riferimento del gruppo di inserimento
|
|
Frame3d frLoc ;
|
|
if ( ! pGeomDB->GetGroupGlobFrame( nParentId, frLoc))
|
|
return false ;
|
|
// porto la regione nel riferimento
|
|
pSfr->ToLoc( frLoc) ;
|
|
// inserisco la superficie nel DB
|
|
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, pSfr) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
// assegno nome e la dichiaro di sistema e invisibile
|
|
pGeomDB->SetName( nId, NST_SHEET_OUTREG) ;
|
|
pGeomDB->SetLevel( nId, GDB_LV_SYSTEM) ;
|
|
pGeomDB->SetStatus( nId, GDB_ST_OFF) ;
|
|
pGeomDB->SetMaterial( nId, INVISIBLE) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeCreateReferenceRegion( int nParentId, int nOutCrvId, bool bBottomUp)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// se già esiste, posso uscire
|
|
int nRegId = pGeomDB->GetFirstNameInGroup( nParentId, NST_REFERENCE_REG) ;
|
|
if ( nRegId != GDB_ID_NULL)
|
|
return true ;
|
|
|
|
// recupero la curva
|
|
ICurve* pOutCrv = GetCurve( pGeomDB->GetGeoObj( nOutCrvId)) ;
|
|
if ( pOutCrv == nullptr)
|
|
return false ;
|
|
// verifico sia chiusa
|
|
if ( ! pOutCrv->IsClosed())
|
|
return false ;
|
|
// la approssimo con linee
|
|
PolyLine PL ;
|
|
if ( ! pOutCrv->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
|
return false ;
|
|
// porto la polilinea in globale
|
|
Frame3d frOutCrv ;
|
|
pGeomDB->GetGlobFrame( nOutCrvId, frOutCrv) ;
|
|
PL.ToGlob( frOutCrv) ;
|
|
// se oraria la inverto
|
|
double dArea ;
|
|
if ( ! PL.GetAreaXY( dArea))
|
|
return false ;
|
|
if ( dArea < 0)
|
|
PL.Invert() ;
|
|
// la appiattisco sulla Z iniziale
|
|
Point3d ptP ;
|
|
PL.GetFirstPoint( ptP) ;
|
|
PL.Flatten( ptP.z) ;
|
|
// ne ricavo il bbox
|
|
BBox3d b3Box ;
|
|
PL.GetLocalBBox( b3Box) ;
|
|
// cerco i punti più vicini ai quattro vertici (0=BL, 1=BR, 2=TR, 3=TL)
|
|
double dU[4] = { -1, -1, -1, -1} ;
|
|
double dMinSqDist[4] = { SQ_INFINITO, SQ_INFINITO, SQ_INFINITO, SQ_INFINITO} ;
|
|
Point3d ptVert[4] ;
|
|
ptVert[0] = b3Box.GetMin() ;
|
|
ptVert[2] = b3Box.GetMax() ;
|
|
ptVert[1] = ptVert[0] ; ptVert[1].x = ptVert[2].x ;
|
|
ptVert[3] = ptVert[0] ; ptVert[3].y = ptVert[2].y ;
|
|
Point3d ptQ ; double dPar ;
|
|
bool bFound = PL.GetFirstUPoint( &dPar, &ptQ, true) ;
|
|
while ( bFound) {
|
|
for ( int i = 0 ; i < 4 ; ++ i) {
|
|
double dSqDist = SqDistXY( ptQ, ptVert[i]) ;
|
|
if ( dSqDist < dMinSqDist[i]) {
|
|
dMinSqDist[i] = dSqDist ;
|
|
dU[i] = dPar ;
|
|
}
|
|
}
|
|
bFound = PL.GetNextUPoint( &dPar, &ptQ, true) ;
|
|
}
|
|
for ( int i = 0 ; i < 4 ; ++ i) {
|
|
if ( dU[i] == - 1)
|
|
return false ;
|
|
if ( abs( dU[i] - dU[( i > 0 ? i-1 : 3)]) < EPS_SMALL)
|
|
return false ;
|
|
}
|
|
// calcolo i box dei tre lati di interesse
|
|
BBox3d b3Down ;
|
|
BBox3d b3Left ;
|
|
BBox3d b3Up ;
|
|
bFound = PL.GetFirstUPoint( &dPar, &ptQ, true) ;
|
|
while ( bFound) {
|
|
// per lato sotto ( 0 -> 1)
|
|
if ( ( dU[1] > dU[0] && dPar > dU[0] - EPS_ZERO && dPar < dU[1] + EPS_ZERO) ||
|
|
( dU[1] < dU[0] && ( dPar > dU[0] - EPS_ZERO || dPar < dU[1] + EPS_ZERO)))
|
|
b3Down.Add( ptQ) ;
|
|
// per lato sopra ( 2 -> 3)
|
|
if ( ( dU[3] > dU[2] && dPar > dU[2] - EPS_ZERO && dPar < dU[3] + EPS_ZERO) ||
|
|
( dU[3] < dU[2] && ( dPar > dU[2] - EPS_ZERO || dPar < dU[3] + EPS_ZERO)))
|
|
b3Up.Add( ptQ) ;
|
|
// per lato a sinistra ( 3 -> 0)
|
|
if ( ( dU[0] > dU[3] && dPar > dU[3] - EPS_ZERO && dPar < dU[0] + EPS_ZERO) ||
|
|
( dU[0] < dU[3] && ( dPar > dU[3] - EPS_ZERO || dPar < dU[0] + EPS_ZERO)))
|
|
b3Left.Add( ptQ) ;
|
|
// prossimo punto
|
|
bFound = PL.GetNextUPoint( &dPar, &ptQ, true) ;
|
|
}
|
|
// verifiche su box del lato a sinistra
|
|
const double MAX_WIDTH_SIDE = 400 ;
|
|
double dLeftDimX = b3Left.GetMax().x - b3Left.GetMin().x ;
|
|
if ( dLeftDimX > MAX_WIDTH_SIDE) {
|
|
b3Left.Translate( Vector3d( -dLeftDimX + 0.25 * MAX_WIDTH_SIDE, 0, 0)) ;
|
|
}
|
|
// costruisco la regione di riferimento
|
|
PolyLine PL2 ;
|
|
if ( bBottomUp) {
|
|
PL2.AddUPoint( 0, Point3d( b3Box.GetMin().x - SPESS, b3Box.GetMin().y - SPESS, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 1, Point3d( b3Box.GetMax().x + SPESS, b3Box.GetMin().y - SPESS, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 2, Point3d( b3Box.GetMax().x + SPESS, b3Down.GetMax().y, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 3, Point3d( b3Left.GetMax().x, b3Down.GetMax().y, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 4, Point3d( b3Left.GetMax().x, b3Box.GetMax().y + SPESS, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 5, Point3d( b3Box.GetMin().x - SPESS, b3Box.GetMax().y + SPESS, b3Box.GetMin().z)) ;
|
|
PL2.Close() ;
|
|
}
|
|
else {
|
|
PL2.AddUPoint( 0, Point3d( b3Box.GetMin().x - SPESS, b3Box.GetMin().y - SPESS, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 1, Point3d( b3Left.GetMax().x, b3Box.GetMin().y - SPESS, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 2, Point3d( b3Left.GetMax().x, b3Up.GetMin().y, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 3, Point3d( b3Box.GetMax().x + SPESS, b3Up.GetMin().y, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 4, Point3d( b3Box.GetMax().x + SPESS, b3Box.GetMax().y + SPESS, b3Box.GetMin().z)) ;
|
|
PL2.AddUPoint( 5, Point3d( b3Box.GetMin().x - SPESS, b3Box.GetMax().y + SPESS, b3Box.GetMin().z)) ;
|
|
PL2.Close() ;
|
|
}
|
|
// la converto in curva composita
|
|
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
|
|
if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL2))
|
|
return false ;
|
|
// costruisco la regione piana
|
|
SurfFlatRegionByContours SfrCntr ;
|
|
SfrCntr.AddCurve( Release( pCompo)) ;
|
|
ISurfFlatRegion* pSfr = SfrCntr.GetSurf() ;
|
|
if ( pSfr == nullptr)
|
|
return false ;
|
|
// recupero il riferimento del gruppo di inserimento
|
|
Frame3d frLoc ;
|
|
if ( ! pGeomDB->GetGroupGlobFrame( nParentId, frLoc))
|
|
return false ;
|
|
// porto la regione nel riferimento
|
|
pSfr->ToLoc( frLoc) ;
|
|
// inserisco la superficie nel DB
|
|
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, pSfr) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
// assegno nome e la dichiaro di sistema e invisibile
|
|
pGeomDB->SetName( nId, NST_REFERENCE_REG) ;
|
|
pGeomDB->SetLevel( nId, GDB_LV_SYSTEM) ;
|
|
pGeomDB->SetMaterial( nId, INVISIBLE) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeCreateDamagedRegion( int nParentId, int nDmgCrvId)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// verifico se esiste già la regione associata
|
|
int nRegId = pGeomDB->GetFirstNameInGroup( nParentId, NST_DAMAGED_REG) ;
|
|
while ( nRegId != GDB_ID_NULL) {
|
|
// recupero l'indice della curva di origine
|
|
int nOriId ;
|
|
if ( pGeomDB->GetInfo( nRegId, CRV_ORIG, nOriId) && nOriId == nDmgCrvId)
|
|
return true ;
|
|
// passo alla regione successiva
|
|
nRegId = pGeomDB->GetNextName( nRegId, NST_DAMAGED_REG) ;
|
|
}
|
|
|
|
// recupero la curva e verifico sia chiusa
|
|
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nDmgCrvId)) ;
|
|
if ( pCrv == nullptr || ! pCrv->IsClosed())
|
|
return false ;
|
|
// la approssimo con linee
|
|
PolyLine PL ;
|
|
if ( ! pCrv->ApproxWithLines( LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
|
return GDB_ID_NULL ;
|
|
// porto la polilinea in globale
|
|
Frame3d frDmgCrv ;
|
|
pGeomDB->GetGlobFrame( nDmgCrvId, frDmgCrv) ;
|
|
PL.ToGlob( frDmgCrv) ;
|
|
// se oraria la inverto
|
|
double dArea ;
|
|
if ( ! PL.GetAreaXY( dArea))
|
|
return false ;
|
|
if ( dArea < 0)
|
|
PL.Invert() ;
|
|
// la appiattisco sulla Z iniziale
|
|
Point3d ptP ;
|
|
PL.GetFirstPoint( ptP) ;
|
|
PL.Flatten( ptP.z) ;
|
|
// la converto in curva composita
|
|
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
|
|
if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL))
|
|
return false ;
|
|
// costruisco la regione piana
|
|
SurfFlatRegionByContours SfrCntr ;
|
|
SfrCntr.AddCurve( Release( pCompo)) ;
|
|
ISurfFlatRegion* pSfr = SfrCntr.GetSurf() ;
|
|
if ( pSfr == nullptr)
|
|
return false ;
|
|
// recupero il riferimento del gruppo di inserimento
|
|
Frame3d frLoc ;
|
|
if ( ! pGeomDB->GetGroupGlobFrame( nParentId, frLoc))
|
|
return false ;
|
|
// porto la regione nel riferimento
|
|
pSfr->ToLoc( frLoc) ;
|
|
// inserisco la superficie nel DB
|
|
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, pSfr) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
// assegno nome, id curva di origine e la dichiaro di sistema e invisibile
|
|
pGeomDB->SetName( nId, NST_DAMAGED_REG) ;
|
|
pGeomDB->SetInfo( nId, CRV_ORIG, nDmgCrvId) ;
|
|
pGeomDB->SetLevel( nId, GDB_LV_SYSTEM) ;
|
|
pGeomDB->SetMaterial( nId, INVISIBLE) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
SetPreviewStatus( IGeomDB* pGeomDB, const INTVECTOR& vIds, bool bShow)
|
|
{
|
|
for ( const auto nId : vIds) {
|
|
int nPvId = pGeomDB->GetFirstNameInGroup(nId, MCH_PV) ;
|
|
pGeomDB->SetStatus( nPvId, ( bShow ? GDB_ST_ON : GDB_ST_OFF)) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
UpdateToolOffset( IGeomDB* pGeomDB, const INTVECTOR& vIds, bool bReducedCut, double& dOffs)
|
|
{
|
|
for ( const auto nId : vIds) {
|
|
int nPvId = pGeomDB->GetFirstNameInGroup(nId, MCH_PV) ;
|
|
int nCutId = pGeomDB->GetFirstGroupInGroup( nPvId) ;
|
|
while ( nCutId != GDB_ID_NULL) {
|
|
int nPathId = pGeomDB->GetFirstGroupInGroup( nCutId) ;
|
|
while ( nPathId != GDB_ID_NULL) {
|
|
double dVal ;
|
|
if ( pGeomDB->GetInfo( nPathId, MCH_PV_KEY_WT, dVal) && dVal > dOffs)
|
|
dOffs = dVal ;
|
|
if ( ! bReducedCut && pGeomDB->GetInfo( nPathId, MCH_PV_KEY_DT, dVal) && dVal > dOffs)
|
|
dOffs = dVal ;
|
|
nPathId = pGeomDB->GetNextGroup( nPathId) ;
|
|
}
|
|
nCutId = pGeomDB->GetNextGroup( nCutId) ;
|
|
}
|
|
}
|
|
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 ;
|
|
int m_nRefReg ;
|
|
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 la regione di riferimento e verifico se disabilitata
|
|
m_nRefReg = pGeomDB->GetFirstNameInGroup( nGroupId, NST_REFERENCE_REG) ;
|
|
if ( pGeomDB->ExistsInfo( m_nRefReg, KEY_NST_OFF))
|
|
m_nRefReg = GDB_ID_NULL ;
|
|
// 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
|
|
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 la regione di riferimento
|
|
if ( m_nRefReg != GDB_ID_NULL) {
|
|
Intervals inOut ;
|
|
if ( ! TrimLineWithRegion( pLine, m_nRefReg, true, inOut))
|
|
return false ;
|
|
inOk.Intersect( inOut) ;
|
|
}
|
|
|
|
// 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, EPS_SMALL, 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)
|
|
{
|
|
// Determino le regioni dei pezzi
|
|
INTVECTOR vReg ;
|
|
INTVECTOR vUpReg ;
|
|
INTVECTOR vDwnReg ;
|
|
INTVECTOR vCutReg ;
|
|
INTVECTOR vDwnCutReg ;
|
|
BBox3d b3RegCluster ;
|
|
for ( int nId : vTrueIds) {
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nId) ;
|
|
BBox3d b3Reg ;
|
|
if ( pGeomDB->GetGlobalBBox( nRegId, b3Reg, BBF_PART_MY_FLAG)) {
|
|
vReg.emplace_back( nRegId) ;
|
|
b3RegCluster.Add( b3Reg) ;
|
|
}
|
|
else
|
|
return false ;
|
|
// recupero eventuale regione in alto del pezzo
|
|
int nUpRegId = GetFlatPartUpRegion( pGeomDB, nId) ;
|
|
vUpReg.emplace_back( nUpRegId) ;
|
|
// recupero eventuale regione in basso del pezzo
|
|
int nDwnRegId = GetFlatPartDownRegion( pGeomDB, nId) ;
|
|
vDwnReg.emplace_back( nDwnRegId) ;
|
|
// recupero regioni dei tagli del pezzo
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nId, bReducedCut, vCutReg))
|
|
return false ;
|
|
// recupero regioni in basso dei tagli del pezzo
|
|
GetFlatPartDownCutRegions( pGeomDB, nId, bReducedCut, vDwnCutReg) ;
|
|
}
|
|
|
|
// Verifico se pezzi sotto la radice o pezzi in altro gruppo
|
|
int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ;
|
|
bool bInRoot = ( nGroupId == GDB_ID_ROOT) ;
|
|
|
|
// Verifico di essere nella regione valida
|
|
int nBoxId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_SHEET_OUTREG) ;
|
|
BBox3d b3Region ;
|
|
if ( nBoxId == GDB_ID_NULL || ! pGeomDB->GetGlobalBBox( nBoxId, b3Region))
|
|
return false ;
|
|
// box delle regioni dei pezzi rispetto al box dell'esterno
|
|
if ( ! b3Region.EnclosesXY( b3RegCluster))
|
|
return false ;
|
|
// regioni dei pezzi rispetto alla regione dell'esterno
|
|
for ( int nRegId : vReg) {
|
|
if ( ExeSurfFrChunkSimpleClassify( nRegId, 0, nBoxId, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
for ( int nDwnRegId : vDwnReg) {
|
|
if ( nDwnRegId != GDB_ID_NULL &&
|
|
ExeSurfFrChunkSimpleClassify( nDwnRegId, 0, nBoxId, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
|
|
// Verifico con l'eventuale regione di riferimento
|
|
// recupero la regione
|
|
int nRefReg = pGeomDB->GetFirstNameInGroup( nGroupId, NST_REFERENCE_REG) ;
|
|
if ( pGeomDB->ExistsInfo( nRefReg, KEY_NST_OFF))
|
|
nRefReg = GDB_ID_NULL ;
|
|
if ( nRefReg != GDB_ID_NULL) {
|
|
// regioni dei pezzi rispetto alla regione di riferimento
|
|
for ( int nRegId : vReg) {
|
|
if ( ExeSurfFrChunkSimpleClassify( nRegId, 0, nRefReg, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
for ( int nDwnRegId : vDwnReg) {
|
|
if ( nDwnRegId != GDB_ID_NULL) {
|
|
if ( ExeSurfFrChunkSimpleClassify( nDwnRegId, 0, nRefReg, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Verifico con le eventuali aree danneggiate
|
|
// recupero le aree
|
|
INTVECTOR vDmgReg ;
|
|
int nId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_DAMAGED_REG) ;
|
|
if ( nId != GDB_ID_NULL) {
|
|
while ( nId != GDB_ID_NULL) {
|
|
vDmgReg.emplace_back( nId) ;
|
|
nId = pGeomDB->GetNextName( nId, NST_DAMAGED_REG) ;
|
|
}
|
|
// regioni dei pezzi rispetto alle regioni delle aree danneggiate
|
|
for ( int nRegId : vReg) {
|
|
for ( int nDmgRegId : vDmgReg) {
|
|
if ( ExeSurfFrChunkSimpleClassify( nRegId, 0, nDmgRegId, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
}
|
|
for ( int nDwnRegId : vDwnReg) {
|
|
if ( nDwnRegId != GDB_ID_NULL) {
|
|
for ( int nDmgRegId : vDmgReg) {
|
|
if ( ExeSurfFrChunkSimpleClassify( nDwnRegId, 0, nDmgRegId, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Determino le regioni di tutti gli altri pezzi compresi nella regione di interesse
|
|
INTVECTOR vOthReg ;
|
|
INTVECTOR vOthUpReg ;
|
|
INTVECTOR vOthDwnReg ;
|
|
INTVECTOR vOthCutReg ;
|
|
INTVECTOR vOthDwnCutReg ;
|
|
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) &&
|
|
b3Cluster.OverlapsXY( b3Part2)) {
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nId2) ;
|
|
if ( nRegId != GDB_ID_NULL)
|
|
vOthReg.emplace_back( nRegId) ;
|
|
else
|
|
return false ;
|
|
// recupero eventuale regione in alto del pezzo
|
|
int nUpRegId = GetFlatPartUpRegion( pGeomDB, nId2) ;
|
|
vOthUpReg.emplace_back( nUpRegId) ;
|
|
// recupero eventuale regione in basso del pezzo
|
|
int nDwnRegId = GetFlatPartDownRegion( pGeomDB, nId2) ;
|
|
vOthDwnReg.emplace_back( nDwnRegId) ;
|
|
// recupero regioni dei tagli del pezzo
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nId2, bReducedCut, vOthCutReg))
|
|
return false ;
|
|
// recupero regioni in basso dei tagli del pezzo
|
|
GetFlatPartDownCutRegions( pGeomDB, nId2, bReducedCut, vOthDwnCutReg) ;
|
|
}
|
|
}
|
|
nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ;
|
|
}
|
|
|
|
// Eseguo verifiche
|
|
// regioni dei pezzi
|
|
for ( size_t i = 0 ; i < vReg.size() ; ++ i) {
|
|
// verifico con le regioni degli altri pezzi (sempre regioni standard)
|
|
for ( int nOthRegId : vOthReg) {
|
|
if ( ExeSurfFrChunkSimpleClassify( vReg[i], 0, nOthRegId, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
// e con le regioni dei tagli degli altri pezzi (se esistono le regioni up devo usarle)
|
|
int nRegUpId = ((vUpReg[i] == GDB_ID_NULL) ? vReg[i] : vUpReg[i]) ;
|
|
for ( int nOthCutRegId : vOthCutReg) {
|
|
if ( ExeSurfFrChunkSimpleClassify( nRegUpId, 0, nOthCutRegId, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
}
|
|
// regioni sotto dei pezzi
|
|
for ( size_t i = 0 ; i < vDwnReg.size() ; ++ i) {
|
|
// verifico con le regioni sotto degli altri pezzi
|
|
for ( size_t j = 0 ; j < vOthDwnReg.size() ; ++ j) {
|
|
if ( vDwnReg[i] != GDB_ID_NULL || vOthDwnReg[j] != GDB_ID_NULL) {
|
|
int nDwnRegId = ( vDwnReg[i] != GDB_ID_NULL ? vDwnReg[i] : vReg[i]) ;
|
|
int nOthDwnRegId = ( vOthDwnReg[j] != GDB_ID_NULL ? vOthDwnReg[j] : vOthReg[j]) ;
|
|
if ( ExeSurfFrChunkSimpleClassify( nDwnRegId, 0, nOthDwnRegId, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
}
|
|
// e con le regioni sotto dei tagli degli altri pezzi
|
|
for ( size_t j = 0 ; j < vOthDwnCutReg.size() ; ++ j) {
|
|
if ( vDwnReg[i] != GDB_ID_NULL || vOthDwnCutReg[j] != GDB_ID_NULL) {
|
|
int nDwnRegId = ( vDwnReg[i] != GDB_ID_NULL ? vDwnReg[i] : vReg[i]) ;
|
|
int nOthDwnCutRegId = ( vOthDwnCutReg[j] != GDB_ID_NULL ? vOthDwnCutReg[j] : vOthCutReg[j]) ;
|
|
if ( ExeSurfFrChunkSimpleClassify( nDwnRegId, 0, nOthDwnCutRegId, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
// regioni delle lavorazioni dei pezzi
|
|
for ( int nCutRegId : vCutReg) {
|
|
// le confronto con le regioni degli altri pezzi
|
|
for ( size_t j = 0 ; j < vOthReg.size() ; ++ j) {
|
|
int nOthUpRegId = (( vOthUpReg[j] == GDB_ID_NULL) ? vOthReg[j] : vOthUpReg[j]) ;
|
|
if ( ExeSurfFrChunkSimpleClassify( nCutRegId, 0, nOthUpRegId, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
}
|
|
// regioni sotto delle lavorazioni dei pezzi
|
|
for ( size_t i = 0 ; i < vDwnCutReg.size() ; ++ i) {
|
|
// le confronto con le regioni sotto degli altri pezzi
|
|
for ( size_t j = 0 ; j < vOthDwnReg.size() ; ++ j) {
|
|
if ( vDwnCutReg[i] != GDB_ID_NULL || vOthDwnReg[j] != GDB_ID_NULL) {
|
|
int nDwnCutRegId = ( vDwnCutReg[i] != GDB_ID_NULL ? vDwnCutReg[i] : vCutReg[i]) ;
|
|
int nOthDwnRegId = ( vOthDwnReg[j] != GDB_ID_NULL ? vOthDwnReg[j] : vOthReg[j]) ;
|
|
if ( ExeSurfFrChunkSimpleClassify( nDwnCutRegId, 0, nOthDwnRegId, 0) != REGC_OUT)
|
|
return false ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeVerifyPartCluster( const INTVECTOR& vIds, bool bReducedCut)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// Risolvo identificativi a selezionati
|
|
INTVECTOR vTrueIds ;
|
|
BBox3d b3Cluster ;
|
|
AdjustClusterObjIds( pGeomDB, vIds, vTrueIds, b3Cluster) ;
|
|
if ( vTrueIds.empty())
|
|
return true ;
|
|
|
|
// Eseguo verifica
|
|
return MyVerifyPartCluster( pGeomDB, vTrueIds, b3Cluster, bReducedCut) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
MyPackPartCluster( const INTVECTOR& vTrueIds, bool bReducedCut,
|
|
double dXmin, double dYmin, double dXmax, double dYmax, bool bBottomUp)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// Verifico se pezzi sotto la radice o pezzi in altro gruppo
|
|
int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ;
|
|
bool bInRoot = ( nGroupId == GDB_ID_ROOT) ;
|
|
|
|
// Box della regione di interesse
|
|
BBox3d b3Region( dXmin, dYmin, 0, dXmax, dYmax, 0) ;
|
|
|
|
// Determino tutti gli altri pezzi compresi nella regione di interesse
|
|
INTVECTOR vOtherIds ;
|
|
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) &&
|
|
b3Region.OverlapsXY( b3Part2)) {
|
|
vOtherIds.emplace_back( nId2) ;
|
|
}
|
|
}
|
|
nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ;
|
|
}
|
|
|
|
// nascondo preview delle lavorazioni
|
|
SetPreviewStatus( pGeomDB, vTrueIds, false) ;
|
|
SetPreviewStatus( pGeomDB, vOtherIds, false) ;
|
|
|
|
// calcolo offset per ingombro lavorazioni
|
|
double dOffs = 0 ;
|
|
UpdateToolOffset( pGeomDB, vTrueIds, bReducedCut, dOffs) ;
|
|
UpdateToolOffset( pGeomDB, vOtherIds, bReducedCut, dOffs) ;
|
|
|
|
// eseguo primo movimento come box
|
|
bool bOk = ExePackBoxCluster( vTrueIds, dXmin, dYmin, dXmax, dYmax, dOffs, bBottomUp) ;
|
|
|
|
// ripristino preview delle lavorazioni
|
|
SetPreviewStatus( pGeomDB, vTrueIds, true) ;
|
|
SetPreviewStatus( pGeomDB, vOtherIds, true) ;
|
|
|
|
// verifica
|
|
bOk = bOk && ExeVerifyPartCluster( vTrueIds, bReducedCut) ;
|
|
|
|
// se inserimento di massima riuscito, provo a migliorare
|
|
if ( bOk) {
|
|
const double BIG_MOVE = 1000 ;
|
|
Vector3d vtMoveY = ( bBottomUp ? - 1 : 1) * BIG_MOVE * Y_AX ;
|
|
ExeMovePartCluster( vTrueIds, bReducedCut, vtMoveY) ;
|
|
Vector3d vtMoveX = - BIG_MOVE * X_AX ;
|
|
ExeMovePartCluster( vTrueIds, bReducedCut, vtMoveX) ;
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExePackPartClusterInRectangle( const INTVECTOR& vIds, bool bReducedCut, bool bBottomUp)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// Risolvo identificativi a selezionati
|
|
INTVECTOR vTrueIds ;
|
|
BBox3d b3Cluster ;
|
|
AdjustClusterObjIds( pGeomDB, vIds, vTrueIds, b3Cluster) ;
|
|
if ( vTrueIds.empty())
|
|
return true ;
|
|
|
|
// Recupero gruppo dei pezzi
|
|
int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ;
|
|
|
|
// Calcolo il box interno della regione valida
|
|
int nBoxId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_SHEET_OUTREG) ;
|
|
BBox3d b3Box ;
|
|
if ( ! pGeomDB->GetGlobalBBox( nBoxId, b3Box))
|
|
return false ;
|
|
b3Box.Expand( - SPESS, - SPESS, 0) ;
|
|
if ( b3Box.IsEmpty())
|
|
return false ;
|
|
double dXmin = b3Box.GetMin().x ;
|
|
double dYmin = b3Box.GetMin().y ;
|
|
double dXmax = b3Box.GetMax().x ;
|
|
double dYmax = b3Box.GetMax().y ;
|
|
|
|
// se con tagli ridotti
|
|
if ( bReducedCut) {
|
|
return MyPackPartCluster( vTrueIds, true, dXmin, dYmin, dXmax, dYmax, bBottomUp) ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
// provo con tagli ridotti
|
|
if ( ! MyPackPartCluster( vTrueIds, true, dXmin, dYmin, dXmax, dYmax, bBottomUp))
|
|
return false ;
|
|
// se posizione valida
|
|
if ( ExeVerifyPartCluster( vTrueIds, false)) {
|
|
return true ;
|
|
}
|
|
// altrimenti, riprovo con tagli standard
|
|
else {
|
|
return MyPackPartCluster( vTrueIds, false, dXmin, dYmin, dXmax, dYmax, bBottomUp) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExePackPartCluster( const INTVECTOR& vIds, bool bReducedCut, bool bBottomUp)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// Risolvo identificativi a selezionati
|
|
INTVECTOR vTrueIds ;
|
|
BBox3d b3Cluster ;
|
|
AdjustClusterObjIds( pGeomDB, vIds, vTrueIds, b3Cluster) ;
|
|
if ( vTrueIds.empty())
|
|
return true ;
|
|
|
|
// Recupero gruppo dei pezzi
|
|
int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ;
|
|
|
|
// Calcolo il box di ingombro interno della regione valida
|
|
int nBoxId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_SHEET_OUTREG) ;
|
|
BBox3d b3Box ;
|
|
if ( ! pGeomDB->GetGlobalBBox( nBoxId, b3Box))
|
|
return false ;
|
|
b3Box.Expand( - SPESS, - SPESS, 0) ;
|
|
if ( b3Box.IsEmpty())
|
|
return false ;
|
|
|
|
// Calcolo il box di ingombro delle regioni dei pezzi
|
|
BBox3d b3RegCluster ;
|
|
for ( int nId : vTrueIds) {
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nId) ;
|
|
BBox3d b3Reg ;
|
|
if ( pGeomDB->GetGlobalBBox( nRegId, b3Reg, BBF_PART_MY_FLAG)) {
|
|
b3RegCluster.Add( b3Reg) ;
|
|
}
|
|
else
|
|
return false ;
|
|
}
|
|
double dRegClDimX = b3RegCluster.GetMax().x - b3RegCluster.GetMin().x ;
|
|
double dRegClDimY = b3RegCluster.GetMax().y - b3RegCluster.GetMin().y ;
|
|
Point3d ptOrig = b3RegCluster.GetMin() ;
|
|
|
|
// 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) {
|
|
int k = ( j > 1 ? j : 1 - j) ;
|
|
// posizione di prova
|
|
Point3d ptIns = Point3d( dXmin + k * 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) {
|
|
// riporto nella posizione originale
|
|
Vector3d vtMove = ptOrig - b3RegCluster.GetMin() ;
|
|
for ( auto nId : vTrueIds)
|
|
pGeomDB->TranslateGlob( nId, vtMove) ;
|
|
return false ;
|
|
}
|
|
|
|
// Inserimento riuscito, provo a migliorare
|
|
const double BIG_MOVE = 1000 ;
|
|
Vector3d vtMoveY = ( bBottomUp ? - 1 : 1) * BIG_MOVE * Y_AX ;
|
|
MyMovePartCluster( pGeomDB, vTrueIds, b3Cluster, bReducedCut, vtMoveY) ;
|
|
Vector3d vtMoveX = - BIG_MOVE * X_AX ;
|
|
MyMovePartCluster( pGeomDB, vTrueIds, b3Cluster, bReducedCut, vtMoveX) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static SCollInfoEx s_scInfo ;
|
|
static SCollInfoEx s_scInfoSaved ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static double
|
|
UpdateCollId( double dLen, double dPrevLen, int nId1, int nId2, bool bIsCut1, bool bIsCut2, const SCollInfo& scInfoCurr)
|
|
{
|
|
if ( abs( dLen - dPrevLen) < EPS_SMALL) {
|
|
if ( scInfoCurr.nType == SCI_PNT_LINE || scInfoCurr.nType == SCI_LINE_LINE) {
|
|
s_scInfo = scInfoCurr ;
|
|
s_scInfo.nIdM = nId1 ;
|
|
s_scInfo.nIdF = nId2 ;
|
|
s_scInfo.bIsCutM = bIsCut1 ;
|
|
s_scInfo.bIsCutF = bIsCut2 ;
|
|
}
|
|
return dPrevLen ;
|
|
}
|
|
else if ( dLen < dPrevLen) {
|
|
s_scInfo = scInfoCurr ;
|
|
s_scInfo.nIdM = nId1 ;
|
|
s_scInfo.nIdF = nId2 ;
|
|
s_scInfo.bIsCutM = bIsCut1 ;
|
|
s_scInfo.bIsCutF = bIsCut2 ;
|
|
return dLen ;
|
|
}
|
|
else
|
|
return dPrevLen ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
MySurfFrMoveSimpleNoCollision( int nId1, int nId2, const Vector3d& vtDir, double& dLen, SCollInfo& scInfo)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
|
|
// recupero la prima superficie FlatRegion
|
|
ISurfFlatRegion* pSfr1 = GetSurfFlatRegion( pGeomDB->GetGeoObj( nId1)) ;
|
|
bool bOk = ( pSfr1 != nullptr) ;
|
|
// recupero il riferimento della superficie
|
|
Frame3d frSurf1 ;
|
|
bOk = bOk && pGeomDB->GetGlobFrame( nId1, frSurf1) ;
|
|
// recupero la seconda superficie FlatRegion
|
|
const ISurfFlatRegion* pSfr2 = GetSurfFlatRegion( pGeomDB->GetGeoObj( nId2)) ;
|
|
bOk = bOk && ( pSfr2 != nullptr) ;
|
|
// recupero il riferimento della superficie
|
|
Frame3d frSurf2 ;
|
|
bOk = bOk && pGeomDB->GetGlobFrame( nId2, frSurf2) ;
|
|
// se riferimenti diversi, porto una copia della seconda nel riferimento della prima
|
|
const ISurfFlatRegion* pSfr2L = pSfr2 ;
|
|
PtrOwner<ISurfFlatRegion> pTmp ;
|
|
if ( ! AreSameFrame( frSurf1, frSurf2)) {
|
|
pTmp.Set( pSfr2->Clone()) ;
|
|
bOk = bOk && ! IsNull( pTmp) ;
|
|
bOk = bOk && pTmp->LocToLoc( frSurf2, frSurf1) ;
|
|
pSfr2L = pTmp ;
|
|
}
|
|
// porto in locale alla prima superficie il versore di movimento
|
|
Vector3d vtDirL = vtDir ;
|
|
vtDirL.ToLoc( frSurf1) ;
|
|
// calcolo massima lunghezza di traslazione della prima regione senza semplice collisione con la seconda
|
|
CAvSimpleSurfFrMove ScdSfrMove( *pSfr1, *pSfr2L) ;
|
|
bOk = bOk && ScdSfrMove.Translate( vtDirL, dLen) ;
|
|
if ( bOk) {
|
|
scInfo = ScdSfrMove.GetSCollInfo() ;
|
|
if ( scInfo.nType != SCI_NONE) {
|
|
scInfo.ptP1.ToGlob( frSurf1) ;
|
|
scInfo.vtDirM.ToGlob( frSurf1) ;
|
|
scInfo.vtDirF.ToGlob( frSurf1) ;
|
|
}
|
|
if ( scInfo.nType == SCI_LINE_LINE)
|
|
scInfo.ptP2.ToGlob( frSurf1) ;
|
|
}
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
MyMovePartCluster( IGeomDB* pGeomDB, const INTVECTOR& vTrueIds, BBox3d b3Cluster, bool bReducedCut, Vector3d& vtMove)
|
|
{
|
|
// Reset info di collisione
|
|
s_scInfo.nType = SCI_NONE ;
|
|
|
|
// Vettore movimento nel piano XY globale
|
|
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ;
|
|
vtMove = V_NULL ;
|
|
if ( vtMoveXY.IsSmall())
|
|
return true ;
|
|
|
|
// Verifico se pezzi sotto la radice o pezzi in altro gruppo
|
|
int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ;
|
|
bool bInRoot = ( nGroupId == GDB_ID_ROOT) ;
|
|
|
|
// Recupero regione di interesse
|
|
int nBoxId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_SHEET_OUTREG) ;
|
|
BBox3d b3Region ;
|
|
if ( nBoxId == GDB_ID_NULL || ! pGeomDB->GetGlobalBBox( nBoxId, b3Region))
|
|
return false ;
|
|
|
|
// Recupero eventuale regione di riferimento
|
|
int nRefReg = pGeomDB->GetFirstNameInGroup( nGroupId, NST_REFERENCE_REG) ;
|
|
if ( pGeomDB->ExistsInfo( nRefReg, KEY_NST_OFF))
|
|
nRefReg = GDB_ID_NULL ;
|
|
|
|
// Recupero le eventuali aree danneggiate
|
|
INTVECTOR vDmgReg ;
|
|
int nId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_DAMAGED_REG) ;
|
|
while ( nId != GDB_ID_NULL) {
|
|
vDmgReg.emplace_back( nId) ;
|
|
nId = pGeomDB->GetNextName( nId, NST_DAMAGED_REG) ;
|
|
}
|
|
|
|
// Determino le regioni di tutti gli altri pezzi compresi nella regione di interesse
|
|
INTVECTOR vOthReg ;
|
|
INTVECTOR vOthUpReg ;
|
|
INTVECTOR vOthDwnReg ;
|
|
INTVECTOR vOthCutReg ;
|
|
INTVECTOR vOthDwnCutReg ;
|
|
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) &&
|
|
b3Region.OverlapsXY( b3Part2)) {
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nId2) ;
|
|
if ( nRegId != GDB_ID_NULL)
|
|
vOthReg.emplace_back( nRegId) ;
|
|
else
|
|
return false ;
|
|
// recupero eventuale regione in alto del pezzo
|
|
int nUpRegId = GetFlatPartUpRegion( pGeomDB, nId2) ;
|
|
vOthUpReg.emplace_back( nUpRegId) ;
|
|
// recupero eventuale regione in basso del pezzo
|
|
int nDwnRegId = GetFlatPartDownRegion( pGeomDB, nId2) ;
|
|
vOthDwnReg.emplace_back( nDwnRegId) ;
|
|
// recupero regioni dei tagli del pezzo
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nId2, bReducedCut, vOthCutReg))
|
|
return false ;
|
|
// recupero regioni in basso dei tagli del pezzo
|
|
GetFlatPartDownCutRegions( pGeomDB, nId2, bReducedCut, vOthDwnCutReg) ;
|
|
}
|
|
}
|
|
nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ;
|
|
}
|
|
|
|
// Verifico movimento dei pezzi del cluster rispetto al contorno, alle aree danneggiate e agli altri pezzi
|
|
bool bOk = true ;
|
|
double dLen = vtMoveXY.Len() ;
|
|
double dPrevLen = dLen ;
|
|
Vector3d vtDir = ( dLen > EPS_SMALL ? vtMoveXY / dLen : V_NULL) ;
|
|
for ( auto nTrueId : vTrueIds) {
|
|
// info di collisione correnti
|
|
SCollInfo scInfoCurr ;
|
|
// -----------------------------------------
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nTrueId) ;
|
|
if ( nRegId == GDB_ID_NULL) {
|
|
bOk = false ;
|
|
break ;
|
|
}
|
|
// la confronto con il box
|
|
MySurfFrMoveSimpleNoCollision( nRegId, nBoxId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nRegId, nBoxId, false, false, scInfoCurr) ;
|
|
// la confronto con la regione di riferimento
|
|
if ( nRefReg != GDB_ID_NULL) {
|
|
MySurfFrMoveSimpleNoCollision( nRegId, nRefReg, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nRegId, nRefReg, false, false, scInfoCurr) ;
|
|
}
|
|
// la confronto con le aree danneggiate
|
|
for ( int nDmgRegId : vDmgReg) {
|
|
MySurfFrMoveSimpleNoCollision( nRegId, nDmgRegId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nRegId, nDmgRegId, false, false, scInfoCurr) ;
|
|
}
|
|
// la confronto con le regioni degli altri pezzi
|
|
for ( int nOthRegId : vOthReg) {
|
|
MySurfFrMoveSimpleNoCollision( nRegId, nOthRegId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nRegId, nOthRegId, false, false, scInfoCurr) ;
|
|
}
|
|
// e con le regioni dei tagli degli altri pezzi
|
|
// recupero regione in alto del pezzo
|
|
int nUpRegId = GetFlatPartUpRegion( pGeomDB, nTrueId) ;
|
|
int nTestRegId = (( nUpRegId == GDB_ID_NULL) ? nRegId : nUpRegId) ;
|
|
for ( int nOthCutRegId : vOthCutReg) {
|
|
MySurfFrMoveSimpleNoCollision( nTestRegId, nOthCutRegId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nTestRegId, nOthCutRegId, false, true, scInfoCurr) ;
|
|
}
|
|
// -----------------------------------------
|
|
// recupero regione in basso del pezzo
|
|
int nDwnRegId = GetFlatPartDownRegion( pGeomDB, nTrueId) ;
|
|
// la confronto con il box
|
|
if ( nDwnRegId != GDB_ID_NULL) {
|
|
MySurfFrMoveSimpleNoCollision( nDwnRegId, nBoxId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nDwnRegId, nBoxId, false, false, scInfoCurr) ;
|
|
}
|
|
// la confronto con la regione di riferimento
|
|
if ( nDwnRegId != GDB_ID_NULL && nRefReg != GDB_ID_NULL) {
|
|
MySurfFrMoveSimpleNoCollision( nDwnRegId, nRefReg, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nDwnRegId, nRefReg, false, false, scInfoCurr) ;
|
|
}
|
|
// la confronto con le aree danneggiate
|
|
if ( nDwnRegId != GDB_ID_NULL) {
|
|
for ( int nDmgRegId : vDmgReg) {
|
|
MySurfFrMoveSimpleNoCollision( nDwnRegId, nDmgRegId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nDwnRegId, nDmgRegId, false, false, scInfoCurr) ;
|
|
}
|
|
}
|
|
// la confronto con le regioni in basso degli altri pezzi
|
|
for ( size_t j = 0 ; j < vOthDwnReg.size() ; ++ j) {
|
|
if ( nDwnRegId != GDB_ID_NULL || vOthDwnReg[j] != GDB_ID_NULL) {
|
|
int nTmpDwnRegId = ( nDwnRegId != GDB_ID_NULL ? nDwnRegId : nRegId) ;
|
|
int nOthDwnRegId = ( vOthDwnReg[j] != GDB_ID_NULL ? vOthDwnReg[j] : vOthReg[j]) ;
|
|
MySurfFrMoveSimpleNoCollision( nTmpDwnRegId, nOthDwnRegId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nTmpDwnRegId, nOthDwnRegId, false, false, scInfoCurr) ;
|
|
}
|
|
}
|
|
// e con le regioni in basso dei tagli degli altri pezzi
|
|
for ( size_t j = 0 ; j < vOthDwnCutReg.size() ; ++ j) {
|
|
if ( nDwnRegId != GDB_ID_NULL || vOthDwnCutReg[j] != GDB_ID_NULL) {
|
|
int nTmpDwnRegId = ( nDwnRegId != GDB_ID_NULL ? nDwnRegId : nRegId) ;
|
|
int nOthDwnCutRegId = ( vOthDwnCutReg[j] != GDB_ID_NULL ? vOthDwnCutReg[j] : vOthCutReg[j]) ;
|
|
MySurfFrMoveSimpleNoCollision( nTmpDwnRegId, nOthDwnCutRegId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nTmpDwnRegId, nOthDwnCutRegId, false, true, scInfoCurr) ;
|
|
}
|
|
}
|
|
// -----------------------------------------
|
|
// recupero regioni di lavorazione del pezzo
|
|
INTVECTOR vCrId ;
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nTrueId, bReducedCut, vCrId)) {
|
|
bOk = false ;
|
|
break ;
|
|
}
|
|
// le confronto con le regioni degli altri pezzi
|
|
for ( int nCrId : vCrId) {
|
|
for ( size_t k = 0 ; k < vOthReg.size() ; ++ k) {
|
|
int nOthRegId = ( vOthUpReg[k] == GDB_ID_NULL ? vOthReg[k] : vOthUpReg[k]) ;
|
|
MySurfFrMoveSimpleNoCollision( nCrId, nOthRegId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nCrId, nOthRegId, true, false, scInfoCurr) ;
|
|
}
|
|
}
|
|
// -----------------------------------------
|
|
// recupero regioni in basso di lavorazione del pezzo
|
|
INTVECTOR vDwnCrId ;
|
|
if ( ! GetFlatPartDownCutRegions( pGeomDB, nTrueId, bReducedCut, vDwnCrId)) {
|
|
bOk = false ;
|
|
break ;
|
|
}
|
|
// le confronto con le regioni in basso degli altri pezzi
|
|
for ( size_t j = 0 ; j < vDwnCrId.size() ; ++ j) {
|
|
for ( size_t k = 0 ; k < vOthDwnReg.size() ; ++ k) {
|
|
if ( vDwnCrId[j] != GDB_ID_NULL || vOthDwnReg[k] != GDB_ID_NULL) {
|
|
int nTmpDwnCrId = ( vDwnCrId[j] != GDB_ID_NULL ? vDwnCrId[j] : vCrId[j]) ;
|
|
int nOthDwnRegId = ( vOthDwnReg[k] != GDB_ID_NULL ? vOthDwnReg[k] : vOthReg[k]) ;
|
|
MySurfFrMoveSimpleNoCollision( nTmpDwnCrId, nOthDwnRegId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nTmpDwnCrId, nOthDwnRegId, true, false, scInfoCurr) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Se errore
|
|
if ( ! bOk)
|
|
return false ;
|
|
|
|
// Log per debug
|
|
if ( false) {
|
|
if ( s_scInfo.nType != SCI_NONE) {
|
|
string sOut = "Id1=" + ToString( s_scInfo.nIdM) + " Id2=" + ToString( s_scInfo.nIdF) + " Info type=" ;
|
|
switch ( s_scInfo.nType) {
|
|
case SCI_NONE : sOut += "NONE" ; break ;
|
|
case SCI_PNT_PNT : sOut += "PNT_PNT" ; break ;
|
|
case SCI_PNT_LINE : sOut += "PNT_LINE" ; break ;
|
|
case SCI_LINE_PNT : sOut += "LINE_PNT" ; break ;
|
|
case SCI_LINE_LINE : sOut += "LINE_LINE" ; break ;
|
|
}
|
|
sOut += " Crv1=" + ToString( s_scInfo.nCrvM) + " Crv2=" + ToString( s_scInfo.nCrvF) ;
|
|
sOut += " ptA=(" + ToString( s_scInfo.ptP1) + ")" ;
|
|
if ( s_scInfo.nType == SCI_LINE_LINE)
|
|
sOut += " ptB=(" + ToString( s_scInfo.ptP2) + ")" ;
|
|
if ( s_scInfo.nType == SCI_LINE_PNT || s_scInfo.nType == SCI_LINE_LINE)
|
|
sOut += " Dir1=(" + ToString( s_scInfo.vtDirM) + ")" ;
|
|
if ( s_scInfo.nType == SCI_PNT_LINE || s_scInfo.nType == SCI_LINE_LINE)
|
|
sOut += " Dir2=(" + ToString( s_scInfo.vtDirF) + ")" ;
|
|
LOG_INFO( GetLogger(), sOut.c_str()) ;
|
|
}
|
|
}
|
|
|
|
// Se movimento risultante nullo, non faccio alcunché
|
|
vtMoveXY = vtDir * dLen ;
|
|
if ( vtMoveXY.IsSmall())
|
|
return true ;
|
|
|
|
// Eseguo movimento dei pezzi del cluster
|
|
for ( auto nTrueId : vTrueIds)
|
|
pGeomDB->TranslateGlob( nTrueId, vtMoveXY) ;
|
|
ExeSetModified() ;
|
|
vtMove = vtMoveXY ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeMovePartCluster( const INTVECTOR& vIds, bool bReducedCut, Vector3d& vtMove)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// Risolvo identificativi a selezionati
|
|
INTVECTOR vTrueIds ;
|
|
BBox3d b3Cluster ;
|
|
AdjustClusterObjIds( pGeomDB, vIds, vTrueIds, b3Cluster) ;
|
|
if ( vTrueIds.empty())
|
|
return true ;
|
|
|
|
// se con tagli ridotti
|
|
if ( bReducedCut) {
|
|
return MyMovePartCluster( pGeomDB, vTrueIds, b3Cluster, true, vtMove) ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
// provo con tagli ridotti
|
|
Vector3d vtM = vtMove ;
|
|
if ( ! MyMovePartCluster( pGeomDB, vTrueIds, b3Cluster, true, vtM))
|
|
return false ;
|
|
// se posizione valida
|
|
BBox3d b3CluMoved = b3Cluster ;
|
|
b3CluMoved.Translate( vtM) ;
|
|
if ( MyVerifyPartCluster( pGeomDB, vTrueIds, b3CluMoved, false)) {
|
|
vtMove = vtM ;
|
|
return true ;
|
|
}
|
|
// altrimenti, riprovo con tagli standard
|
|
else {
|
|
// annullo il movimento
|
|
for ( int nId : vTrueIds)
|
|
pGeomDB->TranslateGlob( nId, - vtM) ;
|
|
// riprovo
|
|
return MyMovePartCluster( pGeomDB, vTrueIds, b3Cluster, false, vtMove) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
MyRotatePartCluster( IGeomDB* pGeomDB, const INTVECTOR& vTrueIds, BBox3d& b3Cluster, bool bReducedCut,
|
|
const Point3d& ptCen, double& dRotAngDeg)
|
|
{
|
|
// Reset info di collisione
|
|
s_scInfo.nType = SCI_NONE ;
|
|
|
|
// Rotazione nel piano XY globale
|
|
|
|
// Verifico se pezzi sotto la radice o pezzi in altro gruppo
|
|
int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ;
|
|
bool bInRoot = ( nGroupId == GDB_ID_ROOT) ;
|
|
|
|
// Recupero regione di interesse
|
|
int nBoxId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_SHEET_OUTREG) ;
|
|
BBox3d b3Region ;
|
|
if ( nBoxId == GDB_ID_NULL || ! pGeomDB->GetGlobalBBox( nBoxId, b3Region))
|
|
return false ;
|
|
|
|
// Recupero eventuale regione di riferimento
|
|
int nRefReg = pGeomDB->GetFirstNameInGroup( nGroupId, NST_REFERENCE_REG) ;
|
|
if ( pGeomDB->ExistsInfo( nRefReg, KEY_NST_OFF))
|
|
nRefReg = GDB_ID_NULL ;
|
|
|
|
// Recupero le eventuali aree danneggiate
|
|
INTVECTOR vDmgReg ;
|
|
int nId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_DAMAGED_REG) ;
|
|
while ( nId != GDB_ID_NULL) {
|
|
vDmgReg.emplace_back( nId) ;
|
|
nId = pGeomDB->GetNextName( nId, NST_DAMAGED_REG) ;
|
|
}
|
|
|
|
// Determino le regioni di tutti gli altri pezzi compresi nella regione di interesse
|
|
INTVECTOR vOthReg ;
|
|
INTVECTOR vOthUpReg ;
|
|
INTVECTOR vOthDwnReg ;
|
|
INTVECTOR vOthCutReg ;
|
|
INTVECTOR vOthDwnCutReg ;
|
|
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) &&
|
|
b3Region.OverlapsXY( b3Part2)) {
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nId2) ;
|
|
if ( nRegId != GDB_ID_NULL)
|
|
vOthReg.emplace_back( nRegId) ;
|
|
else
|
|
return false ;
|
|
// recupero eventuale regione in alto del pezzo
|
|
int nUpRegId = GetFlatPartUpRegion( pGeomDB, nId2) ;
|
|
vOthUpReg.emplace_back( nUpRegId) ;
|
|
// recupero eventuale regione in basso del pezzo
|
|
int nDwnRegId = GetFlatPartDownRegion( pGeomDB, nId2) ;
|
|
vOthDwnReg.emplace_back( nDwnRegId) ;
|
|
// recupero regioni dei tagli del pezzo
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nId2, bReducedCut, vOthCutReg))
|
|
return false ;
|
|
// recupero eventuali regioni in basso dei tagli del pezzo
|
|
GetFlatPartDownCutRegions( pGeomDB, nId2, bReducedCut, vOthDwnCutReg) ;
|
|
}
|
|
}
|
|
nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ;
|
|
}
|
|
|
|
// Verifico rotazione dei pezzi del cluster rispetto al contorno, alle aree danneggiate e agli altri pezzi
|
|
bool bOk = true ;
|
|
double dAng = dRotAngDeg ;
|
|
for ( auto nTrueId : vTrueIds) {
|
|
// -----------------------------------------
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nTrueId) ;
|
|
if ( nRegId == GDB_ID_NULL) {
|
|
bOk = false ;
|
|
break ;
|
|
}
|
|
// la confronto con il box
|
|
ExeSurfFrRotateSimpleNoCollision( nRegId, nBoxId, ptCen, dAng, RTY_GLOB) ;
|
|
// la confronto con la regione di riferimento
|
|
if ( nRefReg != GDB_ID_NULL) {
|
|
ExeSurfFrRotateSimpleNoCollision( nRegId, nRefReg, ptCen, dAng, RTY_GLOB) ;
|
|
}
|
|
// la confronto con le aree danneggiate
|
|
for ( int nDmgRegId : vDmgReg) {
|
|
ExeSurfFrRotateSimpleNoCollision( nRegId, nDmgRegId, ptCen, dAng, RTY_GLOB) ;
|
|
}
|
|
// la confronto con le regioni degli altri pezzi
|
|
for ( int nOthRegId : vOthReg) {
|
|
ExeSurfFrRotateSimpleNoCollision( nRegId, nOthRegId, ptCen, dAng, RTY_GLOB) ;
|
|
}
|
|
// e con le regioni dei tagli degli altri pezzi
|
|
// recupero regione in alto del pezzo
|
|
int nUpRegId = GetFlatPartUpRegion( pGeomDB, nTrueId) ;
|
|
int nTestRegId = (( nUpRegId == GDB_ID_NULL) ? nRegId : nUpRegId) ;
|
|
for ( int nOthCutRegId : vOthCutReg) {
|
|
ExeSurfFrRotateSimpleNoCollision( nTestRegId, nOthCutRegId, ptCen, dAng, RTY_GLOB) ;
|
|
}
|
|
// -----------------------------------------
|
|
// recupero regione in basso del pezzo
|
|
int nDwnRegId = GetFlatPartDownRegion( pGeomDB, nTrueId) ;
|
|
// la confronto con il box
|
|
if ( nDwnRegId != GDB_ID_NULL)
|
|
ExeSurfFrRotateSimpleNoCollision( nDwnRegId, nBoxId, ptCen, dAng, RTY_GLOB) ;
|
|
// la confronto con la regione di riferimento
|
|
if ( nRefReg != GDB_ID_NULL) {
|
|
ExeSurfFrRotateSimpleNoCollision( nDwnRegId, nRefReg, ptCen, dAng, RTY_GLOB) ;
|
|
}
|
|
// la confronto con le aree danneggiate
|
|
if ( nDwnRegId != GDB_ID_NULL) {
|
|
for ( int nDmgRegId : vDmgReg) {
|
|
ExeSurfFrRotateSimpleNoCollision( nDwnRegId, nDmgRegId, ptCen, dAng, RTY_GLOB) ;
|
|
}
|
|
}
|
|
// la confronto con le regioni in basso degli altri pezzi
|
|
for ( size_t j = 0 ; j < vOthDwnReg.size() ; ++ j) {
|
|
if ( nDwnRegId != GDB_ID_NULL || vOthDwnReg[j] != GDB_ID_NULL) {
|
|
int nTmpDwnRegId = ( nDwnRegId != GDB_ID_NULL ? nDwnRegId : nRegId) ;
|
|
int nOthDwnRegId = ( vOthDwnReg[j] != GDB_ID_NULL ? vOthDwnReg[j] : vOthReg[j]) ;
|
|
ExeSurfFrRotateSimpleNoCollision( nTmpDwnRegId, nOthDwnRegId, ptCen, dAng, RTY_GLOB) ;
|
|
}
|
|
}
|
|
// e con le regioni in basso dei tagli degli altri pezzi
|
|
for ( size_t j = 0 ; j < vOthDwnCutReg.size() ; ++ j) {
|
|
if ( nDwnRegId != GDB_ID_NULL || vOthDwnCutReg[j] != GDB_ID_NULL) {
|
|
int nTmpDwnRegId = ( nDwnRegId != GDB_ID_NULL ? nDwnRegId : nRegId) ;
|
|
int nOthDwnCutRegId = ( vOthDwnCutReg[j] != GDB_ID_NULL ? vOthDwnCutReg[j] : vOthCutReg[j]) ;
|
|
ExeSurfFrRotateSimpleNoCollision( nTmpDwnRegId, nOthDwnCutRegId, ptCen, dAng, RTY_GLOB) ;
|
|
}
|
|
}
|
|
// -----------------------------------------
|
|
// recupero regioni di lavorazione del pezzo
|
|
INTVECTOR vCrId ;
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nTrueId, bReducedCut, vCrId)) {
|
|
bOk = false ;
|
|
break ;
|
|
}
|
|
// le confronto con le regioni degli altri pezzi
|
|
for ( int nCrId : vCrId) {
|
|
for ( size_t k = 0 ; k < vOthReg.size() ; ++ k) {
|
|
int nOthRegId = ( vOthUpReg[k] == GDB_ID_NULL ? vOthReg[k] : vOthUpReg[k]) ;
|
|
ExeSurfFrRotateSimpleNoCollision( nCrId, nOthRegId, ptCen, dAng, RTY_GLOB) ;
|
|
}
|
|
}
|
|
// -----------------------------------------
|
|
// recupero regioni in basso di lavorazione del pezzo
|
|
INTVECTOR vDwnCrId ;
|
|
if ( ! GetFlatPartDownCutRegions( pGeomDB, nTrueId, bReducedCut, vDwnCrId)) {
|
|
bOk = false ;
|
|
break ;
|
|
}
|
|
// le confronto con le regioni in basso degli altri pezzi
|
|
for ( size_t j = 0 ; j < vDwnCrId.size() ; ++ j) {
|
|
for ( size_t k = 0 ; k < vOthDwnReg.size() ; ++ k) {
|
|
if ( vDwnCrId[j] != GDB_ID_NULL || vOthDwnReg[k] != GDB_ID_NULL) {
|
|
int nTmpDwnCrId = ( vDwnCrId[j] != GDB_ID_NULL ? vDwnCrId[j] : vCrId[j]) ;
|
|
int nOthDwnRegId = ( vOthDwnReg[k] != GDB_ID_NULL ? vOthDwnReg[k] : vOthReg[k]) ;
|
|
ExeSurfFrRotateSimpleNoCollision( nTmpDwnCrId, nOthDwnRegId, ptCen, dAng, RTY_GLOB) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Se errore
|
|
if ( ! bOk)
|
|
return false ;
|
|
|
|
// Se movimento risultante nullo, non faccio alcunché
|
|
dRotAngDeg = dAng ;
|
|
if ( abs( dAng) < EPS_ANG_SMALL)
|
|
return true ;
|
|
|
|
// Eseguo rotazione dei pezzi del cluster
|
|
for ( auto nTrueId : vTrueIds)
|
|
pGeomDB->RotateGlob( nTrueId, ptCen, Z_AX, dRotAngDeg) ;
|
|
ExeSetModified() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeRotatePartCluster( const INTVECTOR& vIds, bool bReducedCut, const Point3d& ptCen, double& dRotAngDeg)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// Risolvo identificativi a selezionati
|
|
INTVECTOR vTrueIds ;
|
|
BBox3d b3Cluster ;
|
|
AdjustClusterObjIds( pGeomDB, vIds, vTrueIds, b3Cluster) ;
|
|
if ( vTrueIds.empty())
|
|
return true ;
|
|
|
|
// Eseguo rotazione
|
|
return MyRotatePartCluster( pGeomDB, vTrueIds, b3Cluster, bReducedCut, ptCen, dRotAngDeg) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
GetObstacleTangent( Vector3d& vtTang)
|
|
{
|
|
if ( s_scInfo.nType != SCI_PNT_LINE && s_scInfo.nType != SCI_LINE_LINE)
|
|
return false ;
|
|
vtTang = s_scInfo.vtDirF ;
|
|
return vtTang.Normalize() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
GetMovingTangent( Vector3d& vtTang)
|
|
{
|
|
if ( s_scInfo.nType != SCI_LINE_PNT && s_scInfo.nType != SCI_LINE_LINE)
|
|
return false ;
|
|
vtTang = s_scInfo.vtDirM ;
|
|
return vtTang.Normalize() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeTgMovePartClusterOnCollision( const INTVECTOR& vIds, bool bReducedCut, Vector3d& vtMove)
|
|
{
|
|
// recupero tangente lineare di ostacolo o di mobile
|
|
Vector3d vtTang ;
|
|
if ( ! GetObstacleTangent( vtTang) && ! GetMovingTangent( vtTang)) {
|
|
vtMove = V_NULL ;
|
|
return false ;
|
|
}
|
|
// calcolo il movimento tangente
|
|
vtMove = ( vtMove * vtTang) * vtTang ;
|
|
// riprovo con questo movimento
|
|
if ( ! ExeMovePartCluster( vIds, bReducedCut, vtMove))
|
|
return false ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeAlignPartClusterOnCollision( const INTVECTOR& vIds, bool bReducedCut, bool& bMoved)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
// verifico sia collisione punto->linea
|
|
if ( s_scInfo.nType != SCI_PNT_LINE)
|
|
return false ;
|
|
// recupero la regione mobile interessata dalla collision
|
|
ISurfFlatRegion* pSfr = GetSurfFlatRegion( pGeomDB->GetGeoObj( s_scInfo.nIdM)) ;
|
|
if ( pSfr == nullptr)
|
|
return false ;
|
|
// recupero il suo sistema di riferimento
|
|
Frame3d frSfr ;
|
|
if ( ! pGeomDB->GetGlobFrame( s_scInfo.nIdM, frSfr))
|
|
return false ;
|
|
// porto il punto di contatto nel riferimento della superficie
|
|
Point3d ptCntL = s_scInfo.ptP1 ;
|
|
ptCntL.ToLoc( frSfr) ;
|
|
// cerco le direzioni tangenti prima e dopo il punto di contatto sulle parti mobili
|
|
PtrOwner<ICurve> pCrv( pSfr->GetLoop( s_scInfo.nChunkM, 0)) ;
|
|
if ( IsNull( pCrv))
|
|
return false ;
|
|
double dU ;
|
|
if ( ! pCrv->GetParamAtPoint( ptCntL, dU, 10 * EPS_SMALL))
|
|
return false ;
|
|
if ( abs( dU - round( dU)) < 100 * EPS_PARAM)
|
|
dU = round( dU) ;
|
|
Point3d ptPp ;
|
|
Vector3d vtTp ;
|
|
if ( ! pCrv->GetPointTang( dU, ICurve::FROM_MINUS, ptPp, vtTp))
|
|
return false ;
|
|
Point3d ptPn ;
|
|
Vector3d vtTn ;
|
|
if ( ! pCrv->GetPointTang( dU, ICurve::FROM_PLUS, ptPn, vtTn))
|
|
return false ;
|
|
// verifico che le tangenti siano diverse
|
|
if ( AreSameVectorApprox( vtTp, vtTn))
|
|
return false ;
|
|
// porto le tangenti nel riferimento globale e le confronto con la tangente dell'ostacolo
|
|
vtTp.ToGlob( frSfr) ;
|
|
vtTn.ToGlob( frSfr) ;
|
|
// log per debug
|
|
if ( false) {
|
|
string sOut = "vtTp=(" + ToString( vtTp) + ") vtTn=(" + ToString( vtTn) + ")" ;
|
|
LOG_INFO( GetLogger(), sOut.c_str()) ;
|
|
}
|
|
// ruoto dalla parte dell'angolo più piccolo (componente più grande)
|
|
double dRotAngDeg = ( abs( vtTp * s_scInfo.vtDirF) > abs( vtTn * s_scInfo.vtDirF)) ? 90 : - 90 ;
|
|
// provo a ruotare sul punto di collisione in senso orario
|
|
Point3d ptCen = s_scInfo.ptP1 ;
|
|
if ( ! ExeRotatePartCluster( vIds, bReducedCut, ptCen, dRotAngDeg))
|
|
return false ;
|
|
bMoved = ( abs( dRotAngDeg) > 100.0 * EPS_ANG_ZERO) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeMoveToSnapPointOnCollision( const INTVECTOR& vIds, bool bReducedCut, double dMaxMove, bool& bMoved)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
IMachMgr* pMachMgr = GetCurrMachMgr() ;
|
|
VERIFY_MACHMGR( pMachMgr, false)
|
|
// la collisione deve essere di tipo linea-linea o punto linea
|
|
if ( s_scInfo.nType != SCI_LINE_LINE && s_scInfo.nType != SCI_PNT_LINE)
|
|
return false ;
|
|
// cerco i due tagli in collisione
|
|
int nCutM = GDB_ID_NULL ;
|
|
int nGeoM = GDB_ID_NULL ;
|
|
Point3d ptStartM, ptEndM ;
|
|
Vector3d vtDirM ;
|
|
Frame3d frGeoM ;
|
|
int nCutF = GDB_ID_NULL ;
|
|
int nGeoF = GDB_ID_NULL ;
|
|
Point3d ptStartF, ptEndF ;
|
|
Vector3d vtDirF ;
|
|
Frame3d frGeoF ;
|
|
// se mobile è già un taglio, ne ricavo i dati
|
|
if ( s_scInfo.bIsCutM) {
|
|
nCutM = s_scInfo.nIdM ;
|
|
nGeoM = GetGeometryFromCut( pGeomDB, pMachMgr, nCutM) ;
|
|
ICurveLine* pLineM = GetCurveLine( pGeomDB->GetGeoObj( nGeoM)) ;
|
|
if ( nCutM == GDB_ID_NULL || nGeoM == GDB_ID_NULL ||
|
|
pLineM == nullptr || ! pGeomDB->GetGlobFrame( nGeoM, frGeoM))
|
|
return false ;
|
|
ptStartM = pLineM->GetStart() ;
|
|
ptStartM.ToGlob( frGeoM) ;
|
|
ptEndM = pLineM->GetEnd() ;
|
|
ptEndM.ToGlob( frGeoM) ;
|
|
vtDirM = ptEndM - ptStartM ;
|
|
vtDirM.Normalize() ;
|
|
}
|
|
// se fisso è già un taglio, ne ricavo i dati
|
|
if ( s_scInfo.bIsCutF) {
|
|
nCutF = s_scInfo.nIdF ;
|
|
nGeoF = GetGeometryFromCut( pGeomDB, pMachMgr, nCutF) ;
|
|
ICurveLine* pLineF = GetCurveLine( pGeomDB->GetGeoObj( nGeoF)) ;
|
|
if ( nCutF == GDB_ID_NULL || nGeoF == GDB_ID_NULL ||
|
|
pLineF == nullptr || ! pGeomDB->GetGlobFrame( nGeoF, frGeoF))
|
|
return false ;
|
|
ptStartF = pLineF->GetStart() ;
|
|
ptStartF.ToGlob( frGeoF) ;
|
|
ptEndF = pLineF->GetEnd() ;
|
|
ptEndF.ToGlob( frGeoF) ;
|
|
vtDirF = ptEndF - ptStartF ;
|
|
vtDirF.Normalize() ;
|
|
}
|
|
// se fisso pezzo e mobile taglio, cerco il taglio sul fisso
|
|
if ( ! s_scInfo.bIsCutF && s_scInfo.bIsCutM) {
|
|
// cerco il pezzo del fisso
|
|
int nPartId = GetFlatPartFromRegion( pGeomDB, s_scInfo.nIdF) ;
|
|
// recupero i suoi tagli
|
|
INTVECTOR vCuts ;
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nPartId, bReducedCut, vCuts))
|
|
return false ;
|
|
GetFlatPartDownCutRegions( pGeomDB, nPartId, bReducedCut, vCuts) ;
|
|
// cerco il taglio che si sovrappone a quello del mobile
|
|
BBox3d b3CutM ;
|
|
pGeomDB->GetGlobalBBox( nCutM, b3CutM) ;
|
|
for ( auto nId : vCuts) {
|
|
BBox3d b3Temp ;
|
|
pGeomDB->GetGlobalBBox( nId, b3Temp) ;
|
|
if ( b3Temp.OverlapsXY( b3CutM)) {
|
|
int nGeom = GetGeometryFromCut( pGeomDB, pMachMgr, nId) ;
|
|
ICurveLine* pLine = GetCurveLine( pGeomDB->GetGeoObj( nGeom)) ;
|
|
if ( nGeom == GDB_ID_NULL || pLine == nullptr || ! pGeomDB->GetGlobFrame( nGeom, frGeoF))
|
|
continue ;
|
|
ptStartF = pLine->GetStart() ;
|
|
ptStartF.ToGlob( frGeoF) ;
|
|
ptEndF = pLine->GetEnd() ;
|
|
ptEndF.ToGlob( frGeoF) ;
|
|
vtDirF = ptEndF - ptStartF ;
|
|
vtDirF.Normalize() ;
|
|
if ( AreOppositeVectorApprox( vtDirF, vtDirM)) {
|
|
nCutF = nId ;
|
|
nGeoF = nGeom ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// se mobile pezzo e fisso taglio, cerco il taglio sul mobile
|
|
if ( ! s_scInfo.bIsCutM && s_scInfo.bIsCutF) {
|
|
// cerco il pezzo del mobile
|
|
int nPartId = GetFlatPartFromRegion( pGeomDB, s_scInfo.nIdM) ;
|
|
// recupero i suoi tagli
|
|
INTVECTOR vCuts ;
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nPartId, bReducedCut, vCuts))
|
|
return false ;
|
|
GetFlatPartDownCutRegions( pGeomDB, nPartId, bReducedCut, vCuts) ;
|
|
// cerco il taglio che si sovrappone a quello del fisso
|
|
BBox3d b3CutF ;
|
|
pGeomDB->GetGlobalBBox( nCutF, b3CutF) ;
|
|
for ( auto nId : vCuts) {
|
|
BBox3d b3Temp ;
|
|
pGeomDB->GetGlobalBBox( nId, b3Temp) ;
|
|
if ( b3Temp.OverlapsXY( b3CutF)) {
|
|
int nGeom = GetGeometryFromCut( pGeomDB, pMachMgr, nId) ;
|
|
ICurveLine* pLine = GetCurveLine( pGeomDB->GetGeoObj( nGeom)) ;
|
|
if ( nGeom == GDB_ID_NULL || pLine == nullptr || ! pGeomDB->GetGlobFrame( nGeom, frGeoM))
|
|
continue ;
|
|
ptStartM = pLine->GetStart() ;
|
|
ptStartM.ToGlob( frGeoM) ;
|
|
ptEndM = pLine->GetEnd() ;
|
|
ptEndM.ToGlob( frGeoM) ;
|
|
vtDirM = ptEndM - ptStartM ;
|
|
vtDirM.Normalize() ;
|
|
if ( AreOppositeVectorApprox( vtDirF, vtDirM)) {
|
|
nCutM = nId ;
|
|
nGeoM = nGeom ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// se un taglio non definito, esco
|
|
if ( nCutM == GDB_ID_NULL || nCutF == GDB_ID_NULL)
|
|
return false ;
|
|
|
|
// linee adiacenti sul mobile
|
|
int nGeoMp = pGeomDB->GetPrev( nGeoM) ;
|
|
if ( nGeoMp == GDB_ID_NULL)
|
|
nGeoMp = pGeomDB->GetLastInGroup( pGeomDB->GetParentId( nGeoM)) ;
|
|
Vector3d vtDirMp ;
|
|
if ( pGeomDB->GetGeoType( nGeoMp) == CRV_LINE) {
|
|
ICurveLine* pLine = GetCurveLine( pGeomDB->GetGeoObj( nGeoMp)) ;
|
|
pLine->GetStartDir( vtDirMp) ;
|
|
vtDirMp.ToGlob( frGeoM) ;
|
|
}
|
|
int nGeoMn = pGeomDB->GetNext( nGeoM) ;
|
|
if ( nGeoMn == GDB_ID_NULL)
|
|
nGeoMn = pGeomDB->GetFirstInGroup( pGeomDB->GetParentId( nGeoM)) ;
|
|
Vector3d vtDirMn ;
|
|
if ( pGeomDB->GetGeoType( nGeoMn) == CRV_LINE) {
|
|
ICurveLine* pLine = GetCurveLine( pGeomDB->GetGeoObj( nGeoMn)) ;
|
|
pLine->GetStartDir( vtDirMn) ;
|
|
vtDirMn.ToGlob( frGeoM) ;
|
|
}
|
|
// linee adiacenti sul fisso
|
|
int nGeoFp = pGeomDB->GetPrev( nGeoF) ;
|
|
if ( nGeoFp == GDB_ID_NULL)
|
|
nGeoFp = pGeomDB->GetLastInGroup( pGeomDB->GetParentId( nGeoF)) ;
|
|
Vector3d vtDirFp ;
|
|
if ( pGeomDB->GetGeoType( nGeoFp) == CRV_LINE) {
|
|
ICurveLine* pLine = GetCurveLine( pGeomDB->GetGeoObj( nGeoFp)) ;
|
|
pLine->GetStartDir( vtDirFp) ;
|
|
vtDirFp.ToGlob( frGeoF) ;
|
|
}
|
|
int nGeoFn = pGeomDB->GetNext( nGeoF) ;
|
|
if ( nGeoFn == GDB_ID_NULL)
|
|
nGeoFn = pGeomDB->GetFirstInGroup( pGeomDB->GetParentId( nGeoF)) ;
|
|
Vector3d vtDirFn ;
|
|
if ( pGeomDB->GetGeoType( nGeoFn) == CRV_LINE) {
|
|
ICurveLine* pLine = GetCurveLine( pGeomDB->GetGeoObj( nGeoFn)) ;
|
|
pLine->GetStartDir( vtDirFn) ;
|
|
vtDirFn.ToGlob( frGeoF) ;
|
|
}
|
|
|
|
// verifico se possibile allineare i tagli precedente di mobile e successivo di fisso
|
|
double dMoveMp = 2 * dMaxMove ;
|
|
if ( ! vtDirMp.IsSmall() && ! vtDirFn.IsSmall()) {
|
|
if ( AreSameVectorApprox( vtDirMp, vtDirFn)) {
|
|
double dDenom = CrossXY( vtDirF, vtDirFn) ;
|
|
if ( abs( dDenom) > EPS_ZERO)
|
|
dMoveMp = CrossXY( ptEndF - ptStartM, vtDirFn) / dDenom ;
|
|
}
|
|
}
|
|
double dMoveMn = 2 * dMaxMove ;
|
|
if ( ! vtDirMn.IsSmall() && ! vtDirFp.IsSmall()) {
|
|
if ( AreSameVectorApprox( vtDirMn, vtDirFp)) {
|
|
double dDenom = CrossXY( vtDirF, vtDirFp) ;
|
|
if ( abs( dDenom) > EPS_ZERO)
|
|
dMoveMn = CrossXY( ptStartF - ptEndM, vtDirFp) / dDenom ;
|
|
}
|
|
}
|
|
// pareggio la parte più vicina, se almeno una sotto soglia
|
|
if ( abs( dMoveMp) < dMaxMove || abs( dMoveMn) < dMaxMove) {
|
|
// calcolo movimento necessario, se nullo già a posto
|
|
Vector3d vtMove = (( abs( dMoveMp) < abs( dMoveMn)) ? dMoveMp : dMoveMn) * vtDirF ;
|
|
if ( vtMove.IsSmall()) {
|
|
bMoved = false ;
|
|
return true ;
|
|
}
|
|
// eseguo movimento
|
|
if ( ExeMovePartCluster( vIds, bReducedCut, vtMove)) {
|
|
if ( ! vtMove.IsSmall()) {
|
|
bMoved = true ;
|
|
return true ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// verifico se possibile allineare i tagli correnti
|
|
// calcolo ingombro dei tagli su direzione del taglio fisso
|
|
Frame3d frCutF ;
|
|
frCutF.Set( ptStartF, Z_AX, vtDirF) ;
|
|
BBox3d b3CutF ;
|
|
pGeomDB->GetRefBBox( nCutF, frCutF, b3CutF) ;
|
|
BBox3d b3CutM ;
|
|
pGeomDB->GetRefBBox( nCutM, frCutF, b3CutM) ;
|
|
double dStartDelta = b3CutF.GetMin().x - b3CutM.GetMin().x ;
|
|
double dEndDelta = b3CutF.GetMax().x - b3CutM.GetMax().x ;
|
|
// pareggio la parte più vicina, se sotto soglia
|
|
if ( abs( dStartDelta) > dMaxMove && abs( dEndDelta) > dMaxMove)
|
|
return false ;
|
|
Vector3d vtMove = (( abs( dStartDelta) < abs( dEndDelta)) ? dStartDelta : dEndDelta) * vtDirF ;
|
|
if ( ! ExeMovePartCluster( vIds, bReducedCut, vtMove))
|
|
return false ;
|
|
bMoved = ( ! vtMove.IsSmall()) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
ExeSaveCollInfo( void)
|
|
{
|
|
s_scInfoSaved = s_scInfo ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
ExeRestoreCollInfo( void)
|
|
{
|
|
s_scInfo = s_scInfoSaved ;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool
|
|
ExeGetPartClusterCenterGlob( const INTVECTOR& vIds, Point3d& ptCen)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
// Risolvo eventuali riferimenti a oggetti selezionati
|
|
INTVECTOR vTrueIds ;
|
|
vTrueIds.reserve( vIds.size()) ;
|
|
for ( auto nId : vIds) {
|
|
int nTrueId = (( nId != GDB_ID_SEL) ? nId : pGeomDB->GetFirstSelectedObj()) ;
|
|
while ( nTrueId != GDB_ID_NULL) {
|
|
vTrueIds.push_back( nTrueId) ;
|
|
// passo al successivo
|
|
nTrueId = (( nId != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ;
|
|
}
|
|
}
|
|
// Se non sono rimasti oggetti, esco con errore
|
|
if ( vTrueIds.empty())
|
|
return false ;
|
|
|
|
// Recupero il centro della regione associata ad ogni oggetto
|
|
double dTotArea = 0 ;
|
|
ptCen = ORIG ;
|
|
for ( auto nTrueId : vTrueIds) {
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nTrueId) ;
|
|
ISurfFlatRegion* pSfr = GetSurfFlatRegion( pGeomDB->GetGeoObj( nRegId)) ;
|
|
if ( pSfr == nullptr)
|
|
return false ;
|
|
// ne ricavo il centro e l'area
|
|
Point3d ptRcen ;
|
|
if ( ! pSfr->GetCentroid( ptRcen))
|
|
return false ;
|
|
double dArea ;
|
|
if ( ! pSfr->GetArea( dArea))
|
|
return false ;
|
|
// lo porto in globale
|
|
Frame3d frRef ;
|
|
if ( ! pGeomDB->GetGlobFrame( nRegId, frRef))
|
|
return false ;
|
|
ptRcen.ToGlob( frRef) ;
|
|
// lo sommo al centro complessivo
|
|
ptCen += ptRcen * dArea ;
|
|
dTotArea += dArea ;
|
|
}
|
|
|
|
// Verifico di aver trovato qualcosa
|
|
if ( dTotArea < EPS_SMALL * EPS_SMALL)
|
|
return false ;
|
|
|
|
// Medio il centro
|
|
ptCen /= dTotArea ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeAutomaticPackParts( INTVECTOR& vIds, bool bMinimizeOnXvsY, bool bReducedCut, bool bGuillotineMode, int nMaxTime)
|
|
{
|
|
// Dichiaro tutti i pezzi non nestati
|
|
for ( int i = 0 ; i < int( vIds.size()) ; ++ i)
|
|
vIds[i] = - vIds[i] ;
|
|
|
|
// Verifico gestore DB geometrico
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// Verifico pezzi e determino se sotto la radice o in altro gruppo
|
|
int nGroupId = pGeomDB->GetParentId( ( vIds.size() > 0 ? abs( vIds[0]) : GDB_ID_NULL)) ;
|
|
if ( nGroupId == GDB_ID_NULL)
|
|
return false ;
|
|
bool bInRoot = ( nGroupId == GDB_ID_ROOT) ;
|
|
|
|
// Avvio nesting automatico
|
|
ExeAutoNestStart() ;
|
|
|
|
// Modalità ghigliottina incompatibile con tagli completi
|
|
if ( ! bReducedCut)
|
|
bGuillotineMode = false ;
|
|
|
|
// Definisco un solo pannello
|
|
int nSheetId = 1 ;
|
|
// Assegno il contorno del pannello ( parte utile)
|
|
int nKerfId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_SHEET_KERF) ;
|
|
if ( nKerfId == GDB_ID_NULL)
|
|
return false ;
|
|
bool bIsRect = false ;
|
|
ExeAutoNestAddSheet( nSheetId, nKerfId, 0.0, 0, 1, &bIsRect) ;
|
|
// Recupero la regione di riferimento e verifico se disabilitata
|
|
int nRefReg = pGeomDB->GetFirstNameInGroup( nGroupId, NST_REFERENCE_REG) ;
|
|
if ( ! pGeomDB->ExistsInfo( nRefReg, KEY_NST_OFF))
|
|
ExeAutoNestAddDefectToSheet( nSheetId, nRefReg) ;
|
|
// Recupero le aree danneggiate
|
|
int nDamId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_DAMAGED_REG) ;
|
|
while ( nDamId != GDB_ID_NULL) {
|
|
ExeAutoNestAddDefectToSheet( nSheetId, nDamId) ;
|
|
nDamId = pGeomDB->GetNextName( nDamId, NST_DAMAGED_REG) ;
|
|
}
|
|
|
|
// Modalità ghigliottina incompatibile con pannelli non rettangolari
|
|
if ( ! bIsRect)
|
|
bGuillotineMode = false ;
|
|
|
|
// Assegno le aree occupate dai pezzi già nestati
|
|
bool bPartAlreadyNested = false ;
|
|
BBox3d b3Sheet ;
|
|
pGeomDB->GetGlobalBBox( nRefReg, b3Sheet) ;
|
|
int nId = ( bInRoot ? ExeGetFirstPart( true) : ExeGetFirstGroupInGroup( nGroupId)) ;
|
|
while ( nId != GDB_ID_NULL) {
|
|
// se pezzo non nell'elenco
|
|
if ( find( vIds.begin(), vIds.end(), -nId) == vIds.end()) {
|
|
BBox3d b3Part ;
|
|
if ( pGeomDB->GetGlobalBBox( nId, b3Part, BBF_PART_MY_FLAG) &&
|
|
b3Sheet.OverlapsXY( b3Part)) {
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nId) ;
|
|
ExeAutoNestAddDefectToSheet( nSheetId, nRegId) ;
|
|
// recupero eventuale regione in basso del pezzo
|
|
int nDwnRegId = GetFlatPartDownRegion( pGeomDB, nId) ;
|
|
if ( nDwnRegId != GDB_ID_NULL)
|
|
ExeAutoNestAddDefectToSheet( nSheetId, nDwnRegId) ;
|
|
// recupero regioni dei tagli del pezzo
|
|
INTVECTOR vCutReg ;
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nId, bReducedCut, vCutReg))
|
|
return false ;
|
|
// recupero eventuali regioni in basso dei tagli del pezzo
|
|
GetFlatPartDownCutRegions( pGeomDB, nId, bReducedCut, vCutReg) ;
|
|
for ( int nRegId : vCutReg)
|
|
ExeAutoNestAddDefectToSheet( nSheetId, nRegId) ;
|
|
// dichiaro ci sono pezzi già nestati
|
|
bPartAlreadyNested = true ;
|
|
}
|
|
}
|
|
nId = ( bInRoot ? ExeGetNextPart( nId, true) : ExeGetNextGroup( nId)) ;
|
|
}
|
|
|
|
// Pezzi già nestati incompatibili con ghigliottina
|
|
if ( bPartAlreadyNested)
|
|
bGuillotineMode = false ;
|
|
|
|
// Se richiesta modalità ghigliottina
|
|
if ( bGuillotineMode) {
|
|
// cerco il gap necessario tra le parti
|
|
double dGap = 0 ;
|
|
for ( int nPartId : vIds) {
|
|
nPartId = abs( nPartId) ;
|
|
double dCurrGap = 0 ;
|
|
if ( GetFlatPartInterpartGap( pGeomDB, nPartId, dCurrGap) && dCurrGap > dGap)
|
|
dGap = dCurrGap ;
|
|
}
|
|
// se non trovato disabilito richiesta modalità ghigliottina
|
|
if ( dGap < EPS_SMALL)
|
|
bGuillotineMode = false ;
|
|
// altrimenti lo imposto
|
|
else
|
|
ExeAutoNestSetInterpartGap( dGap) ;
|
|
}
|
|
|
|
// Se richiesto e abilitato, imposto modalità ghigliottina
|
|
if ( bGuillotineMode)
|
|
ExeAutoNestSetGuillotineMode() ;
|
|
|
|
// Assegno i pezzi da nestare
|
|
for ( int nPartId : vIds) {
|
|
nPartId = abs( nPartId) ;
|
|
// flag rotazione
|
|
bool bEnableRot = ! pGeomDB->ExistsInfo( nPartId, NST_PART_ROT) ;
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nPartId) ;
|
|
ExeAutoNestAddPart( nPartId, nRegId, false, bEnableRot, 0.0, 0, 1) ;
|
|
// recupero eventuale regione in basso del pezzo
|
|
int nDwnRegId = GetFlatPartDownRegion( pGeomDB, nPartId) ;
|
|
if ( nDwnRegId != GDB_ID_NULL)
|
|
ExeAutoNestAddAnotherOutlineToPart( nPartId, nDwnRegId) ;
|
|
// se non è ghigliottina imposto le regioni dei tagli (con ghigliottina si usa il gap)
|
|
if ( ! bGuillotineMode) {
|
|
// recupero regioni dei tagli del pezzo
|
|
INTVECTOR vCutReg ;
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nPartId, bReducedCut, vCutReg))
|
|
return false ;
|
|
// recupero eventuali regioni in basso dei tagli del pezzo
|
|
GetFlatPartDownCutRegions( pGeomDB, nPartId, bReducedCut, vCutReg) ;
|
|
for ( int nRegId : vCutReg)
|
|
ExeAutoNestAddToolOutlineToPart( nPartId, nRegId) ;
|
|
}
|
|
}
|
|
|
|
// Eseguo il nesting
|
|
ExeAutoNestCompute( bMinimizeOnXvsY, nMaxTime) ;
|
|
bool bOk = true ;
|
|
int nTime = 0 ;
|
|
while ( bOk) {
|
|
int nStat ;
|
|
bOk = ExeAutoNestGetComputationStatus( nStat) ;
|
|
if ( nStat == 2 || nStat == 3) {
|
|
// eventuale raccolta dati e visualizzazione dinamica
|
|
}
|
|
if ( nStat == 3)
|
|
break ;
|
|
nTime += 1 ;
|
|
if ( ExeProcessEvents( int( 1.0 * nTime / nMaxTime * 100), 995) == 1) {
|
|
bOk = ExeAutoNestCancelComputation() ;
|
|
break ;
|
|
}
|
|
}
|
|
|
|
// Recupero i risultati
|
|
int nNestedParts, nParts, nSheets, nNestings ; double dTotFillRatio ;
|
|
if ( ! ExeAutoNestGetResults( nNestedParts, nParts, nSheets, nNestings, dTotFillRatio))
|
|
return false ;
|
|
for ( int j = 0 ; ; ++ j) {
|
|
int nType, nId, nFlag ; double dX, dY, dAngRot ;
|
|
if ( ! ExeAutoNestGetOneResult( j, nType, nId, nFlag, dX, dY, dAngRot))
|
|
break ;
|
|
if ( nType == 0) {
|
|
// flip su Y escluso, si fanno rotazione e spostamento
|
|
pGeomDB->RotateGlob( nId, ORIG, Z_AX, dAngRot) ;
|
|
pGeomDB->TranslateGlob( nId, Vector3d( dX, dY, 0)) ;
|
|
// segnalo che pezzo nestato
|
|
for ( int i = 0 ; i < int( vIds.size()) ; ++ i) {
|
|
if ( vIds[i] == - nId)
|
|
vIds[i] = nId ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|