df864c93a8
- adattamenti e ricompilazione per passaggio a C++ 20
1429 lines
54 KiB
C++
1429 lines
54 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2015
|
|
//----------------------------------------------------------------------------
|
|
// File : BtlGeomOutline.cpp Data : 06.11.15 Versione : 1.6k2
|
|
// Contenuto : Implementazione delle funzioni su outline per BtlGeom.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 06.11.15 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "BtlGeom.h"
|
|
#include "DllMain.h"
|
|
#include "/EgtDev/Include/EGkCurveLine.h"
|
|
#include "/EgtDev/Include/EGkCurveArc.h"
|
|
#include "/EgtDev/Include/EGkCurveComposite.h"
|
|
#include "/EgtDev/Include/EgkChainCurves.h"
|
|
#include "/EgtDev/Include/EGkOffsetCurve.h"
|
|
#include "/EgtDev/Include/EGkSfrCreate.h"
|
|
#include "/EgtDev/Include/EGkStmStandard.h"
|
|
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
|
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
|
|
#include "/EgtDev/Include/EGkExtText.h"
|
|
#include "/EgtDev/Include/EGnStringUtils.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::AddPartOutline( int nSide, const FCEDEQUE& dqFce, int nContType, int nContData, double dContPar, const STRVECTOR& vsUAtt)
|
|
{
|
|
// verifico esistenza pezzo
|
|
if ( m_nBoxId == GDB_ID_NULL)
|
|
return false ;
|
|
// verifico validità faccia
|
|
if ( ! IsTrueSide( nSide))
|
|
return false ;
|
|
// verifico siano definiti almeno 3 punti (2 archi)
|
|
if ( dqFce.size() < 3)
|
|
return false ;
|
|
// verifico che primo e ultimo punto coincidano
|
|
if ( ! AreSamePointApprox( dqFce.front().ptP, dqFce.back().ptP))
|
|
return false ;
|
|
// verifico che sia un percorso semplice
|
|
if ( dqFce.front().nType != FreeContourEnt::START)
|
|
return false ;
|
|
// costruisco il percorso di contorno
|
|
PtrOwner<ICurveComposite> pCrvCompo( CurveFromFces( dqFce)) ;
|
|
if ( IsNull( pCrvCompo))
|
|
return false ;
|
|
// aggiusto orientamento affinché sia antiorario (devo inoltre invertire il segno dell'angolo di fianco)
|
|
double dArea ;
|
|
pCrvCompo->GetAreaXY( dArea) ;
|
|
if ( dArea < 0) {
|
|
pCrvCompo->Invert() ;
|
|
for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) {
|
|
int nAng ;
|
|
if ( pCrvCompo->GetCurveTempProp( i, nAng) && abs( nAng) > 10)
|
|
pCrvCompo->SetCurveTempProp( i, - nAng) ;
|
|
}
|
|
}
|
|
// Porto il percorso sul piano corretto
|
|
Frame3d frRef = GetSideFrame( nSide) ;
|
|
pCrvCompo->ToGlob( frRef) ;
|
|
// Sistemazioni della curva
|
|
pCrvCompo->SetExtrusion( frRef.VersZ()) ;
|
|
pCrvCompo->SetThickness( -GetSideHeight( nSide)) ;
|
|
// Creo la superficie
|
|
PtrOwner<ISurfTriMesh> pStm ;
|
|
pStm.Set( CreateOneCurveFreeContour( pCrvCompo)) ;
|
|
if ( IsNull( pStm))
|
|
return false ;
|
|
// Inserisco la superficie nel layer Outline
|
|
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pStm)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
// recupero eventuali angoli di fianco
|
|
DBLVECTOR vSideAng ;
|
|
if ( VerifyFreeContourCurveSideAng( pCrvCompo))
|
|
GetFreeContourCurveSideAngles( pCrvCompo, vSideAng) ;
|
|
// inserisco la curva nel DB geometrico
|
|
int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pCrvCompo)) ;
|
|
if ( nTId != GDB_ID_NULL && vSideAng.size() > 0)
|
|
m_pGDB->SetInfo( nTId, IKEY_SIDEANGS, vSideAng) ;
|
|
// colore
|
|
Color cCol = m_ProcsCol ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
m_pGDB->SetMaterial( nTId, cCol) ;
|
|
// nome
|
|
m_pGDB->SetName( nId, GetOutlineOutName( nSide)) ;
|
|
// info con tipo
|
|
m_pGDB->SetInfo( nId, IKEY_GROUP, 4) ;
|
|
m_pGDB->SetInfo( nId, IKEY_PROC, 251) ;
|
|
m_pGDB->SetInfo( nId, IKEY_SIDE, nSide) ;
|
|
// eventuali parametri del contorno
|
|
if ( nContType > 0 || ( nContType >= 0 && nContData != 0))
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_TYPE, nContType) ;
|
|
if ( nContData != 0)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_DATA, nContData) ;
|
|
if ( abs( dContPar) > EPS_SMALL)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_PAR, dContPar) ;
|
|
// eventuali attributi utente
|
|
if ( ! SetUserAttributes( nId, vsUAtt))
|
|
return false ;
|
|
// identificativi di geometrie ausiliarie
|
|
SetAuxId( nId, {nTId}) ;
|
|
// se richiesto Outline nel piano XY verifico ed eventualmente ruoto il pezzo
|
|
if ( m_nFlatVertPos == 4) {
|
|
Frame3d frOutline ;
|
|
if ( m_pGDB->GetGroupGlobFrame( m_nOutsId, frOutline)) {
|
|
Vector3d vtNorm = GetSideVersN( nSide) ;
|
|
vtNorm.ToGlob( frOutline) ;
|
|
if ( ! AreSameOrOppositeVectorApprox( vtNorm, Z_AX)) {
|
|
BBox3d b3Part ;
|
|
if ( m_pGDB->GetGlobalBBox( m_nBoxId, b3Part)) {
|
|
Vector3d vtDim = b3Part.GetMax() - b3Part.GetMin() ;
|
|
Point3d ptAx = b3Part.GetMin() + 0.5 * Vector3d( 0, vtDim.y, vtDim.y) ;
|
|
m_pGDB->RotateGlob( m_nPartId, ptAx, X_AX, 0, 1) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::AddPartOutline( int nSide, int nCrvId, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt)
|
|
{
|
|
// reset dell'identificativo della geometria principale della feature
|
|
m_nProcId = GDB_ID_NULL ;
|
|
// verifico esistenza pezzo
|
|
if ( m_nBoxId == GDB_ID_NULL)
|
|
return false ;
|
|
// verifico validità faccia
|
|
if ( ! IsTrueSide( nSide))
|
|
return false ;
|
|
// verifica dei parametri
|
|
if ( vdPar.size() < 14)
|
|
return false ;
|
|
// sistemo i dati
|
|
int nContType = lround( vdPar[11]) ; // P13
|
|
int nContData = lround( vdPar[12]) ; // P14
|
|
double dContPar = vdPar[13] ; // P15
|
|
// verifico esista il percorso di contorno
|
|
if ( nCrvId == GDB_ID_NULL) {
|
|
// inserisco superficie vuota come marcatore
|
|
PtrOwner<ISurfTriMesh> pStm( CreateSurfTriMesh()) ;
|
|
if ( IsNull( pStm) || ! pStm->AdjustTopology())
|
|
return false ;
|
|
// la inserisco nel DB geometrico
|
|
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pStm)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
// nome
|
|
m_pGDB->SetName( nId, GetOutlineOutName( nSide)) ;
|
|
// info con tipo
|
|
m_pGDB->SetInfo( nId, IKEY_GROUP, 4) ;
|
|
m_pGDB->SetInfo( nId, IKEY_PROC, 251) ;
|
|
m_pGDB->SetInfo( nId, IKEY_SIDE, nSide) ;
|
|
// eventuali parametri del contorno
|
|
if ( nContType > 0 || ( nContType >= 0 && nContData != 0))
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_TYPE, nContType) ;
|
|
if ( nContData != 0)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_DATA, nContData) ;
|
|
if ( abs( dContPar) > EPS_SMALL)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_PAR, dContPar) ;
|
|
// eventuali attributi utente
|
|
if ( ! SetUserAttributes( nId, vsUAtt))
|
|
return false ;
|
|
m_nProcId = nId ;
|
|
// messaggio di warning in log
|
|
string sOut = " Warning : Empty Outline (" + ToString( nSide) +
|
|
") on line " + ToString( m_nBtlLine) ;
|
|
LOG_WARN( GetEExLogger(), sOut.c_str())
|
|
return true ;
|
|
}
|
|
// copio il percorso di contorno
|
|
PtrOwner<ICurveComposite> pCrvCompo ;
|
|
if ( m_pGDB->GetGeoType( nCrvId) & GEO_CURVE) {
|
|
pCrvCompo.Set( CreateCurveComposite()) ;
|
|
if ( ! pCrvCompo->CopyFrom( m_pGDB->GetGeoObj( nCrvId)))
|
|
pCrvCompo.Reset() ;
|
|
}
|
|
if ( IsNull( pCrvCompo))
|
|
return false ;
|
|
// verifico che sia chiuso
|
|
if ( ! pCrvCompo->IsClosed())
|
|
return false ;
|
|
// assegno eventuali angoli di fianco
|
|
{ DBLVECTOR vSideAng ;
|
|
if ( m_pGDB->GetInfo( nCrvId, IKEY_SIDEANGS, vSideAng)) {
|
|
for ( int i = 0 ; i < int( vSideAng.size()) ; ++ i)
|
|
pCrvCompo->SetCurveTempProp( i, int( vSideAng[i] * 1000)) ;
|
|
}
|
|
}
|
|
// Lo porto nel riferimento del lato e ve lo appiattisco
|
|
Frame3d frRef = GetSideFrame( nSide) ;
|
|
pCrvCompo->ToLoc( frRef) ;
|
|
pCrvCompo->Scale( Frame3d(), 1, 1, 0) ;
|
|
// aggiusto orientamento affinché sia antiorario (devo inoltre invertire il segno dell'angolo di fianco)
|
|
double dArea ;
|
|
pCrvCompo->GetAreaXY( dArea) ;
|
|
if ( dArea < 0) {
|
|
pCrvCompo->Invert() ;
|
|
for ( int i = 0 ; i < pCrvCompo->GetCurveCount() ; ++ i) {
|
|
int nAng ;
|
|
if ( pCrvCompo->GetCurveTempProp( i, nAng) && abs( nAng) > 10)
|
|
pCrvCompo->SetCurveTempProp( i, -nAng) ;
|
|
}
|
|
}
|
|
// Porto il percorso sul piano corretto
|
|
pCrvCompo->ToGlob( frRef) ;
|
|
// Sistemazioni della curva
|
|
pCrvCompo->SetExtrusion( frRef.VersZ()) ;
|
|
pCrvCompo->SetThickness( -GetSideHeight( nSide)) ;
|
|
// Creo la superficie
|
|
PtrOwner<ISurfTriMesh> pStm ;
|
|
pStm.Set( CreateOneCurveFreeContour( pCrvCompo)) ;
|
|
if ( IsNull( pStm))
|
|
return false ;
|
|
// Inserisco la superficie nel layer Outline
|
|
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pStm)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
// recupero eventuali angoli di fianco
|
|
DBLVECTOR vSideAng ;
|
|
if ( VerifyFreeContourCurveSideAng( pCrvCompo))
|
|
GetFreeContourCurveSideAngles( pCrvCompo, vSideAng) ;
|
|
// inserisco la curva nel DB geometrico
|
|
int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pCrvCompo)) ;
|
|
if ( nTId != GDB_ID_NULL && vSideAng.size() > 0)
|
|
m_pGDB->SetInfo( nTId, IKEY_SIDEANGS, vSideAng) ;
|
|
// colore
|
|
Color cCol = m_ProcsCol ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
m_pGDB->SetMaterial( nTId, cCol) ;
|
|
// nome
|
|
m_pGDB->SetName( nId, GetOutlineOutName( nSide)) ;
|
|
// info con tipo
|
|
m_pGDB->SetInfo( nId, IKEY_GROUP, 4) ;
|
|
m_pGDB->SetInfo( nId, IKEY_PROC, 251) ;
|
|
m_pGDB->SetInfo( nId, IKEY_SIDE, nSide) ;
|
|
// eventuali parametri del contorno
|
|
if ( nContType > 0 || ( nContType >= 0 && nContData != 0))
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_TYPE, nContType) ;
|
|
if ( nContData != 0)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_DATA, nContData) ;
|
|
if ( abs( dContPar) > EPS_SMALL)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_PAR, dContPar) ;
|
|
// eventuali attributi utente
|
|
if ( ! SetUserAttributes( nId, vsUAtt))
|
|
return false ;
|
|
// identificativi di geometrie ausiliarie
|
|
SetAuxId( nId, {nTId}) ;
|
|
|
|
m_nProcId = nId ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::AddPartAperture( int nSide, const FCEDEQUE& dqFce, int nContType, int nContData, double dContPar, const STRVECTOR& vsUAtt)
|
|
{
|
|
// verifico esistenza pezzo
|
|
if ( m_nBoxId == GDB_ID_NULL)
|
|
return false ;
|
|
// verifico validità faccia
|
|
if ( ! IsTrueSide( nSide))
|
|
return false ;
|
|
// verifico siano definiti almeno 3 punti (2 archi)
|
|
if ( dqFce.size() < 3)
|
|
return false ;
|
|
// verifico che primo e ultimo punto coincidano
|
|
if ( ! AreSamePointApprox( dqFce.front().ptP, dqFce.back().ptP))
|
|
return false ;
|
|
// verifico che sia un percorso semplice
|
|
if ( dqFce.front().nType != FreeContourEnt::START)
|
|
return false ;
|
|
// costruisco il percorso di contorno
|
|
PtrOwner<ICurveComposite> pCrvCompo( CurveFromFces( dqFce)) ;
|
|
if ( IsNull( pCrvCompo))
|
|
return false ;
|
|
// aggiusto orientamento affinché sia orario
|
|
double dArea ;
|
|
pCrvCompo->GetAreaXY( dArea) ;
|
|
if ( dArea > 0)
|
|
pCrvCompo->Invert() ;
|
|
// Porto il percorso sul piano corretto
|
|
Frame3d frRef = GetSideFrame( nSide) ;
|
|
pCrvCompo->ToGlob( frRef) ;
|
|
// Sistemazioni della curva
|
|
pCrvCompo->SetExtrusion( frRef.VersZ()) ;
|
|
pCrvCompo->SetThickness( -GetSideHeight( nSide)) ;
|
|
// Creo la superficie
|
|
PtrOwner<ISurfTriMesh> pStm ;
|
|
pStm.Set( CreateOneCurveFreeContour( pCrvCompo)) ;
|
|
if ( IsNull( pStm))
|
|
return false ;
|
|
// Inserisco la superficie nel layer Outline
|
|
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pStm)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
// recupero eventuali angoli di fianco
|
|
DBLVECTOR vSideAng ;
|
|
if ( VerifyFreeContourCurveSideAng( pCrvCompo))
|
|
GetFreeContourCurveSideAngles( pCrvCompo, vSideAng) ;
|
|
// inserisco la curva nel DB geometrico
|
|
int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pCrvCompo)) ;
|
|
if ( nTId != GDB_ID_NULL && vSideAng.size() > 0)
|
|
m_pGDB->SetInfo( nTId, IKEY_SIDEANGS, vSideAng) ;
|
|
// colore
|
|
Color cCol = m_ProcsCol ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
m_pGDB->SetMaterial( nTId, cCol) ;
|
|
// nome
|
|
m_pGDB->SetName( nId, GetOutlineApertureName( nSide)) ;
|
|
// info con tipo
|
|
m_pGDB->SetInfo( nId, IKEY_GROUP, 4) ;
|
|
m_pGDB->SetInfo( nId, IKEY_PROC, 252) ;
|
|
m_pGDB->SetInfo( nId, IKEY_SIDE, nSide) ;
|
|
// eventuali parametri del contorno
|
|
if ( nContType > 0 || ( nContType >= 0 && nContData != 0))
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_TYPE, nContType) ;
|
|
if ( nContData != 0)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_DATA, nContData) ;
|
|
if ( abs( dContPar) > EPS_SMALL)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_PAR, dContPar) ;
|
|
// eventuali attributi utente
|
|
if ( ! SetUserAttributes( nId, vsUAtt))
|
|
return false ;
|
|
// identificativi di geometrie ausiliarie
|
|
SetAuxId( nId, {nTId}) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::AddPartAperture( int nSide, int nCrvId, const DBLVECTOR& vdPar, const STRVECTOR& vsUAtt)
|
|
{
|
|
// reset dell'identificativo della geometria principale della feature
|
|
m_nProcId = GDB_ID_NULL ;
|
|
// verifico esistenza pezzo
|
|
if ( m_nBoxId == GDB_ID_NULL)
|
|
return false ;
|
|
// verifico validità faccia
|
|
if ( ! IsTrueSide( nSide))
|
|
return false ;
|
|
// verifica dei parametri
|
|
if ( vdPar.size() < 14)
|
|
return false ;
|
|
// sistemo i dati
|
|
int nContType = lround( vdPar[11]) ; // P13
|
|
int nContData = lround( vdPar[12]) ; // P14
|
|
double dContPar = vdPar[13] ; // P15
|
|
// verifico esista il percorso di contorno
|
|
if ( nCrvId == GDB_ID_NULL) {
|
|
// inserisco superficie vuota come marcatore
|
|
PtrOwner<ISurfTriMesh> pStm( CreateSurfTriMesh()) ;
|
|
if ( IsNull( pStm) || ! pStm->AdjustTopology())
|
|
return false ;
|
|
// la inserisco nel DB geometrico
|
|
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pStm)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
// nome
|
|
m_pGDB->SetName( nId, GetOutlineApertureName( nSide)) ;
|
|
// info con tipo
|
|
m_pGDB->SetInfo( nId, IKEY_GROUP, 4) ;
|
|
m_pGDB->SetInfo( nId, IKEY_PROC, 252) ;
|
|
m_pGDB->SetInfo( nId, IKEY_SIDE, nSide) ;
|
|
// eventuali parametri del contorno
|
|
if ( nContType > 0 || ( nContType >= 0 && nContData != 0))
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_TYPE, nContType) ;
|
|
if ( nContData != 0)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_DATA, nContData) ;
|
|
if ( abs( dContPar) > EPS_SMALL)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_PAR, dContPar) ;
|
|
// eventuali attributi utente
|
|
if ( ! SetUserAttributes( nId, vsUAtt))
|
|
return false ;
|
|
m_nProcId = nId ;
|
|
// messaggio di warning in log
|
|
string sOut = " Warning : Empty Aperture (" + ToString( nSide) +
|
|
") on line " + ToString( m_nBtlLine) ;
|
|
LOG_WARN( GetEExLogger(), sOut.c_str())
|
|
return true ;
|
|
}
|
|
// copio il percorso di contorno
|
|
PtrOwner<ICurveComposite> pCrvCompo ;
|
|
if ( m_pGDB->GetGeoType( nCrvId) & GEO_CURVE) {
|
|
pCrvCompo.Set( CreateCurveComposite()) ;
|
|
if ( ! pCrvCompo->CopyFrom( m_pGDB->GetGeoObj( nCrvId)))
|
|
pCrvCompo.Reset() ;
|
|
}
|
|
if ( IsNull( pCrvCompo))
|
|
return false ;
|
|
// verifico che sia chiuso
|
|
if ( ! pCrvCompo->IsClosed())
|
|
return false ;
|
|
// assegno eventuali angoli di fianco
|
|
{ DBLVECTOR vSideAng ;
|
|
if ( m_pGDB->GetInfo( nCrvId, IKEY_SIDEANGS, vSideAng)) {
|
|
for ( int i = 0 ; i < int( vSideAng.size()) ; ++ i)
|
|
pCrvCompo->SetCurveTempProp( i, int( vSideAng[i] * 1000)) ;
|
|
}
|
|
}
|
|
// Lo porto nel riferimento del lato e ve lo appiattisco
|
|
Frame3d frRef = GetSideFrame( nSide) ;
|
|
pCrvCompo->ToLoc( frRef) ;
|
|
pCrvCompo->Scale( Frame3d(), 1, 1, 0) ;
|
|
// aggiusto orientamento affinché sia orario
|
|
double dArea ;
|
|
pCrvCompo->GetAreaXY( dArea) ;
|
|
if ( dArea > 0)
|
|
pCrvCompo->Invert() ;
|
|
// Porto il percorso sul piano corretto e ve lo appiattisco
|
|
pCrvCompo->ToGlob( frRef) ;
|
|
// Sistemazioni della curva
|
|
pCrvCompo->SetExtrusion( frRef.VersZ()) ;
|
|
pCrvCompo->SetThickness( -GetSideHeight( nSide)) ;
|
|
// Creo la superficie
|
|
PtrOwner<ISurfTriMesh> pStm ;
|
|
pStm.Set( CreateOneCurveFreeContour( pCrvCompo)) ;
|
|
if ( IsNull( pStm))
|
|
return false ;
|
|
// Inserisco la superficie nel layer Outline
|
|
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pStm)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
// recupero eventuali angoli di fianco
|
|
DBLVECTOR vSideAng ;
|
|
if ( VerifyFreeContourCurveSideAng( pCrvCompo))
|
|
GetFreeContourCurveSideAngles( pCrvCompo, vSideAng) ;
|
|
// inserisco la curva nel DB geometrico
|
|
int nTId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pCrvCompo)) ;
|
|
if ( nTId != GDB_ID_NULL && vSideAng.size() > 0)
|
|
m_pGDB->SetInfo( nTId, IKEY_SIDEANGS, vSideAng) ;
|
|
// colore
|
|
Color cCol = m_ProcsCol ;
|
|
m_pGDB->SetMaterial( nId, cCol) ;
|
|
m_pGDB->SetMaterial( nTId, cCol) ;
|
|
// nome
|
|
m_pGDB->SetName( nId, GetOutlineApertureName( nSide)) ;
|
|
// info con tipo
|
|
m_pGDB->SetInfo( nId, IKEY_GROUP, 4) ;
|
|
m_pGDB->SetInfo( nId, IKEY_PROC, 252) ;
|
|
m_pGDB->SetInfo( nId, IKEY_SIDE, nSide) ;
|
|
// eventuali parametri del contorno
|
|
if ( nContType > 0 || ( nContType >= 0 && nContData != 0))
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_TYPE, nContType) ;
|
|
if ( nContData != 0)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_DATA, nContData) ;
|
|
if ( abs( dContPar) > EPS_SMALL)
|
|
m_pGDB->SetInfo( nId, IKEY_CNT_PAR, dContPar) ;
|
|
// eventuali attributi utente
|
|
if ( ! SetUserAttributes( nId, vsUAtt))
|
|
return false ;
|
|
// identificativi di geometrie ausiliarie
|
|
SetAuxId( nId, {nTId}) ;
|
|
|
|
m_nProcId = nId ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::UpdateOutLine( void)
|
|
{
|
|
// verifiche
|
|
if ( m_pGDB == nullptr || m_nPartId == GDB_ID_NULL)
|
|
return false ;
|
|
// pulisco il gruppo di Outline (elimino tutte le regioni)
|
|
int nOutId = m_pGDB->GetFirstInGroup( m_nOutsId) ;
|
|
while ( nOutId != GDB_ID_NULL) {
|
|
int nNextId = m_pGDB->GetNext( nOutId) ;
|
|
if ( m_pGDB->GetGeoType( nOutId) == SRF_FLATRGN)
|
|
m_pGDB->Erase( nOutId) ;
|
|
nOutId = nNextId ;
|
|
}
|
|
// se non riesco a creare l'outline speciale
|
|
if ( ! AddPartCustomOutline())
|
|
// creo quello standard
|
|
AddPartStdOutline() ;
|
|
|
|
// taglio con tutte le aperture
|
|
TrimOutlineWithApertures() ;
|
|
|
|
// taglio con tutte le features
|
|
TrimOutlineWithProcesses() ;
|
|
|
|
// se presente Shape e abilitato, nascondo Outline
|
|
int nDO ;
|
|
int nShapeId = m_pGDB->GetFirstNameInGroup( m_nOutsId, OL_SHAPE_NAME) ;
|
|
if ( nShapeId != GDB_ID_NULL && m_pGDB->GetInfo( nShapeId, IKEY_DO, nDO) && nDO != 0) {
|
|
int nEntId = m_pGDB->GetFirstInGroup( m_nOutsId) ;
|
|
while ( nEntId != GDB_ID_NULL) {
|
|
if ( nEntId != nShapeId)
|
|
m_pGDB->SetStatus( nEntId, GDB_ST_OFF) ;
|
|
nEntId = m_pGDB->GetNext( nEntId) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::AddPartStdOutline( void)
|
|
{
|
|
// verifico esistenza pezzo
|
|
if ( m_nBoxId == GDB_ID_NULL)
|
|
return false ;
|
|
// aggiungo le regioni delle facce
|
|
for ( int nSide = BTL_SIDE_FRONT ; nSide <= BTL_SIDE_RIGHT ; ++ nSide) {
|
|
PtrOwner<ISurfFlatRegion> pSfr( GetSurfFlatRegionRectangle( GetSideLength( nSide),GetSideWidth( nSide))) ;
|
|
if ( IsNull( pSfr))
|
|
return false ;
|
|
pSfr->ToGlob( GetSideFrame( nSide)) ;
|
|
// Inserisco la regione nel layer Outline
|
|
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pSfr)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGDB->SetName( nId, GetOutlineTopName( nSide)) ;
|
|
m_pGDB->SetInfo( nId, IKEY_OTL_SIDE, nSide) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::AddPartCustomOutline( void)
|
|
{
|
|
// se gruppo di Outline vuoto
|
|
if ( m_pGDB->GetGroupObjs( m_nOutsId) == 0)
|
|
return false ;
|
|
|
|
// Cerco contorno per creare le facce sopra e sotto
|
|
bool bDone = false ;
|
|
int nOutId = m_pGDB->GetFirstInGroup( m_nOutsId) ;
|
|
while ( nOutId != GDB_ID_NULL) {
|
|
int nDO = 1 ;
|
|
m_pGDB->GetInfo( nOutId, IKEY_DO, nDO) ;
|
|
int nPrc = 0 ;
|
|
m_pGDB->GetInfo( nOutId, IKEY_PROC, nPrc) ;
|
|
if ( nDO != 0 && nPrc == 251 && m_pGDB->GetGeoType( nOutId) == SRF_TRIMESH) {
|
|
// Riferimento
|
|
int nSide = 0 ;
|
|
m_pGDB->GetInfo( nOutId, IKEY_SIDE, nSide) ;
|
|
Frame3d frRef = GetSideFrame( nSide) ;
|
|
Vector3d vtExtr = - frRef.VersZ() * GetSideHeight( nSide) ;
|
|
// Superficie del contorno
|
|
const ISurfTriMesh* pStm = GetSurfTriMesh( m_pGDB->GetGeoObj( nOutId)) ;
|
|
// Creo le regioni sopra e sotto
|
|
PtrOwner<ISurfFlatRegion> pSfr1 ;
|
|
PtrOwner<ISurfFlatRegion> pSfr2 ;
|
|
// dai contorni della superficie
|
|
POLYLINEVECTOR vPL ;
|
|
bool bOk = pStm->GetLoops( vPL) && vPL.size() == 2 ;
|
|
if ( bOk) {
|
|
PtrOwner<ICurveComposite> pLoop1( CreateCurveComposite()) ;
|
|
PtrOwner<ISurfFlatRegion> pMySfr1( CreateSurfFlatRegion()) ;
|
|
bOk = ( ! IsNull( pLoop1) && ! IsNull( pMySfr1) && pLoop1->FromPolyLine( vPL[0]) && pMySfr1->AddExtLoop( Release( pLoop1))) ;
|
|
bOk = bOk && pMySfr1->Invert() ;
|
|
PtrOwner<ICurveComposite> pLoop2( CreateCurveComposite()) ;
|
|
PtrOwner<ISurfFlatRegion> pMySfr2( CreateSurfFlatRegion()) ;
|
|
bOk = ( bOk && ! IsNull( pLoop2) && ! IsNull( pMySfr2) && pLoop2->FromPolyLine( vPL[1]) && pMySfr2->AddExtLoop( Release( pLoop2))) ;
|
|
bOk = bOk && pMySfr2->Invert() ;
|
|
if ( AreSameVectorApprox( pMySfr1->GetNormVersor(), frRef.VersZ())) {
|
|
pSfr1.Set( pMySfr1) ;
|
|
pSfr2.Set( pMySfr2) ;
|
|
}
|
|
else {
|
|
pSfr1.Set( pMySfr2) ;
|
|
pSfr2.Set( pMySfr1) ;
|
|
}
|
|
}
|
|
// se non riesce, li calcolo in modo approssimato
|
|
if ( ! bOk) {
|
|
int nAuxId = GDB_ID_NULL ;
|
|
m_pGDB->GetInfo( nOutId, IKEY_AUXID, nAuxId) ;
|
|
if ( nAuxId == GDB_ID_NULL)
|
|
return false ;
|
|
nAuxId += nOutId ;
|
|
const ICurveComposite* pCrvCompo = GetCurveComposite( m_pGDB->GetGeoObj( nAuxId)) ;
|
|
if ( pCrvCompo == nullptr)
|
|
return false ;
|
|
pSfr1.Set( CreateSurfFlatRegion()) ;
|
|
if ( IsNull( pSfr1) || ! pSfr1->AddExtLoop( *pCrvCompo))
|
|
return false ;
|
|
pSfr2.Set( pSfr1->Clone()) ;
|
|
if ( IsNull( pSfr2))
|
|
return false ;
|
|
pSfr2->Invert() ;
|
|
pSfr2->Translate( vtExtr) ;
|
|
}
|
|
// Inserisco le regioni nel layer Outline
|
|
int nId1 = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pSfr1)) ;
|
|
if ( nId1 == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGDB->SetName( nId1, GetOutlineTopName( nSide)) ;
|
|
m_pGDB->SetInfo( nId1, IKEY_OTL_SIDE, nSide) ;
|
|
int nId2 = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pSfr2)) ;
|
|
if ( nId2 == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGDB->SetName( nId2, GetOutlineBottomName( nSide)) ;
|
|
m_pGDB->SetInfo( nId2, IKEY_OTL_SIDE, GetOppositeSide( nSide)) ;
|
|
// faccio una copia di queste regioni (non vanno ridotte con altre feature)
|
|
int nCopyId1 = m_pGDB->Copy( nId1, GDB_ID_NULL, nId1, GDB_AFTER) ;
|
|
m_pGDB->SetName( nCopyId1, GetOutlineTopName( nSide) + OL_SUFFIX_REGION_NAME) ;
|
|
m_pGDB->SetInfo( nCopyId1, IKEY_OTL_REGION, 1) ;
|
|
m_pGDB->SetStatus( nCopyId1, GDB_ST_OFF) ;
|
|
int nCopyId2 = m_pGDB->Copy( nId2, GDB_ID_NULL, nId2, GDB_AFTER) ;
|
|
m_pGDB->SetName( nCopyId2, GetOutlineBottomName( nSide) + OL_SUFFIX_REGION_NAME) ;
|
|
m_pGDB->SetInfo( nCopyId2, IKEY_OTL_REGION, 1) ;
|
|
m_pGDB->SetStatus( nCopyId2, GDB_ST_OFF) ;
|
|
// dichiaro di aver creato le superfici
|
|
bDone = true ;
|
|
}
|
|
nOutId = m_pGDB->GetNext( nOutId) ;
|
|
}
|
|
return bDone ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::TrimOutlineWithApertures( void)
|
|
{
|
|
// Cerco eventuali aperture per tagliare le facce sopra e sotto
|
|
int nApeId = m_pGDB->GetFirstInGroup( m_nOutsId) ;
|
|
while ( nApeId != GDB_ID_NULL) {
|
|
int nDO = 1 ;
|
|
m_pGDB->GetInfo( nApeId, IKEY_DO, nDO) ;
|
|
int nPrc = 0 ;
|
|
m_pGDB->GetInfo( nApeId, IKEY_PROC, nPrc) ;
|
|
if ( nDO != 0 && nPrc == 252 && m_pGDB->GetGeoType( nApeId) == SRF_TRIMESH) {
|
|
// Riferimento
|
|
int nSide = 0 ;
|
|
m_pGDB->GetInfo( nApeId, IKEY_SIDE, nSide) ;
|
|
Frame3d frRef = GetSideFrame( nSide) ;
|
|
Vector3d vtExtr = - frRef.VersZ() * GetSideHeight( nSide) ;
|
|
// Recupero la curva ausiliaria
|
|
int nAuxId = GDB_ID_NULL ;
|
|
m_pGDB->GetInfo( nApeId, IKEY_AUXID, nAuxId) ;
|
|
if ( nAuxId == GDB_ID_NULL)
|
|
return false ;
|
|
nAuxId += nApeId ;
|
|
const ICurveComposite* pCrvAux = GetCurveComposite( m_pGDB->GetGeoObj( nAuxId)) ;
|
|
PtrOwner<ICurveComposite> pCrvCompo( ( pCrvAux != nullptr ? pCrvAux->Clone() : nullptr)) ;
|
|
if ( pCrvCompo == nullptr)
|
|
return false ;
|
|
// Creo le regioni sopra e sotto
|
|
pCrvCompo->Invert() ;
|
|
PtrOwner<ISurfFlatRegion> pSfr1( CreateSurfFlatRegion()) ;
|
|
if ( IsNull( pSfr1) || ! pSfr1->AddExtLoop( Release( pCrvCompo)))
|
|
return false ;
|
|
PtrOwner<ISurfFlatRegion> pSfr2( pSfr1->Clone()) ;
|
|
if ( IsNull( pSfr2))
|
|
return false ;
|
|
pSfr2->Invert() ;
|
|
pSfr2->Translate( vtExtr) ;
|
|
// Sottraggo le regioni da quelle già presenti nell'outline
|
|
ISurfFlatRegion* pSfrTop = GetSurfFlatRegion( m_pGDB->GetGeoObj( GetFaceRegion( nSide))) ;
|
|
if ( pSfrTop == nullptr)
|
|
return false ;
|
|
pSfrTop->Subtract( *pSfr1) ;
|
|
ISurfFlatRegion* pSfrBot = GetSurfFlatRegion( m_pGDB->GetGeoObj( GetFaceRegion( GetOppositeSide( nSide)))) ;
|
|
if ( pSfrBot == nullptr)
|
|
return false ;
|
|
pSfrBot->Subtract( *pSfr2) ;
|
|
}
|
|
nApeId = m_pGDB->GetNext( nApeId) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::TrimOutlineWithProcesses( void)
|
|
{
|
|
// calcolo il numero dei processi di trimming presenti
|
|
int nProcCount = 0 ;
|
|
for ( int nProcId = m_pGDB->GetFirstInGroup( m_nProcsId) ;
|
|
nProcId != GDB_ID_NULL ;
|
|
nProcId = m_pGDB->GetNext( nProcId)) {
|
|
// deve essere una superficie
|
|
if ( m_pGDB->GetGeoType( nProcId) != SRF_TRIMESH)
|
|
continue ;
|
|
// deve essere attiva
|
|
int nDO = 1 ;
|
|
m_pGDB->GetInfo( nProcId, IKEY_DO, nDO) ;
|
|
if ( nDO == 0)
|
|
continue ;
|
|
// deve essere abilitata al trimming
|
|
int nTrim = 1 ;
|
|
m_pGDB->GetInfo( nProcId, IKEY_TRIM, nTrim) ;
|
|
if ( nTrim == 0 || ! UseProcessToTrimOutline( nProcId))
|
|
continue ;
|
|
// incremento il conteggio
|
|
++ nProcCount ;
|
|
}
|
|
// se troppi, salto i fori
|
|
bool bSkipDrills = ( nProcCount > 200) ;
|
|
// eseguo il trim
|
|
for ( int nProcId = m_pGDB->GetFirstInGroup( m_nProcsId) ;
|
|
nProcId != GDB_ID_NULL ;
|
|
nProcId = m_pGDB->GetNext( nProcId)) {
|
|
// deve essere una superficie
|
|
if ( m_pGDB->GetGeoType( nProcId) != SRF_TRIMESH)
|
|
continue ;
|
|
// deve essere attiva
|
|
int nDO = 1 ;
|
|
m_pGDB->GetInfo( nProcId, IKEY_DO, nDO) ;
|
|
if ( nDO == 0)
|
|
continue ;
|
|
// deve essere abilitata al trimming
|
|
int nTrim = 1 ;
|
|
m_pGDB->GetInfo( nProcId, IKEY_TRIM, nTrim) ;
|
|
if ( nTrim == 0 || ! UseProcessToTrimOutline( nProcId))
|
|
continue ;
|
|
// se fori da saltare, non deve essere un foro
|
|
if ( bSkipDrills) {
|
|
int nProc = 0 ;
|
|
m_pGDB->GetInfo( nProcId, IKEY_PROC, nProc) ;
|
|
if ( nProc == 40)
|
|
continue ;
|
|
}
|
|
// eseguo il trim
|
|
TrimOutline( nProcId) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::UseProcessToTrimOutline( int nProcId)
|
|
{
|
|
// se non trim speciale per pareti...
|
|
if ( ! m_bSpecialTrim)
|
|
return true ;
|
|
// recupero il box della superficie
|
|
BBox3d b3Proc ;
|
|
Point3d ptMin, ptMax ;
|
|
if ( ! m_pGDB->GetLocalBBox( nProcId, b3Proc) || ! b3Proc.GetMinMax( ptMin, ptMax))
|
|
return true ;
|
|
// verifico rispetto allo spessore perpendicolare alla faccia maggiore
|
|
if ( m_vtDim.y > m_vtDim.z)
|
|
return ( ( ptMax.z - ptMin.z) > m_vtDim.z - 100 * EPS_SMALL) ;
|
|
else
|
|
return ( ( ptMax.y - ptMin.y) > m_vtDim.y - 100 * EPS_SMALL) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::TrimOutline( int nProcSurfId)
|
|
{
|
|
// Recupero tipo di trim
|
|
int nTrim = 0 ;
|
|
m_pGDB->GetInfo( nProcSurfId, IKEY_TRIM, nTrim) ;
|
|
|
|
// Recupero eventuale superficie originale
|
|
int nOrigId = 0 ;
|
|
if ( m_pGDB->GetInfo( nProcSurfId, IKEY_ORIGID, nOrigId))
|
|
nProcSurfId += nOrigId ;
|
|
|
|
// Se processo con più superfici da usare insieme per trim, devo unirle
|
|
if ( nTrim == 2) {
|
|
// Recupero le due superfici del processo di lavorazione
|
|
int nAux ;
|
|
if ( m_pGDB->GetInfo( nProcSurfId, IKEY_AUXID, nAux) && nAux != 0) {
|
|
const ISurfTriMesh* pStm = GetSurfTriMesh( m_pGDB->GetGeoObj( nProcSurfId)) ;
|
|
const ISurfTriMesh* pAux = GetSurfTriMesh( m_pGDB->GetGeoObj( nProcSurfId + nAux)) ;
|
|
if ( pStm != nullptr && pAux != nullptr) {
|
|
PtrOwner<ISurfTriMesh> pTrim ;
|
|
pTrim.Set( pAux->Clone()) ;
|
|
pTrim->DoSewing( *pStm) ;
|
|
return TrimOutline( pTrim) ;
|
|
}
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
// Trim con una sola superficie
|
|
const ISurfTriMesh* pStm = GetSurfTriMesh( m_pGDB->GetGeoObj( nProcSurfId)) ;
|
|
if ( pStm == nullptr)
|
|
return false ;
|
|
// eseguo trim
|
|
return TrimOutline( pStm) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::TrimOutline( const ISurfTriMesh* pStm)
|
|
{
|
|
// Ne recupero le curve di contorno
|
|
POLYLINEVECTOR vPL ;
|
|
if ( ! pStm->GetLoops( vPL))
|
|
return false ;
|
|
// elimino i loop troppo piccoli
|
|
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
|
BBox3d b3PL ;
|
|
double dDiam ;
|
|
if ( ! vPL[i].GetLocalBBox( b3PL) || ! b3PL.GetDiameter( dDiam) || dDiam < 500 * EPS_SMALL) {
|
|
vPL.erase( vPL.begin() + i) ;
|
|
-- i ;
|
|
}
|
|
}
|
|
// unisco tratti allineati
|
|
for ( int i = 0 ; i < int( vPL.size()) ; ++ i)
|
|
vPL[i].RemoveAlignedPoints( EPS_SMALL) ;
|
|
// Divido le curve sulle varie facce del box del pezzo
|
|
bool bOk = true ;
|
|
bool bSomeInFace = false ;
|
|
ICURVEPOVECTOR vCrvP[SIDE_NBR] ;
|
|
for ( auto& PL : vPL) {
|
|
// ciclo sulle linee della polilinea
|
|
Point3d ptP1, ptP2 ;
|
|
for ( bool bFound = PL.GetFirstLine( ptP1, ptP2) ;
|
|
bFound ;
|
|
bFound = PL.GetNextLine( ptP1, ptP2)) {
|
|
// verifico la faccia di appartenenza
|
|
int nFace ;
|
|
if ( GetLineInFace( ptP1, ptP2, nFace)) {
|
|
// creo la linea
|
|
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
|
if ( ! IsNull( pLine) && pLine->Set( ptP1, ptP2)) {
|
|
vCrvP[ nFace - 1].emplace_back( Release( pLine)) ;
|
|
bSomeInFace = true ;
|
|
}
|
|
else
|
|
bOk = false ;
|
|
}
|
|
}
|
|
}
|
|
// Se trovate curve che stanno completamente in una faccia
|
|
if ( bSomeInFace) {
|
|
// elimino curve troppo corte
|
|
const double TOLER = 10 * EPS_SMALL ;
|
|
for ( int i = 0 ; i < SIDE_NBR ; ++ i) {
|
|
double dFaceLen = 0 ;
|
|
for ( const auto& pLine : vCrvP[i]) {
|
|
double dLen ;
|
|
if ( pLine->GetLength( dLen))
|
|
dFaceLen += dLen ;
|
|
}
|
|
if ( dFaceLen < TOLER)
|
|
vCrvP[i].clear() ;
|
|
}
|
|
// elimino eventuale faccia che rimarrebbe penzolante
|
|
int nCross ;
|
|
if ( IsCrossCut( vPL, nCross)) {
|
|
if ( ! RemoveDanglingFace( nCross, vCrvP, pStm))
|
|
bOk = false ;
|
|
}
|
|
// per ogni faccia
|
|
for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_RIGHT ; ++ i) {
|
|
if ( ! AdjustOneOutlineFace( i, vCrvP[i-1]))
|
|
bOk = false ;
|
|
}
|
|
}
|
|
// Altrimenti, verifico se la superficie di lavorazione coincide con una faccia
|
|
else {
|
|
Point3d ptCen ;
|
|
Vector3d vtN ;
|
|
// se la superficie è formata da una sola faccetta
|
|
if ( pStm->GetFacetCount() == 1 && pStm->GetFacetCenter( 0, ptCen, vtN)) {
|
|
// per ogni faccia
|
|
for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_RIGHT ; ++ i) {
|
|
// piano della faccia
|
|
Plane3d plFace = GetSidePlane( i) ;
|
|
// verifico se la faccetta coincide con la faccia
|
|
if ( PointInPlaneApprox( ptCen, plFace) && AreSameVectorApprox( vtN, plFace.GetVersN())) {
|
|
// cancello la regione della faccia
|
|
int nRegId = GetFaceRegion( i) ;
|
|
m_pGDB->Erase( nRegId) ;
|
|
break ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return bOk ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::GetLineInFace( const Point3d& ptP1, const Point3d& ptP2, int& nFace) const
|
|
{
|
|
// ciclo di verifica con le diverse facce
|
|
nFace = BTL_SIDE_NONE ;
|
|
for ( int i = BTL_SIDE_FRONT ; i <= BTL_SIDE_RIGHT ; ++ i) {
|
|
// se sta sulla faccia
|
|
if ( IsLineOnFace( ptP1, ptP2, i)) {
|
|
// se appartiene anche ad altra faccia, è sul bordo comune e quindi non interna
|
|
if ( nFace != BTL_SIDE_NONE)
|
|
return false ;
|
|
// assegno la faccia
|
|
else
|
|
nFace = i ;
|
|
}
|
|
}
|
|
|
|
return ( nFace != BTL_SIDE_NONE) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::IsLineOnFace( const Point3d& ptP1, const Point3d& ptP2, int nFace) const
|
|
{
|
|
// piano della faccia
|
|
Plane3d plFace = GetSidePlane( nFace) ;
|
|
// sulla faccia se i due punti appartengono alla faccia
|
|
return ( PointInPlaneEpsilon( ptP1, plFace, EPS_SMALL) && PointInPlaneEpsilon( ptP2, plFace, EPS_SMALL)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::IsCrossCut( const POLYLINEVECTOR& vPL, int& nCross) const
|
|
{
|
|
const double TOLER = 10 * EPS_SMALL ;
|
|
// inizializzo flag
|
|
int nCrossX = 0 ;
|
|
int nCrossY = 0 ;
|
|
int nCrossZ = 0 ;
|
|
// ciclo sulle polilinee
|
|
for ( auto& PL : vPL) {
|
|
// ciclo sui punti della polilinea
|
|
Point3d ptP ;
|
|
for ( bool bFound = PL.GetFirstPoint( ptP) ;
|
|
bFound ;
|
|
bFound = PL.GetNextPoint( ptP)) {
|
|
// verifica di appartenenza ad edge lungo X
|
|
if ( abs( ptP.y) < TOLER && abs( ptP.z) < TOLER)
|
|
nCrossX |= 1 ;
|
|
if ( abs( ptP.y - m_vtDim.y) < TOLER && abs( ptP.z) < TOLER)
|
|
nCrossX |= 2 ;
|
|
if ( abs( ptP.y - m_vtDim.y) < TOLER && abs( ptP.z - m_vtDim.z) < TOLER)
|
|
nCrossX |= 4 ;
|
|
if ( abs( ptP.y) < TOLER && abs( ptP.z - m_vtDim.z) < TOLER)
|
|
nCrossX |= 8 ;
|
|
// verifica di appartenenza ad edge lungo Y
|
|
if ( abs( ptP.z) < TOLER && abs( ptP.x) < TOLER)
|
|
nCrossY |= 1 ;
|
|
if ( abs( ptP.z - m_vtDim.z) < TOLER && abs( ptP.x) < TOLER)
|
|
nCrossY |= 2 ;
|
|
if ( abs( ptP.z - m_vtDim.z) < TOLER && abs( ptP.x - m_vtDim.x) < TOLER)
|
|
nCrossY |= 4 ;
|
|
if ( abs( ptP.z) < TOLER && abs( ptP.x - m_vtDim.x) < TOLER)
|
|
nCrossY |= 8 ;
|
|
// verifica di appartenenza ad edge lungo Z
|
|
if ( abs( ptP.x) < TOLER && abs( ptP.y) < TOLER)
|
|
nCrossZ |= 1 ;
|
|
if ( abs( ptP.x - m_vtDim.x) < TOLER && abs( ptP.y) < TOLER)
|
|
nCrossZ |= 2 ;
|
|
if ( abs( ptP.x - m_vtDim.x) < TOLER && abs( ptP.y - m_vtDim.y) < TOLER)
|
|
nCrossZ |= 4 ;
|
|
if ( abs( ptP.x) < TOLER && abs( ptP.y - m_vtDim.y) < TOLER)
|
|
nCrossZ |= 8 ;
|
|
}
|
|
}
|
|
// non taglia niente
|
|
nCross = CROSS_CUT_NONE ;
|
|
// determino se taglia tutti gli edge di una direzione
|
|
if ( nCrossX == ( 1 | 2 | 4 | 8))
|
|
nCross = CROSS_CUT_X ;
|
|
else if ( nCrossY == ( 1 | 2 | 4 | 8))
|
|
nCross = CROSS_CUT_Y ;
|
|
else if ( nCrossZ == ( 1 | 2 | 4 | 8))
|
|
nCross = CROSS_CUT_Z ;
|
|
// determino se taglia gli edge combinati di due direzioni
|
|
if ( ( ( nCrossZ & ( 1|8)) == ( 1|8) || ( nCrossZ & ( 2|4)) == ( 2|4)) &&
|
|
( ( nCrossX & ( 1|2)) == ( 1|2) || ( nCrossX & ( 4|8)) == ( 4|8)))
|
|
nCross = CROSS_CUT_Z | CROSS_CUT_X ;
|
|
else if ( ( ( nCrossX & ( 1|8)) == ( 1|8) || ( nCrossX & ( 2|4)) == ( 2|4)) &&
|
|
( ( nCrossY & ( 1|2)) == ( 1|2) || ( nCrossY & ( 4|8)) == ( 4|8)))
|
|
nCross = CROSS_CUT_X | CROSS_CUT_Y ;
|
|
else if ( ( ( nCrossY & ( 1|8)) == ( 1|8) || ( nCrossY & ( 2|4)) == ( 2|4)) &&
|
|
( ( nCrossZ & ( 1|2)) == ( 1|2) || ( nCrossZ & ( 4|8)) == ( 4|8)))
|
|
nCross = CROSS_CUT_Y | CROSS_CUT_Z ;
|
|
return ( nCross != CROSS_CUT_NONE) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::RemoveDanglingFace( int nCross, const ICURVEPOVECTOR vCrvP[], const ISurfTriMesh* pStm)
|
|
{
|
|
// normale media alla superficie
|
|
Vector3d vtN ;
|
|
for ( int i = 0 ; i < pStm->GetFacetCount() ; ++ i) {
|
|
Vector3d vtFacN ;
|
|
double dFacArea ;
|
|
if ( pStm->GetFacetNormal( i, vtFacN) && pStm->GetFacetArea( i, dFacArea))
|
|
vtN += vtFacN * dFacArea ;
|
|
}
|
|
if ( ! vtN.Normalize())
|
|
return false ;
|
|
// verifico facce BTL_SIDE_LEFT (5) e BTL_SIDE_RIGHT (6)
|
|
if ( ( nCross & CROSS_CUT_X) != 0) {
|
|
if ( vtN.x < - SIN_EPS_ANG_SMALL && vCrvP[5-1].size() == 0) {
|
|
// cancello la regione della faccia
|
|
int nRegId = GetFaceRegion( 5) ;
|
|
m_pGDB->Erase( nRegId) ;
|
|
}
|
|
else if ( vtN.x > SIN_EPS_ANG_SMALL && vCrvP[6-1].size() == 0) {
|
|
// cancello la regione della faccia
|
|
int nRegId = GetFaceRegion( 6) ;
|
|
m_pGDB->Erase( nRegId) ;
|
|
}
|
|
}
|
|
// verifico facce BTL_SIDE_FRONT (1) e BTL_SIDE_BACK (3)
|
|
if ( ( nCross & CROSS_CUT_Y) != 0) {
|
|
if ( vtN.y < - SIN_EPS_ANG_SMALL && vCrvP[1-1].size() == 0) {
|
|
// cancello la regione della faccia
|
|
int nRegId = GetFaceRegion( 1) ;
|
|
m_pGDB->Erase( nRegId) ;
|
|
}
|
|
else if ( vtN.y > SIN_EPS_ANG_SMALL && vCrvP[3-1].size() == 0) {
|
|
// cancello la regione della faccia
|
|
int nRegId = GetFaceRegion( 3) ;
|
|
m_pGDB->Erase( nRegId) ;
|
|
}
|
|
}
|
|
// verifico facce BTL_SIDE_BOTTOM (2) e BTL_SIDE_TOP (4)
|
|
if ( ( nCross & CROSS_CUT_Z) != 0) {
|
|
if ( vtN.z < - SIN_EPS_ANG_SMALL && vCrvP[2-1].size() == 0) {
|
|
// cancello la regione della faccia
|
|
int nRegId = GetFaceRegion( 2) ;
|
|
m_pGDB->Erase( nRegId) ;
|
|
}
|
|
else if ( vtN.z > SIN_EPS_ANG_SMALL && vCrvP[4-1].size() == 0) {
|
|
// cancello la regione della faccia
|
|
int nRegId = GetFaceRegion( 4) ;
|
|
m_pGDB->Erase( nRegId) ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::AdjustOneOutlineFace( int nSide, ICURVEPOVECTOR& vCrvP)
|
|
{
|
|
// verifico ci siano delle curve di taglio
|
|
if ( vCrvP.size() == 0)
|
|
return true ;
|
|
// recupero la regione associata alla faccia
|
|
int nRegId = GetFaceRegion( nSide) ;
|
|
ISurfFlatRegion* pFaceReg = GetSurfFlatRegion( m_pGDB->GetGeoObj( nRegId)) ;
|
|
if ( pFaceReg == nullptr)
|
|
return true ;
|
|
// preparo la regione da sottrarre
|
|
PtrOwner<ISurfFlatRegion> pSubReg ;
|
|
// recupero il riferimento della faccia
|
|
Frame3d frFace = GetSideFrame( nSide) ;
|
|
// recupero il contorno della faccia nel suo proprio riferimento
|
|
PtrOwner<ICurve> pFaceCnt( GetFaceContour( nSide)) ;
|
|
if ( IsNull( pFaceCnt))
|
|
return false ;
|
|
// porto le linee nel riferimento della faccia
|
|
for ( auto& pCrv : vCrvP) {
|
|
pCrv->ToLoc( frFace) ;
|
|
pCrv->Scale( GLOB_FRM, 1, 1, 0) ;
|
|
}
|
|
// concateno le linee senza invertirle
|
|
const double TOLER = 10 * EPS_SMALL ;
|
|
ChainCurves chainC ;
|
|
chainC.Init( false, TOLER, ssize( vCrvP)) ;
|
|
for ( int i = 0 ; i < ssize( vCrvP) ; ++ i) {
|
|
Point3d ptStart, ptEnd ;
|
|
Vector3d vtStart, vtEnd ;
|
|
if ( ! vCrvP[i]->GetStartPoint( ptStart) || ! vCrvP[i]->GetStartDir( vtStart) ||
|
|
! vCrvP[i]->GetEndPoint( ptEnd) || ! vCrvP[i]->GetEndDir( vtEnd))
|
|
return false ;
|
|
if ( ! chainC.AddCurve( int( i+1), ptStart, vtStart, ptEnd, vtEnd))
|
|
return false ;
|
|
}
|
|
Point3d ptNearL = ORIG ;
|
|
INTVECTOR vId2s ;
|
|
while ( chainC.GetChainFromNear( ptNearL, false, vId2s)) {
|
|
// creo una curva composita
|
|
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
|
if ( IsNull( pCrvCompo))
|
|
return false ;
|
|
// recupero le curve semplici e le inserisco nella curva composita
|
|
for ( int i = 0 ; i < ssize( vId2s) ; ++ i) {
|
|
// indice della curva
|
|
int j = vId2s[i] - 1 ;
|
|
// la aggiungo alla curva composta
|
|
bool bOk = pCrvCompo->AddCurve( Release( vCrvP[j]), true, TOLER) ;
|
|
if ( ! bOk)
|
|
return false ;
|
|
}
|
|
// se curva aperta, la completo con il contorno della faccia
|
|
if ( ! pCrvCompo->IsClosed()) {
|
|
const double EXTRA_LEN = 5 * EPS_SMALL ;
|
|
// per sicurezza allungo gli estremi
|
|
pCrvCompo->ExtendStartByLen( EXTRA_LEN) ;
|
|
pCrvCompo->ExtendEndByLen( EXTRA_LEN) ;
|
|
// intersezione della curva col contorno
|
|
IntersCurveCurve intCC( *pCrvCompo, *pFaceCnt) ;
|
|
int nIntCount = intCC.GetIntersCount() ;
|
|
if ( nIntCount < 2)
|
|
continue ;
|
|
IntCrvCrvInfo iccInfo ;
|
|
intCC.GetIntCrvCrvInfo( 0, iccInfo) ;
|
|
double dParStart = iccInfo.IciA[0].dU ;
|
|
double dParCntEnd = iccInfo.IciB[0].dU ;
|
|
intCC.GetIntCrvCrvInfo( nIntCount - 1, iccInfo) ;
|
|
double dParEnd = iccInfo.IciA[0].dU ;
|
|
double dParCntStart = iccInfo.IciB[0].dU ;
|
|
// aggiusto la curva
|
|
pCrvCompo->TrimStartEndAtParam( dParStart, dParEnd) ;
|
|
// recupero parte del contorno tra intersezione fine e intersezione inizio
|
|
PtrOwner<ICurve> pTmpCrv( pFaceCnt->CopyParamRange( dParCntStart, dParCntEnd)) ;
|
|
if ( IsNull( pTmpCrv) || ! pCrvCompo->AddCurve( Release( pTmpCrv)))
|
|
continue ;
|
|
// se ora non è chiusa, salto alla prossima concatenazione
|
|
if ( ! pCrvCompo->IsClosed())
|
|
continue ;
|
|
}
|
|
// porto la curva nel riferimento del pezzo
|
|
pCrvCompo->ToGlob( frFace) ;
|
|
// creo una regione a partire dalla curva
|
|
SurfFlatRegionByContours SfrCntr ;
|
|
SfrCntr.AddCurve( Release( pCrvCompo)) ;
|
|
PtrOwner<ISurfFlatRegion> pSfrReg( SfrCntr.GetSurf()) ;
|
|
if ( IsNull( pSfrReg))
|
|
continue ;
|
|
// se opposta alla faccia, devo prenderne il complementare rispetto a questa
|
|
if ( AreOppositeVectorApprox( pFaceReg->GetNormVersor(), pSfrReg->GetNormVersor())) {
|
|
PtrOwner<ISurfFlatRegion> pSfrTmp( Release( pSfrReg)) ;
|
|
pSfrReg.Set( pFaceReg->Clone()) ;
|
|
if ( IsNull( pSfrReg))
|
|
continue ;
|
|
pSfrTmp->Invert() ;
|
|
pSfrReg->Subtract( *pSfrTmp) ;
|
|
}
|
|
// se la regione sottrazione totale non esiste, la assegno
|
|
if ( IsNull( pSubReg))
|
|
pSubReg.Set( pSfrReg) ;
|
|
// altrimenti la combino con la nuova
|
|
else {
|
|
// salvo una copia della regione sottrazione totale
|
|
PtrOwner<ISurfFlatRegion> pSubCopy( pSubReg->Clone()) ;
|
|
if ( IsNull( pSubCopy))
|
|
return false ;
|
|
// provo a intersecarle
|
|
pSubReg->Intersect( *pSfrReg) ;
|
|
// se non rimane alcunché, provo a unirle
|
|
if ( ! pSubReg->IsValid()) {
|
|
pSubReg.Set( pSubCopy) ;
|
|
pSubReg->Add( *pSfrReg) ;
|
|
}
|
|
}
|
|
}
|
|
// se esiste regione sottrazione, la tolgo dalla regione della faccia
|
|
if ( ! IsNull( pSubReg)) {
|
|
// eseguo sottrazione
|
|
pFaceReg->Subtract( *pSubReg) ;
|
|
// se vuota, la elimino
|
|
if ( ! pFaceReg->IsValid())
|
|
m_pGDB->Erase( nRegId) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
BtlGeom::GetFaceRegion( int nSide)
|
|
{
|
|
int nId = m_pGDB->GetFirstInGroup( m_nOutsId) ;
|
|
while ( nId != GDB_ID_NULL) {
|
|
int nS ;
|
|
if ( m_pGDB->GetGeoType( nId) == SRF_FLATRGN &&
|
|
m_pGDB->GetInfo( nId, IKEY_OTL_SIDE, nS) && nS == nSide &&
|
|
! m_pGDB->ExistsInfo( nId, IKEY_OTL_REGION))
|
|
return nId ;
|
|
nId = m_pGDB->GetNext( nId) ;
|
|
}
|
|
return GDB_ID_NULL ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
BtlGeom::GetFaceContour( int nSide)
|
|
{
|
|
// verifico validità indice di faccia
|
|
if ( nSide < BTL_SIDE_FRONT || nSide > BTL_SIDE_RIGHT)
|
|
return nullptr ;
|
|
// creo il contorno antiorario
|
|
PolyLine PL ;
|
|
PL.AddUPoint( 0, ORIG) ;
|
|
PL.AddUPoint( 1, Point3d( GetSideLength( nSide), 0, 0)) ;
|
|
PL.AddUPoint( 2, Point3d( GetSideLength( nSide), GetSideWidth( nSide), 0)) ;
|
|
PL.AddUPoint( 3, Point3d( 0, GetSideWidth( nSide), 0)) ;
|
|
PL.AddUPoint( 4, ORIG) ;
|
|
// creo la curva composita
|
|
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
|
|
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( PL))
|
|
return nullptr ;
|
|
else
|
|
return Release( pCrvCompo) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::IsPointOnFaceContour( const Point3d& ptP, int nSide)
|
|
{
|
|
// Il punto è nel riferimento faccia
|
|
// Verifico se sta sul contorno
|
|
return ( abs( ptP.x) < EPS_SMALL || abs( ptP.x - GetSideLength( nSide)) < EPS_SMALL ||
|
|
abs( ptP.y) < EPS_SMALL || abs( ptP.y - GetSideWidth( nSide)) < EPS_SMALL) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::IsPointNearFaceContour( const Point3d& ptP, int nSide)
|
|
{
|
|
// Il punto è nel riferimento faccia
|
|
// Verifico se sta vicino al contorno o fuori entro il limite
|
|
const double EPS_IN_NEAR = 0.2 ;
|
|
const double EPS_OUT_NEAR = 5.0 ;
|
|
double dL = GetSideLength( nSide) ;
|
|
double dW = GetSideWidth( nSide) ;
|
|
return ( ( ptP.x > - EPS_OUT_NEAR && ptP.x < EPS_IN_NEAR) ||
|
|
( ptP.x > dL - EPS_IN_NEAR && ptP.x < dL + EPS_OUT_NEAR) ||
|
|
( ptP.y > - EPS_OUT_NEAR && ptP.y < EPS_IN_NEAR) ||
|
|
( ptP.y > dW - EPS_IN_NEAR && ptP.y < dW + EPS_OUT_NEAR)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::IsPointOutFaceContour( const Point3d& ptP, int nSide)
|
|
{
|
|
// Il punto è nel riferimento faccia
|
|
// Verifico se sta all'esterno del contorno
|
|
return ( ptP.x < -EPS_SMALL || ptP.x > GetSideLength( nSide) - EPS_SMALL ||
|
|
ptP.y < -EPS_SMALL || ptP.y > GetSideWidth( nSide) - EPS_SMALL) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::SetPointOnFaceContour( Point3d& ptP, int nSide)
|
|
{
|
|
// Il punto è nel riferimento faccia
|
|
// Dimensioni della faccia
|
|
double dL = GetSideLength( nSide) ;
|
|
double dW = GetSideWidth( nSide) ;
|
|
// Sistemazioni per punto esterno
|
|
if ( ptP.x < 0)
|
|
ptP.x = 0 ;
|
|
else if ( ptP.x > dL)
|
|
ptP.x = dL ;
|
|
if ( ptP.y < 0)
|
|
ptP.y = 0 ;
|
|
else if ( ptP.y > dW)
|
|
ptP.y = dW ;
|
|
// Sistemazioni per punto interno
|
|
double vDist[4] = { abs( ptP.x), abs( ptP.x - dL), abs( ptP.y), abs( ptP.y - dW)} ;
|
|
int nMinDistSide = 0 ;
|
|
for ( int i = 1 ; i < 4 ; ++i) {
|
|
if ( vDist[i] < vDist[nMinDistSide])
|
|
nMinDistSide = i ;
|
|
}
|
|
switch ( nMinDistSide) {
|
|
case 0 : ptP.x = 0 ; break ;
|
|
case 1 : ptP.x = dL ; break ;
|
|
case 2 : ptP.y = 0 ; break ;
|
|
case 3 : ptP.y = dW ; break ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::TrimRayWithFaceContour( const Point3d& ptP, const Vector3d& vtDir, int nSide, Point3d& ptInt)
|
|
{
|
|
// Punto e direzione sono nel riferimento faccia
|
|
// Dimensioni della faccia
|
|
double dL = GetSideLength( nSide) ;
|
|
double dW = GetSideWidth( nSide) ;
|
|
// Verifico che il punto sia nella faccia
|
|
if ( ptP.x < EPS_SMALL || ptP.x > dL - EPS_SMALL ||
|
|
ptP.y < EPS_SMALL || ptP.y > dW - EPS_SMALL)
|
|
return false ;
|
|
// Creo la linea rappresentativa del raggio
|
|
PtrOwner<ICurveLine> pRay( CreateCurveLine()) ;
|
|
if ( IsNull( pRay) || ! pRay->SetPVL( ptP, vtDir, dL + dW))
|
|
return false ;
|
|
// Recupero il contorno della faccia
|
|
PtrOwner<ICurve> pCont( GetFaceContour( nSide)) ;
|
|
if ( IsNull( pCont))
|
|
return false ;
|
|
// Calcolo l'intersezione del raggio con il contorno della faccia
|
|
return IntersCurveCurve( *pRay, *pCont).GetIntersPointNearTo( 0, ptP, ptInt) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::TrimProcessWithOutline( int nProcId)
|
|
{
|
|
// se non richiesto, esco subito
|
|
if ( ! m_bTrimWithOutline)
|
|
return true ;
|
|
// verifico esistenza superficie della feature da trimmare
|
|
ISurfTriMesh* pStm = GetSurfTriMesh( m_pGDB->GetGeoObj( nProcId)) ;
|
|
if ( pStm == nullptr)
|
|
return false ;
|
|
// se prevista anche una seconda superficie da trimmare
|
|
ISurfTriMesh* pStm2 = nullptr ;
|
|
int nTrim = 0 ;
|
|
if ( m_pGDB->GetInfo( nProcId, IKEY_TRIM, nTrim) && nTrim == 2) {
|
|
int nAux ;
|
|
if ( m_pGDB->GetInfo( nProcId, IKEY_AUXID, nAux) && nAux != 0)
|
|
pStm2 = GetSurfTriMesh( m_pGDB->GetGeoObj( nProcId + nAux)) ;
|
|
if ( pStm2 == nullptr)
|
|
return false ;
|
|
}
|
|
// verifico esistenza superficie di outline
|
|
int nOutId = GDB_ID_NULL ;
|
|
int nEntId = m_pGDB->GetFirstInGroup( m_nOutsId) ;
|
|
while ( nEntId != GDB_ID_NULL) {
|
|
int nDO = 1 ;
|
|
m_pGDB->GetInfo( nEntId, IKEY_DO, nDO) ;
|
|
int nProc = 0 ;
|
|
m_pGDB->GetInfo( nEntId, IKEY_PROC, nProc) ;
|
|
int nSide = 0 ;
|
|
m_pGDB->GetInfo( nEntId, IKEY_SIDE, nSide) ;
|
|
if ( nDO != 0 && nProc == 251 && nSide != 0) {
|
|
nOutId = nEntId ;
|
|
break ;
|
|
}
|
|
nEntId = m_pGDB->GetNext( nEntId) ;
|
|
}
|
|
if ( nOutId == GDB_ID_NULL)
|
|
return true ;
|
|
// recupero la curva associata alla superficie di trim
|
|
int nAuxId = 0 ;
|
|
m_pGDB->GetInfo( nOutId, IKEY_AUXID, nAuxId) ;
|
|
if ( nAuxId == 0)
|
|
return true ;
|
|
int nCrv = nOutId + nAuxId ;
|
|
const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nCrv)) ;
|
|
if ( pCrv == nullptr)
|
|
return true ;
|
|
// creo una copia della superficie come originale
|
|
int nCopyId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, pStm->Clone()) ;
|
|
if ( nCopyId == GDB_ID_NULL)
|
|
return false ;
|
|
string sOrigId = ( nCopyId - nProcId > 0 ? "+" : "") + ToString( nCopyId - nProcId) ;
|
|
m_pGDB->SetInfo( nProcId, IKEY_ORIGID, sOrigId) ;
|
|
string sMainId = ( nProcId - nCopyId > 0 ? "+" : "") + ToString( nProcId - nCopyId) ;
|
|
m_pGDB->SetInfo( nCopyId, IKEY_MAINID, sMainId) ;
|
|
m_pGDB->SetMode( nCopyId, GDB_MD_HIDDEN) ;
|
|
// se esiste anche seconda superficie, copio anche questa
|
|
if ( pStm2 != nullptr) {
|
|
int nCopy2Id = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nProcsId, pStm2->Clone()) ;
|
|
if ( nCopy2Id == GDB_ID_NULL)
|
|
return false ;
|
|
string sAuxId = ( nCopy2Id - nCopyId > 0 ? "+" : "") + ToString( nCopy2Id - nCopyId) ;
|
|
m_pGDB->SetInfo( nCopyId, IKEY_AUXID, sAuxId) ;
|
|
m_pGDB->SetMode( nCopy2Id, GDB_MD_HIDDEN) ;
|
|
}
|
|
// eseguo piccolo offset della curva per evitare problemi di sovrapposizioni
|
|
OffsetCurve OffsCrv ;
|
|
if ( ! OffsCrv.Make( pCrv, -50 * EPS_SMALL, ICurve::OFF_EXTEND) || OffsCrv.GetCurveCount() == 0) {
|
|
return false ;
|
|
}
|
|
PtrOwner<ICurve> pCopyCrv( OffsCrv.GetLongerCurve()) ;
|
|
// eseguo il trim
|
|
return ( pStm->GeneralizedCut( *pCopyCrv, false) &&
|
|
( pStm2 == nullptr || pStm2->GeneralizedCut( *pCopyCrv, false))) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
BtlGeom::AddShapeBTLX( const INTMATRIX& vFacesVertices, const PNTVECTOR& vPoints)
|
|
{
|
|
StmFromTriangleSoup StmFts ;
|
|
if ( ! StmFts.Start()) {
|
|
LOG_ERROR( GetEExLogger(), " Error reading Part Shape: StmFts.Start error")
|
|
return false ;
|
|
}
|
|
|
|
for ( auto it = vFacesVertices.begin() ; it != vFacesVertices.end() ; it++) {
|
|
INTVECTOR vVertices = *it ;
|
|
if ( vVertices.size() < 3) {
|
|
LOG_ERROR( GetEExLogger(), " Error reading Part Shape: Face not valid")
|
|
return false ;
|
|
}
|
|
// creo il contorno della faccia
|
|
PtrOwner<ICurveComposite> pCurveCompo( CreateCurveComposite()) ;
|
|
pCurveCompo->AddPoint( vPoints[vVertices[0]]) ;
|
|
for ( int i = 1 ; i < ssize( vVertices) ; i++)
|
|
pCurveCompo->AddLine( vPoints[vVertices[i]]) ;
|
|
pCurveCompo->AddLine( vPoints[vVertices[0]]) ;
|
|
// creo la faccia e recupero i suoi triangoli
|
|
PtrOwner<ISurfTriMesh> pSurf( GetSurfTriMeshByFlatContour( pCurveCompo)) ;
|
|
if ( ! IsNull( pSurf))
|
|
StmFts.AddSurfTriMesh( *pSurf) ;
|
|
}
|
|
|
|
if ( ! StmFts.End()) {
|
|
LOG_ERROR( GetEExLogger(), " Error reading Part Shape: StmFts.End error")
|
|
return false ;
|
|
}
|
|
|
|
PtrOwner<ISurfTriMesh> pShape( StmFts.GetSurf()) ;
|
|
int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, m_nOutsId, Release( pShape)) ;
|
|
if ( nId == GDB_ID_NULL)
|
|
return false ;
|
|
m_pGDB->SetName( nId, OL_SHAPE_NAME) ;
|
|
m_pGDB->SetMaterial( nId, m_OutsCol) ;
|
|
m_pGDB->SetStatus( nId, GDB_ST_OFF) ;
|
|
m_pGDB->SetInfo( nId, IKEY_DO, 0) ;
|
|
|
|
return true ;
|
|
}
|