Files
EgtExecutor/EXE_NstPartNesting.cpp
T
Dario Sassi f7dd86494c EgtExecutor 1.6l5 :
- aggiunte EXE e LUA CreateArcCPA
- aggiunte EXE e LUA CreateSurfFrRectangle3P
- aggiunte EXE e LUA SurfFrMoveSimpleNoCollision e SurfFrRotateSimpleNoCollision
- aggiunte EXE e LUA SurfFrChunkSimpleClassify
- aggiunte a EXE funzione per nesting di pezzi
- in LUA rinominate funzioni di nesting di pezzi usando i box in PackBox...
2016-01-05 11:37:09 +00:00

423 lines
15 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_Macro.h"
#include "/EgtDev/Include/EXeExecutor.h"
#include "/EgtDev/Include/EXeConst.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <functional>
using namespace std ;
//----------------------------------------------------------------------------
static int
GetFlatPartRegion( IGeomDB* pGeomDB, int nId)
{
// recupero regione del pezzo (è la prima del sottogruppo di nome Region)
int nRegGrp = pGeomDB->GetFirstNameInGroup( nId, "Region") ;
int nRegId = pGeomDB->GetFirstInGroup( nRegGrp) ;
while ( nRegId != GDB_ID_NULL) {
if ( pGeomDB->GetGeoType( nRegId) == SRF_FLATRGN)
break ;
nRegId = pGeomDB->GetNext( nRegId) ;
}
return nRegId ;
}
//----------------------------------------------------------------------------
static bool
GetFlatPartCutRegions( IGeomDB* pGeomDB, int nId, INTVECTOR& vCrId)
{
// recupero gruppo preview lavorazioni del pezzo
int nPVGrp = pGeomDB->GetFirstNameInGroup( nId, "PV") ;
if ( nPVGrp == GDB_ID_NULL)
return false ;
// ciclo sulle lavorazioni
int nMchId = pGeomDB->GetFirstGroupInGroup( nPVGrp) ;
while ( nMchId != GDB_ID_NULL) {
int nClId = pGeomDB->GetFirstGroupInGroup( nMchId) ;
while ( nClId != GDB_ID_NULL) {
int nCrId = pGeomDB->GetFirstNameInGroup( nClId, "RCUT") ;
while ( nCrId != GDB_ID_NULL) {
vCrId.emplace_back( nCrId) ;
nCrId = pGeomDB->GetNextName( nCrId, "RCUT") ;
}
nClId = pGeomDB->GetNextGroup( nClId) ;
}
nMchId = pGeomDB->GetNextGroup( nMchId) ;
}
return true ;
}
//----------------------------------------------------------------------------
static int
CreateOutBoxRegion( IGeomDB* pGeomDB, int nParentId, double dXmin, double dYmin, double dXmax, double dYmax)
{
// creo polilinea attorno al box (avvolta a serpente)
const double SPESS = 100 ;
const double DELTA = 1 ;
PolyLine PL ;
PL.AddUPoint( 0, Point3d( dXmin, dYmin, 0)) ;
PL.AddUPoint( 1, Point3d( dXmin, dYmax, 0)) ;
PL.AddUPoint( 2, Point3d( dXmax, dYmax, 0)) ;
PL.AddUPoint( 3, Point3d( dXmax, dYmin + DELTA + 2 * EPS_SMALL, 0)) ;
PL.AddUPoint( 4, Point3d( dXmax + SPESS, dYmin + DELTA + 2 * EPS_SMALL, 0)) ;
PL.AddUPoint( 5, Point3d( dXmax + SPESS, dYmax + SPESS, 0)) ;
PL.AddUPoint( 6, Point3d( dXmin - SPESS, dYmax + SPESS, 0)) ;
PL.AddUPoint( 7, Point3d( dXmin - SPESS, dYmin - SPESS, 0)) ;
PL.AddUPoint( 8, Point3d( dXmax + SPESS, dYmin - SPESS, 0)) ;
PL.AddUPoint( 9, Point3d( dXmax + SPESS, dYmin + DELTA, 0)) ;
PL.AddUPoint( 10, Point3d( dXmax, dYmin + DELTA, 0)) ;
PL.AddUPoint( 11, Point3d( dXmax, dYmin, 0)) ;
PL.Close() ;
// la converto in curva composita
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL))
return GDB_ID_NULL ;
// costruisco la regione piana
SurfFlatRegionByContours SfrCntr ;
SfrCntr.AddCurve( Release( pCompo)) ;
ISurfFlatRegion* pSfr = SfrCntr.GetSurf() ;
if ( pSfr == nullptr)
return GDB_ID_NULL ;
// inserisco la superficie nel DB
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, pSfr) ;
if ( nId == GDB_ID_NULL)
return GDB_ID_NULL ;
// la dichiaro temporanea e invisibile
pGeomDB->SetLevel( nId, GDB_LV_TEMP) ;
pGeomDB->SetMaterial( nId, INVISIBLE) ;
return nId ;
}
//----------------------------------------------------------------------------
bool
ExeMovePartCluster( const INTVECTOR& vIds, Vector3d& vtMove,
double dXmin, double dYmin, double dXmax, double dYmax)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// Verifiche sui parametri
if ( dXmax < dXmin + EPS_SMALL ||
dYmax < dYmin + EPS_SMALL)
return false ;
// Vettore movimento nel piano XY globale
Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ;
vtMove = V_NULL ;
if ( vtMoveXY.IsSmall())
return true ;
// Box della regione di interesse
BBox3d b3Region( dXmin, dYmin, 0, dXmax, dYmax, 0) ;
// Flag per calcolo box
const int BBF_MY_FLAG = BBF_ONLY_VISIBLE | BBF_IGNORE_TEXT | BBF_IGNORE_DIM ;
// Risolvo eventuali riferimenti a oggetti selezionati, compresi nella regione e
// calcolo il box del cluster risultante
INTVECTOR vTrueIds ;
vTrueIds.reserve( vIds.size()) ;
BBox3d b3Cluster ;
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_MY_FLAG) &&
b3Region.OverlapsXY( b3Part)) {
// 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()) ;
}
}
// Se non sono rimasti oggetti, esco con successo
if ( vTrueIds.empty())
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) ;
// Determino le regioni di tutti gli altri pezzi compresi nella regione di interesse
INTVECTOR vReg ;
INTVECTOR vCutReg ;
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_MY_FLAG) &&
b3Region.OverlapsXY( b3Part2)) {
// recupero regione del pezzo
int nRegId = GetFlatPartRegion( pGeomDB, nId2) ;
if ( nRegId != GDB_ID_NULL)
vReg.emplace_back( nRegId) ;
else
return false ;
// recupero regioni dei tagli del pezzo
if ( ! GetFlatPartCutRegions( pGeomDB, nId2, vCutReg))
return false ;
}
}
nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ;
}
// Creo SurfFlatRegion che delimita la regione valida
int nBoxId = CreateOutBoxRegion( pGeomDB, GDB_ID_ROOT, dXmin, dYmin, dXmax, dYmax) ;
if ( nBoxId == GDB_ID_NULL)
return false ;
// Verifico movimento dei pezzi del cluster rispetto agli altri pezzi
bool bOk = true ;
double dLen = vtMoveXY.Len() ;
Vector3d vtDir = ( dLen > EPS_SMALL ? vtMoveXY / dLen : V_NULL) ;
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
ExeSurfFrMoveSimpleNoCollision( nRegId, nBoxId, vtDir, dLen, RTY_GLOB) ;
// la confronto con le regioni degli altri pezzi
for ( int nOthRegId : vReg) {
ExeSurfFrMoveSimpleNoCollision( nRegId, nOthRegId, vtDir, dLen, RTY_GLOB) ;
}
// e con le regioni dei tagli degli altri pezzi
for ( int nOthCutRegId : vCutReg) {
ExeSurfFrMoveSimpleNoCollision( nRegId, nOthCutRegId, vtDir, dLen, RTY_GLOB) ;
}
// recupero regioni di lavorazione del pezzo
INTVECTOR vCrId ;
if ( ! GetFlatPartCutRegions( pGeomDB, nTrueId, vCrId)) {
bOk = false ;
break ;
}
// le confronto con le regioni degli altri pezzi
for ( int nCrId : vCrId) {
for ( int nOthRegId : vReg) {
ExeSurfFrMoveSimpleNoCollision( nCrId, nOthRegId, vtDir, dLen, RTY_GLOB) ;
}
}
}
// Elimino la regione aggiunta per il Box
pGeomDB->Erase( nBoxId) ;
// Se errore
if ( ! bOk)
return false ;
// 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
ExeRotatePartCluster( const INTVECTOR& vIds, const Point3d& ptCen, double& dRotAngDeg,
double dXmin, double dYmin, double dXmax, double dYmax)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// Verifiche sui parametri
if ( dXmax < dXmin + EPS_SMALL ||
dYmax < dYmin + EPS_SMALL)
return false ;
// Rotazione nel piano XY globale
// Box della regione di interesse
BBox3d b3Region( dXmin, dYmin, 0, dXmax, dYmax, 0) ;
// Flag per calcolo box
const int BBF_MY_FLAG = BBF_ONLY_VISIBLE | BBF_IGNORE_TEXT | BBF_IGNORE_DIM ;
// Risolvo eventuali riferimenti a oggetti selezionati, compresi nella regione e
// calcolo il box del cluster risultante
INTVECTOR vTrueIds ;
vTrueIds.reserve( vIds.size()) ;
BBox3d b3Cluster ;
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_MY_FLAG) &&
b3Region.OverlapsXY( b3Part)) {
// 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()) ;
}
}
// Se non sono rimasti oggetti, esco con successo
if ( vTrueIds.empty())
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) ;
// Determino le regioni di tutti gli altri pezzi compresi nella regione di interesse
INTVECTOR vReg ;
INTVECTOR vCutReg ;
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_MY_FLAG) &&
b3Region.OverlapsXY( b3Part2)) {
// recupero regione del pezzo
int nRegId = GetFlatPartRegion( pGeomDB, nId2) ;
if ( nRegId != GDB_ID_NULL)
vReg.emplace_back( nRegId) ;
else
return false ;
// recupero regioni dei tagli del pezzo
if ( ! GetFlatPartCutRegions( pGeomDB, nId2, vCutReg))
return false ;
}
}
nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ;
}
// Creo SurfFlatRegion che delimita la regione valida
int nBoxId = CreateOutBoxRegion( pGeomDB, GDB_ID_ROOT, dXmin, dYmin, dXmax, dYmax) ;
if ( nBoxId == GDB_ID_NULL)
return false ;
// Verifico rotazione dei pezzi del cluster rispetto 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 le regioni degli altri pezzi
for ( int nOthRegId : vReg) {
ExeSurfFrRotateSimpleNoCollision( nRegId, nOthRegId, ptCen, dAng, RTY_GLOB) ;
}
// e con le regioni dei tagli degli altri pezzi
for ( int nOthCutRegId : vCutReg) {
ExeSurfFrRotateSimpleNoCollision( nRegId, nOthCutRegId, ptCen, dAng, RTY_GLOB) ;
}
// recupero regioni di lavorazione del pezzo
INTVECTOR vCrId ;
if ( ! GetFlatPartCutRegions( pGeomDB, nTrueId, vCrId)) {
bOk = false ;
break ;
}
// le confronto con le regioni degli altri pezzi
for ( int nCrId : vCrId) {
for ( int nOthRegId : vReg) {
ExeSurfFrRotateSimpleNoCollision( nCrId, nOthRegId, ptCen, dAng, RTY_GLOB) ;
}
}
}
// Elimino la regione aggiunta per il Box
pGeomDB->Erase( nBoxId) ;
// Se errore
if ( ! bOk)
return false ;
// Se movimento risultante nullo, non faccio alcunché
dRotAngDeg = dAng ;
if ( fabs( 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
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
int nCount = 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
Point3d ptRcen ;
if ( ! pSfr->GetCentroid( ptRcen))
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 ;
++ nCount ;
}
// Verifico di aver trovato qualcosa
if ( nCount == 0)
return false ;
// Medio il centro
ptCen /= nCount ;
return true ;
}