Files
EgtExecutor/EXE_Trimming.cpp
T
Daniele Bariletti 56973037ab EgtExecutor :
- piccole correzioni e migliorie a trimming.
2026-05-19 15:35:25 +02:00

1446 lines
64 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/EGkGeoVector3d.h"
#include "/EgtDev/Include/EGkCurveAux.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 "/EgtDev/Include/EGkDistPointSurfBz.h"
#include "/EgtDev/Include/EGkSbzFromCurves.h"
#include <unordered_map>
#include <algorithm>
using namespace std ;
// ---------------------------------------------------------------------------
bool
ExeTrimmingGetHoleBorder( int nParentId, const INTVECTOR& vSurfIds, const INTVECTOR& vOtherSurfIds,
double dSurfLinTol, double dSurfAngTol, double dEdgeLinTol, double dEdgeAngTol,
double dEdgeThick, int& nFirstId, int& nCount)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// Inizializzo i valori di ritorno
nFirstId = GDB_ID_NULL ;
nCount = 0 ;
// Se non ho geometrie da ricercare, non faccio nulla
if ( vSurfIds.empty())
return true ;
// Recupero le superfici da cui estrarre i bordi
CISURFPVECTOR vpSurfs ; vpSurfs.reserve( vSurfIds.size()) ;
for ( int i = 0 ; i < ssize( vSurfIds) ; ++ i) {
int nSurfId = vSurfIds[i] ;
// Recupero l'entità
const IGeoObj* pGeoObj = pGeomDB->GetGeoObj( nSurfId) ;
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())
vpSurfs.emplace_back( pSurf) ;
}
}
}
// Se non ho superfici non faccio nulla
if ( vpSurfs.empty())
return false ;
// Calcolo il Centroide delle superfici complessive
Point3d ptRef = P_INVALID ;
if ( ! vOtherSurfIds.empty()) {
int nToTSurf = 0 ;
for ( int nOtherSurfId : vOtherSurfIds) {
// Recupero l'entità
const IGeoObj* pGeoObj = pGeomDB->GetGeoObj( nOtherSurfId) ;
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()) {
// Recupero il Centroide
Point3d ptCentroid ;
pSurf->GetCentroid( ptCentroid) ;
if ( ! ptRef.IsValid())
ptRef = ptCentroid ;
else
ptRef += ptCentroid ;
++ nToTSurf ;
}
}
}
}
if ( nToTSurf > 0) {
for ( const ISurf* pSurf : vpSurfs) {
Point3d ptCentroid ;
pSurf->GetCentroid( ptCentroid) ;
if ( ! ptRef.IsValid())
ptRef = ptCentroid ;
else
ptRef += ptCentroid ;
++ nToTSurf ;
}
ptRef /= nToTSurf ;
}
}
// Recupero i Bordi per fori ed asole
ICRVCOMPOPOVECTOR vHoleBorders ;
bool bOk = GetTrimmingHoleBorders( vpSurfs, ptRef, dSurfLinTol, dSurfAngTol, dEdgeLinTol, dEdgeAngTol,
dEdgeThick, vHoleBorders) ;
if ( bOk) {
// Inserisco le curve nel DB e imposto i parametri di ritorno
bool bFirst = true ;
for ( int i = 0 ; bOk && i < ssize( vHoleBorders) ; ++ i) {
// Verifico che sia valida
if ( ! IsNull( vHoleBorders[i]) && vHoleBorders[i]->IsValid()) {
int nCrvId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( vHoleBorders[i])) ;
bOk = ( nCrvId != GDB_ID_NULL) ;
if ( bOk) {
++ nCount ;
if ( bFirst) {
nFirstId = nCrvId ;
bFirst = false ;
}
}
}
}
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingGetHoleBorder(" + ToString( nParentId) + "," +
ToString( vSurfIds) + "," +
ToString( dSurfLinTol) + "," +
ToString( dSurfAngTol) + "," +
ToString( dEdgeLinTol) + "," +
ToString( dEdgeAngTol) + "," +
ToString( dEdgeThick) + ")" +
" bOk=" + ToString( bOk) +
" nNewSurfId=" + ToString( nFirstId) + ", nCount= " + ToString( nCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
// ---------------------------------------------------------------------------
int
ExeTrimmingGetSurfTmFaceAdj( int nParentId, int nSurfId, int nTria, const Point3d& ptTria,
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()) ;
// 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, nTria, ptTria, 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( nTria) + "," +
"{ " + ToString( ptTria.x) + "," +
ToString( ptTria.y) + "," +
ToString( ptTria.z) + "}," +
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 ( 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 dSurfLinTol, double dSurfAngTol,
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, dSurfLinTol, dSurfAngTol, 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( dSurfLinTol) + "," +
ToString( dSurfAngTol) + "," +
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 dSurfLinTol,
double dSurfAngTol, double dLinTol, double dAngTol, double dThick,
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, dSurfLinTol, dSurfAngTol, dLinTol, dAngTol, dThick, vBezierEdges) ;
if ( bOk) {
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 ;
}
}
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
ExeTrimmingInterpolateSyncLines( int nParentId, int nSync1Id, int nSync2Id, int nBorder1Id,
int nBorder2Id, double dEdgeLinTol, double dEdgeAngTol,
int& nFirstId, int& nCount)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL)
// Reset parametri di ritorno
nFirstId = GDB_ID_NULL ;
nCount = 0 ;
// Aggiusto la tolleranza lineare e angolare se necessario
double dMyEdgeLinTol = Clamp( dEdgeLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
double dMyEdgeAngTol = Clamp( dEdgeAngTol, EPS_ANG_SMALL, 60.) ;
// recupero le due curve di sincronizzazione
const ICurve* pSync1 = GetCurve( pGeomDB->GetGeoObj( nSync1Id)) ;
const ICurve* pSync2 = GetCurve( pGeomDB->GetGeoObj( nSync2Id)) ;
bool bOk = ( pSync1 != nullptr && pSync1->IsValid() &&
pSync2 != nullptr && pSync2->IsValid()) ;
// Recupero le due curve di bordo
const ICurve* pCrvEdge1 = GetCurve( pGeomDB->GetGeoObj( nBorder1Id)) ;
const ICurve* pCrvEdge2 = GetCurve( pGeomDB->GetGeoObj( nBorder2Id)) ;
bOk = bOk && ( pCrvEdge1 != nullptr && pCrvEdge1->IsValid()) ;
bOk = bOk && ( pCrvEdge2 != nullptr && pCrvEdge2->IsValid()) ;
// Calcolo le Curve di sincornizzazione Interpolate
BIPNTVECTOR vSyncPoints ;
bOk = bOk && GetTrimmingSyncInterpolation( pCrvEdge1, pCrvEdge2, pSync1, pSync2, dMyEdgeLinTol,
dMyEdgeAngTol, vSyncPoints) ;
if ( bOk && ! vSyncPoints.empty()) {
// Inserisco le curve di sincronizzazione nel DB
// [orientate da pCrvEdge1 a pCrvEdge2]
for ( int i = 0 ; bOk && i < ssize( vSyncPoints) ; ++ i) {
PtrOwner<ICurveLine> pSyncLine( CreateCurveLine()) ;
bOk = ( ! IsNull( pSyncLine) && pSyncLine->Set( vSyncPoints[i].first, vSyncPoints[i].second)) ;
if ( bOk) {
if ( pCrvEdge1->IsPointOn( vSyncPoints[i].second, dMyEdgeLinTol))
pSyncLine->Invert() ;
int nSyncId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pSyncLine)) ;
bOk = ( nSyncId != CMD_ID_NULL) ;
if ( i == 0)
nFirstId = nSyncId ;
}
}
nCount = ssize( vSyncPoints) ;
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingInterpolateSyncLines(" + ToString( nParentId) + "," +
ToString( nSync1Id) + "," +
ToString( nSync2Id) + "," +
ToString( nBorder1Id) + "," +
ToString( nBorder2Id) + "," +
ToString( dEdgeLinTol) + "," +
ToString( dEdgeAngTol) + ")" +
" -- bOk=" + ToString( bOk) +
" -- nFirstId=" + ToString( nFirstId) + " nCount=" + ToString( nCount) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
// ---------------------------------------------------------------------------
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()) ;
// Verifico che le curve siano entrambe Aperte o entrambe Chiuse
bOk = bOk && ( pCrvEdge1->IsClosed() == pCrvEdge2->IsClosed()) ;
// Recupero i punti di sincronizzazione
BIPNTVECTOR vSyncPoints ;
bOk = bOk && GetTrimmingSurfBzSyncPoints( pCrvEdge1, pCrvEdge2, dMyLinTol, vSyncPoints) &&
( ! vSyncPoints.empty()) ;
int nToTSyncLines = ssize( vSyncPoints) ;
// Ogni punto di sincronizzazione deve avere gli estremi sulle curve di Bordo
for ( int i = 0 ; bOk && i < ssize( vSyncPoints) ; ++ i) {
double dSqDistStart = INFINITO, dSqDistEnd = INFINITO ;
bOk = ( DistPointCurve( vSyncPoints[i].first, *pCrvEdge1).GetSqDist( dSqDistStart) &&
dSqDistStart < dMyLinTol * dMyLinTol &&
DistPointCurve( vSyncPoints[i].second, *pCrvEdge2).GetSqDist( dSqDistEnd) &&
dSqDistEnd < dMyLinTol * dMyLinTol) ;
}
if ( bOk) {
INTSET setInds ;
// Se devo visualizzare più linee di quante ne ho ricavate, allora le devo visualizzare tutte
if ( nLineNbr >= nToTSyncLines) {
for ( int i = 0 ; i < nToTSyncLines ; ++ i)
setInds.insert( i) ;
}
// Altrimenti
else {
// Se voglio visualizzare gli Spigoli
if ( bShowOnCorners) {
for ( int nL = 0 ; bOk && nL < nToTSyncLines ; ++ nL) {
// Controllo se punto su 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
if ( bOk && nLineNbr > 0) {
bool bBothOpen = ( ! pCrvEdge1->IsClosed() && ! pCrvEdge2->IsClosed()) ;
bool bBothClosed = ( ! bBothOpen) ;
int nLastIdx = nToTSyncLines - 1 ;
if ( bBothClosed) {
int nLine = nLineNbr ;
if ( nLine == 1)
setInds.insert( 0) ;
else {
int nMaxIndex = nToTSyncLines - 2 ;
for ( int i = 0 ; i < nLine ; ++ i) {
double dT = double( i) / double( nLine) ;
int nIdx = int( 0.5 + dT * nMaxIndex) ;
setInds.insert( nIdx) ;
}
setInds.erase( nLastIdx) ;
}
}
else {
int nInternal = nLineNbr ;
setInds.insert( 0) ;
setInds.insert( nLastIdx) ;
int nMaxIndex = nLastIdx ;
for ( int i = 0; i < nInternal ; ++ i) {
double dT = double( i + 1) / double( nInternal + 1) ;
int nIdx = int( 0.5 + dT * nMaxIndex) ;
setInds.insert( nIdx) ;
}
}
}
}
// Visualizzo i segmenti lineari 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 ;
}
// ---------------------------------------------------------------------------
bool
ExeTrimmingGetToolOrientationLines( int nParentId, int nMainEdgeId, int nOtherEdgeId, int nSyncLayerId, int nLineSId, int nLineEId,
double dThetaStart, double dPhiStart, double dThetaEnd, double dPhiEnd, double dInterpLenS,
double dInterpLenE, double dLinTol,
int& nInterpStartId, int& nStartId, int& nEndId, int& nInterpEndId)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// Imposto i parametri di ritorno
nInterpStartId = GDB_ID_NULL, nStartId = GDB_ID_NULL, nEndId = GDB_ID_NULL, nInterpEndId = GDB_ID_NULL ;
// Se necessario aggiusto le tolleranze
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
const double TOL = dMyLinTol ;
// Definisco costanti per interpolazione
const double INTERPOLATION_DIST = 0.5 ; // alzare
const double ISO_PAR_SAMPLE = 20.0 ;
// Recupero il riferimento del gruppo di destinazione
Frame3d frDest ;
bool bOk = ( pGeomDB->GetGlobFrame( nParentId, frDest)) ;
// Recupero le due Curve di bordo
const ICurve* pCrvMainEdge = GetCurve( pGeomDB->GetGeoObj( nMainEdgeId)) ;
const ICurve* pCrvOtherEdge = GetCurve( pGeomDB->GetGeoObj( nOtherEdgeId)) ;
bOk = bOk && ( pCrvMainEdge != nullptr && pCrvMainEdge->IsValid() && pCrvOtherEdge != nullptr && pCrvOtherEdge->IsValid()) ;
// Verifico che le curve siano entrambe Aperte o entrambe Chiuse e memorizzo il risultato
bOk = bOk && ( pCrvMainEdge->IsClosed() == pCrvOtherEdge->IsClosed()) ;
bool bBorderClosed = ( pCrvMainEdge->IsClosed()) ;
// Recupero le Linee di Sincronizzazione iniziali e finali e verifico che giacciano sulle Curve di Bordo
PtrOwner<ICurve> pCrvSyncS( GetCurve( pGeomDB->GetGeoObj( nLineSId))->Clone()) ;
PtrOwner<ICurve> pCrvSyncE( GetCurve( pGeomDB->GetGeoObj( nLineEId))->Clone()) ;
bOk = bOk && ( pCrvSyncS != nullptr && pCrvSyncS->IsValid() && pCrvSyncE != nullptr && pCrvSyncE->IsValid()) ;
BIPOINT Line1, Line2 ;
bOk = bOk && ( pCrvSyncS->GetStartPoint( Line1.first)) && ( pCrvSyncS->GetEndPoint( Line1.second)) ;
bOk = bOk && ( pCrvSyncE->GetStartPoint( Line2.first)) && ( pCrvSyncE->GetEndPoint( Line2.second)) ;
// --- se necessario oriento le linee di Sync in modo che inizino entrambe dal Bordo Main
if ( bOk) {
if ( pCrvMainEdge->IsPointOn( Line1.first, TOL))
bOk = ( pCrvOtherEdge->IsPointOn( Line1.second, TOL)) ;
else if ( pCrvOtherEdge->IsPointOn( Line1.first, TOL)) {
bOk = ( pCrvMainEdge->IsPointOn( Line1.second, TOL)) ;
if ( bOk) {
swap( Line1.first, Line1.second) ;
pCrvSyncS->Invert() ;
}
}
else
bOk = false ;
}
if ( bOk) {
if ( pCrvMainEdge->IsPointOn( Line2.first, TOL))
bOk = ( pCrvOtherEdge->IsPointOn( Line2.second, TOL)) ;
else if ( pCrvOtherEdge->IsPointOn( Line2.first, TOL)) {
bOk = ( pCrvMainEdge->IsPointOn( Line2.second, TOL)) ;
if ( bOk) {
swap( Line2.first, Line2.second) ;
pCrvSyncE->Invert() ;
}
}
else bOk = false ;
}
// Il percorso selezionato è il minore tra le due possibilità di percorrenza
if ( bOk && bBorderClosed) {
double dParS = 0. ;
PtrOwner<ICurveComposite> pCompoMainCL( ConvertCurveToComposite( pCrvMainEdge->Clone())) ;
bOk = ( ! IsNull( pCompoMainCL) && pCompoMainCL->IsValid() &&
pCompoMainCL->GetParamAtPoint( Line1.first, dParS, TOL)) ;
if ( bOk) {
pCompoMainCL->ChangeStartPoint( dParS) ;
double dLenE = 0., dLenMain = 0. ;
bOk = ( pCompoMainCL->GetLengthAtPoint( Line2.first, dLenE, TOL) &&
pCompoMainCL->GetLength( dLenMain)) ;
if ( dLenE > dLenMain / 2. + EPS_SMALL) {
swap( Line1, Line2) ;
swap( pCrvSyncS, pCrvSyncE) ;
}
}
}
// Calcolo la lunghezza delle due curve di Bordo
double dLenMain = 0., dLenOther = 0. ;
bOk = bOk && ( pCrvMainEdge->GetLength( dLenMain) && pCrvOtherEdge->GetLength( dLenOther) &&
dLenMain > 2. * TOL + dInterpLenS + dInterpLenE + EPS_SMALL &&
dLenOther > 2. * TOL + dInterpLenS + dInterpLenE + EPS_SMALL) ;
// Recupero i punti di sincronizzazione (se presenti)
BIPNTVECTOR vSyncPoints ; vSyncPoints.reserve( pGeomDB->GetGroupObjs( nSyncLayerId)) ;
int nLineId = pGeomDB->GetFirstInGroup( nSyncLayerId) ;
while ( bOk && nLineId != GDB_ID_NULL) {
// Recupero la Curva
const ICurve* pLine = GetCurve( pGeomDB->GetGeoObj( nLineId)) ;
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 ( in un verso o nell'altro, mantengo il verso)
double dDistS1 = INFINITO ;
if ( ! DistPointCurve( ptStart, *pCrvMainEdge).GetDist( dDistS1)) {
nLineId = pGeomDB->GetNext( nLineId) ;
continue ;
}
if ( dDistS1 < dLinTol) {
double dDistE2 = INFINITO ;
if ( ! DistPointCurve( ptEnd, *pCrvOtherEdge).GetDist( dDistE2) || dDistE2 > dLinTol) {
nLineId = pGeomDB->GetNext( nLineId) ;
continue ;
}
}
else {
double dDistS2 = INFINITO ;
if ( ! DistPointCurve( ptStart, *pCrvOtherEdge).GetDist( dDistS2) || dDistS2 > dLinTol) {
nLineId = pGeomDB->GetNext( nLineId) ;
continue ;
}
double dDistE1 = INFINITO ;
if ( ! DistPointCurve( ptEnd, *pCrvMainEdge).GetDist( dDistE1) || dDistE1 > dLinTol) {
nLineId = pGeomDB->GetNext( nLineId) ;
continue ;
}
}
vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
}
nLineId = pGeomDB->GetNext( nLineId) ;
}
// Recupero la superficie Bezier rigata
PtrOwner<ISurfBezier> pSurfBzRuled ;
if ( bOk) {
// Se non ho linee di sincronizzazione
if ( vSyncPoints.empty())
pSurfBzRuled.Set( GetSurfBezierRuledSmooth( pCrvMainEdge, pCrvOtherEdge, vSyncPoints, ISO_PAR_SAMPLE)) ;
// Se ho linee di sincronizzazione
else
pSurfBzRuled.Set( GetSurfBezierRuledGuided( pCrvMainEdge, pCrvOtherEdge, vSyncPoints, dMyLinTol)) ;
bOk = bOk && ( ! IsNull( pSurfBzRuled) && pSurfBzRuled->IsValid()) ;
}
// --- Calcolo delle Linee di Orientamento ---
if ( bOk) {
// Rotazione delle curve di Bordo rispetto al Bordo Main
double dLenS ; pCrvSyncS->GetLength( dLenS) ;
Line1.second = Line1.first + FromSpherical( dLenS, dThetaStart, dPhiStart) ;
double dLenE ; pCrvSyncE->GetLength( dLenE) ;
Line2.second = Line2.first + FromSpherical( dLenE, dThetaEnd, dPhiEnd) ;
// --- Eventuale Interpolazione Lineare di Raccordo all'Inizio ---
if ( dInterpLenS > TOL) {
double dExtension = dInterpLenS ;
double dLen = -1. ; pCrvMainEdge->GetLengthAtPoint( Line1.first, dLen, TOL) ;
if ( bBorderClosed) {
dLen -= dInterpLenS ;
if ( dLen < EPS_SMALL)
dLen = dLenMain + dLen ;
}
else {
if ( dLen < dInterpLenS - EPS_SMALL) {
dExtension = dLen ;
dLen = 0 ;
}
}
double dU = - 1;
bOk = pCrvMainEdge->GetParamAtLength( dLen, dU) ;
if ( bOk) {
// Definisco la linea si sincronizzazione
Point3d ptInterpS ; double dParU, dParV ;
PtrOwner<ICurveComposite> pCompoIso( nullptr) ;
BIPOINT LineInterpS ;
bOk = ( pCrvMainEdge->GetPointD1D2( dU, ICurve::FROM_MINUS, ptInterpS) &&
DistPointSurfBz( ptInterpS, *pSurfBzRuled).GetParamsAtMinDistPoint( dParU, dParV) &&
pCompoIso.Set( pSurfBzRuled->GetCurveOnV( dParU)) &&
pCompoIso->IsValid() &&
pCompoIso->GetStartPoint( LineInterpS.first) &&
pCompoIso->GetEndPoint( LineInterpS.second)) ;
if ( bOk) {
bool bFirst = true ;
// Interpolo
double dLenLineInterpS = Dist( LineInterpS.first, LineInterpS.second) ;
double dLenLine1 = Dist( Line1.first, Line1.second) ;
int nStep = max( 1, int( ceil( dExtension / INTERPOLATION_DIST))) ;
Vector3d vtInterpStart = ( LineInterpS.second - LineInterpS.first) ; vtInterpStart.Normalize() ;
Vector3d vtInterpEnd = ( Line1.second - Line1.first) ; vtInterpEnd.Normalize() ;
Vector3d vtDiff = vtInterpEnd - vtInterpStart ;
for ( int i = 0 ; bOk && i < ( nStep - 1) ; ++ i) { // ( nStep - 1) per evitare sovrapposizione con la Copia del vettore
double dI = double( i) ;
Vector3d vtInterp = vtInterpStart + ( dI / ( nStep - 1)) * vtDiff ;
double dUInterpMain = 0. ; Point3d ptInterpOnMain ;
double dCurrLen = dLen + ( dI * dExtension / ( nStep - 1)) ;
if ( dCurrLen > dLenMain)
dCurrLen -= dLenMain ;
bOk = ( pCrvMainEdge->GetParamAtLength( dCurrLen, dUInterpMain) &&
pCrvMainEdge->GetPointD1D2( dUInterpMain, ICurve::FROM_MINUS, ptInterpOnMain)) ;
if ( bOk) {
double dMagnitude = dLenLineInterpS + ( dI / ( nStep - 1)) * ( dLenLine1 - dLenLineInterpS) ;
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
bOk = ( ! IsNull( pLine) && pLine->Set( ptInterpOnMain, ptInterpOnMain + vtInterp * dMagnitude)) ;
if ( bOk) {
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ;
bOk = ( nNewId != GDB_ID_NULL) ;
if ( bOk) {
if ( bFirst) {
nInterpStartId = nNewId ;
bFirst = false ;
}
}
}
}
}
}
}
}
// --- Interpolazione tra le due Linee di Sincronizzazione ---
if ( bOk) {
double dLenS = -1., dLenE = -1 ;
bOk = ( pCrvMainEdge->GetLengthAtPoint( Line1.first, dLenS, TOL) &&
pCrvMainEdge->GetLengthAtPoint( Line2.first, dLenE, TOL)) ;
if ( bOk) {
double dToTDist = 0. ;
if ( dLenS < dLenE)
dToTDist = dLenE - dLenS ;
else
dToTDist = ( dLenMain - dLenS) + dLenE ;
if ( dToTDist > TOL) {
bool bFirst = true ;
// Interpolo
double dLenLine1 = Dist( Line1.first, Line1.second) ;
double dLenLine2 = Dist( Line2.first, Line2.second) ;
int nStep = max( 1, int( ceil( dToTDist / INTERPOLATION_DIST))) ;
Vector3d vtLineS = ( Line1.second - Line1.first) ; vtLineS.Normalize() ;
Vector3d vtLineE = ( Line2.second - Line2.first) ; vtLineE.Normalize() ;
Vector3d vtDiff = ( vtLineE - vtLineS) ;
for ( int i = 0 ; bOk && i <= nStep ; ++ i) {
double dI = double( i) ;
Vector3d vtInterp = vtLineS + ( dI / nStep) * vtDiff ;
double dUInterpMain = 0. ; Point3d ptInterpOnMain ;
double dCurrLen = dLenS + ( dI * dToTDist / nStep) ;
if ( dCurrLen > dLenMain)
dCurrLen -= dLenMain ;
bOk = ( pCrvMainEdge->GetParamAtLength( dCurrLen, dUInterpMain) &&
pCrvMainEdge->GetPointD1D2( dUInterpMain, ICurve::FROM_MINUS, ptInterpOnMain)) ;
if ( bOk) {
double dMagnitude = dLenLine1 + ( dI / nStep) * ( dLenLine2 - dLenLine1) ;
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
bOk = ( ! IsNull( pLine) && pLine->Set( ptInterpOnMain, ptInterpOnMain + vtInterp * dMagnitude)) ;
if ( bOk) {
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ;
bOk = ( nNewId != GDB_ID_NULL) ;
if ( bOk) {
if ( bFirst) {
nStartId = nNewId ;
bFirst = false ;
}
nEndId = nNewId ;
}
}
}
}
}
}
}
// --- Eventuale Interpolazione Lineare di Raccordo alla Fine ---
if ( bOk && dInterpLenE > TOL) {
double dExtension = dInterpLenE ;
double dLen = -1. ; pCrvMainEdge->GetLengthAtPoint( Line2.first, dLen, TOL) ;
if ( bBorderClosed) {
dLen += dInterpLenE ;
if ( dLen > dLenMain - EPS_SMALL)
dLen -= dLenMain ;
}
else {
if ( dLen > dLenMain - dInterpLenE - EPS_SMALL) {
dExtension = dLenMain - dLen ;
dLen = dLenMain ;
}
}
double dU = - 1 ;
bOk = pCrvMainEdge->GetParamAtLength( dLen, dU) ;
if ( bOk) {
// Definisco la linea si sincronizzazione
Point3d ptInterpE ; double dParU, dParV ;
PtrOwner<ICurveComposite> pCompoIso( nullptr) ;
BIPOINT LineInterpE ;
bOk = ( pCrvMainEdge->GetPointD1D2( dU, ICurve::FROM_MINUS, ptInterpE) &&
DistPointSurfBz( ptInterpE, *pSurfBzRuled).GetParamsAtMinDistPoint( dParU, dParV) &&
pCompoIso.Set( pSurfBzRuled->GetCurveOnV( dParU)) &&
pCompoIso->IsValid() &&
pCompoIso->GetStartPoint( LineInterpE.first) &&
pCompoIso->GetEndPoint( LineInterpE.second)) ;
if ( bOk) {
// Interpolo
double dLenLineInterpE = Dist( LineInterpE.first, LineInterpE.second) ;
double dLenLine2 = Dist( Line2.first, Line2.second) ;
int nStep = max( 1, int( ceil( dExtension / INTERPOLATION_DIST))) ;
Vector3d vtInterpStart = ( Line2.second - Line2.first) ; vtInterpStart.Normalize() ;
Vector3d vtInterpEnd = ( LineInterpE.second - LineInterpE.first) ; vtInterpEnd.Normalize() ;
Vector3d vtDiff = vtInterpEnd - vtInterpStart ;
for ( int i = 1 ; bOk && i < nStep ; ++ i) { // i = 1 per evitare la sopvrapposizione con la Copia del vettore
double dI = double( i) ;
Vector3d vtInterp = vtInterpStart + ( dI / ( nStep - 1)) * vtDiff ;
double dUInterpMain = 0. ; Point3d ptInterpOnMain ;
double dCurrLen = ( dLen - dExtension) + ( dI * dExtension / ( nStep - 1)) ;
if ( dCurrLen > dLenMain)
dCurrLen -= dLenMain ;
bOk = ( pCrvMainEdge->GetParamAtLength( dCurrLen, dUInterpMain) &&
pCrvMainEdge->GetPointD1D2( dUInterpMain, ICurve::FROM_MINUS, ptInterpOnMain)) ;
if ( bOk) {
double dMagnitude = dLenLine2 + ( dI / ( nStep - 1)) * ( dLenLineInterpE - dLenLine2) ;
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
bOk = ( ! IsNull( pLine) && pLine->Set( ptInterpOnMain, ptInterpOnMain + vtInterp * dMagnitude)) ;
if ( bOk) {
int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pLine)) ;
bOk = ( nNewId != GDB_ID_NULL) ;
if ( bOk)
nInterpEndId = nNewId ;
}
}
}
}
}
}
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingGetToolOrientationLines(" + ToString( nParentId) + "," +
ToString( nMainEdgeId) + "," +
ToString( nOtherEdgeId) + "," +
ToString( nLineSId) + "," +
ToString( nLineEId) + "," +
ToString( dThetaStart) + "," +
ToString( dPhiStart) + "," +
ToString( dThetaEnd) + "," +
ToString( dPhiEnd) + "," +
ToString( dLinTol) + "," +
ToString( dInterpLenS) + "," +
ToString( dInterpLenE) + "," +
" -- bOk=" + ToString( bOk) +
" -- nInterpStartId=" + ToString( nInterpStartId) + ", nStartId=" + ToString( nStartId) +
", nEndId=" + ToString( nEndId) + ", nInterpEndId=" + ToString( nInterpEndId) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
// ---------------------------------------------------------------------------
struct TrimmingInterval {
double dLenStart ;
double dLenEnd ;
Vector3d vtStart ;
Vector3d vtEnd ;
TrimmingInterval()
: dLenStart( - EPS_SMALL), dLenEnd( - EPS_SMALL), vtStart( V_INVALID), vtEnd( V_INVALID) {} ;
TrimmingInterval( double dLenS, double dLenE, const Vector3d& vtS, const Vector3d& vtE)
: dLenStart( dLenS), dLenEnd( dLenE), vtStart( vtS), vtEnd( vtE) {} ;
} ;
typedef vector<TrimmingInterval> TRIMMINGINTERVALVECTOR ;
// ---------------------------------------------------------------------------
bool
GetTrimmingInterval( const IGeomDB* pGeomDB, const ICurveComposite* pCompo, const Frame3d& frCompo, int nIdS, int nIdE, bool bInvert, TrimmingInterval& TrimmingInt)
{
// Verifico validità dei parametri
VERIFY_GEOMDB( pGeomDB, false)
if ( pCompo == nullptr || ! pCompo->IsValid() || ! frCompo.IsValid())
return false ;
// Recupero le linee di Orienting
const ICurve* pGeoCrvS = GetCurve( pGeomDB->GetGeoObj( nIdS)) ;
const ICurve* pGeoCrvE = GetCurve( pGeomDB->GetGeoObj( nIdE)) ;
if ( pGeoCrvS != nullptr && pGeoCrvE != nullptr && pGeoCrvS->IsValid() && pGeoCrvE->IsValid()) {
// Recupero i punti base ches stanno sulla pCompo e i vettori direzioni ( sono ICurveLine*, ma le tratto come ICurve* generiche)
Point3d ptS = P_INVALID ;
Point3d ptE = P_INVALID ;
if ( ! bInvert) {
pGeoCrvS->GetStartPoint( ptS) ; // Line1.ptStart
pGeoCrvE->GetStartPoint( ptE) ; // Line2.ptStart
}
else {
pGeoCrvS->GetEndPoint( ptS) ;
pGeoCrvE->GetEndPoint( ptE) ;
}
Vector3d vtS = V_INVALID ; pGeoCrvS->GetStartDir( vtS) ; // Line1.vtStart
Vector3d vtE = V_INVALID ; pGeoCrvE->GetStartDir( vtE) ; // Line2.vtStart
if ( ptS.IsValid() && ptE.IsValid() && vtS.IsValid() && vtE.IsValid()) {
// Recupero il Frame delle Linee
Frame3d frCrv1, frCrv2 ;
if ( ! pGeomDB->GetGlobFrame( nIdS, frCrv1) || ! pGeomDB->GetGlobFrame( nIdE, frCrv2))
return false ;
// Porto Tali valori nel riferimento dalla Composita
Point3d ptSLoc = GetLocToLoc( ptS, frCrv1, frCompo) ;
Point3d ptELoc = GetLocToLoc( ptE, frCrv2, frCompo) ;
Vector3d vtSLoc = GetLocToLoc( vtS, frCrv1, frCompo) ;
Vector3d vtELoc = GetLocToLoc( vtE, frCrv2, frCompo) ;
// Recupero il parametro sulla curva
double dParS = - EPS_PARAM, dParE = - EPS_PARAM ;
int nFlag = 0 ;
if ( DistPointCurve( ptSLoc, *pCompo).GetParamAtMinDistPoint( EPS_SMALL, dParS, nFlag) &&
DistPointCurve( ptELoc, *pCompo).GetParamAtMinDistPoint( EPS_SMALL, dParE, nFlag)) {
// Recupero la lunghezza su tale curva
double dLenS = - EPS_SMALL, dLenE = - EPS_SMALL ;
if ( pCompo->GetLengthAtParam( dParS, dLenS) && pCompo->GetLengthAtParam( dParE, dLenE)) {
TrimmingInt = TrimmingInterval( dLenS, dLenE, vtSLoc, vtELoc) ;
return true ;
}
}
}
}
return false ;
}
// ---------------------------------------------------------------------------
bool
Exe5AxTrimmingModifyToolDir( int nCrvId, int nPathId, int nTrimLayId, const INTVECTOR& vnOrientingId, const INTVECTOR& vnOrientingISId,
const INTVECTOR& vnOrientingSId, const INTVECTOR& vnOrientingEId, const INTVECTOR& vnOrientingIEId)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// Verifico validità dei parametri
bool bOk = ( nCrvId != GDB_ID_NULL && nPathId != GDB_ID_NULL && nTrimLayId != GDB_ID_NULL &&
ssize( vnOrientingId) == ssize( vnOrientingISId) && ssize( vnOrientingISId) == ssize( vnOrientingSId) &&
ssize( vnOrientingSId) == ssize( vnOrientingEId) && ssize( vnOrientingEId) == ssize( vnOrientingIEId)) ;
// Recupero la curva di Bordo e la sua composit associata
const ICurve* pCrvBorder = GetCurve( pGeomDB->GetGeoObj( nCrvId)) ;
bOk = bOk && ( pCrvBorder != nullptr && pCrvBorder->IsValid()) ;
PtrOwner<ICurveComposite> pCompoBorder( nullptr) ;
if ( bOk)
bOk = ( pCompoBorder.Set( ConvertCurveToComposite( pCrvBorder->Clone())) && pCompoBorder->IsValid()) ;
double dLen = - EPS_SMALL ;
if ( bOk)
bOk = pCompoBorder->GetLength( dLen) ;
// Recupero il Frame della curva corrente
Frame3d frCompo ;
bOk = bOk && ( pGeomDB->GetGlobFrame( nCrvId, frCompo)) ;
bool bInvert = false ;
if ( ssize( vnOrientingISId) > 0 && vnOrientingISId[0] != GDB_ID_NULL) {
const ICurve* pGeoCrvS = GetCurve( pGeomDB->GetGeoObj( vnOrientingISId[0])) ;
Point3d ptS ; pGeoCrvS->GetStartPoint( ptS) ;
double dDist = 1 ;
if ( DistPointCurve( ptS, *pCompoBorder).GetDist( dDist) && dDist > EPS_SMALL)
bInvert = true ;
}
// Recupero i versori di interpolazione e creo dei gruppi
TRIMMINGINTERVALVECTOR vInterval ; vInterval.reserve( 3 * ssize( vnOrientingId)) ;
for ( int i = 0 ; bOk && i < ssize( vnOrientingId) ; ++ i) {
// Se presente Interpolazione iniziale
if ( vnOrientingISId[i] != GDB_ID_NULL && vnOrientingSId[i] != GDB_ID_NULL) {
TrimmingInterval myTrimInt ;
if ( GetTrimmingInterval( pGeomDB, pCompoBorder, frCompo, vnOrientingISId[i], vnOrientingSId[i], bInvert, myTrimInt))
vInterval.emplace_back( myTrimInt) ;
}
// Interpolazione ( deve essere sempre presente, ma per scrupolo si controlla lo stesso)
if ( vnOrientingSId[i] != GDB_ID_NULL && vnOrientingEId[i] != GDB_ID_NULL) {
TrimmingInterval myTrimInt ;
if ( GetTrimmingInterval( pGeomDB, pCompoBorder, frCompo, vnOrientingSId[i], vnOrientingEId[i], bInvert, myTrimInt))
vInterval.emplace_back( myTrimInt) ;
}
// Se presente Interpolazione finale
if ( vnOrientingEId[i] != GDB_ID_NULL && vnOrientingIEId[i] != GDB_ID_NULL) {
TrimmingInterval myTrimInt ;
if ( GetTrimmingInterval( pGeomDB, pCompoBorder, frCompo, vnOrientingEId[i], vnOrientingIEId[i], bInvert, myTrimInt))
vInterval.emplace_back( myTrimInt) ;
}
}
// Se ho degli intervalli di Interpolazione
if ( ! vInterval.empty()) {
// Scorro i vettori presenti nel Layer ausiliario della lavorazione
int nId = pGeomDB->GetFirstInGroup( nPathId) ;
while ( bOk && nId != GDB_ID_NULL) {
IGeoVector3d* vGeo = GetGeoVector3d( pGeomDB->GetGeoObj( nId)) ;
if ( vGeo != nullptr && vGeo->IsValid()) {
// Recupero i parametri di tale vettore
Point3d ptBase = vGeo->GetBase() ;
Vector3d vtDirV = V_INVALID ; ;
if ( pGeomDB->GetInfo( nId, "DirV", vtDirV) && vtDirV.IsValid()) {
// Recupero la lunghezza associata al Punto di Base sulla Compo
double dCurrPar = - EPS_SMALL ;
int nFlag = 0 ;
if ( DistPointCurve( ptBase, *pCompoBorder).GetParamAtMinDistPoint( 0., dCurrPar, nFlag)) {
double dCurrLen = - EPS_SMALL ;
if ( pCompoBorder->GetLengthAtParam( dCurrPar, dCurrLen)) {
for ( const TrimmingInterval& CurrInterval : vInterval) {
// Controlli per Intervalli a cavallo dei punti iniziali e finali della curva
double dLenA = CurrInterval.dLenStart ;
double dLenB = CurrInterval.dLenEnd ;
double dLenC = dCurrLen ;
if ( dLenA > dLenB) {
dLenB += dLen ;
if ( dLenC < CurrInterval.dLenStart - EPS_SMALL)
dLenC += dLen ;
}
// Se l'intervallo non è troppo piccolo e se sono all'interno di tale Intervallo
if ( dLenB - dLenA > 10. * EPS_SMALL && /* bastava anche 2 * EPS_SMALL */
dLenA + EPS_SMALL < dLenC && dLenC < dLenB + EPS_SMALL /* estremi esclusi, va bene ? */) {
// Media pesata dei due vettori
double dMeanPar = ( dLenC - dLenA) / ( dLenB - dLenA) ;
Vector3d vtMean = Media( CurrInterval.vtStart, CurrInterval.vtEnd, dMeanPar) ;
// Assegno la Info a tale vettore
pGeomDB->SetInfo( nId, "DirV", vtMean) ;
break ; // non controllo altri intervalli
}
}
}
}
}
}
nId = pGeomDB->GetNext( nId) ;
}
}
ExeSetModified() ;
// Se richiesto, salvo il comando Lua equivalente
if ( IsCmdLog()) {
string sLua = "EgtTrimmingGetToolOrientationLines(" + ToString( nCrvId) + "," +
ToString( nPathId) + "," +
ToString( nTrimLayId) + "," +
ToString( vnOrientingId) + "," +
ToString( vnOrientingISId) + "," +
ToString( vnOrientingSId) + "," +
ToString( vnOrientingEId) + "," +
ToString( vnOrientingIEId) + "," +
" -- bOk=" + ToString( bOk) ;
LOG_INFO( GetCmdLogger(), sLua.c_str()) ;
}
return bOk ;
}
// ---------------------------------------------------------------------------
int
ExeRegolarizeSurfaceLocally( int nParentId, int nSurfId, int nSyncStartId, int nSyncEndId, double dLinTol, int nType)
{
// Verifica database geometrico
IGeomDB* pGeomDB = GetCurrGeomDB() ;
VERIFY_GEOMDB( pGeomDB, false)
// recupero la superficie
ISurfBezier* pSurfBez = GetSurfBezier( GetSurf( pGeomDB->GetGeoObj( nSurfId))) ;
// recupero le due isocurve
const ICurve* pSyncStart = GetCurveLine( GetCurve( pGeomDB->GetGeoObj( nSyncStartId))) ;
const ICurve* pSyncEnd = GetCurveLine( GetCurve( pGeomDB->GetGeoObj( nSyncEndId))) ;
Point3d ptS1 ; pSyncStart->GetStartPoint( ptS1) ;
Point3d ptE1 ; pSyncStart->GetEndPoint( ptE1) ;
BIPOINT bpIsoStart( ptS1, ptE1) ;
Point3d ptS2 ; pSyncEnd->GetStartPoint( ptS2) ;
Point3d ptE2 ; pSyncEnd->GetEndPoint( ptE2) ;
BIPOINT bpIsoEnd( ptS2, ptE2) ;
PtrOwner<ISurfBezier> pNewSurf( RegolarizeBordersLocally( pSurfBez, bpIsoStart, bpIsoEnd, dLinTol, nType)) ;
if ( IsNull( pNewSurf))
return GDB_ID_NULL ;
int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, Release( pNewSurf)) ;
return nId ;
}