Files
EgtMachKernel/MachMgrRawParts.cpp
T
DarioS b82cdd0bc7 EgtMachKernel :
- corretto link tra lavorazioni quando HomeZ standard non va bene ma serve GetExtraZ
- disabilitate svuotature a spirale ottimizzate per problemi quando ci sono tre lati aperti
- sistemate maiuscole/minuscole nei nomi dei file inclusi.
2022-02-26 17:53:11 +01:00

1050 lines
40 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : MachMgr.cpp Data : 16.04.15 Versione : 1.6d3
// Contenuto : Implementazione gestione grezzi e pezzi della classe MachMgr.
//
//
//
// Modifiche : 16.04.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "DllMain.h"
#include "MachMgr.h"
#include "MachConst.h"
#include "Disposition.h"
#include "/EgtDev/Include/EMkMachiningGeoConst.h"
#include "/EgtDev/Include/EXeCmdLogOff.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkGdbIterator.h"
#include "/EgtDev/Include/EGkGeoPoint3d.h"
#include "/EgtDev/Include/EGkCurveAux.h"
#include "/EgtDev/Include/EGkOffsetCurve.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EGkStmStandard.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
int
MachMgr::GetRawPartCount( void) const
{
// recupero il gruppo dei grezzi nella macchinata corrente
int nRawGroupId = GetCurrRawGroupId() ;
if ( nRawGroupId == GDB_ID_NULL)
return 0 ;
// ritorno numero dei grezzi della macchinata
return m_pGeomDB->GetGroupObjs( nRawGroupId) ;
}
//----------------------------------------------------------------------------
int
MachMgr::GetFirstRawPart( void) const
{
// recupero il gruppo dei grezzi nella macchinata corrente
int nRawGroupId = GetCurrRawGroupId() ;
if ( nRawGroupId == GDB_ID_NULL)
return GDB_ID_NULL ;
// recupero il primo sottogruppo
int nId = m_pGeomDB->GetFirstGroupInGroup( nRawGroupId) ;
return nId ;
}
//----------------------------------------------------------------------------
int
MachMgr::GetNextRawPart( int nId) const
{
// recupero il gruppo dei grezzi nella macchinata corrente
int nRawGroupId = GetCurrRawGroupId() ;
if ( nRawGroupId == GDB_ID_NULL)
return GDB_ID_NULL ;
// verifico che il gruppo ricevuto sia corretto
if ( m_pGeomDB->GetParentId( nId) != nRawGroupId)
return GDB_ID_NULL ;
// recupero il successivo sottogruppo
int nNextId = m_pGeomDB->GetNextGroup( nId) ;
return nNextId ;
}
//----------------------------------------------------------------------------
int
MachMgr::AddRawPart( const Point3d& ptOrig, double dLen, double dWidth, double dHeight, Color cCol)
{
// recupero il gruppo dei grezzi nella macchinata corrente
int nRawGroupId = GetCurrRawGroupId() ;
if ( nRawGroupId == GDB_ID_NULL)
return GDB_ID_NULL ;
// se definita una tavola corrente, esprimo il punto rispetto alla sua prima origine
Point3d ptMyOrig = ptOrig ;
Point3d ptRef1 ;
if ( GetTableRef( 1, ptRef1))
ptMyOrig += ptRef1 ;
// inserisco il gruppo del grezzo nei grezzi della macchinata
int nRawId = m_pGeomDB->AddGroup( GDB_ID_NULL, nRawGroupId, Frame3d( ptMyOrig)) ;
if ( nRawId == GDB_ID_NULL)
return GDB_ID_NULL ;
// assegno il nome al gruppo
bool bOk = m_pGeomDB->SetName( nRawId, MACH_RAW_PART) ;
// assegno la fase al gruppo
m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, m_nCurrPhase) ;
// creo solido e outline
bOk = bOk && ModifyRawPart( nRawId, ptOrig, dLen, dWidth, dHeight, cCol) ;
// se qualcosa è andato storto, cancello tutto
if ( ! bOk) {
m_pGeomDB->Erase( nRawId) ;
return GDB_ID_NULL ;
}
// tutto ok
return nRawId ;
}
//----------------------------------------------------------------------------
bool
MachMgr::ModifyRawPart( int nRawId, const Point3d& ptOrig, double dLen, double dWidth, double dHeight, Color cCol)
{
// le dimensioni non possono essere nulle
if ( dLen < EPS_SMALL || dWidth < EPS_SMALL || dHeight < EPS_SMALL)
return false ;
// verifica validità grezzo
if ( ! VerifyRawPart( nRawId))
return false ;
// creo il solido
PtrOwner<ISurfTriMesh> pStm( GetSurfTriMeshBox( dLen, dWidth, dHeight)) ;
if ( IsNull( pStm))
return false ;
// creo il contorno esterno
PolyLine PL ;
PL.AddUPoint( 0, ORIG) ;
PL.AddUPoint( 1, Point3d( dLen, 0, 0)) ;
PL.AddUPoint( 2, Point3d( dLen, dWidth, 0)) ;
PL.AddUPoint( 3, Point3d( 0, dWidth, 0)) ;
PL.AddUPoint( 4, ORIG) ;
// creo la curva
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( PL) || ! pCrvCompo->SetExtrusion( Z_AX))
return false ;
// cancello eventuali vecchi solidi e curve di outline
int nOldRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
if ( nOldRawSolId != GDB_ID_NULL)
m_pGeomDB->Erase( nOldRawSolId) ;
int nOldRawOutId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ;
if ( nOldRawOutId != GDB_ID_NULL)
m_pGeomDB->Erase( nOldRawOutId) ;
// se definita una tavola corrente, esprimo il punto rispetto alla sua prima origine
Point3d ptMyOrig = ptOrig ;
Point3d ptRef1 ;
if ( GetTableRef( 1, ptRef1))
ptMyOrig += ptRef1 ;
// aggiorno l'origine del gruppo
m_pGeomDB->GetGroupFrame( nRawId)->ChangeOrig( ptMyOrig) ;
// inserisco il solido nel gruppo
int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pStm)) ;
bool bOk = ( nId != GDB_ID_NULL) ;
// assegno il nome al solido
bOk = bOk && m_pGeomDB->SetName( nId, MACH_RAW_SOLID) ;
// assegno il colore al solido
bOk = bOk && m_pGeomDB->SetMaterial( nId, cCol) ;
// calcolo il punto centro del solido
bOk = bOk && SetRawPartCenter( nRawId) ;
// inserisco la curva composita nel DB
int nCrvId = ( bOk ? m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pCrvCompo)) : GDB_ID_NULL) ;
bOk = bOk && ( nCrvId != GDB_ID_NULL) ;
// assegno il nome al contorno
bOk = bOk && m_pGeomDB->SetName( nCrvId, MACH_RAW_OUTLINE) ;
// assegno il colore al contorno
bOk = bOk && m_pGeomDB->SetMaterial( nCrvId, cCol) ;
return bOk ;
}
//----------------------------------------------------------------------------
int
MachMgr::AddRawPartWithPart( int nPartId, int nCrvSrfId, double dOverMat, Color cCol)
{
// verifico il gruppo dei grezzi nella macchinata corrente
if ( GetCurrRawGroupId() == GDB_ID_NULL)
return GDB_ID_NULL ;
// verifico che il pezzo non sia già usato nella macchinata corrente
if ( m_pGeomDB->GetParentId( nPartId) != GDB_ID_ROOT)
return GDB_ID_NULL ;
// recupero il tipo di oggetto per definire il grezzo
int nGtype = m_pGeomDB->GetGeoType( nCrvSrfId) ;
// punto di riferimento del pezzo nel grezzo
Point3d ptRef ;
// costruzione del grezzo
int nRawId = GDB_ID_NULL ;
// se grezzo da superficie (per ora senza possibilità di offset)
if ( ( nGtype & GEO_SURF) != 0) {
// inserisco il grezzo
nRawId = AddRawPart( nCrvSrfId, cCol) ;
// annullo il sovra-materiale
dOverMat = 0 ;
// calcolo il punto di inserimento nel grezzo
// determino l'ingombro del pezzo
BBox3d b3Part ;
if ( ! m_pGeomDB->GetGlobalBBox( nPartId, b3Part, BBF_EXACT))
return GDB_ID_NULL ;
// recupero il box del solido del grezzo in globale
int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
BBox3d b3RawSolid ;
if ( ! m_pGeomDB->GetGlobalBBox( nRawSolidId, b3RawSolid))
return false ;
// calcolo il punto di inserimento (come differenza tra i punti minimi)
ptRef = b3Part.GetMin() + ( ORIG - b3RawSolid.GetMin()) ;
}
// se altrimenti grezzo da contorno
else if ( ( nGtype & GEO_CURVE) != 0) {
// determino l'ingombro del pezzo
BBox3d b3Part ;
if ( ! m_pGeomDB->GetGlobalBBox( nPartId, b3Part, BBF_EXACT))
return GDB_ID_NULL ;
// inserisco il grezzo
double dZmin = b3Part.GetMin().z ;
double dH = ( b3Part.GetMax() - b3Part.GetMin()).z ;
if ( dH < RAW_MIN_H)
dH = RAW_MIN_H ;
nRawId = AddRawPart( nCrvSrfId, dOverMat, dZmin, dH, cCol) ;
// calcolo il punto di inserimento nel grezzo
// recupero il box del solido del grezzo in globale
int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
BBox3d b3RawSolid ;
if ( ! m_pGeomDB->GetGlobalBBox( nRawSolidId, b3RawSolid))
return false ;
// calcolo il punto di inserimento (come differenza tra i punti minimi)
ptRef = b3Part.GetMin() + ( ORIG - b3RawSolid.GetMin()) ;
}
// altrimenti grezzo rettangolare da ingombro pezzo
else {
// determino l'ingombro del pezzo
BBox3d b3Part ;
if ( ! m_pGeomDB->GetGlobalBBox( nPartId, b3Part, BBF_EXACT))
return GDB_ID_NULL ;
// deduco i dati del grezzo
b3Part.Expand( dOverMat, dOverMat, 0) ;
Vector3d vtDiff = b3Part.GetMax() - b3Part.GetMin() ;
if ( vtDiff.z < RAW_MIN_H)
vtDiff.z = RAW_MIN_H ;
// inserisco il grezzo
nRawId = AddRawPart( ORIG, vtDiff.x, vtDiff.y, vtDiff.z, cCol) ;
// il riferimento deve tenere conto dell'offset
ptRef = Point3d( dOverMat, dOverMat, 0) ;
}
// verifico costruzione grezzo
if ( nRawId == GDB_ID_NULL)
return GDB_ID_NULL ;
// se definita tavola, aggiusto posizione del grezzo
Point3d ptTabRef ;
if ( GetTableRef( 1, ptTabRef)) {
// recupero box del solido
int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
BBox3d b3RawSolid ;
// lo porto nell'angolo in basso a sinistra della tavola
if ( m_pGeomDB->GetGlobalBBox( nRawSolidId, b3RawSolid))
m_pGeomDB->TranslateGlob( nRawId, ptTabRef - b3RawSolid.GetMin()) ;
}
// inserisco il pezzo nel grezzo
if ( ! AddPartToRawPart( nPartId, ptRef, nRawId)) {
RemoveRawPart( nRawId) ;
return GDB_ID_NULL ;
}
return nRawId ;
}
//----------------------------------------------------------------------------
int
MachMgr::AddRawPart( int nCrvId, double dOverMat, double dZmin, double dHeight, Color cCol)
{
// recupero il gruppo dei grezzi nella macchinata corrente
int nRawGroupId = GetCurrRawGroupId() ;
if ( nRawGroupId == GDB_ID_NULL)
return GDB_ID_NULL ;
// recupero l'ingombro della curva in globale
BBox3d b3Crv ;
if ( ! m_pGeomDB->GetGlobalBBox( nCrvId, b3Crv))
return GDB_ID_NULL ;
// determino il riferimento del grezzo
Point3d ptOrig = b3Crv.GetMin() ;
ptOrig.z = dZmin ;
Frame3d frRaw( ptOrig) ;
// inserisco il gruppo del grezzo nella macchinata
int nRawId = m_pGeomDB->AddGroup( GDB_ID_NULL, nRawGroupId, frRaw) ;
if ( nRawId == GDB_ID_NULL)
return GDB_ID_NULL ;
// assegno il nome al gruppo
bool bOk = m_pGeomDB->SetName( nRawId, MACH_RAW_PART) ;
// assegno la fase al gruppo
m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, m_nCurrPhase) ;
// creo solido e outline
bOk = bOk && ModifyRawPart( nRawId, nCrvId, dOverMat, dZmin, dHeight, cCol) ;
// se qualcosa è andato storto, cancello tutto
if ( ! bOk) {
m_pGeomDB->Erase( nRawId) ;
return GDB_ID_NULL ;
}
// tutto ok
return nRawId ;
}
//----------------------------------------------------------------------------
bool
MachMgr::ModifyRawPart( int nRawId, int nCrvId, double dOverMat, double dZmin, double dHeight, Color cCol)
{
// verifica validità grezzo
if ( ! VerifyRawPart( nRawId))
return false ;
// recupero il riferimento della curva
Frame3d frCrv ;
if ( ! m_pGeomDB->GetGlobFrame( nCrvId, frCrv))
return false ;
// recupero la curva
const ICurve* pCrv = GetCurve( m_pGeomDB->GetGeoObj( nCrvId)) ;
if ( pCrv == nullptr)
return false ;
// copio la curva in una composita
PtrOwner<ICurveComposite> pMyCrv( CreateCurveComposite()) ;
if ( IsNull( pMyCrv) || ! pMyCrv->AddCurve( *pCrv))
return false ;
// determino il riferimento del grezzo
Frame3d frRaw ;
if ( ! m_pGeomDB->GetGroupGlobFrame( nRawId, frRaw))
return false ;
// porto la curva in questo riferimento
pMyCrv->LocToLoc( frCrv, frRaw) ;
// la schiaccio a Z = 0
if ( ! pMyCrv->Scale( Frame3d(), 1, 1, 0))
return false ;
// se non è chiusa, la chiudo
pMyCrv->Close() ;
// la oriento in senso CCW
double dAreaXY ;
if ( ! pMyCrv->GetAreaXY( dAreaXY))
return false ;
if ( dAreaXY < 0)
pMyCrv->Invert() ;
// ne eseguo l'offset
OffsetCurve OffsCrv ;
OffsCrv.Make( pMyCrv, dOverMat, ICurve::OFF_EXTEND) ;
PtrOwner<ICurve> pOffsCrv( OffsCrv.GetLongerCurve()) ;
if ( IsNull( pOffsCrv))
return false ;
// creo il solido
PtrOwner<ISurfTriMesh> pStm( GetSurfTriMeshByExtrusion( pOffsCrv, Vector3d(0,0,dHeight), true)) ;
if ( IsNull( pStm))
return false ;
// cancello eventuali vecchi solidi e curve di outline
int nOldRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
if ( nOldRawSolId != GDB_ID_NULL)
m_pGeomDB->Erase( nOldRawSolId) ;
int nOldRawOutId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ;
if ( nOldRawOutId != GDB_ID_NULL)
m_pGeomDB->Erase( nOldRawOutId) ;
// inserisco il solido nel gruppo
int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pStm)) ;
bool bOk = ( nId != GDB_ID_NULL) ;
// assegno il nome al solido
bOk = bOk && m_pGeomDB->SetName( nId, MACH_RAW_SOLID) ;
// assegno il colore al solido
bOk = bOk && m_pGeomDB->SetMaterial( nId, cCol) ;
// calcolo il punto centro del solido
bOk = bOk && SetRawPartCenter( nRawId) ;
// inserisco nel DB la curva di offset come contorno del grezzo
int nOutCrvId = ( bOk ? m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pOffsCrv)) : GDB_ID_NULL) ;
bOk = bOk && ( nOutCrvId != GDB_ID_NULL) ;
// assegno il nome al contorno
bOk = bOk && m_pGeomDB->SetName( nOutCrvId, MACH_RAW_OUTLINE) ;
// assegno il colore al contorno
bOk = bOk && m_pGeomDB->SetMaterial( nOutCrvId, cCol) ;
return bOk ;
}
//----------------------------------------------------------------------------
int
MachMgr::AddRawPart( int nSurfId, Color cCol)
{
// recupero il gruppo dei grezzi nella macchinata corrente
int nRawGroupId = GetCurrRawGroupId() ;
if ( nRawGroupId == GDB_ID_NULL)
return GDB_ID_NULL ;
// recupero l'ingombro della superficie in globale
BBox3d b3Crv ;
if ( ! m_pGeomDB->GetGlobalBBox( nSurfId, b3Crv))
return GDB_ID_NULL ;
// inserisco il gruppo del grezzo nella macchinata
Frame3d frRaw( b3Crv.GetMin()) ;
int nRawId = m_pGeomDB->AddGroup( GDB_ID_NULL, nRawGroupId, frRaw) ;
if ( nRawId == GDB_ID_NULL)
return GDB_ID_NULL ;
// assegno il nome al gruppo
bool bOk = m_pGeomDB->SetName( nRawId, MACH_RAW_PART) ;
// assegno la fase al gruppo
m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, m_nCurrPhase) ;
// copio la superficie nel gruppo
int nId = m_pGeomDB->CopyGlob( nSurfId, GDB_ID_NULL, nRawId) ;
bOk = bOk && ( nId != GDB_ID_NULL) ;
// assegno il nome al solido
bOk = bOk && m_pGeomDB->SetName( nId, MACH_RAW_SOLID) ;
// assegno il colore al solido
bOk = bOk && m_pGeomDB->SetMaterial( nId, cCol) ;
// rendo visibile il solido
bOk = bOk && m_pGeomDB->SetStatus( nId, GDB_ST_ON) ;
// calcolo il punto centro del solido
bOk = bOk && SetRawPartCenter( nRawId) ;
// calcolo la curva di contorno
if ( bOk) {
// creo la curva
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo))
return GDB_ID_NULL ;
// recupero la superficie trimesh
ISurfTriMesh* pStm = GetSurfTriMesh( m_pGeomDB->GetGeoObj( nId)) ;
if ( pStm == nullptr)
return GDB_ID_NULL ;
// recupero l'ingombro della superficie in locale
BBox3d b3Srf ;
pStm->GetLocalBBox( b3Srf) ;
// ne calcolo la silhouette secondo Z+
POLYLINEVECTOR vPL ;
bool bSilh = false ;
if ( pStm->GetSilhouette( Z_AX, 10.0, vPL) && vPL.size() > 0) {
// cerco il contorno esterno
int nInd = - 1 ;
double dMaxArea = 0 ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
double dArea ;
if ( vPL[i].GetAreaXY( dArea) && abs( dArea) > dMaxArea) {
if ( dArea < 0)
vPL[i].Invert() ;
dMaxArea = abs( dArea) ;
nInd = i ;
}
}
// ne deduco la curva
PtrOwner<ICurveComposite> pCrvSilh( CreateCurveComposite()) ;
if ( nInd >= 0 && pCrvSilh->FromPolyLine( vPL[nInd])) {
pCrvSilh->SetExtrusion( Z_AX) ;
Plane3d plProj ;
plProj.Set( b3Srf.GetMin(), Z_AX) ;
pCrvCompo.Set( GetCurveComposite( ProjectCurveOnPlane( *pCrvSilh, plProj))) ;
pCrvCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ;
bSilh = ( ! IsNull( pCrvCompo)) ;
}
}
// non riuscita, la calcolo come contorno del box
if ( ! bSilh) {
Point3d ptMin ;
double dDimX, dDimY, dDimZ ;
b3Srf.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ;
PolyLine PL ;
PL.AddUPoint( 0, ptMin) ;
PL.AddUPoint( 1, ptMin + Vector3d( dDimX, 0,0)) ;
PL.AddUPoint( 2, ptMin + Vector3d( dDimX, dDimY,0)) ;
PL.AddUPoint( 3, ptMin + Vector3d( 0, dDimY,0)) ;
PL.AddUPoint( 4, ptMin) ;
if ( ! pCrvCompo->FromPolyLine( PL) && ! pCrvCompo->SetExtrusion( Z_AX))
bOk = false ;
}
// inserisco la curva composita nel DB
int nCrvId = ( bOk ? m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pCrvCompo)) : GDB_ID_NULL) ;
bOk = bOk && ( nCrvId != GDB_ID_NULL) ;
// assegno il nome alla curva
bOk = bOk && m_pGeomDB->SetName( nCrvId, MACH_RAW_SOLID) ;
// assegno il colore alla curva
bOk = bOk && m_pGeomDB->SetMaterial( nCrvId, cCol) ;
}
// se qualcosa è andato storto, cancello tutto
if ( ! bOk) {
m_pGeomDB->Erase( nRawId) ;
return GDB_ID_NULL ;
}
// nascondo la superficie originale
m_pGeomDB->SetStatus( nSurfId, GDB_ST_OFF) ;
// tutto ok
return nRawId ;
}
//----------------------------------------------------------------------------
bool
MachMgr::ModifyRawPartSize( int nRawId, double dLength, double dWidth, double dHeight)
{
// le nuove dimensioni non possono essere nulle
if ( dLength < EPS_SMALL || dWidth < EPS_SMALL || dHeight < EPS_SMALL)
return false ;
// verifica validità grezzo
if ( ! VerifyRawPart( nRawId))
return false ;
// recupero il solido del grezzo
int nRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
if ( nRawSolId == GDB_ID_NULL)
return false ;
// recupero il contorno del grezzo
int nRawOutId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ;
if ( nRawOutId == GDB_ID_NULL)
return false ;
// recupero il box del grezzo
BBox3d b3Raw ;
if ( ! m_pGeomDB->GetLocalBBox( nRawSolId, b3Raw))
return false ;
// determino il coefficente di scalatura in X
double dOldL = b3Raw.GetMax().x - b3Raw.GetMin().x ;
if ( dOldL < EPS_SMALL)
return false ;
double dCoeffX = dLength / dOldL ;
// determino il coefficente di scalatura in Y
double dOldW = b3Raw.GetMax().y - b3Raw.GetMin().y ;
if ( dOldW < EPS_SMALL)
return false ;
double dCoeffY = dWidth / dOldW ;
// determino il coefficente di scalatura in Z
double dOldH = b3Raw.GetMax().z - b3Raw.GetMin().z ;
if ( dOldH < EPS_SMALL)
return false ;
double dCoeffZ = dHeight / dOldH ;
// eseguo scalature
bool bOk = m_pGeomDB->Scale( nRawSolId, Frame3d( b3Raw.GetMin()), dCoeffX, dCoeffY, dCoeffZ) &&
m_pGeomDB->Scale( nRawOutId, Frame3d( b3Raw.GetMin()), dCoeffX, dCoeffY, dCoeffZ) ;
// calcolo il punto centro del solido
bOk = bOk && SetRawPartCenter( nRawId) ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
MachMgr::ModifyRawPartHeight( int nRawId, double dHeight)
{
// la nuova altezza non può essere nulla
if ( dHeight < EPS_SMALL)
return false ;
// verifica validità grezzo
if ( ! VerifyRawPart( nRawId))
return false ;
// recupero il solido del grezzo
int nRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
if ( nRawSolId == GDB_ID_NULL)
return false ;
// recupero il box del grezzo
BBox3d b3Raw ;
if ( ! m_pGeomDB->GetLocalBBox( nRawSolId, b3Raw))
return false ;
// determino il coefficente di scalatura in Z
double dOldH = b3Raw.GetMax().z - b3Raw.GetMin().z ;
if ( dOldH < EPS_SMALL)
return false ;
double dCoeff = dHeight / dOldH ;
// eseguo scalatura
bool bOk = m_pGeomDB->Scale( nRawSolId, Frame3d( b3Raw.GetMin()), 1, 1, dCoeff) ;
// calcolo il punto centro del solido
bOk = bOk && SetRawPartCenter( nRawId) ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
MachMgr::GetRawPartPhases( int nRawId, INTVECTOR& vPhase) const
{
// pulisco parametro di ritorno
vPhase.clear() ;
// verifica validità grezzo
if ( ! VerifyRawPart( nRawId))
return false ;
// recupero le fasi in cui è presente il grezzo (se manca è fase 1)
if ( ! m_pGeomDB->GetInfo( nRawId, MACH_RAW_PHASE, vPhase) || vPhase.empty())
vPhase.emplace_back( 1) ;
return true ;
}
//----------------------------------------------------------------------------
bool
MachMgr::KeepRawPart( int nRawId, int nSouPhase)
{
// verifico validità e recupero fasi in cui è presente
INTVECTOR vPhase ;
if ( ! GetRawPartPhases( nRawId, vPhase))
return false ;
// se fase corrente già presente, non devo fare alcunché
if ( find( vPhase.begin(), vPhase.end(), m_nCurrPhase) != vPhase.end())
return true ;
// aggiungo la fase corrente
vPhase.emplace_back( m_nCurrPhase) ;
if ( ! m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, vPhase))
return false ;
// annullo eventuali movimenti del grezzo (riferimento riportato a globale)
Frame3d* pfrRaw = m_pGeomDB->GetGroupFrame( nRawId) ;
if ( pfrRaw == nullptr)
return false ;
pfrRaw->Reset() ;
// visualizzo il grezzo e ne attivo i pezzi
if ( ! m_pGeomDB->SetStatus( nRawId, GDB_ST_ON))
return false ;
if ( ! SwapRawPartParts( nRawId, true))
return false ;
// se fase di origine non definita, esco con successo
if ( nSouPhase == 0)
return true ;
// copio il posizionamento
Disposition* pSouDisp = GetDisposition( m_pGeomDB->GetUserObj( GetPhaseDisposition( nSouPhase))) ;
Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( GetPhaseDisposition( m_nCurrPhase))) ;
if ( pSouDisp == nullptr || pDisp == nullptr)
return false ;
for ( int i = 0 ; ; ++ i) {
int nId ; int nType ; Point3d ptPos ; int nFlag ;
if ( pSouDisp->GetMoveRawData( i, nId, nType, ptPos, nFlag)) {
if ( nId == nRawId) {
switch ( nType) {
case MoveRawData::COR :
pDisp->MoveToCornerRawPart( nRawId, ptPos, nFlag, true, false) ;
break ;
case MoveRawData::CEN :
pDisp->MoveToCenterRawPart( nRawId, ptPos, nFlag, true, false) ;
break ;
case MoveRawData::ROT :
pDisp->ApplyRotationToRawPart( nRawId, ptPos.x, ptPos.y, ptPos.z, true) ;
break ;
}
}
}
else
break ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
MachMgr::VerifyRawPartPhase( int nRawId, int nPhase) const
{
// verifico validità e recupero fasi in cui è presente
INTVECTOR vPhase ;
if ( ! GetRawPartPhases( nRawId, vPhase))
return false ;
return ( find( vPhase.begin(), vPhase.end(), nPhase) != vPhase.end()) ;
}
//----------------------------------------------------------------------------
bool
MachMgr::RemoveRawPartFromCurrPhase( int nRawId)
{
// verifico validità e recupero fasi in cui è presente
INTVECTOR vPhase ;
if ( ! GetRawPartPhases( nRawId, vPhase))
return false ;
// se non appartiene alla fase corrente, non devo fare alcunché
auto iIter = find( vPhase.begin(), vPhase.end(), m_nCurrPhase) ;
if ( iIter == vPhase.end())
return true ;
// se appartiene solo a questa fase, lo elimino
if ( vPhase.size() == 1)
RemoveRawPart( nRawId) ;
// altrimenti
else {
// tolgo dalla disposizione corrente gli eventuali movimenti registrati di questo grezzo
Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( GetPhaseDisposition( m_nCurrPhase))) ;
if ( pDisp != nullptr)
pDisp->RemoveRawPart( nRawId) ;
// aggiorno l'elenco delle fasi di appartenenza
vPhase.erase( iIter) ;
m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, vPhase) ;
// tolgo i pezzi dal grezzo e lo nascondo
SwapRawPartParts( nRawId, false) ;
m_pGeomDB->SetStatus( nRawId, GDB_ST_OFF) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
MachMgr::RemoveRawPart( int nRawId)
{
// verifica validità grezzo
if ( ! VerifyRawPart( nRawId))
return false ;
// tolgo dalle disposizioni in cui compare gli eventuali movimenti registrati di questo grezzo
for ( int nPhase = 1 ; nPhase <= m_nPhasesCount ; ++ nPhase) {
Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( GetPhaseDisposition( nPhase))) ;
if ( pDisp != nullptr)
pDisp->RemoveRawPart( nRawId) ;
}
// devo estrarre i pezzi e riportarli in lista generale
SwapRawPartParts( nRawId, false) ;
// cancello il grezzo
m_pGeomDB->Erase( nRawId) ;
return true ;
}
//----------------------------------------------------------------------------
bool
MachMgr::VerifyRawPart( int nRawId, bool bLinkedAllowed) const
{
// se il grezzo fa parte del gruppo dei grezzi, va bene
int nRawGroupId = GetCurrRawGroupId() ;
if ( nRawGroupId != GDB_ID_NULL && m_pGeomDB->GetParentId( nRawId) == nRawGroupId)
return true ;
// se consentito linkaggio ed il grezzo è linkato ad un gruppo della macchina corrente, va bene
if ( bLinkedAllowed) {
Machine* pMch = GetCurrMachine() ;
if ( pMch != nullptr && pMch->IsLinkedRawPart( nRawId))
return true ;
}
// altrimenti errore
return false ;
}
//----------------------------------------------------------------------------
bool
MachMgr::RotateRawPart( int nRawId, const Vector3d& vtAx, double dAngRotDeg)
{
// recupero l'oggetto disposizione corrente
Disposition* pDisp = ::GetDisposition( m_pGeomDB->GetUserObj( m_nCurrDispId)) ;
if ( pDisp == nullptr)
return false ;
// eseguo l'operazione
if ( ! pDisp->RotateRawPart( nRawId, vtAx, dAngRotDeg)) {
LOG_ERROR( GetEMkLogger(), "Error on RotateRawPart") ;
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
MachMgr::MoveToCornerRawPart( int nRawId, const Point3d& ptP, int nFlag)
{
// recupero l'oggetto disposizione corrente
Disposition* pDisp = ::GetDisposition( m_pGeomDB->GetUserObj( m_nCurrDispId)) ;
if ( pDisp == nullptr)
return false ;
// eseguo l'operazione
if ( ! pDisp->MoveToCornerRawPart( nRawId, ptP, nFlag)) {
LOG_ERROR( GetEMkLogger(), "Error on MoveToCornerRawPart") ;
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
MachMgr::MoveToCenterRawPart( int nRawId, const Point3d& ptP, int nFlag)
{
// recupero l'oggetto disposizione corrente
Disposition* pDisp = ::GetDisposition( m_pGeomDB->GetUserObj( m_nCurrDispId)) ;
if ( pDisp == nullptr)
return false ;
// eseguo l'operazione
if ( ! pDisp->MoveToCenterRawPart( nRawId, ptP, nFlag)) {
LOG_ERROR( GetEMkLogger(), "Error on MoveToCenterRawPart") ;
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
MachMgr::MoveRawPart( int nRawId, const Vector3d& vtMove)
{
// recupero l'oggetto disposizione corrente
Disposition* pDisp = ::GetDisposition( m_pGeomDB->GetUserObj( m_nCurrDispId)) ;
if ( pDisp == nullptr)
return false ;
// eseguo l'operazione
if ( ! pDisp->MoveRawPart( nRawId, vtMove)) {
LOG_ERROR( GetEMkLogger(), "Error on MoveRawPart") ;
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
MachMgr::SetRawPartCenter( int nRawId)
{
// recupero il solido
int nRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
const ISurfTriMesh* pStm = GetSurfTriMesh( m_pGeomDB->GetGeoObj( nRawSolId)) ;
if ( pStm == nullptr)
return false ;
// recupero il punto centro, se non esiste lo creo
int nGPntId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_CENTER) ;
if ( nGPntId == GDB_ID_NULL) {
PtrOwner<IGeoPoint3d> pGeoPnt( CreateGeoPoint3d()) ;
nGPntId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pGeoPnt)) ;
m_pGeomDB->SetName( nGPntId, MACH_RAW_CENTER) ;
Color cCol ;
if ( m_pGeomDB->GetCalcMaterial( nRawSolId, cCol))
m_pGeomDB->SetMaterial( nGPntId, cCol) ;
}
IGeoPoint3d* pGeoPnt = GetGeoPoint3d( m_pGeomDB->GetGeoObj( nGPntId)) ;
if ( pGeoPnt == nullptr)
return false ;
// calcolo il valore del centro
Point3d ptCen ;
if ( ! pStm->GetCentroid( ptCen))
return false ;
// aggiorno e imposto modo a standard
return ( pGeoPnt->Set( ptCen) && m_pGeomDB->SetMode( nGPntId, GDB_MD_STD)) ;
}
//----------------------------------------------------------------------------
bool
MachMgr::ResetRawPartCenter( int nRawId)
{
// recupero il punto centro
int nGPntId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_CENTER) ;
if ( nGPntId == GDB_ID_NULL)
return true ;
// imposto modo a bloccato
return m_pGeomDB->SetMode( nGPntId, GDB_MD_HIDDEN) ;
}
//----------------------------------------------------------------------------
bool
MachMgr::GetRawPartCenter( int nRawId, Point3d& ptCen)
{
// verifica validità grezzo
if ( ! VerifyRawPart( nRawId))
return false ;
// cerco di recuperare l'oggetto
int nGPntId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_CENTER) ;
// ne verifico la validità
int nMode ;
if ( nGPntId == GDB_ID_NULL ||
! m_pGeomDB->GetMode( nGPntId, nMode) || nMode != GDB_MD_STD) {
// provo a crearlo
SetRawPartCenter( nRawId) ;
nGPntId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_CENTER) ;
// se non riesco, errore
if ( nGPntId == GDB_ID_NULL)
return false ;
}
// ne recupero il riferimento globale
Frame3d frGPnt ;
if ( ! m_pGeomDB->GetGlobFrame( nGPntId, frGPnt))
return false ;
// recupero il punto
IGeoPoint3d* pGeoPnt = GetGeoPoint3d( m_pGeomDB->GetGeoObj( nGPntId)) ;
if ( pGeoPnt == nullptr)
return false ;
ptCen = pGeoPnt->GetPoint() ;
ptCen.ToGlob( frGPnt) ;
return true ;
}
//----------------------------------------------------------------------------
bool
MachMgr::GetRawPartBBox( int nRawId, BBox3d& b3Raw)
{
// verifica validità grezzo
if ( ! VerifyRawPart( nRawId))
return false ;
// recupero solido del grezzo
int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
return m_pGeomDB->GetGlobalBBox( nRawSolidId, b3Raw) ;
}
//----------------------------------------------------------------------------
int
MachMgr::SplitFlatRawPartWithMachinings( int nRawId, const INTVECTOR& vMchId)
{
if ( m_pGeomDB == nullptr)
return GDB_ID_NULL ;
// verifico sia un grezzo e non appartenga alla fase corrente
if ( ! VerifyRawPart( nRawId) || VerifyRawPartPhase( nRawId, m_nCurrPhase))
return GDB_ID_NULL ;
// disabilito eventuale registrazione comandi EXE (riabilitazione automatica)
CmdLogOff cmdLogOff ;
// recupero alcuni dati del grezzo
// il solido del grezzo
int nRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ;
if ( nRawSolId == GDB_ID_NULL)
return GDB_ID_NULL ;
// il box del grezzo
BBox3d b3Raw ;
if ( ! m_pGeomDB->GetGlobalBBox( nRawSolId, b3Raw))
return GDB_ID_NULL ;
double dZmin = b3Raw.GetMin().z ;
double dHeight = b3Raw.GetMax().z - b3Raw.GetMin().z ;
// il colore del grezzo
Color cCol = AQUA ;
m_pGeomDB->GetCalcMaterial( nRawSolId, cCol) ;
// il riferimento del grezzo
Frame3d frRaw ;
if ( ! m_pGeomDB->GetGroupGlobFrame( nRawId, frRaw))
return GDB_ID_NULL ;
// creo la regione del grezzo a partire dal suo contorno
// recupero il contorno
int nOutCrvId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ;
if ( nOutCrvId == GDB_ID_NULL)
return GDB_ID_NULL ;
// creo la regione
INTVECTOR vCrvIds ;
vCrvIds.emplace_back( nOutCrvId) ;
int nSfrId = ExeCreateSurfFlatRegion( nRawId, vCrvIds, nullptr) ;
if ( nSfrId == GDB_ID_NULL)
return GDB_ID_NULL ;
m_pGeomDB->SetLevel( nSfrId, GDB_LV_TEMP) ;
// se esiste il kerf, ne creo la regione
PtrOwner<ISurfFlatRegion> pSfrKerf ;
int nKerfId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_KERF) ;
ICurve* pKerfCrv = GetCurve( m_pGeomDB->GetGeoObj( nKerfId)) ;
if ( pKerfCrv != nullptr) {
SurfFlatRegionByContours SfrCntr ;
SfrCntr.AddCurve( pKerfCrv->Clone()) ;
pSfrKerf.Set( SfrCntr.GetSurf()) ;
if ( IsNull( pSfrKerf))
return GDB_ID_NULL ;
}
// recupero le regioni delle lavorazioni
INTVECTOR vMchRReg ;
for ( auto nMchId : vMchId) {
// recupero gruppo preview lavorazioni nella lavorazione
int nPVGrp = m_pGeomDB->GetFirstNameInGroup( nMchId, MCH_PV) ;
if ( nPVGrp == GDB_ID_NULL)
return GDB_ID_NULL ;
// se vuoto, cerco il rimando al preview nel pezzo
if ( m_pGeomDB->GetGroupObjs( nPVGrp) == 0 &&
! m_pGeomDB->GetInfo( nPVGrp, MCH_PV_KEY_RELOCATE, nPVGrp))
return GDB_ID_NULL ;
// ciclo sui percorsi utensile (CL)
int nClId = m_pGeomDB->GetFirstGroupInGroup( nPVGrp) ;
while ( nClId != GDB_ID_NULL) {
// tagli ridotti
int nCrId = m_pGeomDB->GetFirstNameInGroup( nClId, MCH_PV_RRCUT) ;
while ( nCrId != GDB_ID_NULL) {
vMchRReg.emplace_back( nCrId) ;
nCrId = m_pGeomDB->GetNextName( nCrId, MCH_PV_RRCUT) ;
}
// passo al successivo percorso utensile
nClId = m_pGeomDB->GetNextGroup( nClId) ;
}
}
// sottraggo queste regioni a quella del grezzo
for ( auto nMchRReg : vMchRReg) {
ExeSurfFrSubtract( nSfrId, nMchRReg) ;
}
// creo i grezzi risultanti
// creo i nuovi grezzi
INTVECTOR vNewIds ;
int nCount ;
int nChunk = 0 ;
int nFirstLoopId = ExeExtractSurfFrChunkLoops( nSfrId, nChunk, nRawId, &nCount) ;
while ( nFirstLoopId != GDB_ID_NULL) {
// !!! in attesa di gestire i grezzi con i buchi !!!
// cancello le eventuali curve successive (sono i loop interni ovvero i buchi)
for ( int i = 1 ; i < nCount ; ++ i) {
m_pGeomDB->Erase( nFirstLoopId + i) ;
}
// dichiaro temporanea la curva
m_pGeomDB->SetLevel( nFirstLoopId, GDB_LV_TEMP) ;
// creo il grezzo
int nId = AddRawPart( nFirstLoopId, 0, dZmin, dHeight, cCol) ;
if ( nId == GDB_ID_NULL)
return GDB_ID_NULL ;
vNewIds.emplace_back( nId) ;
// imposto lo stato del contorno di questo grezzo come quello del grezzo di partenza
int nStat = GDB_ST_ON ;
if ( m_pGeomDB->GetStatus( nOutCrvId, nStat) && nStat == GDB_ST_OFF)
m_pGeomDB->SetStatus( m_pGeomDB->GetFirstNameInGroup( nId, MACH_RAW_OUTLINE), nStat) ;
// assegno la fase al gruppo
m_pGeomDB->SetInfo( nId, MACH_RAW_PHASE, m_nCurrPhase) ;
// se esiste il kerf uso questa curva per creare il kerf del nuovo grezzo
if ( ! IsNull( pSfrKerf)) {
// creo la regione con la curva
SurfFlatRegionByContours SfrCntr ;
SfrCntr.AddCurve( GetCurve( m_pGeomDB->RemoveGeoObjAndErase( nFirstLoopId))) ;
PtrOwner<ISurfFlatRegion> pSfrNewKerf( SfrCntr.GetSurf()) ;
if ( IsNull( pSfrNewKerf))
return GDB_ID_NULL ;
// la limito con la regione di kerf precedente (va bene anche se fallisce)
pSfrNewKerf->Intersect( *pSfrKerf) ;
// se risultato non vuoto
if ( pSfrNewKerf->IsValid()) {
// riferimento del nuovo grezzo
Frame3d frNewRaw ;
if ( ! m_pGeomDB->GetGroupGlobFrame( nId, frNewRaw))
return GDB_ID_NULL ;
// la porto dal riferimento del grezzo originale al riferimento di questo grezzo
pSfrNewKerf->LocToLoc( frRaw, frNewRaw) ;
// la porto sulla faccia sopra del grezzo
pSfrNewKerf->Translate( Vector3d( 0, 0, dHeight)) ;
// recupero il contorno e lo inserisco come kerf del nuovo grezzo
PtrOwner<ICurve> pCrv( pSfrNewKerf->GetLoop( 0, 0)) ;
int nNewKerfId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nId, Release( pCrv)) ;
if ( nNewKerfId == GDB_ID_NULL)
return GDB_ID_NULL ;
m_pGeomDB->CopyMaterial( nKerfId, nNewKerfId) ;
m_pGeomDB->SetName( nNewKerfId, MACH_RAW_KERF) ;
}
}
// altrimenti la cancello
else
m_pGeomDB->Erase( nFirstLoopId) ;
// passo alla prossima curva
++ nChunk ;
nFirstLoopId = ExeExtractSurfFrChunkLoops( nSfrId, nChunk, nRawId, &nCount) ;
}
// cancello la regione
m_pGeomDB->Erase( nSfrId) ;
// verifico esista almeno un nuovo grezzo
if ( vNewIds.empty())
return GDB_ID_NULL ;
// inserisco i pezzi del grezzo originale nei nuovi grezzi
int nGroupId = m_pGeomDB->GetFirstGroupInGroup( nRawId) ;
while ( nGroupId != GDB_ID_NULL) {
for ( auto nNewId : vNewIds) {
// copio il gruppo
int nNewGroupId = m_pGeomDB->CopyGlob( nGroupId, GDB_ID_NULL, nNewId) ;
// scambio con pezzo
int nPartId = SwapRawPartPart( nNewGroupId, true) ;
// verifico se il pezzo sta nel grezzo
int nLayerId = m_pGeomDB->GetFirstNameInGroup( nPartId, NST_EXT_LAYER) ;
if ( nLayerId == GDB_ID_NULL || m_pGeomDB->GetGdbType( nLayerId) != GDB_TY_GROUP)
nLayerId = m_pGeomDB->GetFirstGroupInGroup( nPartId) ;
int nEntId = m_pGeomDB->GetFirstInGroup( nLayerId) ;
int nEntGeoType = m_pGeomDB->GetGeoType( nEntId) ;
Point3d ptTest ;
if ( ( ( nEntGeoType & GEO_CURVE) != 0 && ExeMidPoint( nEntId, nNewId, ptTest)) ||
( ( nEntGeoType & GEO_CURVE) == 0 && ExeCenterPoint( nEntId, nNewId, ptTest))) {
int nOutCrvId = m_pGeomDB->GetFirstNameInGroup( nNewId, MACH_RAW_OUTLINE) ;
BBox3d b3Raw ; m_pGeomDB->GetGlobalBBox( nOutCrvId, b3Raw) ;
double dRawDiam = 0 ; b3Raw.GetDiameter( dRawDiam) ;
BBox3d b3Part ; m_pGeomDB->GetGlobalBBox( nEntId, b3Part) ;
double dPartDiam = 0 ; b3Part.GetDiameter( dPartDiam) ;
if ( dRawDiam > 0.9 * dPartDiam) {
ICurve* pCurve = GetCurve( m_pGeomDB->GetGeoObj( nOutCrvId)) ;
if ( pCurve != nullptr) {
int nSide ;
double dDist ;
DistPointCurve distPC( ptTest, *pCurve) ;
if ( distPC.GetDist( dDist) &&
( dDist < 100 * EPS_SMALL ||
( distPC.GetSideAtMinDistPoint( 0, Z_AX, nSide) && nSide != MDS_RIGHT)))
break ;
}
}
}
// altrimenti scambio pezzo ed elimino gruppo
nNewGroupId = SwapRawPartPart( nPartId, false) ;
m_pGeomDB->Erase( nNewGroupId) ;
}
nGroupId = m_pGeomDB->GetNextGroup( nGroupId) ;
}
return vNewIds[0] ;
}