80631d875e
- migliorie a nesting (allineamento e rotazione).
921 lines
34 KiB
C++
921 lines
34 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 "/EgtDev/Include/EXeExecutor.h"
|
|
#include "/EgtDev/Include/EXeConst.h"
|
|
#include "/EgtDev/Include/EGkCurveComposite.h"
|
|
#include "/EgtDev/Include/EGkSfrCreate.h"
|
|
#include "/EgtDev/Include/EGkSimpleCDSurfFrMove.h"
|
|
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
|
#include "/EgtDev/Include/EMkMachiningGeoConst.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, NST_PART_REG) ;
|
|
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, bool bReduced, INTVECTOR& vCrId)
|
|
{
|
|
// recupero gruppo preview lavorazioni del pezzo
|
|
int nPVGrp = pGeomDB->GetFirstNameInGroup( nId, MCH_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, ( bReduced ? MCH_PV_RRCUT : MCH_PV_RCUT)) ;
|
|
while ( nCrId != GDB_ID_NULL) {
|
|
vCrId.emplace_back( nCrId) ;
|
|
nCrId = pGeomDB->GetNextName( nCrId, ( bReduced ? MCH_PV_RRCUT : MCH_PV_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, double dZ)
|
|
{
|
|
// creo polilinea attorno al box (avvolta a serpente)
|
|
const double SPESS = 100 ;
|
|
const double DELTA = 1 ;
|
|
PolyLine PL ;
|
|
PL.AddUPoint( 0, Point3d( dXmin, dYmin, dZ)) ;
|
|
PL.AddUPoint( 1, Point3d( dXmin, dYmax, dZ)) ;
|
|
PL.AddUPoint( 2, Point3d( dXmax, dYmax, dZ)) ;
|
|
PL.AddUPoint( 3, Point3d( dXmax, dYmin + DELTA + 2 * EPS_SMALL, dZ)) ;
|
|
PL.AddUPoint( 4, Point3d( dXmax + SPESS, dYmin + DELTA + 2 * EPS_SMALL, dZ)) ;
|
|
PL.AddUPoint( 5, Point3d( dXmax + 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, dYmin + DELTA, dZ)) ;
|
|
PL.AddUPoint( 10, Point3d( dXmax, dYmin + DELTA, dZ)) ;
|
|
PL.AddUPoint( 11, Point3d( dXmax, dYmin, dZ)) ;
|
|
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 ;
|
|
// recupero il riferimento del gruppo di inserimento
|
|
Frame3d frLoc ;
|
|
if ( ! pGeomDB->GetGroupGlobFrame( nParentId, frLoc))
|
|
return GDB_ID_NULL ;
|
|
// 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 GDB_ID_NULL ;
|
|
// assegno nome e la dichiaro temporanea e invisibile
|
|
pGeomDB->SetName( nId, NST_SHEET_OUTREG) ;
|
|
pGeomDB->SetLevel( nId, GDB_LV_SYSTEM) ;
|
|
pGeomDB->SetMaterial( nId, INVISIBLE) ;
|
|
return nId ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeVerifyPartCluster( const INTVECTOR& vIds, bool bReducedCut,
|
|
double dXmin, double dYmin, double dXmax, double dYmax)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// 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)) {
|
|
// 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 ;
|
|
|
|
// Determino le regioni dei pezzi rimasti
|
|
INTVECTOR vReg ;
|
|
INTVECTOR vCutReg ;
|
|
BBox3d b3RegCluster ;
|
|
for ( int nId : vTrueIds) {
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nId) ;
|
|
BBox3d b3Reg ;
|
|
if ( pGeomDB->GetGlobalBBox( nRegId, b3Reg, BBF_MY_FLAG)) {
|
|
vReg.emplace_back( nRegId) ;
|
|
b3RegCluster.Add( b3Reg) ;
|
|
}
|
|
else
|
|
return false ;
|
|
// recupero regioni dei tagli del pezzo
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nId, bReducedCut, vCutReg))
|
|
return false ;
|
|
}
|
|
|
|
// Verifico di essere all'interno del box esterno
|
|
if ( ! b3Region.EnclosesXY( b3RegCluster))
|
|
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) ;
|
|
// Determino le regioni di tutti gli altri pezzi compresi nella regione di interesse
|
|
INTVECTOR vOthReg ;
|
|
INTVECTOR vOthCutReg ;
|
|
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) &&
|
|
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 regioni dei tagli del pezzo
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nId2, bReducedCut, vOthCutReg))
|
|
return false ;
|
|
}
|
|
}
|
|
nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ;
|
|
}
|
|
|
|
// Eseguo verifiche
|
|
bool bOk = true ;
|
|
// regioni dei pezzi
|
|
for ( int nRegId : vReg) {
|
|
// verifico con le regioni degli altri pezzi
|
|
for ( int nOthRegId : vOthReg) {
|
|
if ( ExeSurfFrChunkSimpleClassify( nRegId, 0, nOthRegId, 0) != REGC_OUT)
|
|
bOk = false ;
|
|
}
|
|
// e con le regioni dei tagli degli altri pezzi
|
|
for ( int nOthCutRegId : vOthCutReg) {
|
|
if ( ExeSurfFrChunkSimpleClassify( nRegId, 0, nOthCutRegId, 0) != REGC_OUT)
|
|
bOk = false ;
|
|
}
|
|
}
|
|
// regioni delle lavorazioni dei pezzi
|
|
for ( int nCutRegId : vCutReg) {
|
|
// le confronto con le regioni degli altri pezzi
|
|
for ( int nOthRegId : vOthReg) {
|
|
if ( ExeSurfFrChunkSimpleClassify( nCutRegId, 0, nOthRegId, 0) != REGC_OUT)
|
|
bOk = false ;
|
|
}
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
MyPackPartCluster( const INTVECTOR& vIds, bool bReducedCut,
|
|
double dXmin, double dYmin, double dXmax, double dYmax, bool bBottomUp)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
// Verifiche sui parametri
|
|
if ( dXmax < dXmin + EPS_SMALL ||
|
|
dYmax < dYmin + EPS_SMALL)
|
|
return 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 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) ;
|
|
|
|
// 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 ;
|
|
|
|
// 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_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) ;
|
|
|
|
// 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, dXmin, dYmin, dXmax, dYmax) ;
|
|
Vector3d vtMoveX = - BIG_MOVE * X_AX ;
|
|
ExeMovePartCluster( vTrueIds, bReducedCut, vtMoveX, dXmin, dYmin, dXmax, dYmax) ;
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExePackPartCluster( const INTVECTOR& vIds, bool bReducedCut,
|
|
double dXmin, double dYmin, double dXmax, double dYmax, bool bBottomUp)
|
|
{
|
|
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 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, dXmin, dYmin, dXmax, dYmax)) {
|
|
return true ;
|
|
}
|
|
// altrimenti, riprovo con tagli standard
|
|
else {
|
|
return MyPackPartCluster( vTrueIds, false, dXmin, dYmin, dXmax, dYmax, bBottomUp) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static SCollInfo s_scInfo ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static double
|
|
UpdateCollId( double dLen, double dPrevLen, int nId1, int nId2, 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 ;
|
|
}
|
|
return dPrevLen ;
|
|
}
|
|
else if ( dLen < dPrevLen) {
|
|
s_scInfo = scInfoCurr ;
|
|
s_scInfo.nIdM = nId1 ;
|
|
s_scInfo.nIdF = nId2 ;
|
|
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( CloneSurfFlatRegion( pSfr2)) ;
|
|
bOk = bOk && ! IsNull( pTmp) ;
|
|
bOk = bOk && pTmp->LocToLoc( frSurf2, frSurf1) ;
|
|
pSfr2L = Get( 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
|
|
SimpleCDSurfFrMove 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( const INTVECTOR& vIds, bool bReducedCut, 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 ;
|
|
|
|
// 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 ;
|
|
|
|
// 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 vOthReg ;
|
|
INTVECTOR vOthCutReg ;
|
|
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)
|
|
vOthReg.emplace_back( nRegId) ;
|
|
else
|
|
return false ;
|
|
// recupero regioni dei tagli del pezzo
|
|
if ( ! GetFlatPartCutRegions( pGeomDB, nId2, bReducedCut, vOthCutReg))
|
|
return false ;
|
|
}
|
|
}
|
|
nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ;
|
|
}
|
|
|
|
// Se non esiste, creo SurfFlatRegion che delimita la regione valida
|
|
int nBoxId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_SHEET_OUTREG) ;
|
|
if ( nBoxId == GDB_ID_NULL)
|
|
nBoxId = CreateOutBoxRegion( pGeomDB, nGroupId, dXmin, dYmin, dXmax, dYmax, b3Cluster.GetMin().z) ;
|
|
if ( nBoxId == GDB_ID_NULL)
|
|
return false ;
|
|
|
|
// Verifico movimento dei pezzi del cluster rispetto 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) {
|
|
// recupero regione del pezzo
|
|
int nRegId = GetFlatPartRegion( pGeomDB, nTrueId) ;
|
|
if ( nRegId == GDB_ID_NULL) {
|
|
bOk = false ;
|
|
break ;
|
|
}
|
|
// info di collisione correnti
|
|
SCollInfo scInfoCurr ;
|
|
// la confronto con il box
|
|
MySurfFrMoveSimpleNoCollision( nRegId, nBoxId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nRegId, nBoxId, 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, scInfoCurr) ;
|
|
}
|
|
// e con le regioni dei tagli degli altri pezzi
|
|
for ( int nOthCutRegId : vOthCutReg) {
|
|
MySurfFrMoveSimpleNoCollision( nRegId, nOthCutRegId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nRegId, nOthCutRegId, 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 ( int nOthRegId : vOthReg) {
|
|
MySurfFrMoveSimpleNoCollision( nCrId, nOthRegId, vtDir, dLen, scInfoCurr) ;
|
|
dPrevLen = UpdateCollId( dLen, dPrevLen, nCrId, nOthRegId, scInfoCurr) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Se errore
|
|
if ( ! bOk)
|
|
return false ;
|
|
|
|
// Log provvisorio
|
|
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,
|
|
double dXmin, double dYmin, double dXmax, double dYmax)
|
|
{
|
|
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 con tagli ridotti
|
|
if ( bReducedCut) {
|
|
return MyMovePartCluster( vTrueIds, true, vtMove, dXmin, dYmin, dXmax, dYmax) ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
// provo con tagli ridotti
|
|
Vector3d vtM = vtMove ;
|
|
if ( ! MyMovePartCluster( vTrueIds, true, vtM, dXmin, dYmin, dXmax, dYmax))
|
|
return false ;
|
|
// se posizione valida
|
|
if ( ExeVerifyPartCluster( vTrueIds, false, dXmin, dYmin, dXmax, dYmax)) {
|
|
vtMove = vtM ;
|
|
return true ;
|
|
}
|
|
// altrimenti, riprovo con tagli standard
|
|
else {
|
|
// annullo il movimento
|
|
for ( int nId : vTrueIds)
|
|
pGeomDB->TranslateGlob( nId, - vtM) ;
|
|
// riprovo
|
|
return MyMovePartCluster( vTrueIds, false, vtMove, dXmin, dYmin, dXmax, dYmax) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeGetObstacleTangent( Vector3d& vtTang)
|
|
{
|
|
if ( s_scInfo.nType != SCI_PNT_LINE && s_scInfo.nType != SCI_LINE_LINE)
|
|
return false ;
|
|
vtTang = s_scInfo.vtDirF ;
|
|
return vtTang.Normalize() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeGetMovingTangent( 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
|
|
ExeRotatePartCluster( const INTVECTOR& vIds, bool bReducedCut, 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 ;
|
|
|
|
// Reset info di collisione
|
|
s_scInfo.nType = SCI_NONE ;
|
|
|
|
// 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, bReducedCut, vCutReg))
|
|
return false ;
|
|
}
|
|
}
|
|
nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ;
|
|
}
|
|
|
|
// Creo SurfFlatRegion che delimita la regione valida
|
|
int nBoxId = pGeomDB->GetFirstNameInGroup( nGroupId, NST_SHEET_OUTREG) ;
|
|
if ( nBoxId == GDB_ID_NULL)
|
|
nBoxId = CreateOutBoxRegion( pGeomDB, nGroupId, dXmin, dYmin, dXmax, dYmax, b3Cluster.GetMin().z) ;
|
|
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, bReducedCut, 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) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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
|
|
ExeAlignPartClusterOnCollision( const INTVECTOR& vIds, bool bReducedCut,
|
|
double dXmin, double dYmin, double dXmax, double dYmax)
|
|
{
|
|
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 ;
|
|
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) ;
|
|
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 ;
|
|
return ExeRotatePartCluster( vIds, bReducedCut, ptCen, dRotAngDeg, dXmin, dYmin, dXmax, dYmax) ;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
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 ;
|
|
}
|