11c47c4394
- in Trimming semplificazione delle funzioni per le curve di sincronizzazione.
815 lines
34 KiB
C++
815 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_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, false)
|
|
|
|
// 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 ;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
int
|
|
ExeTrimmingGetSurfTmFaceAdj( int nParentId, int nSurfId, const INTVECTOR& vTria, const PNTVECTOR& vPts,
|
|
double dAngTol, double dSize, double dSizeTol)
|
|
{
|
|
// Verifica database geometrico
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// 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 la superficie formata dai triangoli di adiacenza
|
|
int nNewSurfId = GDB_ID_NULL ;
|
|
if ( bOk) {
|
|
PtrOwner<ISurfTriMesh> pStmAdjFace( CreateSurfTriMesh()) ;
|
|
bOk = ( ! IsNull( pStmAdjFace) && pStmAdjFace->AdjustTopology()) ;
|
|
bOk = GetTrimmingStmAdjTria( pStm, vTria, vPts, dAngTol, dSize, dSizeTol, pStmAdjFace) ;
|
|
bOk = ( ! IsNull( pStmAdjFace) && pStmAdjFace->IsValid() && pStmAdjFace->GetTriangleCount() > 0) ;
|
|
// Inserisco la Superficie nel DB geometrico
|
|
if ( bOk) {
|
|
nNewSurfId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pStmAdjFace)) ;
|
|
bOk = ( nNewSurfId != GDB_ID_NULL) ;
|
|
}
|
|
}
|
|
|
|
ExeSetModified() ;
|
|
// Se richiesto, salvo il comando Lua equivalente
|
|
if ( IsCmdLog()) {
|
|
string sLua = "EgtTrimmingGetSurfTmFromFaceAdj(" + ToString( nParentId) + "," +
|
|
ToString( nSurfId) + "," +
|
|
ToString( vTria) + "," +
|
|
ToString( dAngTol) + ")" +
|
|
" nNewSurfId=" + ToString( nNewSurfId) ;
|
|
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
|
|
}
|
|
|
|
return nNewSurfId ;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
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, false)
|
|
|
|
// 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 = "EgtTrimmingGetAdjSurfs(" + 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, false)
|
|
|
|
// 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
|
|
SELVECTOR 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, false)
|
|
|
|
// 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
|
|
SELVECTOR 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 = "EgtTrimmingGetBordersByNormals(" + 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, false)
|
|
|
|
// 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 = "EgtTrimmingGetFinalBorders(" + 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())) ;
|
|
for ( int i = 0 ; bOk && i < ssize( vnLineId) ; ++ i) {
|
|
// Recupero la Curva
|
|
const ICurve* pLine = GetCurve( pGeomDB->GetGeoObj( vnLineId[i])) ;
|
|
bOk = bOk && ( pLine != nullptr && pLine->IsValid()) ;
|
|
if ( bOk) {
|
|
// Recupero gli Estremi
|
|
Point3d ptStart ; pLine->GetStartPoint( ptStart) ;
|
|
Point3d ptEnd ; pLine->GetEndPoint( ptEnd) ;
|
|
// Mi assicuro che gli estremi siano sulle curve di Bordo e orientati correttamente ( nel caso inverto)
|
|
double dSqDistS1 = INFINITO ;
|
|
if ( ! DistPointCurve( ptStart, *pCrvEdge1).GetSqDist( dSqDistS1))
|
|
continue ;
|
|
if ( dSqDistS1 < dLinTol * dLinTol) {
|
|
double dSqDistE2 = INFINITO ;
|
|
if ( ! DistPointCurve( ptEnd, *pCrvEdge2).GetSqDist( dSqDistE2) ||
|
|
dSqDistE2 > dLinTol * dLinTol)
|
|
continue ;
|
|
}
|
|
else {
|
|
double dSqDistS2 = INFINITO ;
|
|
if ( ! DistPointCurve( ptStart, *pCrvEdge2).GetSqDist( dSqDistS2) ||
|
|
dSqDistS2 > dLinTol * dLinTol)
|
|
continue ;
|
|
double dSqDistE1 = INFINITO ;
|
|
if ( ! DistPointCurve( ptEnd, *pCrvEdge1).GetSqDist( dSqDistE1) ||
|
|
dSqDistE1 > dLinTol * dLinTol)
|
|
continue ;
|
|
swap( ptStart, ptEnd) ;
|
|
}
|
|
vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
|
|
}
|
|
}
|
|
|
|
// Recupero la superficie Bezier rigata
|
|
PtrOwner<ISurfBezier> pSurfBzRuled ;
|
|
if ( bOk) {
|
|
pSurfBzRuled.Set( GetTrimmingRuledBezier( vpSurf, pCrvEdge1, pCrvEdge2, dMyLinTol, vSyncPoints)) ;
|
|
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,
|
|
double dAngTol, int nLineNbr, bool bShowOnCorners,
|
|
int& nFirstId, int& nCount)
|
|
{
|
|
// Verifica database geometrico
|
|
IGeomDB* pGeomDB = GetCurrGeomDB() ;
|
|
VERIFY_GEOMDB( pGeomDB, false)
|
|
|
|
// Imposto i parametri di ritorno
|
|
nFirstId = GDB_ID_NULL ;
|
|
nCount = 0 ;
|
|
|
|
// Se non devo visualizzare alcuna linea, non faccio nulla
|
|
if ( nLineNbr <= 0 && ! bShowOnCorners)
|
|
return true ;
|
|
|
|
// Se necessario aggiusto le tolleranze
|
|
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
|
|
double dMyAngTol = Clamp( dAngTol, EPS_ANG_SMALL, ANG_RIGHT) ;
|
|
|
|
// 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()) ;
|
|
int nToTSyncLines = ssize( vSyncPoints) ;
|
|
|
|
if ( bOk) {
|
|
// Se devo visualizzarne più di quante sono, allora le visualizzo tutte
|
|
if ( nLineNbr >= nToTSyncLines) {
|
|
for ( int nL = 0 ; bOk && nL < nToTSyncLines ; ++ nL) {
|
|
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
|
bOk = ( ! IsNull( pLine) && pLine->Set( vSyncPoints[nL].first, vSyncPoints[nL].second)) ;
|
|
if ( bOk) {
|
|
int nLineId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ;
|
|
bOk = ( nLineId != GDB_ID_NULL) ;
|
|
if ( bOk && nL == 0)
|
|
nFirstId = nLineId ;
|
|
}
|
|
}
|
|
nCount = nToTSyncLines ;
|
|
}
|
|
// Altrimenti devo scremare le curve
|
|
else {
|
|
// Se voglio visualizzare i Corner
|
|
INTSET setInds ;
|
|
if ( bShowOnCorners) {
|
|
for ( int nL = 0 ; bOk && nL < nToTSyncLines ; ++ nL) {
|
|
// Controllo se su uno spigolo della curva
|
|
double dU = 0. ;
|
|
Vector3d vtTanPrev, vtTanAft ;
|
|
Point3d ptUseless ;
|
|
bOk = ( pCrvEdge1->GetParamAtPoint( vSyncPoints[nL].first, dU, dMyLinTol) &&
|
|
pCrvEdge1->GetPointD1D2( dU, ICurve::FROM_MINUS, ptUseless, &vtTanPrev) &&
|
|
pCrvEdge1->GetPointD1D2( dU, ICurve::FROM_PLUS, ptUseless, &vtTanAft)) ;
|
|
if ( ! bOk)
|
|
break ;
|
|
vtTanPrev.Normalize() ;
|
|
vtTanAft.Normalize() ;
|
|
if ( vtTanPrev * vtTanAft < cos( ( dMyAngTol + EPS_ANG_SMALL) * DEGTORAD)) {
|
|
setInds.insert( nL) ;
|
|
continue ;
|
|
}
|
|
bOk = ( pCrvEdge2->GetParamAtPoint( vSyncPoints[nL].second, dU, dMyLinTol) &&
|
|
pCrvEdge2->GetPointD1D2( dU, ICurve::FROM_MINUS, ptUseless, &vtTanPrev) &&
|
|
pCrvEdge2->GetPointD1D2( dU, ICurve::FROM_PLUS, ptUseless, &vtTanAft)) ;
|
|
if ( ! bOk)
|
|
break ;
|
|
vtTanPrev.Normalize() ;
|
|
vtTanAft.Normalize() ;
|
|
if ( vtTanPrev * vtTanAft < cos( ( dMyAngTol + EPS_ANG_SMALL) * DEGTORAD)) {
|
|
setInds.insert( nL) ;
|
|
continue ;
|
|
}
|
|
}
|
|
}
|
|
// Se devo mostrare alcune Linee -> Algoritmo di Pick_Bresenham
|
|
if ( bOk && nLineNbr > 0) {
|
|
if ( nLineNbr == 1)
|
|
setInds.insert( 0) ;
|
|
else {
|
|
int nDx = nToTSyncLines - 1 ;
|
|
int nDy = nLineNbr - 1 ;
|
|
int nErr = 0 ;
|
|
int nX = 0 ;
|
|
for ( int i = 0 ; i <= nDy ; ++ i) {
|
|
setInds.insert( nX) ;
|
|
nErr += nDx ;
|
|
while ( nErr >= nDy) {
|
|
nX += 1 ;
|
|
nErr -= nDy ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Visualizzo i segmenti lineare di sincronizzazione per ogni indice ricavato
|
|
bool bFirst = true ;
|
|
for ( auto Iter = setInds.begin() ; bOk && Iter != setInds.end() ; ++ Iter) {
|
|
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
|
bOk = ( ! IsNull( pLine) && pLine->Set( vSyncPoints[*Iter].first, vSyncPoints[*Iter].second)) ;
|
|
if ( bOk) {
|
|
int nLineId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ;
|
|
bOk = ( nLineId != GDB_ID_NULL) ;
|
|
if ( bFirst) {
|
|
nFirstId = nLineId ;
|
|
bFirst = false ;
|
|
}
|
|
++ nCount ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 ;
|
|
}
|