3a69dcfa79
- Aggiunta funzione in DistPointSurfTm per ottenere i triangoli a minima distanza - Aggiunte funzioni per Offset Fillet di VolZmap e per Offset generici di superfici TriMesh aperte.
243 lines
8.9 KiB
C++
243 lines
8.9 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2025
|
|
//----------------------------------------------------------------------------
|
|
// File : SurfTriMeshOffset.cpp Data : 07.07.25 Versione : 2.7g1
|
|
// Contenuto : Implementazione funzione per Offset di Superfici TriMesh.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 10.06.25 RE Creazione modulo.
|
|
// 10.06.25 RE Offset di superfici chiuse.
|
|
// 04.07.25 RE Thickening Offset di superfici generiche.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "VolZmap.h"
|
|
#include "SurfTriMesh.h"
|
|
#include "EgtDev/Include/EGkDistPointSurfTm.h"
|
|
#include "\EgtDev\Include\EGkSurfTriMeshAux.h"
|
|
|
|
#define DEBUG 0
|
|
#if DEBUG
|
|
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
|
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
|
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
|
#include "/EgtDev/Include/EGkStmStandard.h"
|
|
#include "/EgtDev/Include/EgtPerfCounter.h"
|
|
std::vector<IGeoObj*> VT ;
|
|
std::vector<Color> VC ;
|
|
#endif
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static ISurfTriMesh*
|
|
SumStm( const CISURFTMPVECTOR& vStm)
|
|
{
|
|
// se vettore vuoto, non faccio nulla
|
|
if ( vStm.empty())
|
|
return nullptr ;
|
|
// definisco la superficie somma tra tutte ( la prima deve essere valida)
|
|
PtrOwner<ISurfTriMesh> pStmAdd( CreateSurfTriMesh()) ;
|
|
if ( IsNull( pStmAdd))
|
|
return nullptr ;
|
|
// scorro le superfici
|
|
for ( const ISurfTriMesh* pStm : vStm) {
|
|
if ( pStm == nullptr || ! pStm->IsValid() || pStm->GetTriangleCount() == 0)
|
|
continue ;
|
|
if ( ! pStmAdd->IsValid() || pStmAdd->GetTriangleCount() == 0) {
|
|
if ( ! pStmAdd->CopyFrom( pStm))
|
|
return nullptr ;
|
|
}
|
|
else
|
|
pStmAdd->Add( *pStm) ;
|
|
}
|
|
// restituisco la superficie ottenuta
|
|
return ( Release( pStmAdd)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Funzione che crea l'Offset di una superficie TriMesh
|
|
//----------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
CreateSurfTriMeshOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
|
|
{
|
|
return ( CreateSurfTriMeshesOffset( { pStm}, dOffs, dPrec, nType)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Funzione che crea il Fat Offset di una superficie TriMesh
|
|
//----------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
CreateSurfTriMeshThickeningOffset( const ISurfTriMesh* pStm, double dOffs, double dPrec, int nType)
|
|
{
|
|
return ( CreateSurfTriMeshesThickeningOffset( { pStm}, dOffs, dPrec, nType)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Funzione che crea l'Offset di un insieme di superfici
|
|
//----------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
CreateSurfTriMeshesOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
|
|
{
|
|
// se vettore delle superfici vuoto, non faccio nulla
|
|
if ( vStm.empty())
|
|
return nullptr ;
|
|
// controllo sul valore di tolleranza lineare
|
|
double dMyPrec = max( dPrec, 100. * EPS_SMALL) ;
|
|
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
|
|
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
|
|
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
|
|
if ( abs( dOffs) < 10. * EPS_SMALL)
|
|
return SumStm( vStm) ;
|
|
|
|
// creo lo Zmap associato alle superfici TriMesh
|
|
VolZmap OneVolZmap ;
|
|
if ( ! OneVolZmap.CreateFromTriMeshOffset( vStm, dOffs, dMyPrec, nType))
|
|
return nullptr ;
|
|
if ( ! OneVolZmap.IsValid())
|
|
return nullptr ;
|
|
|
|
// recupero le superfici aperte
|
|
CISURFTMPVECTOR vStmOpen ;
|
|
for ( const ISurfTriMesh* pStm : vStm) {
|
|
if ( pStm != nullptr && pStm->IsValid() && ! pStm->IsClosed())
|
|
vStmOpen.emplace_back( pStm) ;
|
|
}
|
|
|
|
// --- se non ho superfici aperte
|
|
if ( vStmOpen.empty()) {
|
|
// restituisco la superficie TriMesh di Offset
|
|
return ( OneVolZmap.GetSurfTriMesh()) ;
|
|
}
|
|
|
|
// --- se ho delle superfici aperte
|
|
// lo Zmap creato è orientato e definisce una superficie chiusa; devo rimuovere i triangoli in eccesso
|
|
|
|
// anzitutto controllo che lo Zmap sia valido
|
|
if ( ! OneVolZmap.IsValid())
|
|
return nullptr ;
|
|
|
|
// inzializzo la superficie TriMesh da restituire
|
|
PtrOwner<SurfTriMesh> pStm( CreateBasicSurfTriMesh()) ;
|
|
if ( IsNull( pStm) || ! pStm->Init( 3, 1))
|
|
return nullptr ;
|
|
PointGrid3d VertGrid ; VertGrid.Init( 50000) ;
|
|
|
|
// tolleranza di vicinanza alla superficie
|
|
double dTolDist = 30. * EPS_SMALL ;
|
|
|
|
#if DEBUG
|
|
VT.emplace_back( OneVolZmap.Clone()) ;
|
|
VC.emplace_back( BLACK) ;
|
|
#endif
|
|
|
|
// ciclo lungo i blocchi dello ZMap
|
|
for ( int nB = 0 ; nB < OneVolZmap.GetBlockCount() ; ++ nB) {
|
|
|
|
// recupero i triangoli
|
|
TRIA3DEXVECTOR vTria, vTriaSafe ;
|
|
OneVolZmap.GetBlockTriangles( nB, vTria) ;
|
|
|
|
// un triangolo viene ritenuto valido se è non è troppo vicino ( dOffs) alle superfici aperte
|
|
for ( int nT = 0 ; nT < int( vTria.size()) ; ++ nT) {
|
|
|
|
// recupero il triangolo
|
|
Triangle3dEx& Tria = vTria[nT] ;
|
|
|
|
// scorro le superficie aperte
|
|
bool bInsert = true ;
|
|
for ( int nS = 0 ; bInsert && nS < int( vStm.size()) ; ++ nS) {
|
|
|
|
// controllo se posso inserirlo
|
|
vector<DistPointSurfTm> vDistPtStm ;
|
|
for ( int i = 0 ; i < 3 && bInsert ; ++ i) {
|
|
double dDist = 0. ;
|
|
vDistPtStm.emplace_back( DistPointSurfTm( Tria.GetP( i), *vStm[nS])) ;
|
|
bInsert = ( vDistPtStm.back().GetDist( dDist) && dDist > abs( dOffs) - dTolDist) ;
|
|
}
|
|
// se il triangolo è al più a distanza di |dOffs| - dTolDist
|
|
if ( bInsert) {
|
|
// recupero i triangoli a distanza minima dai vertici del triangolo corrente
|
|
bool bPerp = true ;
|
|
for ( int i = 0 ; i < 3 && bPerp ; ++ i) {
|
|
INTVECTOR vTria ;
|
|
vDistPtStm[i].GetMinDistTriaIndices( vTria) ;
|
|
for ( int j = 0 ; j < int( vTria.size()) && bPerp ; ++ j) {
|
|
Triangle3d TriaCloser ;
|
|
vStm[nS]->GetTriangle( vTria[j], TriaCloser) ;
|
|
bPerp = ( abs( Tria.GetN() * TriaCloser.GetN()) < dTolDist) ;
|
|
}
|
|
}
|
|
// se tutti i triangoli a distanza minima sono perpendicolari, allora non lo inserisco
|
|
bInsert = ( ! bPerp) ;
|
|
}
|
|
}
|
|
|
|
// se triangolo da inserire
|
|
if ( bInsert)
|
|
vTriaSafe.emplace_back( Tria) ;
|
|
|
|
#if DEBUG
|
|
ICurveComposite* pCompo = CreateCurveComposite() ;
|
|
pCompo->AddPoint( Tria.GetP( 0)) ;
|
|
pCompo->AddLine( Tria.GetP( 1)) ;
|
|
pCompo->AddLine( Tria.GetP( 2)) ;
|
|
pCompo->Close() ;
|
|
Color myCol = ( bInsert ? Color( 0., 1., 0., .5) : Color( 1., 0., 0., .5)) ;
|
|
VT.emplace_back( CloneCurveComposite( pCompo)) ;
|
|
VC.emplace_back( myCol) ;
|
|
ISurfFlatRegion* pSfrTria = CreateSurfFlatRegion() ;
|
|
pSfrTria->AddExtLoop( pCompo) ;
|
|
VT.emplace_back( pSfrTria) ;
|
|
VC.emplace_back( myCol) ;
|
|
#endif
|
|
}
|
|
|
|
// inserisco tutti i triangoli validi
|
|
if ( ! pStm->AddTriaFromZMap( vTriaSafe, VertGrid))
|
|
return nullptr ;
|
|
}
|
|
|
|
#if DEBUG
|
|
SaveGeoObj( VT, VC, "C:\\Temp\\TriangleSelection.nge") ;
|
|
#endif
|
|
|
|
|
|
// sistemo la topologia
|
|
if ( ! pStm->AdjustTopologyFromZMap())
|
|
return nullptr ;
|
|
|
|
return ( Release( pStm)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//* Funzione che crea il Fat Offset di un insieme di superfici
|
|
//----------------------------------------------------------------------------
|
|
ISurfTriMesh*
|
|
CreateSurfTriMeshesThickeningOffset( const CISURFTMPVECTOR& vStm, double dOffs, double dPrec, int nType)
|
|
{
|
|
// se vettore delle superfici vuoto, non faccio nulla
|
|
if ( vStm.empty())
|
|
return nullptr ;
|
|
// controllo sul valore di tolleranza lineare
|
|
double dMyPrec = max( dPrec, 100 * EPS_SMALL) ;
|
|
// --- NB. ( Il valore di Offset deve essere maggiore di 10 * EPS_SMALL in valore assoluto)
|
|
// Nel caso sia minore, restituisco semplicemente la somma delle superfici
|
|
// ( questo valore serve per rimanere coerente con l'Offset delle curve)
|
|
if ( abs( dOffs) < 10 * EPS_SMALL)
|
|
return SumStm( vStm) ;
|
|
|
|
// creo lo Zmap associato alle superfici TriMesh
|
|
VolZmap OneVolZmap ;
|
|
if ( ! OneVolZmap.CreateFromTriMeshThickeningOffset( vStm, dOffs, dMyPrec, nType))
|
|
return nullptr ;
|
|
if ( ! OneVolZmap.IsValid())
|
|
return nullptr ;
|
|
|
|
// restituisco la superficie TriMesh
|
|
return ( OneVolZmap.GetSurfTriMesh()) ;
|
|
}
|