Files
Dario Sassi 9577795c73 EgtExchange 3.1a2 :
- per BTL aggiunta possibilità di gestione geometrica del PARTOFFSET (controllata da flag).
2026-01-23 18:53:20 +01:00

1049 lines
38 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2020-2020
//----------------------------------------------------------------------------
// File : BeamMgr.cpp Data : 30.08.20 Versione : 2.2h
// Contenuto : Implementazione della classe per l'importazione BTL.
//
//
//
// Modifiche : 22.08.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "BeamMgr.h"
#include "DllMain.h"
#include "/EgtDev/Include/EExDllMain.h"
#include "/EgtDev/Include/EGkStmStandard.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkExtText.h"
#include "/EgtDev/Include/EgtKeyCodes.h"
#include "/EgtDev/Include/EgtStringEncoder.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <future>
using namespace std ;
//----------------------------------------------------------------------------
IBeamMgr*
CreateBeamMgr( void)
{
// verifico la chiave e le opzioni
if ( ! VerifyKey( KEYOPT_EEX_INPADV))
return nullptr ;
// creo l'oggetto
return static_cast<IBeamMgr*> ( new(nothrow) BeamMgr) ;
}
//----------------------------------------------------------------------------
BeamMgr::BeamMgr( void)
{
;
}
//----------------------------------------------------------------------------
bool
BeamMgr::Init( IGeomDB* pGDB, int nFlag)
{
m_pGDB = pGDB ;
return SetFlag( nFlag) ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::SetFlag( int nFlag)
{
// verifico il gestore di DB geometrico
if ( m_pGDB == nullptr)
return false ;
// inizializzo il gestore geometria pezzi Btl
int nFlatVertPos = 0 ;
if (( nFlag & EIBFLAG_OUTL_FLAT_POS) != 0)
nFlatVertPos = 4 ;
else if (( nFlag & EIBFLAG_TS3_POS) != 0)
nFlatVertPos = 3 ;
else if (( nFlag & EIBFLAG_FLAT_POS) != 0)
nFlatVertPos = 1 ;
else if (( nFlag & EIBFLAG_VERT_POS) != 0)
nFlatVertPos = 2 ;
bool bSpecialTrim = (( nFlag & EIBFLAG_SPECIAL_TRIM) != 0) ;
bool bTrimWithOutline = (( nFlag & EIBFLAG_TRIM_WITH_OUTLINE) != 0) ;
bool bUseUAttr = (( nFlag & EIBFLAG_USEUATTR) != 0) ;
bool bPartOffset = (( nFlag & EIBFLAG_PARTOFFSET) != 0) ;
if ( ! m_BtlGeom.Init( m_pGDB, nFlatVertPos, bSpecialTrim, bTrimWithOutline, bUseUAttr, bPartOffset, false)) {
LOG_ERROR( GetEExLogger(), " Error on BtlGeom.Init")
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
int
BeamMgr::CreatePart( void)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return GDB_ID_NULL ;
// Aggiorno posizione
m_BtlGeom.UpdateNextOrigin() ;
// Creo il pezzo
return ( m_BtlGeom.CreatePart() ? m_BtlGeom.GetCurrPartId() : GDB_ID_NULL) ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::SetPart( int nPartId)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Imposto il pezzo come corrente
return m_BtlGeom.SetPart( nPartId) ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::ErasePart( void)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Cancello il pezzo corrente
return m_BtlGeom.ErasePart() ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::UpdatePart( void)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Forzo aggiornamento del pezzo corrente
return ( m_BtlGeom.UpdateOutLine() && m_BtlGeom.ResetPartSolid()) ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::SetPartProdNbr( int nProdNbr)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Verifico validità nuovo PDN
if ( ! m_BtlGeom.VerifyNewPartProdNbr( nProdNbr))
return false ;
// Imposto il numero di produzione sul pezzo corrente
return m_BtlGeom.SetPartProdNbr( nProdNbr) ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::SetPartName( const string& sName)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Imposto il nome sul pezzo corrente
return m_BtlGeom.SetPartName( sName) ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::SetPartCount( int nCount)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Imposto il numero delle parti da produrre sul pezzo corrente
return m_BtlGeom.SetPartCount( nCount) ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::SetPartBox( double dLength, double dHeight, double dWidth, bool bUpdate)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Imposto le dimensioni sul pezzo corrente
if ( ! m_BtlGeom.AddPartBox( dLength, dHeight, dWidth))
return false ;
// Eventuale aggiornamento nomi facce e lato di carico
UpdateFacesName() ;
UpdateLoadingSide() ;
// Se richiesto, aggiorno Outline e cancello Solido
if ( bUpdate) {
m_BtlGeom.UpdateOutLine() ;
m_BtlGeom.ResetPartSolid() ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::GetSideData( int nSide, Frame3d& frRef, double& dLength, double& dWidth, double& dHeight)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Verifico validità identificativo di faccia
if ( nSide < BTL_SIDE_FRONT || nSide > BTL_SIDE_RIGHT)
return false ;
// Recupero riferimento del pezzo corrente
int nPartId = m_BtlGeom.GetCurrPartId() ;
Frame3d frPart ;
if ( ! m_pGDB->GetGroupGlobFrame( nPartId, frPart))
return false ;
// Recupero i dati
frRef = m_BtlGeom.GetSideFrame( nSide) ;
frRef.ToGlob( frPart) ;
dLength = m_BtlGeom.GetSideLength( nSide) ;
dWidth = m_BtlGeom.GetSideWidth( nSide) ;
dHeight = m_BtlGeom.GetSideHeight( nSide) ;
return true ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::ShowFacesName( bool bShow)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Verifico esistenza del pezzo corrente
int nPartId = m_BtlGeom.GetCurrPartId() ;
if ( nPartId == GDB_ID_NULL)
return false ;
// Verifico esistenza del gruppo nomi facce
int nFcsNameLayId = m_pGDB->GetFirstNameInGroup( nPartId, FCSNAME_LAYER_NAME) ;
// Se da visualizzare e non esiste il gruppo
if ( bShow && nFcsNameLayId == GDB_ID_NULL) {
// Creazione del gruppo
nFcsNameLayId = m_pGDB->AddGroup( GDB_ID_NULL, nPartId, GLOB_FRM) ;
m_pGDB->SetLevel( nFcsNameLayId, GDB_LV_TEMP) ;
m_pGDB->SetName( nFcsNameLayId, FCSNAME_LAYER_NAME) ;
m_pGDB->SetMaterial( nFcsNameLayId, NAVY) ;
// Scrittura del nome delle facce come testi del layer ausiliario
for ( int nS = BTL_SIDE_FRONT ; nS <= BTL_SIDE_RIGHT ; ++ nS) {
string sFace ;
if ( nS == BTL_SIDE_LEFT)
sFace = "o" ;
else if ( nS == BTL_SIDE_RIGHT)
sFace = "+" ;
else
sFace = "F" + ToString( nS) ;
PtrOwner<IExtText> pText( CreateExtText()) ;
if ( IsNull( pText))
return false ;
double dSLen = m_BtlGeom.GetSideLength( nS) ;
double dSWid = m_BtlGeom.GetSideWidth( nS) ;
Point3d ptPos( 0.5 * dSLen, ( m_BtlGeom.IsTrueSide( nS) ? 10 : 0.5 * dSWid), 1) ;
Vector3d vtDir = ( nS != BTL_SIDE_RIGHT ? X_AX : -X_AX) ;
int nInsPos = ( m_BtlGeom.IsTrueSide( nS) ? ETXT_IPBC : ETXT_IPMC) ;
double dPLen = m_BtlGeom.GetCurrPartLength() ;
double dPHei = m_BtlGeom.GetCurrPartHeight() ;
double dPWid = m_BtlGeom.GetCurrPartWidth() ;
double dCoeff = ( abs( dPHei - dPWid) / abs( dPHei + dPWid) < 0.51 ? 0.1 : 0.2) ;
double dTextHeight = dCoeff * min( { dPLen, dPHei, dPWid}) ;
if ( ! pText->Set( ptPos, Z_AX, vtDir, sFace, "Arial", 100, false, 2 * dTextHeight, 1, 0, nInsPos))
return false ;
// porto il testo nel piano della faccia
Frame3d frRef = m_BtlGeom.GetSideFrame( nS) ;
pText->ToGlob( frRef) ;
// recupero eventuale nome già presente
int nOldTextId = m_pGDB->GetFirstNameInGroup( nFcsNameLayId, sFace) ;
// se gia presente, lo rimpiazzo
if ( nOldTextId != GDB_ID_NULL) {
if ( ! m_pGDB->ReplaceGeoObj( nOldTextId, Release( pText)))
return false ;
}
// altrimenti, lo inserisco
else {
int nTextId = m_pGDB->AddGeoObj( GDB_ID_NULL, nFcsNameLayId, Release( pText)) ;
if ( nTextId == GDB_ID_NULL)
return false ;
// assegno nome
m_pGDB->SetName( nTextId, sFace) ;
}
}
}
// se altrimenti da eliminare ed esiste
else if ( ! bShow && nFcsNameLayId != GDB_ID_NULL) {
m_pGDB->Erase( nFcsNameLayId) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::UpdateFacesName( void)
{
int nFcsNameLayId = m_pGDB->GetFirstNameInGroup( m_BtlGeom.GetCurrPartId(), FCSNAME_LAYER_NAME) ;
if ( nFcsNameLayId == GDB_ID_NULL)
return true ;
m_pGDB->Erase( nFcsNameLayId) ;
return ShowFacesName( true) ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::ShowLoadingSide( bool bShow, bool bFromLeft)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Verifico esistenza del pezzo corrente
int nPartId = m_BtlGeom.GetCurrPartId() ;
if ( nPartId == GDB_ID_NULL)
return false ;
// Verifico esistenza del gruppo temporaneo lato di carico
int nLsideGrpId = m_pGDB->GetFirstNameInGroup( GDB_ID_ROOT, LOADINGSIDE_GROUP_NAME) ;
// Se da visualizzare e non esiste il gruppo
if ( bShow && nLsideGrpId == GDB_ID_NULL) {
// Creazione del gruppo
nLsideGrpId = m_pGDB->AddGroup( GDB_ID_NULL, GDB_ID_ROOT, GLOB_FRM) ;
m_pGDB->SetLevel( nLsideGrpId, GDB_LV_TEMP) ;
m_pGDB->SetName( nLsideGrpId, LOADINGSIDE_GROUP_NAME) ;
m_pGDB->SetMaterial( nLsideGrpId, NAVY) ;
m_pGDB->SetInfo( nLsideGrpId, IKEY_LSIDE, bFromLeft) ;
// Recupero dati del pezzo
Frame3d frPart ;
if ( ! m_pGDB->GetGroupGlobFrame( nPartId, frPart))
return false ;
BBox3d b3Part( 0, 0, 0, m_BtlGeom.GetCurrPartLength(), m_BtlGeom.GetCurrPartHeight(), m_BtlGeom.GetCurrPartWidth()) ;
b3Part.ToGlob( frPart) ;
// Disegno della freccia
PolyLine PL ;
PL.AddUPoint( 0, Point3d( 140, 0, 0)) ;
PL.AddUPoint( 0, Point3d( 100, -40, 0)) ;
PL.AddUPoint( 0, Point3d( 100, -20, 0)) ;
PL.AddUPoint( 0, Point3d( 0, -20, 0)) ;
PL.AddUPoint( 0, Point3d( 0, 20, 0)) ;
PL.AddUPoint( 0, Point3d( 100, 20, 0)) ;
PL.AddUPoint( 0, Point3d( 100, 40, 0)) ;
PL.AddUPoint( 0, Point3d( 140, 0, 0)) ;
Vector3d vtMove = b3Part.GetMin() + ( b3Part.GetDimX() + 50) * X_AX + b3Part.GetDimY() / 2 * Y_AX - ORIG ;
PL.Translate( vtMove) ;
PtrOwner<ISurfTriMesh> pStm( CreateSurfTriMesh()) ;
if ( IsNull( pStm) || ! pStm->CreateByFlatContour( PL))
return false ;
int nStmId = m_pGDB->AddGeoObj( GDB_ID_NULL, nLsideGrpId, Release( pStm)) ;
if ( nStmId == GDB_ID_NULL)
return false ;
}
// se altrimenti da eliminare ed esiste
else if ( ! bShow && nLsideGrpId != GDB_ID_NULL) {
m_pGDB->Erase( nLsideGrpId) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::UpdateLoadingSide( void)
{
int nLsideGrpId = m_pGDB->GetFirstNameInGroup( GDB_ID_ROOT, LOADINGSIDE_GROUP_NAME) ;
if ( nLsideGrpId == GDB_ID_NULL)
return true ;
bool bFromLeft = true ;
m_pGDB->GetInfo( nLsideGrpId, IKEY_LSIDE, bFromLeft) ;
m_pGDB->Erase( nLsideGrpId) ;
return ShowLoadingSide( true, bFromLeft) ;
}
//----------------------------------------------------------------------------
int
BeamMgr::AddProcess( int nGroup, int nProc, int nSide, const string& sDes, int nProcId,
const Frame3d& frRef, const DBLVECTOR& vdPar, const string& sPar, const STRVECTOR& vsUAtt,
int nCrvId, int nCrv2Id, bool bUpdate)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return GDB_ID_NULL ;
// Recupero i dati di default della feature
INTVECTOR vnDPar ;
int nSPar ;
DBLVECTOR vdBtlPar ;
string sBtlPar ;
if ( ! m_BtlGeom.GetProcessParamInfos( nGroup, nProc, nSide, vnDPar, nSPar, vdBtlPar, sBtlPar))
return GDB_ID_NULL ;
// Imposto i dati della feature
for ( int i = 0 ; i < int( vnDPar.size()) ; ++ i) {
int j = vnDPar[i] ;
if ( j > 0 && j - 1 < int( vdPar.size()))
vdBtlPar[i] = vdPar[j-1] ;
}
sBtlPar = sPar ;
// Gestione speciale per FreeContour
if ( nProc == 250) {
if ( ! m_BtlGeom.AddOneFreeContour( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, vdBtlPar, vsUAtt, nCrvId, nCrv2Id))
return GDB_ID_NULL ;
}
// gestione speciale per Outline
else if ( nProc == 251) {
if ( ! m_BtlGeom.AddPartOutline( nSide, nCrvId, vdBtlPar, vsUAtt))
return GDB_ID_NULL ;
}
// gestione speciale per Aperture
else if ( nProc == 252) {
if ( ! m_BtlGeom.AddPartAperture( nSide, nCrvId, vdBtlPar, vsUAtt))
return GDB_ID_NULL ;
}
// altrimenti Add standard
else {
if ( ! m_BtlGeom.AddProcess( nGroup, nProc, nSide, sDes, nProcId, frRef, vnDPar, nSPar, vdBtlPar, sBtlPar, vsUAtt, 0))
return GDB_ID_NULL ;
}
// Se richiesto, aggiorno Outline e cancello Solido
if ( bUpdate) {
m_BtlGeom.UpdateOutLine() ;
m_BtlGeom.ResetPartSolid() ;
}
// ritorno Id
return m_BtlGeom.GetLastProcessId() ;
}
//----------------------------------------------------------------------------
int
BeamMgr::ModifyProcess( int nGeomId, int nGroup, int nProc, int nSide, const string& sDes, int nProcId,
const Frame3d& frRef, const DBLVECTOR& vdPar, const string& sPar, const STRVECTOR& vsUAtt,
int nCrvId, int nCrv2Id, bool bUpdate)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return GDB_ID_NULL ;
// Recupero il pezzo di appartenenza
int nLayId = m_pGDB->GetParentId( nGeomId) ;
int nPartId = m_pGDB->GetParentId( nLayId) ;
// accetto feature normali e Outline/Aperture
if ( ! m_BtlGeom.SetPart( nPartId) || ( m_BtlGeom.GetCurrProcsLayId() != nLayId && m_BtlGeom.GetCurrOutsLayId() != nLayId))
return GDB_ID_NULL ;
// Aggiungo il nuovo processo modificato
int nNewId = AddProcess( nGroup, nProc, nSide, sDes, nProcId, frRef, vdPar, sPar, vsUAtt, nCrvId, nCrv2Id, false) ;
if ( nNewId == GDB_ID_NULL)
return GDB_ID_NULL ;
// Sposto le geometrie inserite appena sopra le vecchie (mantenendo l'ordine relativo nel gruppo)
INTVECTOR vIds = { nNewId} ;
if ( m_pGDB->ExistsInfo( nNewId, IKEY_AUXID)) {
INTVECTOR vAux ;
m_pGDB->GetInfo( nNewId, IKEY_AUXID, vAux) ;
for ( auto nAux : vAux)
vIds.emplace_back( nNewId + nAux) ;
}
if ( m_pGDB->ExistsInfo( nNewId, IKEY_ADJID)) {
INTVECTOR vAdj ;
m_pGDB->GetInfo( nNewId, IKEY_ADJID, vAdj) ;
for ( auto nAdj : vAdj) {
// aggiunto
vIds.emplace_back( nNewId + nAdj) ;
// eventuali ausiliari dell'aggiunto
if ( m_pGDB->ExistsInfo( nNewId + nAdj, IKEY_AUXID)) {
INTVECTOR vAux ;
m_pGDB->GetInfo( nNewId + nAdj, IKEY_AUXID, vAux) ;
for ( auto nAux : vAux)
vIds.emplace_back( nNewId + nAdj + nAux) ;
}
}
}
sort( vIds.begin(), vIds.end()) ;
for ( auto nId : vIds)
m_pGDB->Relocate( nId, nGeomId, GDB_BEFORE) ;
// Cancello il vecchio processo
EraseProcess( nGeomId, bUpdate) ;
// Restituisco nuovo Id
return nNewId ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::EraseProcess( int nGeomId, bool bUpdate)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Recupero il pezzo di appartenenza
int nLayId = m_pGDB->GetParentId( nGeomId) ;
int nPartId = m_pGDB->GetParentId( nLayId) ;
// accetto feature normali e Outline/Aperture
if ( ! m_BtlGeom.SetPart( nPartId) || ( m_BtlGeom.GetCurrProcsLayId() != nLayId && m_BtlGeom.GetCurrOutsLayId() != nLayId))
return false ;
// Cancello eventuali geometrie aggiuntive
INTVECTOR vAdj ;
if ( m_pGDB->GetInfo( nGeomId, IKEY_ADJID, vAdj) && ! vAdj.empty()) {
for ( auto nAdj : vAdj)
EraseProcess( nGeomId + nAdj, false) ;
}
// Cancello eventuali geometrie ausiliarie
INTVECTOR vAux ;
if ( m_pGDB->GetInfo( nGeomId, IKEY_AUXID, vAux) && ! vAux.empty()) {
for ( auto nAux : vAux)
m_pGDB->Erase( nGeomId + nAux) ;
}
// Cancello eventuali geometrie originali
INTVECTOR vOrig ;
if ( m_pGDB->GetInfo( nGeomId, IKEY_ORIGID, vOrig) && ! vOrig.empty()) {
for ( auto nOrig : vOrig) {
INTVECTOR vAux ;
if ( m_pGDB->GetInfo( nOrig, IKEY_AUXID, vAux) && ! vAux.empty()) {
for ( auto nAux : vAux)
m_pGDB->Erase( nOrig + nAux) ;
}
m_pGDB->Erase( nGeomId + nOrig) ;
}
}
m_pGDB->Erase( nGeomId) ;
// Se richiesto, aggiorno Outline e cancello Solido
if ( bUpdate) {
m_BtlGeom.UpdateOutLine() ;
m_BtlGeom.ResetPartSolid() ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
MyEnableProcess( IGeomDB* pGDB, BtlGeom& BtlG, int nGeomId, bool bEnable)
{
// Recupero lo stato corrente
bool bDo = true ;
pGDB->GetInfo( nGeomId, IKEY_DO, bDo) ;
// Se lo stato non cambia, esco
if ( bEnable == bDo)
return true ;
// Imposto il nuovo stato e il colore
if ( bEnable)
pGDB->RemoveInfo( nGeomId, IKEY_DO) ;
else
pGDB->SetInfo( nGeomId, IKEY_DO, 0) ;
return BtlG.SetProcessColor( nGeomId, bEnable) ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::EnableProcess( int nGeomId, bool bEnable, bool bUpdate)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Recupero il pezzo di appartenenza
int nLayId = m_pGDB->GetParentId( nGeomId) ;
int nPartId = m_pGDB->GetParentId( nLayId) ;
if ( ! m_BtlGeom.SetPart( nPartId) ||
( m_BtlGeom.GetCurrOutsLayId() != nLayId && m_BtlGeom.GetCurrProcsLayId() != nLayId))
return false ;
// Aggiorno il processo
MyEnableProcess( m_pGDB, m_BtlGeom, nGeomId, bEnable) ;
// Aggiorno eventuali geometrie aggiuntive
INTVECTOR vAdj ;
if ( m_pGDB->GetInfo( nGeomId, IKEY_ADJID, vAdj) && ! vAdj.empty()) {
for ( auto nAdj : vAdj)
MyEnableProcess( m_pGDB, m_BtlGeom, nGeomId + nAdj, bEnable) ;
}
// Aggiorno eventuali geometrie originali
INTVECTOR vOrig ;
if ( m_pGDB->GetInfo( nGeomId, IKEY_ORIGID, vOrig) && ! vOrig.empty()) {
for ( auto nOrig : vOrig) {
MyEnableProcess( m_pGDB, m_BtlGeom, nGeomId + nOrig, bEnable) ;
}
}
// Se richiesto, aggiorno Outline e cancello Solido
if ( bUpdate) {
m_BtlGeom.UpdateOutLine() ;
m_BtlGeom.ResetPartSolid() ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::CalcAllSolids( bool bShow, bool bRecalc, pcfProcEvents pFun)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Recupero tutti i pezzi
INTVECTOR vPartId ;
int nPartId = m_pGDB->GetFirstGroupInGroup( GDB_ID_ROOT) ;
while ( nPartId != GDB_ID_NULL) {
int nLevel ;
if ( m_pGDB->GetLevel( nPartId, nLevel) && nLevel == GDB_LV_USER &&
m_pGDB->GetFirstNameInGroup( nPartId, BOX_LAYER_NAME) != GDB_ID_NULL) {
vPartId.push_back( nPartId) ;
// nascondo il layer del solido per non avere problemi con le visualizzazioni durante i calcoli in multithread
m_pGDB->SetStatus( m_pGDB->GetFirstNameInGroup( nPartId, SOLID_LAYER_NAME), GDB_ST_OFF) ;
}
nPartId = m_pGDB->GetNextGroup( nPartId) ;
}
// Calcolo i solidi
bool bOk = true ;
constexpr bool MULTITHREAD = true ;
if ( MULTITHREAD) {
int nPartCnt = int( vPartId.size()) ;
int nThreadMax = min( max( 1, int( thread::hardware_concurrency()) - 1), nPartCnt) ;
vector< future<bool>> vRes( nPartCnt) ;
INTVECTOR vInd( nThreadMax) ;
// lancio tutto quanto possibile
for ( int i = 0 ; i < nThreadMax ; ++ i) {
vInd[i] = i ;
vRes[vInd[i]] = async( launch::async, &BeamMgr::CalcSolid, this, vPartId[vInd[i]], bRecalc) ;
}
// attesa completamento e rilancio successivi (occupando sempre lo stesso numero di thread)
int nNext = nThreadMax ;
int nTerminated = 0 ;
while ( nTerminated < nPartCnt) {
for ( int i = 0 ; i < nThreadMax ; ++ i) {
if ( vInd[i] >= 0 && vRes[vInd[i]].valid() && vRes[vInd[i]].wait_for( chrono::microseconds{ 1}) == future_status::ready) {
++ nTerminated ;
if ( ! vRes[vInd[i]].get())
bOk = false ;
ShowSolid( vPartId[vInd[i]], bShow) ;
if ( pFun != nullptr)
pFun( ( 100 * nTerminated) / nPartCnt, -1) ;
if ( nNext < nPartCnt) {
vInd[i] = nNext ;
++ nNext ;
vRes[vInd[i]] = async( launch::async, &BeamMgr::CalcSolid, this, vPartId[vInd[i]], bRecalc) ;
}
else
vInd[i] = -1 ;
}
}
}
}
// non multithread solo per DEBUG
else {
int nPartCnt = int( vPartId.size()) ;
for ( int i = 0 ; i < nPartCnt ; ++ i) {
if ( ! CalcSolid( vPartId[i], bRecalc))
bOk = false ;
ShowSolid( vPartId[i], bShow) ;
if ( pFun != nullptr)
pFun( ( 100 * ( i + 1)) / nPartCnt, -1) ;
}
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::ShowAllSolids( bool bShow, pcfProcEvents pFun)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Recupero tutti i pezzi
INTVECTOR vPartId ;
int nPartId = m_pGDB->GetFirstGroupInGroup( GDB_ID_ROOT) ;
while ( nPartId != GDB_ID_NULL) {
int nLevel ;
if ( m_pGDB->GetLevel( nPartId, nLevel) && nLevel == GDB_LV_USER &&
m_pGDB->GetFirstNameInGroup( nPartId, BOX_LAYER_NAME) != GDB_ID_NULL)
vPartId.push_back( nPartId) ;
nPartId = m_pGDB->GetNextGroup( nPartId) ;
}
// Aggiorno visualizzazione dei solidi
bool bOk = true ;
int nPartCnt = int( vPartId.size()) ;
for ( int i = 0 ; i < nPartCnt ; ++ i) {
if ( ! ShowSolid( vPartId[i], bShow))
bOk = false ;
if ( pFun != nullptr)
pFun( ( 100 * ( i + 1)) / nPartCnt, -1) ;
}
return bOk ;
}
//----------------------------------------------------------------------------
static ISurfTriMesh*
RegularizeTriMesh( const ISurfTriMesh* pStm, double dStep)
{
// verifico la superficie
if ( pStm == nullptr)
return nullptr ;
// solo per superfici trimesh con poche facce (max4)
int nFacetCnt = pStm->GetFacetCount() ;
if ( nFacetCnt > 4)
return nullptr ;
// box della superficie
BBox3d b3Surf ;
pStm->GetLocalBBox( b3Surf, BBF_STANDARD) ;
if ( b3Surf.IsEmpty() || ( b3Surf.GetMax().x - b3Surf.GetMin().x) < 2 * dStep)
return nullptr ;
// recupero le facce e le divido in X
double dXmin = b3Surf.GetMin().x - 1 ;
double dXmax = b3Surf.GetMax().x + 1 ;
int nStep = int( floor( ( dXmax - dXmin) / dStep + 0.9)) ;
dStep = ( dXmax - dXmin) / nStep ;
PtrOwner<ISurfTriMesh> pStmNew ;
for ( int nF = 0 ; nF < nFacetCnt ; ++ nF) {
// copio la faccia
PtrOwner<ISurfTriMesh> pFac( pStm->CloneFacet( nF)) ;
if ( IsNull( pFac))
return nullptr ;
BBox3d b3Fac ;
pFac->GetLocalBBox( b3Fac, BBF_STANDARD) ;
// la taglio a fette
double dX2 = dXmin ;
for ( int nI = 1 ; nI <= nStep ; ++ nI) {
double dX1 = dX2 ;
dX2 = dX2 + dStep ;
if ( b3Fac.GetMin().x < dX2 && b3Fac.GetMax().x > dX1) {
// eseguo taglio
Plane3d plMin ; plMin.Set( Point3d( dX1, 0, 0), -X_AX) ;
pFac->Cut( plMin, true) ;
Plane3d plMax ; plMax.Set( Point3d( dX2, 0, 0), X_AX) ;
pFac->Cut( plMax, false) ;
// recupero il nuovo contorno
POLYLINEVECTOR vPL ;
pFac->GetFacetLoops( 0, vPL) ;
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
if ( IsNull( pCrvCompo) || vPL.size() == 0 || ! pCrvCompo->FromPolyLine( vPL[0]))
return nullptr ;
// lo compatto
pCrvCompo->MergeCurves( EPS_SMALL, ANG_RIGHT / 6, true) ;
// creo la nuova faccia
PtrOwner<ISurfTriMesh> pStmTmp( GetSurfTriMeshByFlatContour( pCrvCompo, EPS_SMALL)) ;
if ( IsNull( pStmTmp))
return nullptr ;
if ( IsNull( pStmNew))
pStmNew.Set( pStmTmp) ;
else
pStmNew->DoSewing( *pStmTmp) ;
// recupero una nuova copia della faccetta originale
pFac.Set( pStm->CloneFacet( nF)) ;
if ( IsNull( pFac))
return nullptr ;
}
}
}
return Release( pStmNew) ;
}
//----------------------------------------------------------------------------
static bool
IntersectOneFeature( int nProcId, int nTrim, double dStep, IGeomDB* pGDB, ISurfTriMesh* pStm)
{
// recupero eventuale superficie originale
int nProcSurfId = nProcId ;
int nOrigId = 0 ;
if ( pGDB->GetInfo( nProcSurfId, IKEY_ORIGID, nOrigId))
nProcSurfId += nOrigId ;
// se da utilizzare anche superfici ausiliarie
if ( nTrim == 2) {
int nAux ;
if ( pGDB->GetInfo( nProcSurfId, IKEY_AUXID, nAux)) {
const ISurfTriMesh* pStmProc = GetSurfTriMesh( pGDB->GetGeoObj( nProcSurfId)) ;
const ISurfTriMesh* pAux = GetSurfTriMesh( pGDB->GetGeoObj( nProcSurfId + nAux)) ;
if ( pStmProc != nullptr && ! pStmProc->IsEmpty() && pAux != nullptr && ! pAux->IsEmpty()) {
PtrOwner<ISurfTriMesh> pTrim( pAux->Clone()) ;
if ( IsNull( pTrim) || ! pTrim->DoSewing( *pStmProc))
return false ;
PtrOwner<ISurfTriMesh> pStmTmp( RegularizeTriMesh( pTrim, dStep)) ;
const ISurfTriMesh* pStmTool = ( ! IsNull( pStmTmp) ? Get( pStmTmp) : Get( pTrim)) ;
if ( pStmTool == nullptr || ! pStm->Intersect( *pStmTool))
return false ;
}
}
}
// caso standard
else {
const ISurfTriMesh* pStmProc = GetSurfTriMesh( pGDB->GetGeoObj( nProcSurfId)) ;
if ( ! pStmProc->IsEmpty()) {
PtrOwner<ISurfTriMesh> pStmTmp( RegularizeTriMesh( pStmProc, dStep)) ;
if ( ! IsNull( pStmTmp))
pStmProc = Get( pStmTmp) ;
if ( pStmProc == nullptr || ! pStm->Intersect( *pStmProc))
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::CalcSolid( int nPartId, bool bRecalc)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Verifico esistenza del pezzo
if ( ! m_pGDB->ExistsObj( nPartId))
return false ;
// Recupero identificativo del Box
int nBoxId = m_pGDB->GetFirstNameInGroup( m_pGDB->GetFirstNameInGroup( nPartId, BOX_LAYER_NAME), BOX_BOX_NAME) ;
if ( nBoxId == GDB_ID_NULL)
return false ;
// Verifico esistenza del solido
int nSolLayId = m_pGDB->GetFirstNameInGroup( nPartId, SOLID_LAYER_NAME) ;
if ( nSolLayId == GDB_ID_NULL) {
nSolLayId = m_pGDB->AddGroup( GDB_ID_NULL, nPartId, GLOB_FRM) ;
m_pGDB->SetName( nSolLayId, SOLID_LAYER_NAME) ;
m_pGDB->SetMaterial( nSolLayId, Color(255, 160, 32)) ;
}
int nSolidId = m_pGDB->GetFirstNameInGroup( nSolLayId, SOLID_SOLID_NAME) ;
if ( ! m_pGDB->ExistsInfo( nSolidId, IKEY_VALID))
bRecalc = true ;
const ISurfTriMesh* pOldStm = GetSurfTriMesh( m_pGDB->GetGeoObj( nSolidId)) ;
if ( pOldStm == nullptr || pOldStm->IsEmpty())
bRecalc = true ;
// Se non necessario ricalcolo, esco con successo
if ( ! bRecalc)
return true ;
// Calcolo il solido senza feature
BBox3d b3Box ;
m_pGDB->GetLocalBBox( nBoxId, b3Box, BBF_STANDARD) ;
Point3d ptMin ; double dDimX, dDimY, dDimZ ;
if ( ! b3Box.GetMinDim( ptMin, dDimX, dDimY, dDimZ))
return false ;
PtrOwner<ISurfTriMesh> pSTM( GetSurfTriMeshBox( dDimX, dDimY, dDimZ, false)) ;
if ( IsNull( pSTM))
return false ;
pSTM->Translate( ptMin - ORIG) ;
if ( nSolidId != GDB_ID_NULL) {
if ( ! m_pGDB->ReplaceGeoObj( nSolidId, Release( pSTM)))
return false ;
}
else {
nSolidId = m_pGDB->AddGeoObj( GDB_ID_NULL, nSolLayId, Release( pSTM)) ;
if ( nSolidId == GDB_ID_NULL)
return false ;
m_pGDB->SetName( nSolidId, SOLID_SOLID_NAME) ;
}
BBox3d b3Solid ;
m_pGDB->GetLocalBBox( nSolidId, b3Solid, BBF_STANDARD) ;
double dSolidDimY = b3Solid.GetMax().y - b3Solid.GetMin().y ;
double dSolidDimZ = b3Solid.GetMax().z - b3Solid.GetMin().z ;
double dStep = 1.23 * min( max( dSolidDimY, dSolidDimZ), 2 * min( dSolidDimY, dSolidDimZ)) ;
// Esecuzione intersezioni
ISurfTriMesh* pStm = GetSurfTriMesh( m_pGDB->GetGeoObj( nSolidId)) ;
if ( pStm == nullptr)
return false ;
// ciclo su outline e aperture
int nOutLayId = m_pGDB->GetFirstNameInGroup( nPartId, OUTLINE_LAYER_NAME) ;
int nOutId = m_pGDB->GetFirstInGroup( nOutLayId) ;
while ( nOutId != GDB_ID_NULL) {
int nDO = 1 ;
m_pGDB->GetInfo( nOutId, IKEY_DO, nDO) ;
if ( nDO != 0 && m_pGDB->GetGeoType( nOutId) == SRF_TRIMESH) {
// sempre standard
const ISurfTriMesh* pStmOut = GetSurfTriMesh( m_pGDB->GetGeoObj( nOutId)) ;
if ( ! pStmOut->IsEmpty()) {
PtrOwner<ISurfTriMesh> pStmTmp( RegularizeTriMesh( pStmOut, dStep)) ;
if ( ! IsNull( pStmTmp))
pStmOut = Get( pStmTmp) ;
if ( pStmOut == nullptr || ! pStm->Intersect( *pStmOut))
return false ;
}
}
nOutId = m_pGDB->GetNext( nOutId) ;
}
// ciclo su feature troncanti (taglio di testa,..)
int nProcLayId = m_pGDB->GetFirstNameInGroup( nPartId, PROCESSINGS_LAYER_NAME) ;
INTVECTOR vUsedFea ;
int nProcId = m_pGDB->GetFirstInGroup( nProcLayId) ;
while ( nProcId != GDB_ID_NULL) {
int nDO = 1 ;
int nTrim = 1 ;
m_pGDB->GetInfo( nProcId, IKEY_DO, nDO) ;
m_pGDB->GetInfo( nProcId, IKEY_TRIM, nTrim) ;
if ( nDO != 0 && nTrim != 0 && m_pGDB->GetGeoType( nProcId) == SRF_TRIMESH) {
int nGroup = 0 ;
int nProc = 0 ;
m_pGDB->GetInfo( nProcId, IKEY_GROUP, nGroup) ;
m_pGDB->GetInfo( nProcId, IKEY_PROC, nProc) ;
if ( IS_CUT( nGroup, nProc) || IS_DOUBLE_CUT( nGroup, nProc) ||
IS_TENON( nGroup, nProc) || IS_DOVETAIL_TENON( nGroup, nProc)) {
if ( ! IntersectOneFeature( nProcId, nTrim, dStep, m_pGDB, pStm))
return false ;
vUsedFea.push_back( nProcId) ;
}
}
nProcId = m_pGDB->GetNext( nProcId) ;
}
// ciclo sulle altre features
nProcId = m_pGDB->GetFirstInGroup( nProcLayId) ;
while ( nProcId != GDB_ID_NULL) {
int nDO = 1 ;
int nTrim = 1 ;
m_pGDB->GetInfo( nProcId, IKEY_DO, nDO) ;
m_pGDB->GetInfo( nProcId, IKEY_TRIM, nTrim) ;
if ( find( vUsedFea.begin(), vUsedFea.end(), nProcId) == vUsedFea.end() &&
nDO != 0 && nTrim != 0 && m_pGDB->GetGeoType( nProcId) == SRF_TRIMESH) {
if ( ! IntersectOneFeature( nProcId, nTrim, dStep, m_pGDB, pStm))
return false ;
}
nProcId = m_pGDB->GetNext( nProcId) ;
}
// imposto visualizzazione spigoli
pStm->SetShowEdges( true) ;
// dichiaro calcolato il solido
m_pGDB->SetInfo( nSolidId, IKEY_VALID, 1) ;
return true ;
}
//----------------------------------------------------------------------------
int
BeamMgr::GetSolid( int nPartId) const
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Recupero layer del solido e Id del solido
int nSolLayId = m_pGDB->GetFirstNameInGroup( nPartId, SOLID_LAYER_NAME) ;
int nSolidId = m_pGDB->GetFirstNameInGroup( nSolLayId, SOLID_SOLID_NAME) ;
return nSolidId ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::ShowSolid( int nPartId, bool bShow)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// Verifico esistenza del pezzo
if ( ! m_pGDB->ExistsObj( nPartId))
return false ;
// visualizzo il solido e nascondo le geometrie complementari e viceversa
int nSolLayId = m_pGDB->GetFirstNameInGroup( nPartId, SOLID_LAYER_NAME) ;
m_pGDB->SetStatus( nSolLayId, ( bShow ? GDB_ST_ON : GDB_ST_OFF)) ;
int nBoxLayId = m_pGDB->GetFirstNameInGroup( nPartId, BOX_LAYER_NAME) ;
m_pGDB->SetStatus( nBoxLayId, ( bShow ? GDB_ST_OFF : GDB_ST_ON)) ;
int nOutlLayId = m_pGDB->GetFirstNameInGroup( nPartId, OUTLINE_LAYER_NAME) ;
m_pGDB->SetStatus( nOutlLayId, ( bShow ? GDB_ST_OFF : GDB_ST_ON)) ;
int nProcsLayId = m_pGDB->GetFirstNameInGroup( nPartId, PROCESSINGS_LAYER_NAME) ;
m_pGDB->SetStatus( nProcsLayId, ( bShow ? GDB_ST_OFF : GDB_ST_ON)) ;
int nFcsNameLayId = m_pGDB->GetFirstNameInGroup( nPartId, FCSNAME_LAYER_NAME) ;
m_pGDB->SetStatus( nFcsNameLayId, ( bShow ? GDB_ST_OFF : GDB_ST_ON)) ;
return true ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::GetBuildingIsOn( int nAssGrpId) const
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// se gruppo di assemblaggio indicato lo verifico
if ( nAssGrpId != GDB_ID_NULL) {
string sAssName ;
if ( ! m_pGDB->GetName( nAssGrpId, sAssName) || sAssName != ASSEMBLY_GROUP_NAME)
return false ;
}
// altrimenti cerco il primo gruppo di assemblaggio
else {
nAssGrpId = m_pGDB->GetFirstNameInGroup( GDB_ID_ROOT, ASSEMBLY_GROUP_NAME) ;
if ( nAssGrpId == GDB_ID_NULL)
return false ;
}
// recupero il primo oggetto nel gruppo
int nAssId = m_pGDB->GetFirstInGroup( nAssGrpId) ;
if ( nAssId == GDB_ID_NULL)
return false ;
// se contiene oggetti, assemblaggio è On
return ( m_pGDB->GetGroupObjs( nAssId) > 0) ;
}
//----------------------------------------------------------------------------
bool
BeamMgr::ShowBuilding( int nAssGrpId, bool bShow)
{
// Verifico validità GDB
if ( m_pGDB == nullptr)
return false ;
// se gruppo di assemblaggio indicato lo verifico
if ( nAssGrpId != GDB_ID_NULL) {
string sAssName ;
if ( ! m_pGDB->GetName( nAssGrpId, sAssName) || sAssName != ASSEMBLY_GROUP_NAME)
return false ;
}
// altrimenti cerco il primo gruppo di assemblaggio
else {
nAssGrpId = m_pGDB->GetFirstNameInGroup( GDB_ID_ROOT, ASSEMBLY_GROUP_NAME) ;
if ( nAssGrpId == GDB_ID_NULL)
return false ;
}
// ciclo sul gruppo di assemblaggio
int nAssId = m_pGDB->GetFirstInGroup( nAssGrpId) ;
while ( nAssId != GDB_ID_NULL) {
// recupero il successivo
int nNextId = m_pGDB->GetNext( nAssId) ;
// se richiesta visualizzazione assemblato
if ( bShow) {
// recupero il pezzo sorgente
int nSouId ;
if ( m_pGDB->GetInfo( nAssId, GDB_SI_SOURCE, nSouId)) {
m_pGDB->SetMode( nSouId, GDB_MD_STD) ;
m_pGDB->SetStatus( nSouId, GDB_ST_ON) ;
// se già utilizzato, ne faccio una copia
if ( m_pGDB->GetParentId( nSouId) != GDB_ID_ROOT) {
int nCopyId = m_pGDB->Copy( nSouId, GDB_ID_NULL, GDB_ID_ROOT) ;
if ( nCopyId != GDB_ID_NULL) {
m_pGDB->RemoveInfo( nCopyId, GDB_SI_BASE) ;
m_pGDB->RemoveInfo( nCopyId, GDB_SI_LIST) ;
m_pGDB->SetInfo( nCopyId, GDB_SI_COPY, nSouId) ;
nSouId = nCopyId ;
m_pGDB->SetInfo( nAssId, GDB_SI_SOURCE, nSouId) ;
}
}
m_pGDB->SetMode( m_pGDB->GetFirstNameInGroup( nSouId, BOX_LAYER_NAME), GDB_MD_HIDDEN) ;
m_pGDB->GroupSwap( nSouId, nAssId, true, true) ;
}
}
// altrimenti visualizzo insieme dei pezzi
else {
int nBaseId ;
if ( m_pGDB->GetInfo( nAssId, GDB_SI_BASE, nBaseId)) {
m_pGDB->GroupSwap( nAssId, nBaseId, true, true) ;
int nCopyId ;
if ( m_pGDB->GetInfo( nAssId, GDB_SI_COPY, nCopyId)) {
m_pGDB->Erase( nAssId) ;
m_pGDB->SetInfo( nBaseId, GDB_SI_SOURCE, nCopyId) ;
}
else {
m_pGDB->SetMode( m_pGDB->GetFirstNameInGroup( nAssId, BOX_LAYER_NAME), GDB_MD_STD) ;
}
}
}
// passo al successivo
nAssId = nNextId ;
}
// Nascondo o visualizzo tutti i pezzi sotto la radice
int nPartId = m_pGDB->GetFirstInGroup( GDB_ID_ROOT) ;
while ( nPartId != GDB_ID_NULL) {
int nLevel ;
if ( m_pGDB->GetLevel( nPartId, nLevel) && nLevel == GDB_LV_USER &&
m_pGDB->GetFirstNameInGroup( nPartId, BOX_LAYER_NAME) != GDB_ID_NULL)
m_pGDB->SetStatus( nPartId, ( bShow ? GDB_ST_OFF : GDB_ST_ON)) ;
nPartId = m_pGDB->GetNext( nPartId) ;
}
return true ;
}