1d9ecd9b78
- migliorata la collisione e l'allineamento per Regioni Piane.
2228 lines
90 KiB
C++
2228 lines
90 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2018
|
|
//----------------------------------------------------------------------------
|
|
// File : EXE_NstCreateFlatParts.cpp Data : 06.09.18 Versione : 1.9i1
|
|
// 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/EGkCurveLine.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/EGkPointGrid3d.h"
|
|
#include "/EgtDev/Include/EMkMachiningGeoConst.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Raccolte di coppie Point3d,Color
|
|
typedef std::pair<Point3d,Color> POINTCOLOR ; // coppia punto, colore
|
|
typedef std::vector<POINTCOLOR> PNTCOLVECTOR ; // vettore di coppie punto, colore
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Costanti
|
|
const double EPS_PNTCOL = 1.0 ;
|
|
const double MIN_LEN_COLOR = 1.0 ;
|
|
const double MIN_LEN_SPLIT = 10.0 ;
|
|
const double MIN_AREA = 1.0 ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
VerifyCalcLevel( IGdbIterator* pEnt, int nReqLev)
|
|
{
|
|
int nLev ;
|
|
return ( pEnt->GetCalcLevel( nLev) && nLev == nReqLev) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
ApproxCurveIfNeeded( IGdbIterator* pEnt, double dToler)
|
|
{
|
|
// 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_BEZIER)
|
|
bSomeBezier = true ;
|
|
pCrv = pCrvCo->GetNextCurve() ;
|
|
}
|
|
if ( ! bSomeBezier)
|
|
return true ;
|
|
}
|
|
}
|
|
// esecuzione dell'approssimazione
|
|
ICurve* pCrv = GetCurve( pEnt->GetGeoObj()) ;
|
|
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
|
|
PolyArc PA ;
|
|
double dTol = max( dToler, LIN_TOL_FINE) ;
|
|
bool bOk = pCrv->ApproxWithArcsEx( dTol, ANG_TOL_STD_DEG, LIN_FEA_STD, PA) && pCC->FromPolyArc( PA) ;
|
|
// eliminazione di small Z
|
|
bOk = bOk && pCC->RemoveSmallDefects( 0.5 * dTol, ANG_TOL_STD_DEG) ;
|
|
// merge di archi identici di biarchi
|
|
bOk = bOk && pCC->MergeCurves( 0.5 * dTol, ANG_TOL_STD_DEG) ;
|
|
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( double dToler)
|
|
{
|
|
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
|
|
if ( pPar->GetGdbType() != GDB_TY_GROUP || ! VerifyCalcLevel( pPar, 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
|
|
if ( pLay->GetGdbType() != GDB_TY_GROUP || ! VerifyCalcLevel( pLay, 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 o testi di livello User
|
|
bool bCurve = (( pEnt->GetGeoType() & GEO_CURVE) != 0) ;
|
|
bool bText = ( pEnt->GetGeoType() == EXT_TEXT) ;
|
|
if ( ( ! bCurve && ! bText) || ! VerifyCalcLevel( pEnt, GDB_LV_USER)) {
|
|
bEok = pEnt->EraseAndGoToNext() ;
|
|
continue ;
|
|
}
|
|
// aggiustamenti per curve
|
|
if ( bCurve) {
|
|
// eventuale approx della curva se Bezier o Composita con molti piccoli segmenti
|
|
ApproxCurveIfNeeded( pEnt, dToler) ;
|
|
// 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
|
|
SaveColorWithMidPnt( PNTCOLVECTOR& vPntCol)
|
|
{
|
|
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) {
|
|
// ciclo su tutti gli oggetti del pezzo
|
|
bool bLok = pLay->GoToFirstInGroup( *pPar) ;
|
|
while ( bLok) {
|
|
// ciclo su tutti gli oggetti del layer
|
|
bool bEok = pEnt->GoToFirstInGroup( *pLay) ;
|
|
while ( bEok) {
|
|
// se curva composita
|
|
if ( pEnt->GetGeoType() == CRV_COMPO) {
|
|
// se c'è il colore e abbastanza lunga
|
|
Color cCol ;
|
|
double dLen ;
|
|
if ( pEnt->GetCalcMaterial( cCol) &&
|
|
ExeCurveLength( pEnt->GetId(), &dLen) && dLen > MIN_LEN_COLOR) {
|
|
// ciclo sulle curve elementari
|
|
const ICurveComposite* pCompo = GetCurveComposite( pEnt->GetGeoObj()) ;
|
|
const ICurve* pCrv = pCompo->GetFirstCurve() ;
|
|
while ( pCrv != NULL) {
|
|
// recupero il punto medio
|
|
Point3d ptMid ;
|
|
if ( pCrv->GetMidPoint( ptMid)) {
|
|
// inserisco nella lista dei punti-colori, se punto non già presente
|
|
if ( find_if( vPntCol.begin(), vPntCol.end(),
|
|
[&](const POINTCOLOR& PntCol) { return AreSamePointEpsilon( PntCol.first, ptMid, EPS_PNTCOL) ;}) == vPntCol.end())
|
|
vPntCol.emplace_back( ptMid, cCol) ;
|
|
}
|
|
pCrv = pCompo->GetNextCurve() ;
|
|
}
|
|
}
|
|
}
|
|
// altrimenti linea o arco
|
|
else if ( ( pEnt->GetGeoType() & GEO_CURVE) != 0) {
|
|
// recupero il colore proprio e il punto medio
|
|
Color cCol ;
|
|
Point3d ptMid ;
|
|
double dLen ;
|
|
if ( pEnt->GetCalcMaterial( cCol) &&
|
|
ExeMidPoint( pEnt->GetId(), GDB_ID_ROOT, ptMid) &&
|
|
ExeCurveLength( pEnt->GetId(), &dLen) && dLen > MIN_LEN_COLOR) {
|
|
// inserisco nella lista dei punti-colori, se punto non già presente
|
|
if ( find_if( vPntCol.begin(), vPntCol.end(),
|
|
[&](const POINTCOLOR& PntCol) { return AreSamePointEpsilon( PntCol.first, ptMid, EPS_PNTCOL) ;}) == vPntCol.end())
|
|
vPntCol.emplace_back( ptMid, cCol) ;
|
|
}
|
|
}
|
|
// 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
|
|
ApplyColorWithMidPnt( const PNTCOLVECTOR& vPntCol)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
// Points number
|
|
int n = int( vPntCol.size()) ;
|
|
// Overall box
|
|
BBox3d b3All ;
|
|
for ( const auto& PntCol : vPntCol)
|
|
b3All.Add( PntCol.first) ;
|
|
// Grid cell dimension
|
|
double dCellDim ;
|
|
b3All.GetRadius( dCellDim) ;
|
|
dCellDim *= 2 / sqrt( n) ;
|
|
// Grid
|
|
PointGrid3d PntGrid ;
|
|
if ( ! PntGrid.Init( 2 * n, dCellDim))
|
|
return false ;
|
|
for ( int i = 0 ; i < int( vPntCol.size()) ; ++ i)
|
|
PntGrid.InsertPoint( vPntCol[i].first, i) ;
|
|
// Ciclo sui pezzi
|
|
int nPartId = ExeGetFirstPart( false) ;
|
|
while ( nPartId != GDB_ID_NULL) {
|
|
// Ciclo sui layer del pezzo
|
|
int nLayerId = ExeGetFirstLayer( nPartId, false) ;
|
|
while ( nLayerId != GDB_ID_NULL) {
|
|
string sLayName ; pGeomDB->GetName( nLayerId, sLayName) ;
|
|
// Se layer OutLoop, InLoop o OnPath
|
|
if ( sLayName == NST_OUT_LAYER ||
|
|
sLayName == NST_IN_LAYER ||
|
|
sLayName == NST_ON_LAYER) {
|
|
// Ciclo su tutti gli oggetti del layer
|
|
int nEntId = pGeomDB->GetFirstInGroup( nLayerId) ;
|
|
while ( nEntId != GDB_ID_NULL) {
|
|
// se curva
|
|
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nEntId)) ;
|
|
if ( pCrv != nullptr) {
|
|
// recupero il riferimento
|
|
Frame3d frCrv ; pGeomDB->GetGlobFrame( nEntId, frCrv) ;
|
|
// recupero il box e lo espando della tolleranza
|
|
BBox3d b3Ent ; pGeomDB->GetGlobalBBox( nEntId, b3Ent) ;
|
|
b3Ent.Expand( EPS_PNTCOL) ;
|
|
// cerco i punti-colore che possono appartenere all'entità
|
|
INTVECTOR vnIs ; PntGrid.Find( b3Ent, vnIs) ;
|
|
for ( int i = 0 ; i < int( vnIs.size()) ;) {
|
|
Point3d ptCol = vPntCol[vnIs[i]].first ;
|
|
ptCol.ToLoc( frCrv) ;
|
|
if ( pCrv->IsPointOn( ptCol, EPS_PNTCOL))
|
|
++ i ;
|
|
else
|
|
vnIs.erase( vnIs.begin() + i) ;
|
|
}
|
|
// se due punti di colore diverso divido la curva in parti corrispondenti ai punti
|
|
if ( vnIs.size() == 2 && ! ( vPntCol[vnIs[0]].second == vPntCol[vnIs[1]].second)) {
|
|
// recupero la posizione dei punti lungo la curva
|
|
Point3d ptCol1 = vPntCol[vnIs[0]].first ;
|
|
ptCol1.ToLoc( frCrv) ;
|
|
double dLen1 = - 1 ;
|
|
pCrv->GetLengthAtPoint( ptCol1, dLen1, EPS_PNTCOL) ;
|
|
Point3d ptCol2 = vPntCol[vnIs[1]].first ;
|
|
ptCol2.ToLoc( frCrv) ;
|
|
double dLen2 = - 1 ;
|
|
pCrv->GetLengthAtPoint( ptCol2, dLen2, EPS_PNTCOL) ;
|
|
// recupero i colori
|
|
Color cCol1 = vPntCol[vnIs[0]].second ;
|
|
Color cCol2 = vPntCol[vnIs[1]].second ;
|
|
if ( dLen2 < dLen1)
|
|
swap( cCol1, cCol2) ;
|
|
// determino la posizione di divisione
|
|
double dLenSplit = max( 2 * min( dLen1, dLen2), 0.) ;
|
|
double dLenTot ; pCrv->GetLength( dLenTot) ;
|
|
if ( dLenSplit > MIN_LEN_SPLIT && dLenTot - dLenSplit > MIN_LEN_SPLIT) {
|
|
// divido la curva opportunamente
|
|
double dParSplit ; pCrv->GetParamAtLength( dLenSplit, dParSplit) ;
|
|
int nNewId = ExeSplitCurveAtParam( nEntId, dParSplit) ;
|
|
// sistemo opportunamente le info
|
|
pGeomDB->SetInfo( nEntId, MCH_KEY_NEXTANG, 0) ;
|
|
pGeomDB->SetInfo( nNewId, MCH_KEY_PREVANG, 0) ;
|
|
// assegno i colori
|
|
pGeomDB->SetMaterial( nEntId, cCol1) ;
|
|
pGeomDB->SetMaterial( nNewId, cCol2) ;
|
|
// aggiorno entità corrente
|
|
nEntId = nNewId ;
|
|
}
|
|
else if ( dLenSplit > MIN_LEN_SPLIT) {
|
|
// assegno il colore
|
|
pGeomDB->SetMaterial( nEntId, cCol1) ;
|
|
}
|
|
else if ( dLenTot - dLenSplit > MIN_LEN_SPLIT) {
|
|
// assegno il colore
|
|
pGeomDB->SetMaterial( nEntId, cCol2) ;
|
|
}
|
|
}
|
|
// se altrimenti almeno un punto, assegno direttamente il colore del primo
|
|
else if ( vnIs.size() > 0)
|
|
pGeomDB->SetMaterial( nEntId, vPntCol[vnIs[0]].second) ;
|
|
// altrimenti non assegno colore
|
|
}
|
|
// passo alla successiva entità
|
|
nEntId = pGeomDB->GetNext( nEntId) ;
|
|
}
|
|
}
|
|
nLayerId = ExeGetNextLayer( nLayerId, false) ;
|
|
}
|
|
nPartId = ExeGetNextPart( nPartId, false) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
ChainCurves( int& nLay)
|
|
{
|
|
// seleziono tutte e sole le curve
|
|
ExeSetObjFilterForSelect( false, true, false, false, false) ;
|
|
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) ;
|
|
// sposto gli eventuali testi
|
|
ExeSetObjFilterForSelect( false, false, false, false, true) ;
|
|
bOk = ExeSelectAll( false) ;
|
|
int nId = ExeGetFirstSelectedObj() ;
|
|
while ( nId != GDB_ID_NULL) {
|
|
bOk = bOk && ExeRelocateGlob( nId, nLay, GDB_LAST_SON) ;
|
|
nId = ExeGetNextSelectedObj() ;
|
|
}
|
|
ExeDeselectAll() ;
|
|
// cancello i gruppi rimasti vuoti
|
|
ExeEraseEmptyParts() ;
|
|
// ripristino filtro di selezione
|
|
ExeSetObjFilterForSelect( true, true, true, true, true) ;
|
|
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
|
|
INTDBLVECTOR vArea ; // vettore di coppie indice curva chiusa + area
|
|
INTVECTOR vOpenIds ; // vettore indici curve aperte
|
|
INTVECTOR vTextIds ; // vettore indici testi
|
|
bool bEok = pEnt->GoToFirstInGroup( nLay) ;
|
|
while ( bEok) {
|
|
ICurve* pCrv = GetCurve( pEnt->GetGeoObj()) ;
|
|
if ( pCrv == nullptr) {
|
|
IExtText* pTxt = GetExtText( pEnt->GetGeoObj()) ;
|
|
if ( pTxt == nullptr)
|
|
bEok = pEnt->EraseAndGoToNext() ;
|
|
else {
|
|
vTextIds.push_back( pEnt->GetId()) ;
|
|
bEok = pEnt->GoToNext() ;
|
|
}
|
|
}
|
|
else if ( ! pCrv->IsClosed()) {
|
|
vOpenIds.push_back( pEnt->GetId()) ;
|
|
bEok = pEnt->GoToNext() ;
|
|
}
|
|
else {
|
|
double dArea ;
|
|
pCrv->GetAreaXY( dArea) ;
|
|
if ( abs( dArea) > MIN_AREA) {
|
|
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 INTDBL& a, const INTDBL&b) { return abs( a.second) > abs( 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) ;
|
|
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( vArea[i].first)) ;
|
|
// ne determino il box e il centro
|
|
BBox3d b3Part ;
|
|
pGeomDB->GetGlobalBBox( vArea[i].first, b3Part) ;
|
|
Point3d ptPartCen ;
|
|
b3Part.GetCenter( ptPartCen) ;
|
|
// cerco altri contorni chiusi che siano contenuti completamente o parzialmente
|
|
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, EPS_SMALL, 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 = 0 ; 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, EPS_SMALL, 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) ;
|
|
}
|
|
}
|
|
}
|
|
// cerco il testo contenuto almeno parzialmente e più vicino al centro del pezzo
|
|
double dMinSqDist = SQ_INFINITO ;
|
|
int nMinJ = -1 ;
|
|
for ( int j = 0 ; j < int( vTextIds.size()) ; ++ j) {
|
|
if ( vTextIds[j] == GDB_ID_NULL)
|
|
continue ;
|
|
// verifico se il box del testo interferisce con il box del contorno
|
|
BBox3d b3Text ;
|
|
if ( pGeomDB->GetGlobalBBox( vTextIds[j], b3Text) && b3Part.OverlapsXY( b3Text)) {
|
|
// verifico se a minima distanza
|
|
Point3d ptCen ;
|
|
b3Text.GetCenter( ptCen) ;
|
|
double dSqDist = SqDistXY( ptPartCen, ptCen) ;
|
|
if ( dSqDist < dMinSqDist) {
|
|
dMinSqDist = dSqDist ;
|
|
nMinJ = j ;
|
|
}
|
|
}
|
|
}
|
|
// se trovato un testo, lo inserisco nel pezzo
|
|
if ( nMinJ != -1) {
|
|
pGeomDB->RelocateGlob( vTextIds[nMinJ], nLayId) ;
|
|
vTextIds[nMinJ] = GDB_ID_NULL ;
|
|
}
|
|
}
|
|
// 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)
|
|
INTVECTOR vTextIds ; // vettore indici testi
|
|
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 ;
|
|
}
|
|
// se altrimento testi, ne salvo l'identificativo
|
|
else if ( pEnt->GetGeoType() == EXT_TEXT) {
|
|
vTextIds.emplace_back( pEnt->GetId()) ;
|
|
bEok = pEnt->GoToNext() ;
|
|
}
|
|
// altrimenti cancello
|
|
else
|
|
bEok = pEnt->EraseAndGoToNext() ;
|
|
}
|
|
// altro layer del gruppo originale
|
|
bLok = pLay->GoToNextGroup() ;
|
|
}
|
|
// passo al successivo
|
|
bPok = pPar->GoToNextGroup() ;
|
|
}
|
|
// ciclo sui pezzi creati, per eventuale inserimento testi
|
|
for ( bool bPok = pPar->GoToFirstGroupInGroup( GDB_ID_ROOT) ;
|
|
bPok && pPar->GetId() != nFirstId ;
|
|
bPok = pPar->GoToNextGroup()) {
|
|
// ingombro e centro del pezzo
|
|
BBox3d b3Part ;
|
|
if ( ! pGeomDB->GetGlobalBBox( pPar->GetId(), b3Part))
|
|
continue ;
|
|
Point3d ptPartCen ;
|
|
b3Part.GetCenter( ptPartCen) ;
|
|
// cerco il testo contenuto almeno parzialmente e più vicino al centro del pezzo
|
|
double dMinSqDist = SQ_INFINITO ;
|
|
int nMinJ = -1 ;
|
|
for ( int j = 0 ; j < int( vTextIds.size()) ; ++ j) {
|
|
if ( vTextIds[j] == GDB_ID_NULL)
|
|
continue ;
|
|
// verifico se il box del testo interferisce con il box del contorno
|
|
BBox3d b3Text ;
|
|
if ( pGeomDB->GetGlobalBBox( vTextIds[j], b3Text) && b3Part.OverlapsXY( b3Text)) {
|
|
// verifico se a minima distanza
|
|
Point3d ptCen ;
|
|
b3Text.GetCenter( ptCen) ;
|
|
double dSqDist = SqDistXY( ptPartCen, ptCen) ;
|
|
if ( dSqDist < dMinSqDist) {
|
|
dMinSqDist = dSqDist ;
|
|
nMinJ = j ;
|
|
}
|
|
}
|
|
}
|
|
// se trovato un testo, lo inserisco nel pezzo
|
|
if ( nMinJ != -1) {
|
|
pGeomDB->RelocateGlob( vTextIds[nMinJ], pGeomDB->GetFirstGroupInGroup( pPar->GetId())) ;
|
|
vTextIds[nMinJ] = GDB_ID_NULL ;
|
|
}
|
|
}
|
|
// elimino i testi rimasti non assegnati
|
|
for ( int j = 0 ; j < int( vTextIds.size()) ; ++ j) {
|
|
if ( vTextIds[j] != GDB_ID_NULL)
|
|
pGeomDB->Erase( vTextIds[j]) ;
|
|
}
|
|
// cancello i gruppi svuotati
|
|
bPok = pPar->GoTo( nFirstId) ;
|
|
while ( bPok)
|
|
bPok = pPar->EraseAndGoToNext() ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
VerifyPrepareFlatParts( 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
|
|
ExeSetObjFilterForSelect( false, true, false, false, false) ;
|
|
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 ( abs( dArea) < MIN_AREA) {
|
|
bEok = pEnt->EraseAndGoToNext() ;
|
|
continue ;
|
|
}
|
|
else 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 di eventuale testo e delle dimensioni nel layer della regione
|
|
if ( bOk) {
|
|
string sText ;
|
|
// recupero eventuale testo associato al pezzo
|
|
int nTextId = pGeomDB->GetFirstInGroup( pGeomDB->GetFirstGroupInGroup( pPar->GetId())) ;
|
|
while ( nTextId != GDB_ID_NULL && pGeomDB->GetGeoType( nTextId) != EXT_TEXT)
|
|
nTextId = pGeomDB->GetNext( nTextId) ;
|
|
ExeTextGetContent( nTextId, sText) ;
|
|
// se non vuoto lo assegno come nome
|
|
if ( ! IsEmptyOrSpaces( sText))
|
|
pGeomDB->SetName( pPar->GetId(), sText) ;
|
|
// se non vuoto aggiungo separatore di linea
|
|
if ( ! sText.empty())
|
|
sText += ETXT_LINEBREAK ;
|
|
// recupero dimensioni pezzo
|
|
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 ;
|
|
sText += 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, sText, "", 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, EPS_SMALL, 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() ;
|
|
if ( nFirstId == vOpenIds[i] + 1)
|
|
nFirstId = vOpenIds[i] ;
|
|
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() ;
|
|
}
|
|
// ripristino filtro selezione
|
|
ExeSetObjFilterForSelect( true, true, true, true, true) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeCreateAdjustFlatParts( int nType, double dToler)
|
|
{
|
|
// Disabilito registrazione comandi
|
|
CmdLogOff cmdLogOff ;
|
|
// filtro e approssimo le curve
|
|
FilterAndApprox( dToler) ;
|
|
// salvo punto medio curve con colore proprio
|
|
PNTCOLVECTOR vPntCol ;
|
|
SaveColorWithMidPnt( vPntCol) ;
|
|
// creo i pezzi
|
|
if ( ! ExeCreateFlatParts( nType, dToler))
|
|
return false ;
|
|
// sistemo i pezzi
|
|
if ( ! ExeAdjustFlatParts())
|
|
return false ;
|
|
// ripristino dei colori originali delle curve
|
|
ApplyColorWithMidPnt( vPntCol) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeCreateFlatParts( int nType, double dToler)
|
|
{
|
|
// disabilito registrazione comandi
|
|
CmdLogOff cmdLogOff ;
|
|
// filtro e approssimo le curve
|
|
bool bOk = FilterAndApprox( dToler) ;
|
|
// 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) {
|
|
// costruisco i pezzi
|
|
bOk = bOk && CreateFlatPartsByLayers() ;
|
|
}
|
|
// creazione basata su curve chiuse
|
|
else if ( nType == FPC_CLOSEDCURVE) {
|
|
// costruisco i pezzi
|
|
bOk = bOk && CreateFlatPartsByClosedCurves() ;
|
|
}
|
|
// creazione basata sui pezzi NGE
|
|
// sono già a posto
|
|
// verifica e aggiustamento dei pezzi
|
|
bOk = bOk && VerifyPrepareFlatParts() ;
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeAdjustFlatParts( void)
|
|
{
|
|
// Disabilito registrazione comandi
|
|
CmdLogOff cmdLogOff ;
|
|
// Ciclo sui pezzi
|
|
bool bOk = true ;
|
|
int nPartId = ExeGetFirstPart( false) ;
|
|
while ( nPartId != GDB_ID_NULL) {
|
|
// Sistemo il pezzo
|
|
bOk = ExeAdjustFlatPart( nPartId) && bOk ;
|
|
// Passo al pezzo successivo
|
|
nPartId = ExeGetNextPart(nPartId, false) ;
|
|
}
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeAdjustFlatPart( int nPartId)
|
|
{
|
|
// Disabilito registrazione comandi
|
|
CmdLogOff cmdLogOff ;
|
|
// Ciclo sui layer
|
|
int nLayerId = ExeGetFirstLayer( nPartId, false) ;
|
|
while ( nLayerId != GDB_ID_NULL) {
|
|
// Recupero il layer successivo
|
|
int nNextLayerId = ExeGetNextLayer( nLayerId, false) ;
|
|
// Recupero il nome del layer
|
|
string sLayName ;
|
|
if ( ExeGetName( nLayerId, sLayName)) {
|
|
// Se layer OutLoop o InLoop
|
|
if ( sLayName == NST_OUT_LAYER ||
|
|
sLayName == NST_IN_LAYER) {
|
|
// Sistemo i layer per applicare facilmente le lavorazioni
|
|
ExeAdjustFlatPartLayer( nLayerId) ;
|
|
}
|
|
}
|
|
// Se senza nome, lo elimino
|
|
else
|
|
ExeErase( {nLayerId}) ;
|
|
// Passo al layer successivo
|
|
nLayerId = nNextLayerId ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
MyCreateCurveCompoByReorder( IGeomDB* pGeomDB, int nLayerId, const INTVECTOR& vCrvIds)
|
|
{
|
|
int nCount = 0 ;
|
|
int nFirstId = ExeCreateCurveCompoByReorder( nLayerId, vCrvIds, ORIG, false, RTY_GLOB, &nCount) ;
|
|
for ( int i = 0 ; i < nCount ; ++ i) {
|
|
int nCurrId = nFirstId + i ;
|
|
INTVECTOR vOrigId ;
|
|
pGeomDB->GetInfo( nCurrId, CRV_ORIG, vOrigId) ;
|
|
for ( int j = 0 ; j < int( vOrigId.size()) ; ++ j) {
|
|
if ( j == 0)
|
|
pGeomDB->CopyAttributes( vOrigId[j], nCurrId) ;
|
|
pGeomDB->Erase( vOrigId[j]) ;
|
|
}
|
|
}
|
|
return ( nCount > 0) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static double
|
|
MyIntersectRayLayerCurves( IGeomDB* pGeomDB, Point3d ptP, Vector3d vtDir, bool bMatOnLeft, int nLayerId, int nNoId)
|
|
{
|
|
// semiretta tangente
|
|
const double HL_LEN = 10000 ;
|
|
const double HL_OFFS = 0.01 ;
|
|
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
|
if ( IsNull( pLine) || ! pLine->SetPVL( ptP + vtDir * HL_OFFS, vtDir, HL_LEN))
|
|
return 0 ;
|
|
// cerco intersezione con le curve del layer (tranne quella esclusa)
|
|
double dFirstDist = INFINITO ;
|
|
int nIntId = pGeomDB->GetFirstInGroup( nLayerId) ;
|
|
while ( nIntId != GDB_ID_NULL) {
|
|
if ( nIntId != nNoId) {
|
|
const ICurve* pIntCrv = GetCurve( pGeomDB->GetGeoObj( nIntId)) ;
|
|
if ( pIntCrv != nullptr) {
|
|
// cerco intersezioni della semiretta che entrano nel pezzo
|
|
IntersCurveCurve intCC( *pLine, *pIntCrv) ;
|
|
if ( intCC.GetIntersCount() > 0) {
|
|
IntCrvCrvInfo aInfo ;
|
|
intCC.GetIntCrvCrvInfo( 0, aInfo) ;
|
|
if ( ! aInfo.bOverlap) {
|
|
// se intersezione va dentro
|
|
if ( aInfo.IciA[0].nNextTy == ICCT_IN) {
|
|
double dDist = aInfo.IciA[0].dU * HL_LEN ;
|
|
if ( dDist < dFirstDist)
|
|
dFirstDist = dDist ;
|
|
}
|
|
// se intersezione indefinita, la classifico
|
|
else if ( aInfo.IciA[0].nNextTy == ICCT_NULL) {
|
|
Point3d ptMid ; pIntCrv->GetMidPoint( ptMid) ;
|
|
double dDist = CrossXY( vtDir, ( ptMid - ptP)) ;
|
|
if ( ( bMatOnLeft && dDist < -EPS_SMALL) || ( ! bMatOnLeft && dDist > EPS_SMALL)) {
|
|
double dDist = aInfo.IciA[0].dU * HL_LEN ;
|
|
if ( dDist < dFirstDist)
|
|
dFirstDist = dDist ;
|
|
}
|
|
}
|
|
// intersezioni sovrapposte si possono ignorare
|
|
}
|
|
}
|
|
}
|
|
}
|
|
nIntId = pGeomDB->GetNext( nIntId) ;
|
|
}
|
|
// restituisco la distanza del primo punto di intersezione (infinito se non trovata)
|
|
return dFirstDist ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static double
|
|
MyIntersectArcLayerCurves( IGeomDB* pGeomDB, Point3d ptP, Vector3d vtDir, double dRad, bool bMatOnLeft, int nLayerId, int nNoId)
|
|
{
|
|
// semicirconferenza tangente
|
|
const double HA_ANG = 270 ;
|
|
const double HA_OFFS = 0.01 ;
|
|
Vector3d vtOrtho = vtDir ;
|
|
vtOrtho.Rotate( Z_AX, 0, ( dRad > 0 ? -1 : 1)) ;
|
|
Point3d ptIni = ptP + vtDir * HA_OFFS ;
|
|
Point3d ptCen = ptIni - vtOrtho * abs( dRad) ;
|
|
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ;
|
|
if ( IsNull( pArc) || ! pArc->SetCPA( ptCen, ptIni, ( dRad > 0 ? HA_ANG : -HA_ANG), 0))
|
|
return 0 ;
|
|
// cerco intersezione con le curve del layer (tranne quella esclusa)
|
|
double dFirstDist = INFINITO ;
|
|
int nIntId = pGeomDB->GetFirstInGroup( nLayerId) ;
|
|
while ( nIntId != GDB_ID_NULL) {
|
|
if ( nIntId != nNoId) {
|
|
const ICurve* pIntCrv = GetCurve( pGeomDB->GetGeoObj( nIntId)) ;
|
|
if ( pIntCrv != nullptr) {
|
|
// cerco intersezioni della semicirconferenza che entrano nel pezzo
|
|
IntersCurveCurve intCC( *pArc, *pIntCrv) ;
|
|
if ( intCC.GetIntersCount() > 0) {
|
|
IntCrvCrvInfo aInfo ;
|
|
intCC.GetIntCrvCrvInfo( 0, aInfo) ;
|
|
if ( ! aInfo.bOverlap) {
|
|
// se intersezione va dentro
|
|
if ( aInfo.IciA[0].nNextTy == ICCT_IN) {
|
|
double dDist = aInfo.IciA[0].dU * HA_ANG * DEGTORAD * abs( dRad) ;
|
|
if ( dDist < dFirstDist)
|
|
dFirstDist = dDist ;
|
|
}
|
|
// se intersezione indefinita, la classifico
|
|
else if ( aInfo.IciA[0].nNextTy == ICCT_NULL) {
|
|
Point3d ptMid ; pIntCrv->GetMidPoint( ptMid) ;
|
|
double dDist = CrossXY( vtDir, ( ptMid - ptP)) ;
|
|
if ( ( bMatOnLeft && dDist < -EPS_SMALL) || ( ! bMatOnLeft && dDist > EPS_SMALL)) {
|
|
double dDist = aInfo.IciA[0].dU * HA_ANG * DEGTORAD * abs( dRad) ;
|
|
if ( dDist < dFirstDist)
|
|
dFirstDist = dDist ;
|
|
}
|
|
}
|
|
// intersezioni sovrapposte si possono ignorare
|
|
}
|
|
}
|
|
}
|
|
}
|
|
nIntId = pGeomDB->GetNext( nIntId) ;
|
|
}
|
|
// restituisco la distanza del primo punto di intersezione (infinito se non trovata)
|
|
return dFirstDist ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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) && bOk ;
|
|
// Esplodo in curve semplici
|
|
bOk = ExeExplodeCurveCompo( nId, nullptr) && bOk ;
|
|
}
|
|
// Passo all'entità successiva
|
|
nId = nNextId ;
|
|
}
|
|
// Unisco gli archi consecutivi convessi (quindi con angolo al centro positivo)
|
|
INTVECTOR vAccwIds ;
|
|
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) ;
|
|
}
|
|
nId = pGeomDB->GetNext( nId) ;
|
|
}
|
|
if ( vAccwIds.size() > 1)
|
|
bOk = MyCreateCurveCompoByReorder( pGeomDB, nLayerId, vAccwIds) && bOk ;
|
|
// Spezzo le curve composite con discontinuità sulla tangente
|
|
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) && bOk ;
|
|
}
|
|
// Passo all'entità successiva
|
|
nId = nNextId ;
|
|
}
|
|
// Riconduco a curva semplice le composite formate da una sola curva semplice
|
|
nId = pGeomDB->GetFirstInGroup( nLayerId) ;
|
|
while ( nId != GDB_ID_NULL && bOk) {
|
|
// Recupero successiva
|
|
int nNextId = pGeomDB->GetNext( nId) ;
|
|
// Se curva composita formata da una sola curva semplice
|
|
if ( pGeomDB->GetGeoType( nId) == CRV_COMPO) {
|
|
const ICurveComposite* pCrvCompo = GetCurveComposite( pGeomDB->GetGeoObj( nId)) ;
|
|
if ( pCrvCompo->GetCurveCount() == 1)
|
|
bOk = ExeExplodeCurveCompo( nId, nullptr) && bOk ;
|
|
}
|
|
// Passo all'entità successiva
|
|
nId = nNextId ;
|
|
}
|
|
// 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 ;
|
|
}
|
|
// Punto di giunzione
|
|
Point3d ptP ;
|
|
pCrv1->GetEndPoint( ptP) ;
|
|
// 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) {
|
|
// 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_KEY_NEXTANG, dAngDeg1) ;
|
|
pGeomDB->SetInfo( nCalcId, MCH_KEY_PREVANG, dAngDeg2) ;
|
|
// Se precedente non forma angolo interno con successivo
|
|
if ( dAngDeg1 > -EPS_ANG_SMALL) {
|
|
// Cerco lunghezza libera di prosecuzione tangente
|
|
double dFreeDist = MyIntersectRayLayerCurves( pGeomDB, ptP, vtDir1, true, nLayerId, nId) ;
|
|
// Se curva con angolo esterno oltre 30deg cerco eventuale ulteriore limite per prosecuzione curva
|
|
if ( pCrv1->GetType() != CRV_LINE && dAngDeg1 > FL_ARC_ANG_MIN) {
|
|
double dUmin, dUmax ;
|
|
pCrv1->GetDomain( dUmin, dUmax) ;
|
|
CrvPointDiffGeom oDiffG ;
|
|
if ( pCrv1->GetPointDiffGeom( dUmax, ICurve::FROM_MINUS, oDiffG) && oDiffG.nStatus == CrvPointDiffGeom::NCRV) {
|
|
if ( oDiffG.dCurv > EPS_TRIA_H) {
|
|
double dRad = 1 / oDiffG.dCurv * ( CrossXY( oDiffG.vtT, oDiffG.vtN) > 0 ? 1 : -1) ;
|
|
double dArcFreeDist = MyIntersectArcLayerCurves( pGeomDB, ptP, vtDir1, dRad, true, nLayerId, nId) ;
|
|
dFreeDist = min( dFreeDist, dArcFreeDist) ;
|
|
}
|
|
}
|
|
}
|
|
// Se c'è un limite, lo salvo
|
|
if ( dFreeDist < INFINITO)
|
|
pGeomDB->SetInfo( nId, MCH_KEY_END_FREELEN, dFreeDist) ;
|
|
}
|
|
// Se successivo non forma angolo interno con precedente
|
|
if ( dAngDeg2 > -EPS_ANG_SMALL) {
|
|
// Cerco lunghezza libera di prosecuzione tangente all'indietro
|
|
double dFreeDist = MyIntersectRayLayerCurves( pGeomDB, ptP, -vtDir2, false, nLayerId, nCalcId) ;
|
|
// Se curva con angolo esterno oltre 30deg cerco eventuale ulteriore limite per prosecuzione curva
|
|
if ( pCrv2->GetType() != CRV_LINE && dAngDeg2 > FL_ARC_ANG_MIN) {
|
|
double dUmin, dUmax ;
|
|
pCrv2->GetDomain( dUmin, dUmax) ;
|
|
CrvPointDiffGeom oDiffG ;
|
|
if ( pCrv2->GetPointDiffGeom( dUmin, ICurve::FROM_PLUS, oDiffG) && oDiffG.nStatus == CrvPointDiffGeom::NCRV) {
|
|
if ( oDiffG.dCurv > EPS_TRIA_H) {
|
|
double dRad = 1 / oDiffG.dCurv * ( CrossXY( oDiffG.vtT, oDiffG.vtN) > 0 ? -1 : 1) ;
|
|
double dArcFreeDist = MyIntersectArcLayerCurves( pGeomDB, ptP, -vtDir2, dRad, false, nLayerId, nId) ;
|
|
dFreeDist = min( dFreeDist, dArcFreeDist) ;
|
|
}
|
|
}
|
|
}
|
|
// Se c'è un limite, lo salvo
|
|
if ( dFreeDist < INFINITO)
|
|
pGeomDB->SetInfo( nCalcId, MCH_KEY_START_FREELEN, dFreeDist) ;
|
|
}
|
|
}
|
|
// 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)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
ExeUpdateFlatPartRegion( int nPartId, bool bCalc)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// ripristino lo stato originale
|
|
int nRegOrigId = pGeomDB->GetFirstNameInGroup( nPartId, NST_PARTREG_ORIG_LAYER) ;
|
|
if ( nRegOrigId != GDB_ID_NULL) {
|
|
pGeomDB->Erase( pGeomDB->GetFirstNameInGroup( nPartId, NST_PARTREG_LAYER)) ;
|
|
pGeomDB->SetName( nRegOrigId, NST_PARTREG_LAYER) ;
|
|
pGeomDB->SetStatus( nRegOrigId, GDB_ST_ON) ;
|
|
}
|
|
// 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 a singola inclinazione con offset negativo non devo fare alcunchè
|
|
bool bAllFixSides = true ;
|
|
int nCrvId = pGeomDB->GetFirstInGroup( nOlId) ;
|
|
while ( nCrvId != GDB_ID_NULL) {
|
|
double dOffset ;
|
|
if ( pGeomDB->GetInfo( nCrvId, NST_KEY_OFFSET, dOffset) && dOffset < - EPS_SMALL &&
|
|
! pGeomDB->ExistsInfo( nCrvId, NST_KEY_SIDEANG2)) {
|
|
bAllFixSides = false ;
|
|
break ;
|
|
}
|
|
nCrvId = pGeomDB->GetNext( nCrvId) ;
|
|
}
|
|
if ( bAllFixSides)
|
|
return true ;
|
|
|
|
// creo il layer per la nuova regione (con il medesimo riferimento del layer esterno)
|
|
Frame3d frOl ;
|
|
pGeomDB->GetGroupFrame( nOlId, frOl) ;
|
|
int nNewRegId = pGeomDB->AddGroup( GDB_ID_NULL, nPartId, frOl) ;
|
|
if ( nNewRegId == GDB_ID_NULL)
|
|
return false ;
|
|
|
|
// 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, nNewRegId) ;
|
|
if ( nNewId == GDB_ID_NULL)
|
|
return false ;
|
|
// determino ed eseguo offset
|
|
double dOffset = 0 ;
|
|
if ( pGeomDB->GetInfo( nCrvId, NST_KEY_OFFSET, dOffset) && dOffset < - EPS_SMALL &&
|
|
! pGeomDB->ExistsInfo( nCrvId, NST_KEY_SIDEANG2)) {
|
|
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nNewId)) ;
|
|
if ( pCrv == nullptr)
|
|
return false ;
|
|
pCrv->SimpleOffset( dOffset) ;
|
|
}
|
|
// passo alla successiva
|
|
nCrvId = pGeomDB->GetNext( nCrvId) ;
|
|
}
|
|
// aggiusto tra loro le entità offsettate
|
|
int nFirstCrvId = pGeomDB->GetFirstInGroup( nNewRegId) ;
|
|
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( nNewRegId) ;
|
|
nCrvId != GDB_ID_NULL ;
|
|
nCrvId = pGeomDB->GetFirstInGroup( nNewRegId)) {
|
|
ICurve* pCrv = GetCurve( pGeomDB->RemoveGeoObjAndErase( nCrvId)) ;
|
|
if ( pCrv != nullptr)
|
|
pCompo->AddCurve( pCrv) ;
|
|
else
|
|
pGeomDB->Erase( nCrvId) ;
|
|
}
|
|
SurfFlatRegionByContours SfrCntr( false) ;
|
|
SfrCntr.AddCurve( Release( pCompo)) ;
|
|
PtrOwner<ISurfFlatRegion> pSfr2( SfrCntr.GetSurf()) ;
|
|
|
|
// copio le entità del gruppo regione originale nel nuovo gruppo
|
|
int nRegId = pGeomDB->GetFirstNameInGroup( nPartId, NST_PARTREG_LAYER) ;
|
|
int nSrfOrig = GDB_ID_NULL ;
|
|
int nId = pGeomDB->GetFirstInGroup( nRegId) ;
|
|
while ( nId != GDB_ID_NULL) {
|
|
int nNewId = pGeomDB->CopyGlob( nId, GDB_ID_NULL, nNewRegId) ;
|
|
if ( nSrfOrig == GDB_ID_NULL && pGeomDB->GetGeoType( nNewId) == SRF_FLATRGN)
|
|
nSrfOrig = nNewId ;
|
|
nId = pGeomDB->GetNext( nId) ;
|
|
}
|
|
if ( nSrfOrig == GDB_ID_NULL) {
|
|
pGeomDB->Erase( nNewRegId) ;
|
|
return false ;
|
|
}
|
|
|
|
// interseco la vecchia regione con la nuova
|
|
ISurfFlatRegion* pSfr1 = GetSurfFlatRegion( pGeomDB->GetGeoObj( nSrfOrig)) ;
|
|
if ( ! pSfr1->Intersect( *pSfr2) || ! pSfr1->IsValid()) {
|
|
pGeomDB->Erase( nNewRegId) ;
|
|
return false ;
|
|
}
|
|
|
|
// sistemo i nomi e lo stato dei gruppi
|
|
pGeomDB->SetName( nRegId, NST_PARTREG_ORIG_LAYER) ;
|
|
pGeomDB->SetStatus( nRegId, GDB_ST_OFF) ;
|
|
pGeomDB->SetName( nNewRegId, NST_PARTREG_LAYER) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
AdjustLayerCurves( IGeomDB* pGeomDB, int nLayId)
|
|
{
|
|
// aggiusto tra loro le entità curve del layer
|
|
int nFirstCrvId = pGeomDB->GetFirstInGroup( nLayId) ;
|
|
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 ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
ExeCalcFlatPartUpRegion( int nPartId, bool bCalc)
|
|
{
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// aggiorno la regione standard
|
|
if ( ! ExeUpdateFlatPartRegion( nPartId, bCalc))
|
|
return 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 = 0, dOffset2 = 0 ;
|
|
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 curve offsettate (allungandole e/o accorciandole)
|
|
if ( ! AdjustLayerCurves( pGeomDB, nUpRegId))
|
|
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) ;
|
|
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 ;
|
|
int nRegLay = pGeomDB->GetFirstNameInGroup( nPartId, NST_PARTREG_LAYER) ;
|
|
if ( nRegLay != GDB_ID_NULL)
|
|
pGeomDB->GetMaterial( nRegLay, cCol) ;
|
|
cCol.SetAlpha( 0.25) ;
|
|
pGeomDB->SetMaterial( nSfrId, cCol) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool
|
|
IgnoreOutlineFillet( IGeomDB* pGeomDB, int nCrvId, int nLayId)
|
|
{
|
|
// verifico se la curva nCrvId è un raccordo che deve essere ignorato, ovvero se si tratta di un arco non inclinato, in tangenza
|
|
// e consecutivo ad almeno un lato inclinato
|
|
|
|
// verifico se arco
|
|
if ( pGeomDB->GetGeoType( nCrvId) == CRV_ARC) {
|
|
// verifico se non inclinato
|
|
double dSideAng = 0, dSideAng2 = 0 ;
|
|
pGeomDB->GetInfo( nCrvId, NST_KEY_SIDEANG, dSideAng) ;
|
|
pGeomDB->GetInfo( nCrvId, NST_KEY_SIDEANG2, dSideAng2) ;
|
|
if ( abs( dSideAng) < EPS_ANG_SMALL && abs( dSideAng2) < EPS_ANG_SMALL) {
|
|
// verifico se in tangenza con curve consecutive
|
|
double dPrevAng = ANG_RIGHT, dNextAng = ANG_RIGHT ;
|
|
pGeomDB->GetInfo( nCrvId, MCH_KEY_PREVANG, dPrevAng) ;
|
|
pGeomDB->GetInfo( nCrvId, MCH_KEY_NEXTANG, dNextAng) ;
|
|
if ( abs( dPrevAng) < EPS_ANG_SMALL && abs( dNextAng) < EPS_ANG_SMALL) {
|
|
// verifico se è inclinata almeno una tra la curva precedente e quella successiva
|
|
int nPrevId = pGeomDB->GetPrev( nCrvId) ;
|
|
if ( nPrevId == GDB_ID_NULL)
|
|
nPrevId = pGeomDB->GetLastInGroup( nLayId) ;
|
|
if ( nPrevId == GDB_ID_NULL)
|
|
return false ;
|
|
double dSideAng, dSideAng2 ;
|
|
if ( ( pGeomDB->GetInfo( nPrevId, NST_KEY_SIDEANG, dSideAng) && abs( dSideAng) > EPS_ANG_SMALL) ||
|
|
( pGeomDB->GetInfo( nPrevId, NST_KEY_SIDEANG2, dSideAng2) && abs( dSideAng2) > EPS_ANG_SMALL))
|
|
return true ;
|
|
|
|
int nNextId = pGeomDB->GetNext( nCrvId) ;
|
|
if ( nNextId == GDB_ID_NULL)
|
|
nNextId = pGeomDB->GetFirstInGroup( nLayId) ;
|
|
if ( nNextId == GDB_ID_NULL)
|
|
return false ;
|
|
if ( ( pGeomDB->GetInfo( nNextId, NST_KEY_SIDEANG, dSideAng) && abs( dSideAng) > EPS_ANG_SMALL) ||
|
|
( pGeomDB->GetInfo( nNextId, NST_KEY_SIDEANG2, dSideAng2) && abs( dSideAng2) > EPS_ANG_SMALL))
|
|
return true ;
|
|
}
|
|
}
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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) ;
|
|
|
|
// verifico se le curve del layer sono tutte chiuse, quindi sono cerchi non inclinabili
|
|
int nCurves = 0 ;
|
|
int nCircles = 0 ;
|
|
for ( int nCrvId = pGeomDB->GetFirstInGroup( nLayId) ;
|
|
nCrvId != GDB_ID_NULL ;
|
|
nCrvId = pGeomDB->GetNext( nCrvId)) {
|
|
const ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nCrvId)) ;
|
|
if ( pCrv == nullptr)
|
|
return false ;
|
|
++ nCurves ;
|
|
if ( pCrv->IsClosed())
|
|
++ nCircles ;
|
|
}
|
|
if ( nCircles != 0 && nCircles != nCurves)
|
|
return false ;
|
|
bool bCircles = ( nCircles == nCurves) ;
|
|
|
|
// se sono cerchi
|
|
if ( bCircles) {
|
|
// li copio nel layer della regione
|
|
for ( int nCrvId = pGeomDB->GetFirstInGroup( nLayId) ;
|
|
nCrvId != GDB_ID_NULL ;
|
|
nCrvId = pGeomDB->GetNext( nCrvId)) {
|
|
if ( pGeomDB->Copy( nCrvId, GDB_ID_NULL, nLayReg) == GDB_ID_NULL)
|
|
return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
// recupero il riferimento del layer
|
|
Frame3d frLay ;
|
|
pGeomDB->GetGroupFrame( nLayId, frLay) ;
|
|
|
|
// creo un primo layer temporaneo (sotto)
|
|
const string sTmpLayName = "TmpLay" ;
|
|
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 e le offsetto opportunamente
|
|
for ( int nCrvId = pGeomDB->GetFirstInGroup( nLayId) ;
|
|
nCrvId != GDB_ID_NULL ;
|
|
nCrvId = pGeomDB->GetNext( nCrvId)) {
|
|
// 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, dSideAng2 ;
|
|
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 ;
|
|
if ( ! pCrv->SimpleOffset( dCalcOffset))
|
|
pGeomDB->Erase( nNewId) ;
|
|
}
|
|
else if ( pGeomDB->GetInfo( nCrvId, NST_KEY_SIDEANG2, dSideAng2) && abs( dSideAng2) > EPS_ANG_SMALL) {
|
|
double dOffset2 = 0 ;
|
|
pGeomDB->GetInfo( nCrvId, NST_KEY_OFFSET2, dOffset2) ;
|
|
double dDepth2 = 0 ;
|
|
pGeomDB->GetInfo( nCrvId, NST_KEY_DEPTH2, dDepth2) ;
|
|
double dAgg2 = 0 ;
|
|
pGeomDB->GetInfo( nCrvId, NST_KEY_AGG2, dAgg2) ;
|
|
double dCalcOffset = ( dDepth2 - dAgg2) * tan( dSideAng2 * DEGTORAD) + dOffset2 ;
|
|
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nNewId)) ;
|
|
if ( pCrv == nullptr)
|
|
return false ;
|
|
if ( ! pCrv->SimpleOffset( dCalcOffset))
|
|
pGeomDB->Erase( nNewId) ;
|
|
}
|
|
// verifico se raccordo da ignorare per poter calcolare la regione
|
|
else if ( IgnoreOutlineFillet( pGeomDB, nCrvId, nLayId))
|
|
pGeomDB->Erase( nNewId) ;
|
|
}
|
|
// aggiusto tra loro le curve offsettate (allungandole e/o accorciandole)
|
|
if ( ! AdjustLayerCurves( pGeomDB, nTmpLayId))
|
|
return false ;
|
|
|
|
// creo un secondo layer temporaneo (sopra)
|
|
const string sTmpLay2Name = "TmpLay2" ;
|
|
int nTmpLay2Id = pGeomDB->AddGroup( GDB_ID_NULL, pGeomDB->GetParentId( nLayId), frLay) ;
|
|
if ( nTmpLay2Id == GDB_ID_NULL)
|
|
return false ;
|
|
pGeomDB->SetName( nTmpLay2Id, sTmpLay2Name) ;
|
|
pGeomDB->SetLevel( nTmpLay2Id, GDB_LV_TEMP) ;
|
|
|
|
// copio le entità del contorno e le offsetto opportunamente
|
|
for ( int nCrvId = pGeomDB->GetFirstInGroup( nLayId) ;
|
|
nCrvId != GDB_ID_NULL ;
|
|
nCrvId = pGeomDB->GetNext( nCrvId)) {
|
|
// copio la curva nel gruppo temporaneo
|
|
int nNewId = pGeomDB->CopyGlob( nCrvId, GDB_ID_NULL, nTmpLay2Id) ;
|
|
if ( nNewId == GDB_ID_NULL)
|
|
return false ;
|
|
// determino ed eseguo offset
|
|
double dSideAng, dSideAng2 ;
|
|
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 = dOffset ;
|
|
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nNewId)) ;
|
|
if ( pCrv == nullptr)
|
|
return false ;
|
|
if ( ! pCrv->SimpleOffset( dCalcOffset))
|
|
pGeomDB->Erase( nNewId) ;
|
|
}
|
|
else if ( pGeomDB->GetInfo( nCrvId, NST_KEY_SIDEANG2, dSideAng2) && abs( dSideAng2) > EPS_ANG_SMALL) {
|
|
double dOffset2 = 0 ;
|
|
pGeomDB->GetInfo( nCrvId, NST_KEY_OFFSET2, dOffset2) ;
|
|
double dCalcOffset = dOffset2 ;
|
|
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nNewId)) ;
|
|
if ( pCrv == nullptr)
|
|
return false ;
|
|
if ( ! pCrv->SimpleOffset( dCalcOffset))
|
|
pGeomDB->Erase( nNewId) ;
|
|
}
|
|
// verifico se raccordo da ignorare per poter calcolare la regione
|
|
else if ( IgnoreOutlineFillet( pGeomDB, nCrvId, nLayId))
|
|
pGeomDB->Erase( nNewId) ;
|
|
}
|
|
// aggiusto tra loro le curve offsettate (allungandole e/o accorciandole)
|
|
if ( ! AdjustLayerCurves( pGeomDB, nTmpLay2Id))
|
|
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 curve con lo stesso nome nei gruppi delli regioni sotto e sopra
|
|
int nCrvDrId = pGeomDB->GetFirstNameInGroup( nTmpLayId, sName) ;
|
|
int nCrvUrId = pGeomDB->GetFirstNameInGroup( nTmpLay2Id, sName) ;
|
|
// verifico siano curve
|
|
ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nCrvId)) ;
|
|
ICurve* pCrvDr = GetCurve( pGeomDB->GetGeoObj( nCrvDrId)) ;
|
|
ICurve* pCrvUr = GetCurve( pGeomDB->GetGeoObj( nCrvUrId)) ;
|
|
if ( pCrv == nullptr || pCrvDr == nullptr || pCrvUr == nullptr)
|
|
continue ;
|
|
// verifico se devo allungare o accorciare la curva all'inizio
|
|
double dPrevAng = 0 ;
|
|
pGeomDB->GetInfo( nCrvId, MCH_KEY_PREVANG, dPrevAng) ;
|
|
Point3d ptStart ;
|
|
pCrv->GetStartPoint( ptStart) ;
|
|
Vector3d vtStartDir ;
|
|
pCrv->GetStartDir( vtStartDir) ;
|
|
Point3d ptStartDr ;
|
|
pCrvDr->GetStartPoint( ptStartDr) ;
|
|
Point3d ptStartUr ;
|
|
pCrvUr->GetStartPoint( ptStartUr) ;
|
|
double dStartProD = - ( ( ptStartDr - ptStart) * vtStartDir) ;
|
|
double dStartProU = - ( ( ptStartUr - ptStart) * vtStartDir) ;
|
|
if ( dPrevAng > - EPS_ANG_SMALL) {
|
|
//if ( dStartProD > EPS_SMALL)
|
|
// pCrv->ExtendStartByLen( dStartProD) ;
|
|
double dStartProMin = min( dStartProD, dStartProU) ;
|
|
if ( dStartProMin < - EPS_SMALL) {
|
|
pCrv->TrimStartAtLen( - dStartProMin) ;
|
|
if ( abs( dStartProD - dStartProU) > EPS_SMALL)
|
|
pGeomDB->SetInfo( nCrvId, MCH_KEY_START_WHISKEXT, abs( dStartProD - dStartProU)) ;
|
|
}
|
|
else
|
|
pGeomDB->SetInfo( nCrvId, MCH_KEY_START_WHISKEXT, max( dStartProD, dStartProU)) ;
|
|
}
|
|
else {
|
|
if ( dStartProD < - EPS_SMALL)
|
|
pCrv->TrimStartAtLen( - dStartProD) ;
|
|
}
|
|
// verifico se devo allungare la curva alla fine
|
|
double dNextAng = 0 ;
|
|
pGeomDB->GetInfo( nCrvId, MCH_KEY_NEXTANG, dNextAng) ;
|
|
Point3d ptEnd ;
|
|
pCrv->GetEndPoint( ptEnd) ;
|
|
Vector3d vtEndDir ;
|
|
pCrv->GetEndDir( vtEndDir) ;
|
|
Point3d ptEndDr ;
|
|
pCrvDr->GetEndPoint( ptEndDr) ;
|
|
Point3d ptEndUr ;
|
|
pCrvUr->GetEndPoint( ptEndUr) ;
|
|
double dEndProD = ( ptEndDr - ptEnd) * vtEndDir ;
|
|
double dEndProU = ( ptEndUr - ptEnd) * vtEndDir ;
|
|
if ( dNextAng > - EPS_ANG_SMALL) {
|
|
//if ( dEndProD > EPS_SMALL)
|
|
// pCrv->ExtendEndByLen( dEndProD) ;
|
|
double dEndProMin = min( dEndProD, dEndProU) ;
|
|
if ( dEndProMin < - EPS_SMALL) {
|
|
double dLen ;
|
|
pCrv->GetLength( dLen) ;
|
|
pCrv->TrimEndAtLen( dLen + dEndProMin) ;
|
|
if ( abs( dEndProD - dEndProU) > EPS_SMALL)
|
|
pGeomDB->SetInfo( nCrvId, MCH_KEY_END_WHISKEXT, abs( dEndProD - dEndProU)) ;
|
|
}
|
|
else
|
|
pGeomDB->SetInfo( nCrvId, MCH_KEY_END_WHISKEXT, max( dEndProD, dEndProU)) ;
|
|
}
|
|
else {
|
|
if ( dEndProD < - EPS_SMALL) {
|
|
double dLen ;
|
|
pCrv->GetLength( dLen) ;
|
|
pCrv->TrimEndAtLen( dLen + dEndProD) ;
|
|
}
|
|
}
|
|
}
|
|
// concateno le curve del primo 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 i layer temporanei
|
|
pGeomDB->Erase( nTmpLayId) ;
|
|
pGeomDB->Erase( nTmpLay2Id) ;
|
|
// 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, dSideAng2 ;
|
|
if ( ( pGeomDB->GetInfo( nCrvId, NST_KEY_SIDEANG, dSideAng) && abs( dSideAng) > EPS_ANG_SMALL) ||
|
|
( pGeomDB->GetInfo( nCrvId, NST_KEY_SIDEANG2, dSideAng2) && abs( dSideAng2) > 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 ;
|
|
int nRegLay = pGeomDB->GetFirstNameInGroup( nPartId, NST_PARTREG_LAYER) ;
|
|
if ( nRegLay != GDB_ID_NULL)
|
|
pGeomDB->GetMaterial( nRegLay, cCol) ;
|
|
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 false ;
|
|
// 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 false ;
|
|
// 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 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
GetFlatPartInterpartGap(IGeomDB* pGeomDB, int nId, double& dGap)
|
|
{
|
|
if ( pGeomDB == nullptr)
|
|
return false ;
|
|
// valore di default
|
|
dGap = 0 ;
|
|
// 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) {
|
|
double dCurrGap ;
|
|
if ( pGeomDB->GetInfo(nClId, MCH_PV_KEY_WT, dCurrGap) && dCurrGap > dGap)
|
|
dGap = dCurrGap ;
|
|
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)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
INTVECTOR
|
|
GetGeometryFromCut( IGeomDB* pGeomDB, IMachMgr* pMachMgr, int nId)
|
|
{
|
|
INTVECTOR vnIds ;
|
|
if ( pGeomDB == nullptr || pMachMgr == nullptr)
|
|
return vnIds ;
|
|
// verifico appartenga ad una lavorazione
|
|
int nMchId ;
|
|
if ( ! pGeomDB->GetInfo( pGeomDB->GetParentId( pGeomDB->GetParentId( nId)), "MId", nMchId))
|
|
return vnIds ;
|
|
// recupero la geometria di applicazione della lavorazione (deve essere una sola)
|
|
if ( ! pMachMgr->SetCurrMachining( nMchId))
|
|
return vnIds ;
|
|
SELVECTOR vSelIds ;
|
|
pMachMgr->GetMachiningGeometry( vSelIds) ;
|
|
vnIds.reserve( vSelIds.size()) ;
|
|
for ( const SelData& mySelData : vSelIds)
|
|
vnIds.emplace_back( mySelData.nId) ;
|
|
return vnIds ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
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 ;
|
|
}
|