Files
EgtExecutor/EXE_Trimming.cpp
T
Dario Sassi b1fcb75e4f EgtExecutor :
- aggiunte funzioni di striping per trimming dei termoformati
2026-01-04 20:39:53 +01:00

798 lines
34 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2025-2025
//----------------------------------------------------------------------------
// File : EXE_Trimming.cpp Data : 25.10.25 Versione : 2.7j3
// Funzioni per le lavorazioni di Trimming.
//
// Modifiche : 23.10.25 RE Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "EXE.h"
#include "EXE_Macro.h"
#include "DllExchange.h"
#include "GeoTools.h"
#include "AuxTools.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EXeExecutor.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Include/EGkSurfLocal.h"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkTrimming.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include <unordered_map>
#include <algorithm>
using namespace std ;
static string s_sKey_Sync_Coord = "KeyOldCoord" ;
static string s_sKey_Auto_Trim = "AutoTrim" ;
// ---------------------------------------------------------------------------
bool
ExeTrimmingAutoSearch( int nParentId, int nSurfLayerId, double dShapeLinTol, double dShapeAngTol,
double dLinTol, double dEdgeLinTol, double dAngTol, double dAngFaceTol,
const STRVECTOR& vsShapes)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Se non ho geometrie da ricercare, non faccio nulla
if ( vsShapes.empty())
return true ;
// Recupero le superfici presenti nel Layer
CISURFPVECTOR vSurfs ; vSurfs.reserve( pGeomDB->GetGroupObjs( nSurfLayerId)) ;
int nId = pGeomDB->GetFirstInGroup( nSurfLayerId) ;
while ( nId != GDB_ID_NULL) {
// Recupero l'entità
const IGeoObj* pGeoObj = pGeomDB->GetGeoObj( nId) ;
if ( pGeoObj != nullptr) {
// Recupero il Tipo
int nType = pGeoObj->GetType() ;
if ( nType == SRF_TRIMESH || nType == SRF_BEZIER) {
// Recupero la superficie
const ISurf* pSurf = GetSurf( pGeoObj) ;
if ( pSurf != nullptr && pSurf->IsValid())
vSurfs.emplace_back( pSurf) ;
}
}
nId = pGeomDB->GetNext( nId) ;
}
// Se non ho superfici non faccio nulla
if ( vSurfs.empty())
return false ;
// Recupero Le Superfici Selezionate, Le Curve e Le Bezier rigate
ISURFPOMATRIX matSelSurfMatrix ;
ICRVCOMPOPOMATRIX matCompoBorders ;
ISURFBEZPOVECTOR vSurfBz ;
bool bOk = GetTrimmingAutoEntities( vSurfs, dShapeLinTol, dShapeAngTol, dLinTol, dEdgeLinTol, dAngTol, dAngFaceTol, vsShapes,
matSelSurfMatrix, matCompoBorders, vSurfBz) ;
// Per sicurezza verifico che tutte le entità siano a dimensione corretta
bOk = bOk && ( ssize( matSelSurfMatrix) == ssize( matCompoBorders)) &&
( ssize( matSelSurfMatrix) == ssize( vSurfBz)) ;
// Per ogni Entità ricavata inserisco le Geometrie nel Layer
// NB. Ordine di Inserimento : Surf -> Edges -> bezier
// Una anomalia nella serie blocca il flusso corrente e passa al successivo
int nCount = -1 ;
for ( int i = 0 ; bOk && i < int( matSelSurfMatrix.size()) ; ++ i) {
// Verifico che la Superficie sia Valida
bool bOkEntity = true ;
for ( int j = 0 ; bOkEntity && j < ssize( matSelSurfMatrix[i]) ; ++ j)
bOkEntity = ( ! IsNull( matSelSurfMatrix[i][j]) && matSelSurfMatrix[i][j]->IsValid()) ;
if ( ! bOkEntity)
continue ; // anomalia serie livello superfici di selezione
for ( int j = 0 ; bOk && j < ssize( matSelSurfMatrix[i]) ; ++ j) {
int nSurfId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( matSelSurfMatrix[i][j])) ;
bOk = ( ( nSurfId != GDB_ID_NULL) &&
( pGeomDB->SetInfo( nSurfId, s_sKey_Auto_Trim, ToString( ++ nCount)))) ;
}
if ( ! bOk)
break ; // anomalia bloccante
// Verifico che Le Curve di Edges ( Bezier ) siano Valide
for ( int j = 0 ; bOkEntity && j < ssize( matCompoBorders[i]) ; ++ j)
bOkEntity = ( ! IsNull( matCompoBorders[i][j]) && matCompoBorders[i][j]->IsValid()) ;
if ( ! bOkEntity)
continue ; // anomalia serie livello curve di bordo
for ( int j = 0 ; bOk && j < ssize( matCompoBorders[i]) ; ++ j) {
int nCrvId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( matCompoBorders[i][j])) ;
bOk = ( ( nCrvId != GDB_ID_NULL) &&
( pGeomDB->SetInfo( nCrvId, s_sKey_Auto_Trim, ToString( nCount)))) ;
}
if ( ! bOk)
break ; // anomalia bloccante
// Verifico che le Superfici di Bezier rigate siano Valide
bOkEntity = ( ! IsNull( vSurfBz[i]) && vSurfBz[i]->IsValid()) ;
if ( ! bOkEntity)
continue ; // anomalia seria livello Bezier Rigata
int nBzId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vSurfBz[i])) ;
bOk = ( ( nBzId != GDB_ID_NULL) &&
( pGeomDB->SetInfo( nBzId, s_sKey_Auto_Trim, ToString( nCount)))) ;
if ( ! bOk)
break ; // anomali bloccante
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingAutoSearch(" + ToString( nParentId) + "," +
ToString( nSurfLayerId) + "," +
ToString( dShapeLinTol) + "," +
ToString( dShapeAngTol) + "," +
ToString( dLinTol) + "," +
ToString( dEdgeLinTol) + "," +
ToString( dAngTol) + "," +
ToString( dAngFaceTol) + "," +
ToString( vsShapes) + ")" +
" -- bOk=" + ToString( bOk) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
// ---------------------------------------------------------------------------
bool
ExeTrimmingGetSurfTmFaceAdj( int nSurfId, const INTVECTOR& vTria, const PNTVECTOR& vPts,
double dAngTol, double dSize, double dSizeTol, INTVECTOR& vOtherFaces)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Recupero la superficie TriMesh
const ISurfTriMesh* pStm = GetSurfTriMesh( pGeomDB->GetGeoObj( nSurfId)) ;
bool bOk = ( pStm != nullptr && pStm->IsValid()) ;
// Verifico che le facce appartengano alla superficie
bOk = bOk && ( ! vTria.empty()) ;
// Recupero l'insieme dei triangoli
if ( bOk) {
INTVECTOR vOtherTria ; vOtherTria.reserve( pStm->GetTriangleCount()) ;
bOk = GetTrimmingStmAdjTria( pStm, vTria, vPts, dAngTol, dSize, dSizeTol, vOtherTria) ;
// Per ogni triangolo ricavato, recupero la faccia corrispondente
set<int> setFaces ;
for ( const int& nT : vOtherTria)
setFaces.insert( pStm->GetFacetFromTria( nT)) ;
vOtherFaces.assign( setFaces.begin(), setFaces.end()) ;
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingGetSurfTmFromFaceAdj(" + ToString( nSurfId) + "," +
ToString( vTria) + "," +
ToString( dAngTol) + ")" +
" -- bOk=" + ToString( bOk) + "vOtherFaces=" + ToString( vOtherFaces) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
// ---------------------------------------------------------------------------
int
ExeTrimmingGetSurfTmFromStmFaces( int nParentId, int nSurfId, const INTVECTOR& vFaces)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
if ( ! pGeomDB->GetGlobFrame( nParentId, frDest))
return GDB_ID_NULL ;
// Recupero la superficie TriMesh
const ISurfTriMesh* pStm = GetSurfTriMesh( pGeomDB->GetGeoObj( nSurfId)) ;
if ( pStm == nullptr || ! pStm->IsValid())
return GDB_ID_NULL ;
// Verifico che le facce appartengano alla superficie
if ( vFaces.empty())
return CMD_ID_NULL ;
for ( int nF = 0 ; nF < int( vFaces.size()) ; ++ nF) {
double dArea = 0. ;
if ( ! pStm->GetFacetArea( vFaces[nF], dArea))
return GDB_ID_NULL ;
}
// Definisco la superficie
StmFromTriangleSoup TriaSoup ;
TriaSoup.Start() ;
for ( int nF = 0 ; nF < int( vFaces.size()) ; ++ nF) {
INTVECTOR vT ;
if ( ! pStm->GetAllTriaInFacet( vFaces[nF], vT))
return GDB_ID_NULL ;
for ( int nT = 0 ; nT < int( vT.size()) ; ++ nT) {
Triangle3d Tria ;
if ( ! pStm->GetTriangle( vT[nT], Tria) || ! TriaSoup.AddTriangle( Tria))
return GDB_ID_NULL ;
}
}
TriaSoup.End() ;
PtrOwner<ISurfTriMesh> pStmTria( TriaSoup.GetSurf()) ;
if ( IsNull( pStmTria) || ! pStmTria->IsValid() || pStmTria->GetTriangleCount() == 0)
return GDB_ID_NULL ;
// Aggiungo la superficie al DB
int nNewSurfId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pStmTria)) ;
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "TrimmingGetSurfTmFromStmFaces(" + ToString( nParentId) + "," +
ToString( nSurfId) + "," +
ToString( vFaces) + ")" +
" -- nId=" + ToString( nNewSurfId) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return nNewSurfId ;
}
// ---------------------------------------------------------------------------
bool
ExeTrimmingGetAdjSurfs( const INTVECTOR& vSurfId, const INTVECTOR& vOtherSurfId, double dLinTol,
double dAngTol, double dAngFaceTol, INTVECTOR& vResId)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Recupero le superfici di Riferimento
CISURFPVECTOR vRefSurf ; vRefSurf.reserve( vSurfId.size()) ;
bool bOk = true ;
for ( int i = 0 ; bOk && i < int( vSurfId.size()) ; ++ i) {
const ISurf* pSurf = GetSurf( pGeomDB->GetGeoObj( vSurfId[i])) ;
bOk = ( pSurf != nullptr && pSurf->IsValid()) ;
vRefSurf.emplace_back( pSurf) ;
}
// Recupero le superfici complessive, escludendo eventualmente quelle di riferimento se presenti
CISURFPVECTOR vOtherSurf ; vOtherSurf.reserve( vOtherSurfId.size()) ;
INTVECTOR vIds ;
for ( int i = 0 ; bOk && i < int( vOtherSurfId.size()) ; ++ i) {
if ( find( vSurfId.begin(), vSurfId.end(), vOtherSurfId[i]) == vSurfId.end()) {
const ISurf* pSurf = GetSurf( pGeomDB->GetGeoObj( vOtherSurfId[i])) ;
bOk = ( pSurf != nullptr && pSurf->IsValid()) ;
vOtherSurf.emplace_back( pSurf) ;
vIds.push_back( vOtherSurfId[i]) ;
}
}
// Recupero le facce adiancenti nella tolleranza richiesta
INTVECTOR vMyInds ;
bOk = bOk && GetTrimmingAdjSurfs( vRefSurf, vOtherSurf, dLinTol, dAngTol, dAngFaceTol, vMyInds) ;
if ( bOk) {
for ( const int& myInd : vMyInds)
vResId.push_back( vIds[myInd]) ;
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingGetAdjSurf(" + ToString( vSurfId) + "," +
ToString( vOtherSurfId) + "," +
ToString( dAngTol) + ")" +
" -- bOk=" + ToString( bOk) + ",vResId=" + ToString( vResId) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
// ---------------------------------------------------------------------------
bool
ExeTrimmingGetBorders( int nParentId, const SELVECTOR& vIds, double dLinTol, double dAngTol,
int& nFirstId, int& nCount)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Parametri da restituire
nFirstId = GDB_ID_NULL ;
nCount = 0 ;
// vIds : vettore di { nId = SurfId, nSubId = nSurfFace }
// Controllo che vIds non sia vuoto
bool bOk = ( ! vIds.empty()) ;
// Recupero il riferimento della prima superficie
Frame3d frSurf ;
bOk = bOk && pGeomDB->GetGlobFrame( vIds[0].nId, frSurf) ;
// Recupero il riferimento dei gruppi di destinazione
Frame3d frDest ;
bOk = bOk && pGeomDB->GetGlobFrame( nParentId, frDest) ;
// Recupero gli Id univoci delle superfici selezionate
INTSET setUniqueId ;
for ( const SelData& nIds : vIds)
setUniqueId.insert( nIds.nId) ;
// Recupero le superfici e le porto tutte in locale alla prima
unordered_map<int, int> uMapPos ; uMapPos.reserve( setUniqueId.size()) ;
SURFLOCALVECTOR vSurfL ; vSurfL.reserve( setUniqueId.size()) ;
CISURFPVECTOR vpSurf ; vpSurf.reserve( setUniqueId.size()) ;
int nSurf = 0 ;
for ( auto nIter = setUniqueId.begin() ; bOk && nIter != setUniqueId.end() ; ++ nIter) {
vSurfL.emplace_back( pGeomDB, *nIter, frSurf) ;
bOk = ( vSurfL.back().Get() != nullptr) ;
vpSurf.emplace_back( vSurfL.back().Get()) ;
uMapPos[*nIter] = nSurf ;
++ nSurf ;
}
// Recupero il vettore di Selezione associato non più agli Id delle superficie ma alle loro posizioni nel vettore
vector<SelData> vFaces ; vFaces.reserve( vIds.size()) ;
for ( int i = 0 ; bOk && i < int( vIds.size()) ; ++ i)
vFaces.emplace_back( uMapPos[vIds[i].nId], vIds[i].nSub) ;
// Calcolo le curve di Edge grezze ( quindi i tratti lineari)
ICRVCOMPOPOVECTOR vRawEdges ;
bOk = bOk && GetTrimmingRawEdges( vpSurf, vFaces, dLinTol, dAngTol, vRawEdges) &&
( ! vRawEdges.empty()) ;
// Calcolo le curve di Edge approssimate mediante curve di Bezier
ICRVCOMPOPOVECTOR vBezierEdges ;
bOk = bOk && GetTrimmingBezierEdges( vRawEdges, dLinTol, dAngTol, vBezierEdges) ;
nCount = int( vBezierEdges.size()) ;
if ( bOk) {
// Scorro i gli Edges ottenuti
for ( int nCrv = 0 ; bOk && nCrv < nCount ; ++ nCrv) {
vBezierEdges[nCrv]->ToLoc( frDest) ;
// Inserisco la curva nel DB Geometrico
int nCurrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vBezierEdges[nCrv])) ;
bOk = ( nCurrId != GDB_ID_NULL) ;
if ( nCrv == 0)
nFirstId = nCurrId ;
}
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingGetBorders(" + IdToString( nParentId) + "," +
ToString( dLinTol) + "," +
ToString( dAngTol) + ")" ;
sLua += " -- bOk=" + ToString( bOk) +
" -- FirstId=" + ToString( nFirstId) + " CurveCount=" + ToString( nCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
// ---------------------------------------------------------------------------
bool
ExeTrimmingGetBordersByNormals( int nParentId, const SELVECTOR& vIds, double dLinTol,
double dAngTol, double dThick, Point3d& ptNear, int& nFirstId, int& nCount)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Parametri da restituire
nFirstId = GDB_ID_NULL ;
nCount = 0 ;
// vIds : vettore di { nId = SurfId, nSubId = nSurfFace }
// Controllo che vIds non sia vuoto
bool bOk = ( ! vIds.empty()) ;
// Recupero il riferimento della prima superficie
Frame3d frSurf ;
bOk = bOk && pGeomDB->GetGlobFrame( vIds[0].nId, frSurf) ;
// Recupero il riferimento dei gruppi di destinazione
Frame3d frDest ;
bOk = bOk && pGeomDB->GetGlobFrame( nParentId, frDest) ;
// Recupero gli Id univoci delle superfici selezionate
INTSET setUniqueId ;
for ( const SelData& nIds : vIds)
setUniqueId.insert( nIds.nId) ;
// Recupero le superfici e le porto tutte in locale alla prima
unordered_map<int, int> uMapPos ; uMapPos.reserve( setUniqueId.size()) ;
SURFLOCALVECTOR vSurfL ; vSurfL.reserve( setUniqueId.size()) ;
CISURFPVECTOR vpSurf ; vpSurf.reserve( setUniqueId.size()) ;
int nSurf = 0 ;
for ( auto nIter = setUniqueId.begin() ; bOk && nIter != setUniqueId.end() ; ++ nIter) {
vSurfL.emplace_back( pGeomDB, *nIter, frSurf) ;
bOk = ( vSurfL.back().Get() != nullptr) ;
vpSurf.emplace_back( vSurfL.back().Get()) ;
uMapPos[*nIter] = nSurf ;
++ nSurf ;
}
// Recupero il vettore di Selezione associato non più agli Id delle superficie ma alle loro posizioni nel vettore
vector<SelData> vFaces ; vFaces.reserve( vIds.size()) ;
for ( int i = 0 ; bOk && i < int( vIds.size()) ; ++ i)
vFaces.emplace_back( uMapPos[vIds[i].nId], vIds[i].nSub) ;
// Calcolo le curve di Edge approssimate mediante curve di Bezier
ICRVCOMPOPOVECTOR vBezierEdges ;
bOk = bOk && GetTrimmingFinalBorders( vpSurf, vFaces, dLinTol, dAngTol, dThick, vBezierEdges) ;
if ( bOk) {
// Se non ho un punto di vicinanza, le inserisco tutte
if ( ! ptNear.IsValid()) {
nCount = int( vBezierEdges.size()) ;
// Scorro i gli Edges ottenuti
for ( int nCrv = 0 ; bOk && nCrv < nCount ; ++ nCrv) {
vBezierEdges[nCrv]->ToLoc( frDest) ;
// Inserisco la curva nel DB Geometrico
int nCurrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vBezierEdges[nCrv])) ;
bOk = ( nCurrId != GDB_ID_NULL) ;
if ( nCrv == 0)
nFirstId = nCurrId ;
}
}
// Se ho un punto di vicinanza, cerco la coppia di curve più vicina
else {
// Se solo una coppia di curve, le inserisco e non ho ambiguità
if ( int( vBezierEdges.size()) == 2) {
nCount = int( vBezierEdges.size()) ;
// Scorro gli Edges ottenuti
for ( int nCrv = 0 ; bOk && nCrv < nCount ; ++ nCrv) {
vBezierEdges[nCrv]->ToLoc( frDest) ;
// Inserisco la curva nel DB Geometrico
int nCurrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vBezierEdges[nCrv])) ;
bOk = ( nCurrId != GDB_ID_NULL) ;
if ( nCrv == 0)
nFirstId = nCurrId ;
}
}
// altrimenti cerco la coppia più vicia
else {
double dSqMinDist = INFINITO ;
int nInd = 0 ;
for ( int i = 0 ; i + 1 < int( vBezierEdges.size()) ; i = i + 2) {
double dSqDist = 0., dSqDist1 = 0. ;
if ( DistPointCurve( ptNear, *vBezierEdges[i]).GetSqDist( dSqDist) &&
DistPointCurve( ptNear, *vBezierEdges[i + 1]).GetSqDist( dSqDist1)) {
double dCurrMinSqDist = min( dSqDist, dSqDist1) ;
if ( dCurrMinSqDist < dSqMinDist) {
dSqMinDist = dCurrMinSqDist ;
nInd = i ;
}
}
}
vBezierEdges[nInd]->ToLoc( frDest) ;
vBezierEdges[nInd + 1]->ToLoc( frDest) ;
int nCurrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vBezierEdges[nInd])) ;
int nCurrId1 = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vBezierEdges[nInd + 1])) ;
bOk = ( nCurrId != GDB_ID_NULL && nCurrId1 != GDB_ID_NULL) ;
if ( bOk) {
nFirstId = nCurrId1 ;
nCount = 2 ;
}
}
}
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingGetBorders(" + IdToString( nParentId) + "," +
ToString( dLinTol) + "," +
ToString( dAngTol) + ")" ;
sLua += " -- bOk=" + ToString( bOk) +
" -- FirstId=" + ToString( nFirstId) + " CurveCount=" + ToString( nCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
// ---------------------------------------------------------------------------
bool
ExeTrimmingGetFinalBorders( int nParentId, const INTVECTOR& vCrvBezierId, double dLinTol, double dAngTol,
const PNTVECTOR& vBrkPts, double dThick, double dThickTol,
int& nFirstId, int& nCount)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Parametri da restituire
nFirstId = GDB_ID_NULL ;
nCount = 0 ;
// Recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
bool bOk = ( pGeomDB->GetGlobFrame( nParentId, frDest)) ;
// Recupero le curve di Bordo approssimate come Bezier
ICRVCOMPOPOVECTOR vCompoBezierEdges ; vCompoBezierEdges.reserve( vCrvBezierId.size()) ;
for ( int nCrv = 0 ; bOk && nCrv < int( vCrvBezierId.size()) ; ++ nCrv) {
const ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( vCrvBezierId[nCrv])) ;
bOk = ( pCrv != nullptr && pCrv->IsValid()) ;
if ( bOk) {
PtrOwner<ICurveComposite> pCompoRawEdges( ConvertCurveToComposite( pCrv->Clone())) ;
bOk = ( ! IsNull( pCompoRawEdges) && pCompoRawEdges->IsValid() &&
vCompoBezierEdges.emplace_back( Release( pCompoRawEdges))) ;
}
}
// Converto i punti in coppie di punti ( se dispari l'ultimo viene ignorato)
BIPNTVECTOR vBreakingPts ; vBreakingPts.reserve( int( int( vBrkPts.size()) / 2)) ;
for ( int nPt = 0 ; bOk && nPt < int( vBrkPts.size()) - 1 ; nPt += 2)
vBreakingPts.emplace_back( make_pair( vBrkPts[nPt], vBrkPts[nPt+1])) ;
if ( int( vBrkPts.size()) % 2 != 0)
LOG_INFO( GetCmdLogger(), "Warning in EgtExtractSurfFrChunkLoops : Odd number of breaking points") ;
// Calcolo le curve di Edge
bOk = bOk && GetTrimmingFinalBorders( vCompoBezierEdges, dLinTol, dAngTol, vBreakingPts, dThick, dThickTol) ;
nCount = int( vCompoBezierEdges.size()) ;
if ( bOk) {
// Scorro i gli Edges ottenuti
for ( int nCrv = 0 ; bOk && nCrv < nCount ; ++ nCrv) {
vCompoBezierEdges[nCrv]->ToLoc( frDest) ;
// Inserisco la curva nel DB Geometrico
int nCurrId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vCompoBezierEdges[nCrv])) ;
bOk = ( nCurrId != GDB_ID_NULL) ;
if ( nCrv == 0)
nFirstId = nCurrId ;
}
ExeSetModified() ;
}
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingGetFinalEdges(" + IdToString( nParentId) + "," +
ToString( vCrvBezierId) + "," +
ToString( dLinTol) + "," +
ToString( dAngTol) + "," ;
sLua += "{" ;
for ( int nP = 0 ; nP < int( vBrkPts.size()) ; ++ nP) {
sLua += "(" + ToString( vBrkPts[nP].x) + ", " + ToString( vBrkPts[nP].y) + ", " + ToString( vBrkPts[nP].z) + ")" +
( nP != int( vBrkPts.size()) - 1 ? "," : "") ;
}
sLua += "}" ;
sLua += ToString( dThick) + "," + ToString( dThickTol) + ")" ;
sLua += " -- bOk=" + ToString( bOk) +
" -- FirstId=" + ToString( nFirstId) + " CurveCount=" + ToString( nCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
// ---------------------------------------------------------------------------
int
ExeTrimmingGetRuledBezier( int nParentId, const INTVECTOR& vIds, int nEdge1Id, int nEdge2Id, double dLinTol,
const INTVECTOR& vnLineId)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Aggiusto la tolleranza lineare se necessario
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
// Recupero il riferimento dei gruppi di destinazione
Frame3d frDest ;
bool bOk = pGeomDB->GetGlobFrame( nParentId, frDest) ;
// Recupero la prima curva
const ICurve* pCrvEdge1 = GetCurve( pGeomDB->GetGeoObj( nEdge1Id)) ;
bOk = bOk && ( pCrvEdge1 != nullptr && pCrvEdge1->IsValid()) ;
// Recupero la seconda curva
const ICurve* pCrvEdge2 = GetCurve( pGeomDB->GetGeoObj( nEdge2Id)) ;
bOk = bOk && ( pCrvEdge2 != nullptr && pCrvEdge2->IsValid()) ;
// Se ci sono delle superfici di riferimento
CISURFPVECTOR vpSurf ; vpSurf.reserve( vIds.size()) ;
if ( ! vIds.empty()) {
SURFLOCALVECTOR vSurfL ; vSurfL.reserve( vIds.size()) ;
// Recupero il riferimento della prima superficie
Frame3d frSurf ;
bOk = bOk && ( pGeomDB->GetGlobFrame( vIds[0], frSurf)) ;
// Porto le altre nel riferimento della prima
for ( int nSurf = 0 ; bOk && nSurf < int( vIds.size()) ; ++ nSurf) {
vSurfL.emplace_back( pGeomDB, vIds[nSurf], frSurf) ;
if ( vSurfL.back().Get() == nullptr) {
bOk = false ;
break ;
}
vpSurf.emplace_back( vSurfL.back().Get()) ;
}
}
// Recupero i punti di sincronizzazione ( se presenti)
BIPNTVECTOR vSyncPoints ; vSyncPoints.reserve( pGeomDB->GetGroupObjs( vnLineId.size())) ;
INTVECTOR vIndPriority ; vIndPriority.reserve( vSyncPoints.size()) ;
INTVECTOR vIndVisible ; vIndVisible.reserve( vSyncPoints.size()) ;
for ( int i = 0 ; bOk && i < int( vnLineId.size()) ; ++ i) {
// Recupero la Curva
const ICurve* pLine = GetCurve( pGeomDB->GetGeoObj( vnLineId[i])) ;
bOk = bOk && ( pLine != nullptr && pLine->IsValid()) ;
if ( bOk) {
Point3d ptStart ; pLine->GetStartPoint( ptStart) ;
Point3d ptEnd ; pLine->GetEndPoint( ptEnd) ;
vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
// Verifico se la linea è visibile all'utente
int nStatus = GDB_ST_OFF ;
if ( pGeomDB->GetStatus( vnLineId[i], nStatus) && nStatus == GDB_ST_ON)
vIndVisible.emplace_back( int( vSyncPoints.size() - 1)) ;
// Verifico mediante le Info se la curva è stata modificata o aggiunta ( quindi prioritaria)
DBLVECTOR vdOldCoor ; vdOldCoor.reserve( 6) ;
if ( ! pGeomDB->GetInfo( vnLineId[i], s_sKey_Sync_Coord, vdOldCoor) ||
int( vdOldCoor.size()) != 6 ||
! AreSamePointApprox( ptStart, Point3d( vdOldCoor[0], vdOldCoor[1], vdOldCoor[2])) ||
! AreSamePointApprox( ptEnd, Point3d( vdOldCoor[3], vdOldCoor[4], vdOldCoor[5])))
vIndPriority.emplace_back( int( vSyncPoints.size()) - 1) ;
}
}
// Recupero la superficie Bezier rigata
PtrOwner<ISurfBezier> pSurfBzRuled ;
if ( bOk) {
pSurfBzRuled.Set( GetTrimmingRuledBezier( vpSurf, pCrvEdge1, pCrvEdge2, dMyLinTol, vSyncPoints, vIndPriority, vIndVisible)) ;
bOk = bOk && ( ! IsNull( pSurfBzRuled) && pSurfBzRuled->IsValid()) ;
}
// Inserisco la curva nel DB Geometrico
int nSurfBzId = GDB_ID_NULL ;
if ( bOk) {
pSurfBzRuled->ToLoc( frDest) ;
nSurfBzId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pSurfBzRuled)) ;
bOk = bOk && ( nSurfBzId != GDB_ID_NULL) ;
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingGetRuledBezier(" + ToString( nParentId) + "," +
ToString( vIds) + "," +
ToString( nEdge1Id) + "," +
ToString( nEdge2Id) + "," +
ToString( dLinTol) + ")" +
" -- bOk=" + ToString( bOk) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
// Restituisco il risultato
return nSurfBzId ;
}
// ---------------------------------------------------------------------------
bool
ExeTrimmingGetSurfBzSyncPoints( int nParentId, int nEdge1Id, int nEdge2Id, double dLinTol,
int& nFirstId, int& nCount)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Se necessario aggiusto le tolleranze
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
// Recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
bool bOk = ( pGeomDB->GetGlobFrame( nParentId, frDest)) ;
// Recupero le due Curve di bordo
const ICurve* pCrvEdge1 = GetCurve( pGeomDB->GetGeoObj( nEdge1Id)) ;
const ICurve* pCrvEdge2 = GetCurve( pGeomDB->GetGeoObj( nEdge2Id)) ;
bOk = bOk && ( pCrvEdge1 != nullptr && pCrvEdge1->IsValid() &&
pCrvEdge2 != nullptr && pCrvEdge2->IsValid()) ;
// Recupero i punti di sincronizzazione
BIPNTVECTOR vSyncPoints ;
bOk = bOk && GetTrimmingSurfBzSyncPoints( pCrvEdge1, pCrvEdge2, dMyLinTol, vSyncPoints) &&
( ! vSyncPoints.empty()) ;
nCount = int( vSyncPoints.size()) ;
// Inserisco i tratti di sincronizzazione nel DB Geometrico
for ( int nL = 0 ; nL < int( vSyncPoints.size()) ; ++ nL) {
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
if ( ! IsNull( pLine) && pLine->Set( vSyncPoints[nL].first, vSyncPoints[nL].second)) {
int nLineId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ;
if ( nLineId != GDB_ID_NULL) {
if ( nL == 0)
nFirstId = nLineId ;
// Memorizzo come Info le coordinate dei punti ( per tenere traccia in futuro di modifiche)
DBLVECTOR vdCoordInfo = { vSyncPoints[nL].first.x, vSyncPoints[nL].first.y, vSyncPoints[nL].first.z,
vSyncPoints[nL].second.x, vSyncPoints[nL].second.y, vSyncPoints[nL].second.z} ;
pGeomDB->SetInfo( nLineId, s_sKey_Sync_Coord, vdCoordInfo) ;
}
}
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingGetSurfBzSyncPoints(" + ToString( nParentId) + "," +
ToString( nEdge1Id) + "," +
ToString( nEdge2Id) + "," +
ToString( dLinTol) + "," +
ToString( nFirstId) + "," +
ToString( nCount) + ")" +
" -- bOk=" + ToString( bOk) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
ExeTrimmingSkimSyncPoints( int nEdge1Id, int nEdge2Id, const INTVECTOR& vnLineId, double dLinTol,
double dAngTol, int nMaxInvLine)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Se necessario aggiusto le tolleranze
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
double dMyAngTol = Clamp( dAngTol, 1., 45.) ;
int nMyMaxInvLine = Clamp( nMaxInvLine, 1, 100) ;
// Recupero le due Curve di bordo
const ICurve* pCrvEdge1 = GetCurve( pGeomDB->GetGeoObj( nEdge1Id)) ;
const ICurve* pCrvEdge2 = GetCurve( pGeomDB->GetGeoObj( nEdge2Id)) ;
bool bOk = ( pCrvEdge1 != nullptr && pCrvEdge1->IsValid() && pCrvEdge2 != nullptr && pCrvEdge2->IsValid()) ;
// Definisco il vettore degli Estremi
BIPNTVECTOR vSyncPoints ; vSyncPoints.reserve( vnLineId.size()) ;
for ( int i = 0 ; bOk && i < int( vnLineId.size()) ; ++ i) {
const ICurve* pLine = GetCurve( pGeomDB->GetGeoObj( vnLineId[i])) ;
bOk = ( pLine != nullptr && pLine->IsValid()) ;
if ( bOk) {
Point3d ptStart, ptEnd ;
bOk = ( pLine->GetStartPoint( ptStart) && pLine->GetEndPoint( ptEnd)) ;
if ( bOk)
vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
}
}
// Scelta di Selezione delle linee di sincronizzazione
// 1) In presenza di Spigoli, vengono sempre visualizzate ( Spigolo definito da tolleranza angolare)
// 2) 1 Curva su 'nMyMaxInvLine' viene mostrata altrimenti
int nInvisibleCount = 0 ;
for ( int nL = 0 ; bOk && nL < int( vSyncPoints.size()) ; ++ nL) {
bool bVisible = false ;
Point3d ptUseless = P_INVALID ;
// Recupero gli Estremi e controllo se sono su uno spigolo tra una delle due curve
double dUS = 0. ;
bOk = bOk && pCrvEdge1->GetParamAtPoint( vSyncPoints[nL].first, dUS, dMyLinTol) ;
if ( bOk) {
Vector3d vtPrev, vtAft ;
bOk = pCrvEdge1->GetPointD1D2( dUS, ICurve::FROM_MINUS, ptUseless, &vtPrev) &&
pCrvEdge1->GetPointD1D2( dUS, ICurve::FROM_PLUS, ptUseless, &vtAft) ;
if ( bOk) {
vtPrev.Normalize() ; vtAft.Normalize() ;
bVisible = ( vtPrev * vtAft < cos( ( dMyAngTol + EPS_ANG_SMALL) * DEGTORAD)) ;
if ( ! bVisible) {
double dUE = 0. ;
bOk = bOk && pCrvEdge2->GetParamAtPoint( vSyncPoints[nL].second, dUE, dMyLinTol) ;
bOk = pCrvEdge2->GetPointD1D2( dUE, ICurve::FROM_MINUS, ptUseless, &vtPrev) &&
pCrvEdge2->GetPointD1D2( dUE, ICurve::FROM_PLUS, ptUseless, &vtAft) ;
if ( bOk) {
vtPrev.Normalize() ; vtAft.Normalize() ;
bVisible = ( vtPrev * vtAft < cos( ( dMyAngTol + EPS_ANG_SMALL) * DEGTORAD)) ;
}
}
}
if ( bOk) {
// Imposto lo Stato
if ( ! bVisible)
++ nInvisibleCount ;
if ( nInvisibleCount == nMyMaxInvLine) {
bVisible = true ;
nInvisibleCount = 0 ;
}
pGeomDB->SetStatus( vnLineId[nL], bVisible ? GDB_ST_ON : GDB_ST_OFF) ;
}
}
}
return bOk ;
}