Files
EgtExecutor/EXE_NstCreateFlatParts.cpp
T
Dario Sassi be54bcf382 EgtExecutor 1.9g1 :
- aggiunta gestione import punti in Exe e LUA
- corretta gestione regione sotto con lati inclinati interni di pezzi piatti (flatParts)
- aggiunta funzione Exe e Lua CAvGetToolOutline per avere profilo di utensile in uso nella CollisionAvoidance.
2018-07-05 10:28:52 +00:00

1354 lines
53 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : EXE_NstCreateFlatParts.cpp Data : 28.12.15 Versione : 1.6l5
// Contenuto : Funzioni di creazione pezzi piani per EXE.
//
//
//
// Modifiche : 28.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/EXeCmdLogOff.h"
#include "/EgtDev/Include/EGkCurveArc.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EGkExtText.h"
#include "/EgtDev/Include/EGkGdbIterator.h"
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EMkMachiningGeoConst.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
static bool
ApproxCurveIfNeeded( IGdbIterator* pEnt)
{
// deve essere una curva
int nGeoType = pEnt->GetGeoType() ;
if ( (nGeoType & GEO_CURVE) == 0)
return false ;
// verifico se da approssimare
if ( nGeoType == CRV_LINE || nGeoType == CRV_ARC)
return true ;
else if ( nGeoType == CRV_COMPO) {
ICurveComposite* pCrvCo = GetCurveComposite( pEnt->GetGeoObj()) ;
double dLen ;
pCrvCo->GetLength( dLen) ;
int nCrvs = pCrvCo->GetCurveCount() ;
if ( nCrvs <= 5 && dLen > nCrvs * LIN_FEA_STD) {
// controllo non ci siano curve di Bezier
bool bSomeBezier = false ;
const ICurve* pCrv = pCrvCo->GetFirstCurve() ;
while ( pCrv != nullptr) {
if ( pCrv->GetType() == CRV_BEZ)
bSomeBezier = true ;
pCrv = pCrvCo->GetNextCurve() ;
}
if ( ! bSomeBezier)
return true ;
}
}
// esecuzione dell'approssimazione
ICurve* pCrv = GetCurve( pEnt->GetGeoObj()) ;
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
PolyArc PA ;
bool bOk = pCrv->ApproxWithArcsEx( LIN_TOL_STD, ANG_TOL_STD_DEG, LIN_FEA_STD, PA) && pCC->FromPolyArc( PA) ;
bOk = bOk && pEnt->GetGDB()->ReplaceGeoObj( pEnt->GetId(), Release( pCC)) ;
return bOk ;
}
//----------------------------------------------------------------------------
static bool
AdjustNearlyClosedCurve( IGdbIterator* pEnt)
{
// deve essere una curva
int nGeoType = pEnt->GetGeoType() ;
if ( (nGeoType & GEO_CURVE) == 0)
return false ;
// se linea non devo fare alcunché
if ( nGeoType == CRV_LINE)
return true ;
// se arco, verifico se quasi circonferenza
if ( nGeoType == CRV_ARC) {
ICurveArc* pArc = GetCurveArc( pEnt->GetGeoObj()) ;
Point3d ptStart ; pArc->GetStartPoint( ptStart) ;
Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ;
double dAngCenDeg = pArc->GetAngCenter() ;
if ( abs( dAngCenDeg) > ANG_STRAIGHT && AreSamePointEpsilon( ptStart, ptEnd, LIN_TOL_STD))
return pArc->ChangeAngCenter( dAngCenDeg > 0 ? ANG_FULL : - ANG_FULL) ;
return true ;
}
// altrimenti, verifico se approssimativamente chiusa
ICurve* pCrv = GetCurve( pEnt->GetGeoObj()) ;
Point3d ptStart ; pCrv->GetStartPoint( ptStart) ;
Point3d ptEnd ; pCrv->GetEndPoint( ptEnd) ;
if ( AreSamePointEpsilon( ptStart, ptEnd, LIN_TOL_STD))
return pCrv->ModifyEnd( ptStart) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
FilterAndApprox( void)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// preparo gli iteratori
PtrOwner<IGdbIterator> pPar( CreateGdbIterator( pGeomDB)) ;
PtrOwner<IGdbIterator> pLay( CreateGdbIterator( pGeomDB)) ;
PtrOwner<IGdbIterator> pEnt( CreateGdbIterator( pGeomDB)) ;
if ( IsNull( pPar) || IsNull( pLay) || IsNull( pEnt))
return false ;
// ciclo su tutti gli oggetti del DB geometrico
bool bPok = pPar->GoToFirstInGroup( GDB_ID_ROOT) ;
while ( bPok) {
// sotto la radice sono ammessi solo gruppi di livello User -> Pezzi
int nLev ;
if ( pPar->GetGdbType() != GDB_TY_GROUP ||
! pPar->GetCalcLevel( nLev) || nLev != GDB_LV_USER) {
bPok = pPar->EraseAndGoToNext() ;
continue ;
}
// ciclo su tutti gli oggetti del pezzo
bool bLok = pLay->GoToFirstInGroup( *pPar) ;
while ( bLok) {
// sotto ogni pezzo sono ammessi solo gruppi di livello User -> Layer
int nLev ;
if ( pLay->GetGdbType() != GDB_TY_GROUP ||
! pLay->GetCalcLevel( nLev) || nLev != GDB_LV_USER) {
bLok = pLay->EraseAndGoToNext() ;
continue ;
}
// ciclo su tutti gli oggetti del layer
bool bEok = pEnt->GoToFirstInGroup( *pLay) ;
while ( bEok) {
// sotto ogni layer sono ammesse solo curve di livello User
int nLev ;
if ( ( pEnt->GetGeoType() & GEO_CURVE) == 0 ||
! pEnt->GetCalcLevel( nLev) || nLev != GDB_LV_USER) {
bEok = pEnt->EraseAndGoToNext() ;
continue ;
}
// eventuale approx della curva se Bezier o Composita con molti piccoli segmenti
ApproxCurveIfNeeded( pEnt) ;
// se curva approssimativamente chiusa, la chiudo esattamente
AdjustNearlyClosedCurve( pEnt) ;
// passo alla successiva entità
bEok = pEnt->GoToNext() ;
}
// passo al successivo layer
bLok = pLay->GoToNext() ;
}
// passo al successivo pezzo
bPok = pPar->GoToNext() ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
ChainCurves( int& nLay)
{
// seleziono tutte le curve
bool bOk = ExeSelectAll( false) ;
// creo un nuovo pezzo con layer in cui mettere tutti i concatenati
int nPart = ExeCreateGroup( GDB_ID_ROOT, Frame3d(), RTY_GLOB) ;
nLay = ExeCreateGroup( nPart, Frame3d(), RTY_GLOB) ;
bOk = bOk && nLay != GDB_ID_NULL ;
// concateno tutte le curve
INTVECTOR vIds ;
vIds.push_back( GDB_ID_SEL) ;
int nCount ;
int nFirstId = ( bOk ? ExeCreateCurveCompoByChain( nLay, vIds, ORIG, true, RTY_GLOB, &nCount) : GDB_ID_NULL) ;
bOk = bOk && nFirstId != GDB_ID_NULL ;
// cancello i gruppi rimasti vuoti
ExeEraseEmptyParts() ;
return bOk ;
}
//----------------------------------------------------------------------------
static bool
CreateFlatPartsByRegions( int nLay)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// recupero il padre del layer
int nParentId = pGeomDB->GetParentId( nLay) ;
// preparo gli iteratori
PtrOwner<IGdbIterator> pEnt( CreateGdbIterator( pGeomDB)) ;
if ( IsNull( pEnt))
return false ;
// separo le curve aperte da quelle chiuse e salvo vettore aree di queste ultime
INTVECTOR vOpenIds ;
INTVECTOR vClosedIds ;
typedef std::pair<int,double> INDAREA ; // coppia indice, area
typedef std::vector<INDAREA> INDAREAVECTOR ; // vettore di coppie indice, area
INDAREAVECTOR vArea ;
bool bEok = pEnt->GoToFirstInGroup( nLay) ;
while ( bEok) {
ICurve* pCrv = GetCurve( pEnt->GetGeoObj()) ;
if ( pCrv == nullptr) {
bEok = pEnt->EraseAndGoToNext() ;
}
else if ( ! pCrv->IsClosed()) {
vOpenIds.push_back( pEnt->GetId()) ;
bEok = pEnt->GoToNext() ;
}
else {
vClosedIds.push_back( pEnt->GetId()) ;
double dArea ;
pCrv->GetAreaXY( dArea) ;
if ( fabs( dArea) > 1) {
if ( dArea < 0) {
pCrv->Invert() ;
dArea = - dArea ;
}
vArea.emplace_back( pEnt->GetId(), dArea) ;
}
else
vOpenIds.push_back( pEnt->GetId()) ;
bEok = pEnt->GoToNext() ;
}
}
// ordino le aree in senso decrescente
sort( vArea.begin(), vArea.end(),
[]( const INDAREA& a, const INDAREA&b) { return fabs( a.second) > fabs( b.second) ; }) ;
// creo i pezzi a partire dalle curve chiuse più grandi e dalle curve che vi sono contenute
for ( int i = 0 ; i < int( vArea.size()) ; ++ i) {
if ( vArea[i].first == GDB_ID_NULL)
continue ;
// creo pezzo con questa geometria
int nPartId = pGeomDB->InsertGroup( GDB_ID_NULL, nParentId, GDB_BEFORE, Frame3d()) ;
// creo layer nel pezzo
int nLayId = pGeomDB->AddGroup( GDB_ID_NULL, nPartId, Frame3d()) ;
// sposto il contorno nel pezzo
pGeomDB->RelocateGlob( vArea[i].first, nLayId) ;
// cerco altri contorni chiusi che siano contenuti completamente o parzialmente
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( vArea[i].first)) ;
for ( int j = i + 1 ; j < int( vArea.size()) ; ++ j) {
if ( vArea[j].first == GDB_ID_NULL)
continue ;
ICurve* pCrv2 = GetCurve( pGeomDB->GetGeoObj( vArea[j].first)) ;
// intersezione e classificazione
CRVCVECTOR ccClass ;
IntersCurveCurve intCC( *pCrv2, *pCrv) ;
if ( ! intCC.GetCurveClassification( 0, ccClass))
continue ;
// se completamente interna
if ( ccClass.size() == 1 && ccClass[0].nClass == CRVC_IN) {
pGeomDB->RelocateGlob( vArea[j].first, nLayId) ;
vArea[j].first = GDB_ID_NULL ;
}
// se più di un tratto
else if ( ccClass.size() > 1) {
// verifico se parzialmente interna
bool bIn = false ;
bool bOther = false ;
for ( int k = 0 ; k < int( ccClass.size()) ; ++ k) {
if ( ccClass[k].nClass == CRVC_IN)
bIn = true ;
else
bOther = true ;
}
// se parzialmente interna, la sposto negli aperti
if ( bIn && bOther) {
vOpenIds.push_back( vArea[j].first) ;
vArea[j].first = GDB_ID_NULL ;
}
}
}
// verifico i contorni aperti che siano contenuti completamente o parzialmente
for ( int j = i + 1 ; j < int( vOpenIds.size()) ; ++ j) {
if ( vOpenIds[j] == GDB_ID_NULL)
continue ;
ICurve* pCrv2 = GetCurve( pGeomDB->GetGeoObj( vOpenIds[j])) ;
Intervals inCrv ;
double dParS, dParE ;
pCrv2->GetDomain( dParS, dParE) ;
inCrv.Set( dParS, dParE) ;
// intersezione e classificazione
CRVCVECTOR ccClass ;
IntersCurveCurve intCC( *pCrv2, *pCrv) ;
if ( ! intCC.GetCurveClassification( 0, ccClass))
continue ;
// conservo solo le parti interne
for ( int k = 0 ; k < int( ccClass.size()) ; ++ k) {
if ( ccClass[k].nClass != CRVC_IN)
inCrv.Subtract( ccClass[k].dParS, ccClass[k].dParE) ;
}
// tratti di curva rimasti
int nNum = inCrv.GetCount() ;
// se rimangono uno o più tratti
if ( nNum >= 1) {
double dParS, dParE ;
bool bInt = inCrv.GetFirst( dParS, dParE) ;
while ( bInt) {
// copio la curva e la modifico
int nCopyId = pGeomDB->Copy( vOpenIds[j], GDB_ID_NULL, nLayId) ;
// modifico l'originale
ICurve* pOriCrv = GetCurve( pGeomDB->GetGeoObj( nCopyId)) ;
pOriCrv->TrimStartEndAtParam( dParS, dParE) ;
// passo al successivo intervallo
bInt = inCrv.GetNext( dParS, dParE) ;
}
}
}
}
// elimino la geometria originale rimasta
pGeomDB->Erase( nParentId) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
CreateFlatPartsByLayers( void)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// preparo gli iteratori
PtrOwner<IGdbIterator> pPar( CreateGdbIterator( pGeomDB)) ;
PtrOwner<IGdbIterator> pLay( CreateGdbIterator( pGeomDB)) ;
if ( IsNull( pPar) || IsNull( pLay))
return false ;
// ciclo su tutti i gruppi della radice (pezzi)
bool bPok = pPar->GoToFirstGroupInGroup( GDB_ID_ROOT) ;
int nFirstId = pPar->GetId() ;
while ( bPok) {
// ciclo su tutti i sottogruppi (layer)
bool bLok = pLay->GoToFirstGroupInGroup( *pPar) ;
while ( bLok) {
// creo pezzo con questa geometria
int nPartId = pGeomDB->InsertGroup( GDB_ID_NULL, nFirstId, GDB_BEFORE, Frame3d()) ;
// passo al pezzo l'eventuale nome del layer
string sName ;
if ( pLay->GetName( sName)) {
pGeomDB->SetName( nPartId, sName) ;
pLay->RemoveName() ;
}
// sposto il layer sotto questo pezzo
if ( ! pGeomDB->RelocateGlob( pLay->GetId(), nPartId))
return false ;
// altro layer del gruppo originale
bLok = pLay->GoToFirstGroupInGroup( *pPar) ;
}
// passo al successivo
bPok = pPar->GoToNextGroup() ;
}
// cancello i gruppi svuotati
bPok = pPar->GoTo( nFirstId) ;
while ( bPok)
bPok = pPar->EraseAndGoToNext() ;
return true ;
}
//----------------------------------------------------------------------------
static bool
CreateFlatPartsByClosedCurves( void)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// preparo gli iteratori
PtrOwner<IGdbIterator> pPar( CreateGdbIterator( pGeomDB)) ;
PtrOwner<IGdbIterator> pLay( CreateGdbIterator( pGeomDB)) ;
PtrOwner<IGdbIterator> pEnt( CreateGdbIterator( pGeomDB)) ;
if ( IsNull( pPar) || IsNull( pLay) || IsNull( pEnt))
return false ;
// ciclo su tutti i gruppi della radice (pezzi)
bool bPok = pPar->GoToFirstGroupInGroup( GDB_ID_ROOT) ;
int nFirstId = pPar->GetId() ;
while ( bPok) {
// ciclo su tutti i sottogruppi (layer)
bool bLok = pLay->GoToFirstGroupInGroup( *pPar) ;
while ( bLok) {
// ciclo su tutte le entità
bool bEok = pEnt->GoToFirstInGroup( *pLay) ;
while ( bEok) {
// se curva chiusa
if ( ( pEnt->GetGeoType() & GEO_CURVE) != 0 &&
GetCurve( pEnt->GetGeoObj())->IsClosed()) {
// creo pezzo e layer per questa geometria
int nPartId = pGeomDB->InsertGroup( GDB_ID_NULL, nFirstId, GDB_BEFORE, Frame3d()) ;
int nLayerId = pGeomDB->InsertGroup( GDB_ID_NULL, nPartId, GDB_LAST_SON, Frame3d()) ;
int nEntId = pEnt->GetId() ;
// recupero successiva entità
bEok = pEnt->GoToNext() ;
// sposto l'entità sotto questo layer
if ( ! pGeomDB->RelocateGlob( nEntId, nLayerId))
return false ;
}
// altrimenti cancello
else
bEok = pEnt->EraseAndGoToNext() ;
}
// altro layer del gruppo originale
bLok = pLay->GoToNextGroup() ;
}
// passo al successivo
bPok = pPar->GoToNextGroup() ;
}
// cancello i gruppi svuotati
bPok = pPar->GoTo( nFirstId) ;
while ( bPok)
bPok = pPar->EraseAndGoToNext() ;
return true ;
}
//----------------------------------------------------------------------------
static bool
VerifyAndAdjustFlatParts( void)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// preparo gli iteratori
PtrOwner<IGdbIterator> pPar( CreateGdbIterator( pGeomDB)) ;
PtrOwner<IGdbIterator> pEnt( CreateGdbIterator( pGeomDB)) ;
if ( IsNull( pPar) || IsNull( pEnt))
return false ;
// ciclo sui pezzi
bool bPok = pPar->GoToFirstGroupInGroup( GDB_ID_ROOT) ;
while ( bPok) {
// seleziono tutte le curve del pezzo
bool bOk = ExeSelectPartObjs( pPar->GetId()) ;
// creo un nuovo layer in cui mettere tutti i concatenati
int nRegId = ExeCreateGroup( pPar->GetId(), Frame3d(), RTY_GLOB) ;
bOk = bOk && nRegId != GDB_ID_NULL ;
bOk = bOk && pGeomDB->SetName( nRegId, NST_PARTREG_LAYER) ;
// concateno tutte le curve
INTVECTOR vIds ;
vIds.push_back( GDB_ID_SEL) ;
int nCount ;
int nFirstId = ( bOk ? ExeCreateCurveCompoByChain( nRegId, vIds, ORIG, false, RTY_GLOB, &nCount) : GDB_ID_NULL) ;
bOk = bOk && nFirstId != GDB_ID_NULL ;
// deseleziono tutto
pGeomDB->ClearSelection() ;
// elimino le curve aperte del nuovo layer e uso le chiuse per creare la regione
INTVECTOR vOpenIds ;
STRVECTOR vClosedIds ;
SurfFlatRegionByContours SfrCntr( false, false) ;
bool bEok = pEnt->GoToFirstInGroup( nRegId) ;
while ( bEok) {
ICurve* pCrv = GetCurve( pEnt->GetGeoObj()) ;
if ( pCrv == nullptr) {
bEok = pEnt->EraseAndGoToNext() ;
}
else if ( ! pCrv->IsClosed()) {
// salvo Id di origine nell'elenco curve aperte da controllare
INTVECTOR vTmpIds ;
if ( pGeomDB->GetInfo( pEnt->GetId(), CRV_ORIG, vTmpIds))
vOpenIds.insert( vOpenIds.end(), vTmpIds.begin(), vTmpIds.end()) ;
bEok = pEnt->EraseAndGoToNext() ;
}
else {
// verifico sia orientata in senso CCW
double dArea ;
pCrv->GetAreaXY( dArea) ;
if ( dArea < 0)
pCrv->Invert() ;
// salvo Id entità corrente e preparo passaggio a prossima
int nEntId = pEnt->GetId() ;
bEok = pEnt->GoToNext() ;
// salvo stringa con elenco Id di origine
string sInfo ;
if ( pGeomDB->GetInfo( nEntId, CRV_ORIG, sInfo)) {
vClosedIds.emplace_back( sInfo) ;
pCrv->SetTempProp( int( vClosedIds.size())) ;
}
// estraggo curva da entità che viene cancellata
SfrCntr.AddCurve( pCrv) ;
pGeomDB->RemoveGeoObjAndErase( nEntId) ;
}
}
// creo la regione
ISurfFlatRegion* pSfr = SfrCntr.GetSurf() ;
bOk = bOk && ( pSfr != nullptr) ;
// inserisco eventuali curve chiuse non usate nell'elenco delle aperte
if ( ! SfrCntr.AllCurvesUsed()) {
// recupero indice da proprietà temporanea di curve non usate
INTVECTOR vUnId ;
SfrCntr.GetUnusedCurveTempProps( vUnId) ;
// recupero Id originali associati
for ( auto nUnId : vUnId) {
if ( nUnId > 0 && nUnId <= int( vClosedIds.size())) {
INTVECTOR vTmpIds ;
if ( FromString( vClosedIds[nUnId - 1], vTmpIds))
vOpenIds.insert( vOpenIds.end(), vTmpIds.begin(), vTmpIds.end()) ;
}
}
}
// inserisco la superficie nel DB
int nNewId = ( bOk ? pGeomDB->AddGeoObj( GDB_ID_NULL, nRegId, pSfr) : GDB_ID_NULL) ;
bOk = bOk && nNewId != GDB_ID_NULL ;
// assegno il colore
Color cCol = AQUA ;
cCol.SetAlpha( 0.25) ;
bOk = bOk && pGeomDB->SetMaterial( nNewId, cCol) ;
// scrittura delle dimensioni nel layer della regione
if ( bOk) {
BBox3d b3Reg ;
pGeomDB->GetGlobalBBox( nNewId, b3Reg) ;
Point3d ptMin, ptMax ;
b3Reg.GetMinMax( ptMin, ptMax) ;
double dDimX = ptMax.x - ptMin.x ;
double dDimY = ptMax.y - ptMin.y ;
string sOut = ToString( ExeToUiUnits( dDimX), 2) + "x" + ToString( ExeToUiUnits( dDimY), 2) ;
Point3d ptCen = Media( ptMin, ptMax, 0.5) ;
Vector3d vtDir = ( dDimX >= dDimY ? X_AX : Y_AX) ;
double dDimT = min( 0.05 * max( dDimX, dDimY), 0.5 * min( dDimX, dDimY)) ;
PtrOwner<IExtText> pText( CreateExtText()) ;
if ( ! IsNull( pText) &&
pText->Set( ptCen, Z_AX, vtDir, sOut, "", 100, false, dDimT, 1, 0, ETXT_IPMC)) {
int nTextId = pGeomDB->AddGeoObj( GDB_ID_NULL, nRegId, Release( pText)) ;
pGeomDB->SetMaterial( nTextId, BLACK) ;
}
}
// creo un nuovo layer in cui copiare il contorno esterno
PtrOwner<ICurve> pOutCrv( bOk ? pSfr->GetLoop( 0, 0) : nullptr) ;
if ( ! IsNull( pOutCrv)) {
int nOutLoopId = ExeCreateGroup( pPar->GetId(), Frame3d(), RTY_GLOB) ;
bOk = bOk && nOutLoopId != GDB_ID_NULL ;
bOk = bOk && pGeomDB->SetName( nOutLoopId, NST_OUT_LAYER) ;
pGeomDB->AddGeoObj( GDB_ID_NULL, nOutLoopId, Release( pOutCrv)) ;
}
// creo nuovi layer in cui copiare gli eventuali contorni interni
if ( bOk && pSfr->GetLoopCount( 0) > 1) {
int i = 1 ;
PtrOwner<ICurve> pInCrv( bOk ? pSfr->GetLoop( 0, i) : nullptr) ;
while ( ! IsNull( pInCrv)) {
int nInLoopId = ExeCreateGroup( pPar->GetId(), Frame3d(), RTY_GLOB) ;
bOk = bOk && nInLoopId != GDB_ID_NULL ;
bOk = bOk && pGeomDB->SetName( nInLoopId, NST_IN_LAYER) ;
pGeomDB->AddGeoObj( GDB_ID_NULL, nInLoopId, Release( pInCrv)) ;
++ i ;
pInCrv.Set( bOk ? pSfr->GetLoop( 0, i) : nullptr) ;
}
}
// creo nuovi layer in cui mettere le curve aperte
if ( bOk && vOpenIds.size() > 0) {
for ( int i = 0 ; bOk && i < int( vOpenIds.size()) ; ++i) {
int nOnPathId = ExeCreateGroup( pPar->GetId(), Frame3d(), RTY_GLOB) ;
bOk = bOk && nOnPathId != GDB_ID_NULL ;
bOk = bOk && pGeomDB->SetName( nOnPathId, NST_ON_LAYER) ;
pGeomDB->RelocateGlob( vOpenIds[i], nOnPathId) ;
}
}
// taglio le curve aperte con la regione
for ( int i = 0 ; bOk && i < int( vOpenIds.size()) ; ++i) {
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( vOpenIds[i])) ;
// calcolo la classificazione della curva rispetto alla regione
CRVCVECTOR ccClass ;
if ( ! pSfr->GetCurveClassification( *pCrv, ccClass))
continue ;
// conservo solo gli intervalli di curva interni
Intervals inOk ;
for ( auto& ccOne : ccClass) {
if ( ccOne.nClass == CRVC_IN)
inOk.Add( ccOne.dParE, ccOne.dParS) ;
}
// recupero un intervallo di id contigui per tutte le parti
int nFirstId = pGeomDB->GetNewId() ;
pGeomDB->ChangeId( vOpenIds[i], nFirstId) ;
int nCurrId = nFirstId ;
// eseguo la divisione
nCount = 0 ;
double dParS, dParE ;
bool bFound = inOk.GetFirst( dParS, dParE) ;
while ( bFound) {
// copio la curva
int nCopyId = pGeomDB->Copy( nCurrId, GDB_ID_NULL, nCurrId, GDB_AFTER) ;
ICurve* pCopyCrv = GetCurve( pGeomDB->GetGeoObj( nCopyId)) ;
if ( pCopyCrv == nullptr)
break ;
++ nCount ;
// modifico l'originale
bOk = bOk && pCrv->TrimStartEndAtParam( dParS, dParE) ;
// la copia diventa il nuovo corrente
nCurrId = nCopyId ;
pCrv = pCopyCrv ;
// passo alla successiva divisione
bFound = inOk.GetNext( dParS, dParE) ;
}
// cancello l'ultima copia (se non c'erano intervalli validi è l'originale)
if ( nCurrId != GDB_ID_NULL)
pGeomDB->Erase( nCurrId) ;
}
// se errore sul pezzo, lo elimino
if ( ! bOk)
bPok = pPar->EraseAndGoToNextGroup() ;
// passo al pezzo successivo
else
bPok = pPar->GoToNextGroup() ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
ExeCreateFlatParts( int nType)
{
// disabilito registrazione comandi
CmdLogOff cmdLogOff ;
// filtro e approssimo le curve
bool bOk = FilterAndApprox() ;
// creazione basata sulle regioni
if ( nType == FPC_REGION) {
int nLay ;
// concateno
bOk = bOk && ChainCurves( nLay) ;
// costruisco i pezzi
bOk = bOk && CreateFlatPartsByRegions( nLay) ;
}
// creazione basata sui layer
else if ( nType == FPC_LAYER) {
// creazione dei pezzi
bOk = bOk && CreateFlatPartsByLayers() ;
}
// creazione basata su curve chiuse
else if ( nType == FPC_CLOSEDCURVE) {
// creazione dei pezzi
bOk = bOk && CreateFlatPartsByClosedCurves() ;
}
// creazione basata sui pezzi NGE
// sono già a posto
// verifica e aggiustamento dei pezzi
bOk = bOk && VerifyAndAdjustFlatParts() ;
return bOk ;
}
//----------------------------------------------------------------------------
bool
ExeAdjustFlatPartLayer( int nLayerId)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// Disabilito registrazione comandi
CmdLogOff cmdLogOff ;
bool bOk = true ;
// Elimino dal gruppo gli oggetti che non sono curve
int nId = pGeomDB->GetFirstInGroup( nLayerId) ;
while ( nId != GDB_ID_NULL && bOk) {
// Recupero successiva
int nNextId = pGeomDB->GetNext( nId) ;
// Se non è una curva, la cancello
if ( ( pGeomDB->GetGeoType( nId) & GEO_CURVE) == 0)
pGeomDB->Erase( nId) ;
// Passo all'entità successiva
nId = nNextId ;
}
// Compatto e poi esplodo le curve composite
nId = pGeomDB->GetFirstInGroup( nLayerId) ;
while ( nId != GDB_ID_NULL && bOk) {
// Recupero successiva
int nNextId = pGeomDB->GetNext( nId) ;
// Se curva composita
if ( pGeomDB->GetGeoType( nId) == CRV_COMPO) {
// Compatto
bOk = ExeMergeCurvesInCurveCompo( nId, 10 * EPS_SMALL, true) ;
// Esplodo in curve semplici
bOk = bOk && ExeExplodeCurveCompo( nId, nullptr) ;
}
// Passo all'entità successiva
nId = nNextId ;
}
// Unisco gli archi consecutivi con la stessa concavità (escluse circonferenze)
INTVECTOR vAccwIds ;
INTVECTOR vAcwIds ;
nId = pGeomDB->GetFirstInGroup( nLayerId) ;
while ( nId != GDB_ID_NULL && bOk) {
const ICurveArc* pArc = GetCurveArc( pGeomDB->GetGeoObj( nId)) ;
if ( pArc != nullptr) {
double dAngCen = pArc->GetAngCenter() ;
if ( dAngCen > EPS_ANG_SMALL && dAngCen < ANG_FULL - EPS_ANG_SMALL)
vAccwIds.emplace_back( nId) ;
else if ( dAngCen < - EPS_ANG_SMALL && dAngCen > - ANG_FULL + EPS_ANG_SMALL)
vAcwIds.emplace_back( nId) ;
}
nId = pGeomDB->GetNext( nId) ;
}
if ( vAccwIds.size() > 1)
bOk = bOk && ExeCreateCurveCompoByReorder( nLayerId, vAccwIds, ORIG, true, RTY_GLOB, nullptr) != GDB_ID_NULL ;
if ( vAcwIds.size() > 1)
bOk = bOk && ExeCreateCurveCompoByReorder( nLayerId, vAcwIds, ORIG, true, RTY_GLOB, nullptr) != GDB_ID_NULL ;
// spezzo le curve composite con discontinuità
nId = pGeomDB->GetFirstInGroup( nLayerId) ;
while ( nId != GDB_ID_NULL && bOk) {
// Recupero successiva
int nNextId = pGeomDB->GetNext( nId) ;
// Se curva composita
if ( pGeomDB->GetGeoType( nId) == CRV_COMPO) {
bOk = ( ExeSplitCurveAtCorners( nId, 5.0, nullptr) != GDB_ID_NULL) ;
}
// Passo all'entità successiva
nId = nNextId ;
}
// se rimasta una sola curva composita la spezzo in due parti
//if ( pGeomDB->GetGroupObjs( nLayerId) == 1) {
// int nId = pGeomDB->GetFirstInGroup( nLayerId) ;
// ICurveComposite* pCompo = GetCurveComposite( pGeomDB->GetGeoObj( nId)) ;
// if ( pCompo != nullptr) {
// int nTotCurve = pCompo->GetCurveCount() ;
// // se contiene più curve semplici, la spezzo ad una giunzione
// if ( nTotCurve >= 2) {
// int nHalfCurve = nTotCurve / 2 ;
// ExeSplitCurveAtParam( nId, nHalfCurve) ;
// }
// // altrimenti la spezzo esattamente a metà
// else
// ExeSplitCurve( nId, 2) ;
// }
//}
// Aggiorno l'ordinamento
bOk = bOk && ExeReorderCurvesInGroup( nLayerId, ORIG, RTY_GLOB) ;
// Inserisco in ogni curva info su angoli con precedente e successiva
int nFirstId = pGeomDB->GetFirstInGroup( nLayerId) ;
nId = nFirstId ;
while ( bOk && nId != GDB_ID_NULL) {
// Recupero successiva
int nNextId = pGeomDB->GetNext( nId) ;
// Successiva geometrica (si considera il layer formato da curve contigue che si chiudono)
int nCalcId = (( nNextId != GDB_ID_NULL) ? nNextId : nFirstId) ;
if ( nCalcId != GDB_ID_NULL) {
// Recupero le due curve
const ICurve* pCrv1 = GetCurve( pGeomDB->GetGeoObj( nId)) ;
const ICurve* pCrv2 = GetCurve( pGeomDB->GetGeoObj( nCalcId)) ;
if ( pCrv1 == nullptr || pCrv2 == nullptr) {
bOk = false ;
continue ;
}
// Direzione finale curva corrente e iniziale curva successiva
Vector3d vtDir1, vtDir2 ;
if ( ! pCrv1->GetEndDir( vtDir1) || ! pCrv2->GetStartDir( vtDir2)) {
bOk = false ;
continue ;
}
// Determino l'angolo tra le due direzioni
double dAngDeg1 = 0 ;
vtDir1.GetAngleXY( vtDir2, dAngDeg1) ;
double dAngDeg2 = dAngDeg1 ;
// Se angolo piccolo (circa tangenti), verifico se hanno lo stesso raggio di curvatura
const double EPS_ANG_TG = 5.0 ;
if ( abs( dAngDeg1) < EPS_ANG_TG) {
// Punto di giunzione
Point3d ptP ;
pCrv1->GetEndPoint( ptP) ;
// prima curva
double dUStart1, dUEnd1 ;
pCrv1->GetDomain( dUStart1, dUEnd1) ;
Point3d ptP1 ;
pCrv1->GetPointD1D2( dUEnd1 - 0.25, ICurve::FROM_PLUS, ptP1) ;
Vector3d vtDiff1 = ptP - ptP1 ;
double dAngDiff1Deg ;
vtDiff1.GetAngleXY( vtDir1, dAngDiff1Deg) ;
// seconda curva
double dUStart2, dUEnd2 ;
pCrv2->GetDomain( dUStart2, dUEnd2) ;
Point3d ptP2 ;
pCrv2->GetPointD1D2( dUStart2 + 0.25, ICurve::FROM_MINUS, ptP2) ;
Vector3d vtDiff2 = ptP2 - ptP ;
double dAngDiff2Deg ;
vtDir2.GetAngleXY( vtDiff2, dAngDiff2Deg) ;
// se entrambe concave
if ( dAngDiff1Deg < - EPS_ANG_SMALL && dAngDiff2Deg < - EPS_ANG_SMALL) {
// se non sono archi con raggio quasi uguale, li considero entrambi concavi
const ICurveArc* pArc1 = GetCurveArc( pCrv1) ;
const ICurveArc* pArc2 = GetCurveArc( pCrv2) ;
if ( pArc1 == nullptr || pArc2 == nullptr ||
abs( pArc1->GetRadius() - pArc2->GetRadius()) > 10.) {
dAngDeg1 = - 1 ;
dAngDeg2 = - 1 ;
}
}
// se altrimenti prima concava
else if ( dAngDiff1Deg < - EPS_ANG_SMALL)
dAngDeg2 = - 1 ;
// se altrimenti seconda concava
else if ( dAngDiff2Deg < - EPS_ANG_SMALL)
dAngDeg1 = - 1 ;
}
// Scrivo l'angolo nelle info delle curve
pGeomDB->SetInfo( nId, MCH_PV_KEY_NEXTANG, dAngDeg1) ;
pGeomDB->SetInfo( nCalcId, MCH_PV_KEY_PREVANG, dAngDeg2) ;
}
// Passo all'entità successiva
nId = nNextId ;
}
return bOk ;
}
//----------------------------------------------------------------------------
static bool
AdjustCurves( ICurve* pCrv1, ICurve* pCrv2)
{
// se fine della prima coincide con inizio della seconda non devo fare alcunchè
Point3d ptEnd1 ;
pCrv1->GetEndPoint( ptEnd1) ;
Point3d ptStart2 ;
pCrv2->GetStartPoint( ptStart2) ;
if ( AreSamePointApprox( ptEnd1, ptStart2))
return true ;
// allungo le due curve
if ( ! pCrv1->ExtendEndByLen( 200) ||
! pCrv2->ExtendStartByLen( 200))
return false ;
// cerco intersezioni
IntersCurveCurve intCC( *pCrv1, *pCrv2) ;
if ( intCC.GetIntersCount() == 0)
return false ;
// prendo l'intersezione più vicina al punto medio tra gli estremi originali delle curve
Point3d ptMid = 0.5 * ( ptEnd1 + ptStart2) ;
Point3d ptNew1, ptNew2 ;
if ( ! intCC.GetIntersPointNearTo( 0, ptMid, ptNew1) ||
! intCC.GetIntersPointNearTo( 1, ptMid, ptNew2))
return false ;
// modifico le due curve sul punto medio
Point3d ptNew = 0.5 * ( ptNew1 + ptNew2) ;
return ( pCrv1->ModifyEnd( ptNew) && pCrv2->ModifyStart( ptNew)) ;
}
//----------------------------------------------------------------------------
bool
ExeCalcFlatPartUpRegion( int nPartId, bool bCalc)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// ripristino lo stato originale
pGeomDB->Erase( pGeomDB->GetFirstNameInGroup( nPartId, NST_PARTUPREG_LAYER)) ;
// se non richiesto calcolo, non devo fare altro
if ( ! bCalc)
return true ;
// recupero il layer esterno
int nOlId = pGeomDB->GetFirstNameInGroup( nPartId, NST_OUT_LAYER) ;
if ( nOlId == GDB_ID_NULL)
return false ;
// se il pezzo non ha lati esterni con offset negativo non devo fare alcunchè
bool bAllFixSides = true ;
int nCrvId = pGeomDB->GetFirstInGroup( nOlId) ;
while ( nCrvId != GDB_ID_NULL) {
double dOffset, dOffset2 ;
if ( ( pGeomDB->GetInfo( nCrvId, NST_KEY_OFFSET, dOffset) && dOffset < - EPS_SMALL) ||
( pGeomDB->GetInfo( nCrvId, NST_KEY_OFFSET2, dOffset2) && dOffset2 < - EPS_SMALL)) {
bAllFixSides = false ;
break ;
}
nCrvId = pGeomDB->GetNext( nCrvId) ;
}
if ( bAllFixSides)
return true ;
// creo il layer per la regione sopra (con il medesimo riferimento del layer esterno)
Frame3d frOl ;
pGeomDB->GetGroupFrame( nOlId, frOl) ;
int nUpRegId = pGeomDB->AddGroup( GDB_ID_NULL, nPartId, frOl) ;
if ( nUpRegId == GDB_ID_NULL)
return false ;
pGeomDB->SetName( nUpRegId, NST_PARTUPREG_LAYER) ;
// copio le entità del contorno esterno e le offsetto opportunamente
nCrvId = pGeomDB->GetFirstInGroup( nOlId) ;
while ( nCrvId != GDB_ID_NULL) {
// copio la curva nel gruppo temporaneo
int nNewId = pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nUpRegId) ;
if ( nNewId == GDB_ID_NULL)
return false ;
// determino ed eseguo offset
double dOffset, dOffset2 ;
if ( ( pGeomDB->GetInfo( nCrvId, NST_KEY_OFFSET, dOffset) && dOffset < - EPS_SMALL) ||
( pGeomDB->GetInfo( nCrvId, NST_KEY_OFFSET2, dOffset2) && dOffset2 < - EPS_SMALL)) {
double dCalcOffset = min( dOffset, dOffset2) ;
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nNewId)) ;
if ( pCrv == nullptr)
return false ;
pCrv->SimpleOffset( dCalcOffset) ;
}
// passo alla successiva
nCrvId = pGeomDB->GetNext( nCrvId) ;
}
// aggiusto tra loro le entità offsettate
int nFirstCrvId = pGeomDB->GetFirstInGroup( nUpRegId) ;
ICurve* pCrv1 = GetCurve( pGeomDB->GetGeoObj( nFirstCrvId)) ;
int nNextCrvId = pGeomDB->GetNext( nFirstCrvId) ;
ICurve* pCrv2 = GetCurve( pGeomDB->GetGeoObj( nNextCrvId)) ;
while ( nNextCrvId != GDB_ID_NULL) {
// sistemo le curve
pCrv2 = GetCurve( pGeomDB->GetGeoObj( nNextCrvId)) ;
if ( pCrv1 == nullptr || pCrv2 == nullptr || ! AdjustCurves( pCrv1, pCrv2))
return false ;
// passo alla successiva
pCrv1 = pCrv2 ;
nNextCrvId = pGeomDB->GetNext( nNextCrvId) ;
}
// anche prima e ultima
pCrv2 = GetCurve( pGeomDB->GetGeoObj( nFirstCrvId)) ;
if ( pCrv1 == nullptr || pCrv2 == nullptr || ! AdjustCurves( pCrv1, pCrv2))
return false ;
// creo la regione
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
if ( IsNull( pCompo))
return false ;
for ( int nCrvId = pGeomDB->GetFirstInGroup( nUpRegId) ;
nCrvId != GDB_ID_NULL ;
nCrvId = pGeomDB->GetFirstInGroup( nUpRegId)) {
ICurve* pCrv = GetCurve( pGeomDB->RemoveGeoObjAndErase( nCrvId)) ;
if ( pCrv != nullptr) {
pCompo->AddCurve( pCrv) ;
pGeomDB->RemoveGeoObjAndErase( nCrvId) ;
}
else
pGeomDB->Erase( nCrvId) ;
}
SurfFlatRegionByContours SfrCntr( false) ;
SfrCntr.AddCurve( Release( pCompo)) ;
int nSfrId = pGeomDB->InsertGeoObj( GDB_ID_NULL, nUpRegId, GDB_FIRST_SON, SfrCntr.GetSurf()) ;
if ( nSfrId == GDB_ID_NULL)
return false ;
// assegno il colore
Color cCol = AQUA ;
cCol.SetAlpha( 0.25) ;
pGeomDB->SetMaterial( nSfrId, cCol) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
AdjustLayerForSideAngle( IGeomDB* pGeomDB, int nLayOrigId, const string& sLayOrig, int nLayReg, double dH)
{
// creo una copia del layer
int nLayId = pGeomDB->Copy( nLayOrigId, GDB_ID_NULL, nLayOrigId, GDB_AFTER) ;
if ( nLayId == GDB_ID_NULL)
return false ;
pGeomDB->SetName( nLayOrigId, sLayOrig) ;
pGeomDB->SetInfo( nLayOrigId, NST_KEY_COPY, nLayId) ;
pGeomDB->SetStatus( nLayOrigId, GDB_ST_OFF) ;
// creo un layer temporaneo
const string sTmpLayName = "TmpLay" ;
Frame3d frLay ;
pGeomDB->GetGroupFrame( nLayId, frLay) ;
int nTmpLayId = pGeomDB->AddGroup( GDB_ID_NULL, pGeomDB->GetParentId( nLayId), frLay) ;
if ( nTmpLayId == GDB_ID_NULL)
return false ;
pGeomDB->SetName( nTmpLayId, sTmpLayName) ;
pGeomDB->SetLevel( nTmpLayId, GDB_LV_TEMP) ;
// copio le entità del contorno esterno e le offsetto opportunamente
int nCrvId = pGeomDB->GetFirstInGroup( nLayId) ;
while ( nCrvId != GDB_ID_NULL) {
// copio la curva nel gruppo temporaneo
int nNewId = pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nTmpLayId) ;
if ( nNewId == GDB_ID_NULL)
return false ;
// determino ed eseguo offset
double dSideAng ;
if ( pGeomDB->GetInfo( nCrvId, NST_KEY_SIDEANG, dSideAng) && abs( dSideAng) > EPS_ANG_SMALL) {
double dOffset = 0 ;
pGeomDB->GetInfo( nCrvId, NST_KEY_OFFSET, dOffset) ;
double dCalcOffset = dH * tan( dSideAng * DEGTORAD) + dOffset ;
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nNewId)) ;
if ( pCrv == nullptr)
return false ;
pCrv->SimpleOffset( dCalcOffset) ;
}
// passo alla successiva
nCrvId = pGeomDB->GetNext( nCrvId) ;
}
// aggiusto tra loro le entità offsettate
int nFirstCrvId = pGeomDB->GetFirstInGroup( nTmpLayId) ;
ICurve* pCrv1 = GetCurve( pGeomDB->GetGeoObj( nFirstCrvId)) ;
int nNextCrvId = pGeomDB->GetNext( nFirstCrvId) ;
ICurve* pCrv2 = GetCurve( pGeomDB->GetGeoObj( nNextCrvId)) ;
while ( nNextCrvId != GDB_ID_NULL) {
// sistemo le curve
pCrv2 = GetCurve( pGeomDB->GetGeoObj( nNextCrvId)) ;
if ( pCrv1 == nullptr || pCrv2 == nullptr || ! AdjustCurves( pCrv1, pCrv2))
return false ;
// passo alla successiva
pCrv1 = pCrv2 ;
nNextCrvId = pGeomDB->GetNext( nNextCrvId) ;
}
// anche prima e ultima
pCrv2 = GetCurve( pGeomDB->GetGeoObj( nFirstCrvId)) ;
if ( pCrv1 == nullptr || pCrv2 == nullptr || ! AdjustCurves( pCrv1, pCrv2))
return false ;
// eventuali allungamenti/accorciamenti per le curve del loop
for ( int nCrvId = pGeomDB->GetFirstInGroup( nLayId) ;
nCrvId != GDB_ID_NULL ;
nCrvId = pGeomDB->GetNext( nCrvId)) {
// recupero il nome
string sName ;
if ( ! pGeomDB->GetName( nCrvId, sName))
continue ;
// recupero curva con lo stesso nome nel gruppo della regione sotto
int nCrvDrId = pGeomDB->GetFirstNameInGroup( nTmpLayId, sName) ;
if ( nCrvDrId == GDB_ID_NULL)
continue ;
// verifico siano curve
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nCrvId)) ;
ICurve* pCrvDr = GetCurve( pGeomDB->GetGeoObj( nCrvDrId)) ;
if ( pCrv == nullptr || pCrvDr == nullptr)
continue ;
// verifico se devo allungare o accorciare la curva all'inizio
double dPrevAng = 0 ;
pGeomDB->GetInfo( nCrvId, MCH_PV_KEY_PREVANG, dPrevAng) ;
Point3d ptStart ;
pCrv->GetStartPoint( ptStart) ;
Vector3d vtStartDir ;
pCrv->GetStartDir( vtStartDir) ;
Point3d ptStartDr ;
pCrvDr->GetStartPoint( ptStartDr) ;
double dStartPro = - ( ( ptStartDr - ptStart) * vtStartDir) ;
if ( dPrevAng > - EPS_ANG_SMALL) {
if ( dStartPro > EPS_SMALL)
pCrv->ExtendStartByLen( dStartPro) ;
}
else {
if ( dStartPro < - EPS_SMALL)
pCrv->TrimStartAtLen( - dStartPro) ;
}
// verifico se devo allungare la curva alla fine
double dNextAng = 0 ;
pGeomDB->GetInfo( nCrvId, MCH_PV_KEY_NEXTANG, dNextAng) ;
Point3d ptEnd ;
pCrv->GetEndPoint( ptEnd) ;
Vector3d vtEndDir ;
pCrv->GetEndDir( vtEndDir) ;
Point3d ptEndDr ;
pCrvDr->GetEndPoint( ptEndDr) ;
double dEndPro = ( ptEndDr - ptEnd) * vtEndDir ;
if ( dNextAng > - EPS_ANG_SMALL) {
if ( dEndPro > EPS_SMALL)
pCrv->ExtendEndByLen( dEndPro) ;
}
else {
if ( dEndPro < - EPS_SMALL) {
double dLen ;
pCrv->GetLength( dLen) ;
pCrv->TrimEndAtLen( dLen + dEndPro) ;
}
}
}
// concateno le curve del layer temporaneo
PtrOwner<ICurveComposite> pCompo( CreateCurveComposite()) ;
if ( IsNull( pCompo))
return false ;
for ( int nCrvId = pGeomDB->GetFirstInGroup( nTmpLayId) ;
nCrvId != GDB_ID_NULL ;
nCrvId = pGeomDB->GetFirstInGroup( nTmpLayId)) {
ICurve* pCrv = GetCurve( pGeomDB->RemoveGeoObjAndErase( nCrvId)) ;
if ( pCrv != nullptr)
pCompo->AddCurve( pCrv) ;
else
pGeomDB->Erase( nCrvId) ;
}
// cancello il layer temporaneo
pGeomDB->Erase( nTmpLayId) ;
// inserisco la curva concatenata nel layer della regione
if ( pGeomDB->AddGeoObj( GDB_ID_NULL, nLayReg, Release( pCompo)) == GDB_ID_NULL)
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
ExeCalcFlatPartDownRegion( int nPartId, double dH)
{
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// ripristino lo stato originale
pGeomDB->Erase( pGeomDB->GetFirstNameInGroup( nPartId, NST_PARTDOWNREG_LAYER)) ;
int nOlOrigId = pGeomDB->GetFirstNameInGroup( nPartId, NST_OUT_ORIG_LAYER) ;
if ( nOlOrigId != GDB_ID_NULL) {
pGeomDB->Erase( pGeomDB->GetFirstNameInGroup( nPartId, NST_OUT_LAYER)) ;
pGeomDB->SetName( nOlOrigId, NST_OUT_LAYER) ;
pGeomDB->SetStatus( nOlOrigId, GDB_ST_ON) ;
}
for ( int nIlOrigId = pGeomDB->GetFirstNameInGroup( nPartId, NST_IN_ORIG_LAYER) ;
nIlOrigId != GDB_ID_NULL ;
nIlOrigId = pGeomDB->GetFirstNameInGroup( nPartId, NST_IN_ORIG_LAYER)) {
int nCopyId = GDB_ID_NULL ;
pGeomDB->GetInfo( nIlOrigId, NST_KEY_COPY, nCopyId) ;
if ( nCopyId != GDB_ID_NULL)
pGeomDB->Erase( nCopyId) ;
pGeomDB->SetName( nIlOrigId, NST_IN_LAYER) ;
pGeomDB->SetStatus( nIlOrigId, GDB_ST_ON) ;
}
// se spessore nullo, non devo fare altro
if ( dH < EPS_SMALL)
return true ;
// recupero i layer esterno ed interni (primo sempre esterno)
INTVECTOR vLayId ;
int nOlId = pGeomDB->GetFirstNameInGroup( nPartId, NST_OUT_LAYER) ;
if ( nOlId == GDB_ID_NULL)
return false ;
vLayId.push_back( nOlId) ;
for ( int nIlId = pGeomDB->GetFirstNameInGroup( nPartId, NST_IN_LAYER) ;
nIlId != GDB_ID_NULL ;
nIlId = pGeomDB->GetNextName( nIlId, NST_IN_LAYER))
vLayId.push_back( nIlId) ;
// se il pezzo non ha lati esterni o interni inclinati all'infuori non devo fare alcunchè
bool bAllVertSides = true ;
for ( size_t i = 0 ; i < vLayId.size() ; ++ i) {
int nCrvId = pGeomDB->GetFirstInGroup( vLayId[i]) ;
while ( nCrvId != GDB_ID_NULL) {
double dSideAng ;
if ( pGeomDB->GetInfo( nCrvId, NST_KEY_SIDEANG, dSideAng) && abs( dSideAng) > EPS_ANG_SMALL) {
bAllVertSides = false ;
break ;
}
nCrvId = pGeomDB->GetNext( nCrvId) ;
}
}
if ( bAllVertSides)
return true ;
// assegno un nome alle curve dei layer che ne sono prive
for ( size_t i = 0 ; i < vLayId.size() ; ++ i) {
int nCnt = 0 ;
for ( int nCrvId = pGeomDB->GetFirstInGroup( vLayId[i]) ;
nCrvId != GDB_ID_NULL ;
nCrvId = pGeomDB->GetNext( nCrvId)) {
if ( ! pGeomDB->ExistsName( nCrvId) && ( pGeomDB->GetGeoType( nCrvId) & GEO_CURVE) != 0) {
++ nCnt ;
pGeomDB->SetName( nCrvId, "B" + ToString( nCnt)) ;
}
}
}
// creo il layer per la regione sotto (con il medesimo riferimento del layer esterno)
Frame3d frOl ;
pGeomDB->GetGroupFrame( nOlId, frOl) ;
int nDwnRegId = pGeomDB->AddGroup( GDB_ID_NULL, nPartId, frOl) ;
if ( nDwnRegId == GDB_ID_NULL)
return false ;
pGeomDB->SetName( nDwnRegId, NST_PARTDOWNREG_LAYER) ;
// modifico i layer e creo i contorni per la nuova regione
for ( size_t i = 0 ; i < vLayId.size() ; ++ i) {
string sLayOrig = ( i == 0 ? NST_OUT_ORIG_LAYER : NST_IN_ORIG_LAYER) ;
if ( ! AdjustLayerForSideAngle( pGeomDB, vLayId[i], sLayOrig, nDwnRegId, dH))
return false ;
}
// creo la regione
SurfFlatRegionByContours SfrCntr( false) ;
for ( int nCrvId = pGeomDB->GetFirstInGroup( nDwnRegId) ;
nCrvId != GDB_ID_NULL ;
nCrvId = pGeomDB->GetFirstInGroup( nDwnRegId)) {
ICurve* pCrv = GetCurve( pGeomDB->RemoveGeoObjAndErase( nCrvId)) ;
if ( pCrv != nullptr)
SfrCntr.AddCurve( pCrv) ;
else
pGeomDB->Erase( nCrvId) ;
}
int nSfrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDwnRegId, SfrCntr.GetSurf()) ;
if ( nSfrId == GDB_ID_NULL)
return false ;
// assegno il colore
Color cCol = AQUA ;
cCol.SetAlpha( 0.25) ;
pGeomDB->SetMaterial( nSfrId, cCol) ;
return true ;
}
//----------------------------------------------------------------------------
int
GetFlatPartRegion( IGeomDB* pGeomDB, int nId)
{
if ( pGeomDB == nullptr)
return GDB_ID_NULL ;
// recupero regione totale del pezzo (è la prima del sottogruppo di nome Region)
int nRegGrp = pGeomDB->GetFirstNameInGroup( nId, NST_PARTREG_LAYER) ;
int nRegId = pGeomDB->GetFirstInGroup( nRegGrp) ;
while ( nRegId != GDB_ID_NULL) {
if ( pGeomDB->GetGeoType( nRegId) == SRF_FLATRGN)
break ;
nRegId = pGeomDB->GetNext( nRegId) ;
}
return nRegId ;
}
//----------------------------------------------------------------------------
int
GetFlatPartUpRegion( IGeomDB* pGeomDB, int nId)
{
if ( pGeomDB == nullptr)
return GDB_ID_NULL ;
// recupero regione sopra del pezzo (è la prima del sottogruppo di nome UpReg)
int nRegGrp = pGeomDB->GetFirstNameInGroup( nId, NST_PARTUPREG_LAYER) ;
int nRegId = pGeomDB->GetFirstInGroup( nRegGrp) ;
while ( nRegId != GDB_ID_NULL) {
if ( pGeomDB->GetGeoType( nRegId) == SRF_FLATRGN)
break ;
nRegId = pGeomDB->GetNext( nRegId) ;
}
return nRegId ;
}
//----------------------------------------------------------------------------
int
GetFlatPartDownRegion( IGeomDB* pGeomDB, int nId)
{
if ( pGeomDB == nullptr)
return GDB_ID_NULL ;
// recupero regione sotto del pezzo (è la prima del sottogruppo di nome DwnReg)
int nRegGrp = pGeomDB->GetFirstNameInGroup( nId, NST_PARTDOWNREG_LAYER) ;
int nRegId = pGeomDB->GetFirstInGroup( nRegGrp) ;
while ( nRegId != GDB_ID_NULL) {
if ( pGeomDB->GetGeoType( nRegId) == SRF_FLATRGN)
break ;
nRegId = pGeomDB->GetNext( nRegId) ;
}
return nRegId ;
}
//----------------------------------------------------------------------------
bool
GetFlatPartCutRegions( IGeomDB* pGeomDB, int nId, bool bReduced, INTVECTOR& vCrId)
{
if ( pGeomDB == nullptr)
return GDB_ID_NULL ;
// recupero gruppo preview lavorazioni del pezzo
int nPVGrp = pGeomDB->GetFirstNameInGroup( nId, MCH_PV) ;
if ( nPVGrp == GDB_ID_NULL)
return true ;
// 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 ;
}
//----------------------------------------------------------------------------
bool
GetFlatPartDownCutRegions( IGeomDB* pGeomDB, int nId, bool bReduced, INTVECTOR& vDwnCrId)
{
if ( pGeomDB == nullptr)
return GDB_ID_NULL ;
// recupero gruppo preview lavorazioni del pezzo
int nPVGrp = pGeomDB->GetFirstNameInGroup( nId, MCH_PV) ;
if ( nPVGrp == GDB_ID_NULL)
return true ;
// ciclo sulle lavorazioni
int nMchId = pGeomDB->GetFirstGroupInGroup( nPVGrp) ;
while ( nMchId != GDB_ID_NULL) {
int nClId = pGeomDB->GetFirstGroupInGroup( nMchId) ;
while ( nClId != GDB_ID_NULL) {
// ciclo sui sopra e salvo gli eventuali sotto (per tenerli sincronizzati)
int nCrId = pGeomDB->GetFirstNameInGroup( nClId, ( bReduced ? MCH_PV_RRCUT : MCH_PV_RCUT)) ;
int nDwnCrId = pGeomDB->GetFirstNameInGroup( nClId, ( bReduced ? MCH_PV_DOWN_RRCUT : MCH_PV_DOWN_RCUT)) ;
while ( nCrId != GDB_ID_NULL) {
vDwnCrId.emplace_back( nDwnCrId) ;
nCrId = pGeomDB->GetNextName( nCrId, ( bReduced ? MCH_PV_RRCUT : MCH_PV_RCUT)) ;
nDwnCrId = pGeomDB->GetNextName( nDwnCrId, ( bReduced ? MCH_PV_DOWN_RRCUT : MCH_PV_DOWN_RCUT)) ;
}
nClId = pGeomDB->GetNextGroup( nClId) ;
}
nMchId = pGeomDB->GetNextGroup( nMchId) ;
}
return true ;
}
//----------------------------------------------------------------------------
int
GetFlatPartFromRegion( IGeomDB* pGeomDB, int nId)
{
if ( pGeomDB == nullptr)
return GDB_ID_NULL ;
// verifico che il layer di appartenenza sia una regione
int nLayerId = pGeomDB->GetParentId( nId) ;
string sName ;
if ( ! pGeomDB->GetName( nLayerId, sName) &&
! EqualNoCase( sName, NST_PARTREG_LAYER) &&
! EqualNoCase( sName, NST_PARTUPREG_LAYER) &&
! EqualNoCase( sName, NST_PARTDOWNREG_LAYER))
return GDB_ID_NULL ;
// restituisco il padre del layer
return ( pGeomDB->GetParentId( nLayerId)) ;
}
//----------------------------------------------------------------------------
int
GetFlatPartFromCut( IGeomDB* pGeomDB, int nId)
{
if ( pGeomDB == nullptr)
return GDB_ID_NULL ;
// verifico appartenga al gruppo PreView (padre di padre di padre)
int nPvId = pGeomDB->GetParentId( pGeomDB->GetParentId( pGeomDB->GetParentId( nId))) ;
string sName ;
if ( ! pGeomDB->GetName( nPvId, sName) && ! EqualNoCase( sName, MCH_PV))
return GDB_ID_NULL ;
// restituisco il padre del layer
return ( pGeomDB->GetParentId( nPvId)) ;
}
//----------------------------------------------------------------------------
int
GetGeometryFromCut( IGeomDB* pGeomDB, IMachMgr* pMachMgr, int nId)
{
if ( pGeomDB == nullptr || pMachMgr == nullptr)
return GDB_ID_NULL ;
// verifico appartenga ad una lavorazione
int nMchId ;
if ( ! pGeomDB->GetInfo( pGeomDB->GetParentId( pGeomDB->GetParentId( nId)), "MId", nMchId))
return GDB_ID_NULL ;
// recupero la geometria di applicazione della lavorazione (deve essere una sola)
if ( ! pMachMgr->SetCurrMachining( nMchId))
return GDB_ID_NULL ;
SELVECTOR vIds ;
pMachMgr->GetMachiningGeometry( vIds) ;
if ( vIds.size() == 1)
return vIds[0].nId ;
else
return GDB_ID_NULL ;
}
//----------------------------------------------------------------------------
bool
GetFlatPartApproxContour( IGeomDB* pGeomDB, int nId, PolyLine& PL)
{
if ( pGeomDB == nullptr)
return false ;
// Recupero la superficie regione piana
int nRegId = GetFlatPartRegion( pGeomDB, nId) ;
const ISurfFlatRegion* pSfr = GetSurfFlatRegion( pGeomDB->GetGeoObj( nRegId)) ;
if ( pSfr == nullptr)
return false ;
// ne recupero il riferimento globale
Frame3d frSurf ;
pGeomDB->GetGlobFrame( nRegId, frSurf) ;
// ne approssimo il contorno con una polilinea che porto in globale
if ( ! pSfr->ApproxLoopWithLines( 0, 0, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
return false ;
PL.ToGlob( frSurf) ;
return true ;
}