Files
EgtGeomKernel/SurfTriMesh.cpp
T
Dario Sassi 79978655d3 EgtGeomKernel :
- prima versione delle superfici trimesh.
2014-03-27 22:15:42 +00:00

607 lines
18 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2014
//----------------------------------------------------------------------------
// File : SurfTriMesh.cpp Data : 26.03.14 Versione : 1.5c9
// Contenuto : Implementazione della classe Superfici TriMesh.
//
//
//
// Modifiche : 26.03.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "DllMain.h"
#include "SurfTriMesh.h"
#include "GeoConst.h"
#include "DistPointLine.h"
#include "GeoObjFactory.h"
#include "PolynomialPoint3d.h"
#include "\EgtDev\Include\EGkCurveArc.h"
#include "\EgtDev\Include\ENkPolynomial.h"
#include "\EgtDev\Include\EGkStringUtils3d.h"
#include <new>
using namespace std ;
//----------------------------------------------------------------------------
GEOOBJ_REGISTER( SRF_TRIMESH, "S_TRM", SurfTriMesh) ;
//----------------------------------------------------------------------------
SurfTriMesh::SurfTriMesh( void)
: m_nStatus( TO_VERIFY), m_bClosed( false)
{
}
//----------------------------------------------------------------------------
SurfTriMesh::~SurfTriMesh( void)
{
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Init( int nNumVert, int nNumTria)
{
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// verifico validità parametri
if ( nNumVert < 3 || nNumTria < 1)
return false ;
// prealloco la memoria
try {
m_vVert.reserve( nNumVert) ;
m_vTria.reserve( nNumTria) ;
}
catch (...) {
return false ;
}
// completo inizializzazione
m_nStatus = TO_VERIFY ;
m_bClosed = false ;
return true ;
}
//----------------------------------------------------------------------------
int
SurfTriMesh::AddVertex( const Point3d& ptVert)
{
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// inserisco il vertice
try { m_vVert.push_back( StmVert( ptVert)) ;}
catch(...) { return - 1 ;}
// ne determino l'indice
return int( m_vVert.size() - 1) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::SetVertex( int nInd, const StmVert& vV)
{
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// recupero la dimensione originale
int nPrevSize = int( m_vVert.size()) ;
// determino la dimensione necessaria
int nNewSize = max( nInd + 1, nPrevSize) ;
// se necessaria dimensione maggiore
if ( nNewSize > nPrevSize) {
// espando vettore
try { m_vVert.resize( nNewSize) ; }
catch (...) { return false ; }
// inizializzo a cancellati gli eventuali vertici intermedi
StmVert vEmpty( Point3d(), VT_DEL, 0) ;
for ( int i = nPrevSize ; i < nNewSize ; ++ i)
m_vVert[i] = vEmpty ;
}
// inserisco il vertice
m_vVert[nInd] = vV ;
return true ;
}
//----------------------------------------------------------------------------
int
SurfTriMesh::AddTriangle( const int nIdVert[3])
{
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// inserisco il vertice
m_vTria.push_back( StmTria( nIdVert)) ;
// ne determino l'indice
return int( m_vTria.size() - 1) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::SetTriangle( int nInd, const StmTria& tT)
{
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// recupero la dimensione originale
int nPrevSize = int( m_vTria.size()) ;
// determino la dimensione necessaria
int nNewSize = max( nInd + 1, nPrevSize) ;
// se necessaria dimensione maggiore
if ( nNewSize > nPrevSize) {
// espando vettore
try { m_vTria.resize( nNewSize) ; }
catch (...) { return false ; }
// inizializzo a cancellati gli eventuali triangoli intermedi
StmTria tEmpty ;
tEmpty.nIdVert[0] = VT_DEL ;
for ( int i = nPrevSize ; i < nNewSize ; ++ i)
m_vTria[i] = tEmpty ;
}
// inserisco il vertice
m_vTria[nInd] = tT ;
return true ;
}
//----------------------------------------------------------------------------
int
SurfTriMesh::GetFirstTriangle( Point3d& ptP0, Point3d& ptP1, Point3d& ptP2) const
{
return GetNextTriangle( -1, ptP0, ptP1, ptP2) ;
}
//----------------------------------------------------------------------------
int
SurfTriMesh::GetNextTriangle( int nId, Point3d& ptP0, Point3d& ptP1, Point3d& ptP2) const
{
// cerco il primo successivo valido
do {
nId ++ ;
} while ( nId < GetTriangleNum() && m_vTria[nId].nIdVert[0] == VT_DEL) ;
// se oltrepassata fine
if ( nId >= GetTriangleNum())
return -1 ;
// recupero i dati
ptP0 = m_vVert[m_vTria[nId].nIdVert[0]].ptP ;
ptP1 = m_vVert[m_vTria[nId].nIdVert[1]].ptP ;
ptP2 = m_vVert[m_vTria[nId].nIdVert[2]].ptP ;
// ritorno indice triangolo corrente
return nId ;
}
//----------------------------------------------------------------------------
SurfTriMesh*
SurfTriMesh::Clone( void) const
{
// alloco oggetto
SurfTriMesh* pStm = new(nothrow) SurfTriMesh ;
if ( pStm != nullptr) {
if ( ! pStm->Copy( *this)) {
delete pStm ;
return nullptr ;
}
}
return pStm ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Copy( const IGeoObj* pGObjSrc)
{
const SurfTriMesh* pStm = dynamic_cast<const SurfTriMesh*>( pGObjSrc) ;
if ( pStm == nullptr)
return false ;
return Copy( *pStm) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Copy( const SurfTriMesh& stmSrc)
{
if ( &stmSrc == this)
return true ;
if ( ! Init( stmSrc.GetVertexNum(), stmSrc.GetTriangleNum()))
return false ;
m_vVert = stmSrc.m_vVert ;
m_vTria = stmSrc.m_vTria ;
m_bClosed = stmSrc.m_bClosed ;
m_nStatus = stmSrc.m_nStatus ;
return true ;
}
//----------------------------------------------------------------------------
const string&
SurfTriMesh::GetTitle( void) const
{
static const string sTitle = "TriMesh" ;
return sTitle ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Dump( string& sOut, const char* szNewLine) const
{
// se superficie aperta o chiusa
sOut += ( m_bClosed ? "Closed" : "Open") ;
// numero di vertici
sOut += " NbrVert=" + ToString( GetVertexNum()) ;
// numero di triangoli
sOut += " NbrTria=" + ToString( GetTriangleNum()) ;
return true ;
}
//----------------------------------------------------------------------------
const string&
SurfTriMesh::GetKey( void) const
{
return GEOOBJ_GETKEY( SurfTriMesh) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Save( ostream& osOut) const
{
// flag aperta/chiusa
osOut << ToString( m_bClosed) << ";" ;
// numero di vertici
osOut << ToString( GetVertexNum()) << ";" ;
// numero di triangoli
osOut << ToString( GetTriangleNum()) << ";" << endl ;
// ciclo sui vertici
for ( int i = 0 ; i < int( m_vVert.size()) ; ++ i) {
osOut << ToString( i) << ";" ;
osOut << ToString( m_vVert[i].ptP) << ";" ;
osOut << ToString( m_vVert[i].nIdTria) << ";" ;
osOut << ToString( m_vVert[i].nFlag) << ";" << endl ;
}
// ciclo sui triangoli
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
osOut << ToString( i) << ";" ;
osOut << ToString( m_vTria[i].nIdVert[0]) << "," ;
osOut << ToString( m_vTria[i].nIdVert[1]) << "," ;
osOut << ToString( m_vTria[i].nIdVert[2]) << ";" ;
osOut << ToString( m_vTria[i].nIdAdjac[0]) << "," ;
osOut << ToString( m_vTria[i].nIdAdjac[1]) << "," ;
osOut << ToString( m_vTria[i].nIdAdjac[2]) << ";" ;
osOut << ToString( m_vTria[i].vtN) << ";" ;
osOut << ToString( m_vTria[i].nTFlag) << ";" ;
osOut << ToString( m_vTria[i].nEFlag) << ";" << endl ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Load( Scanner& TheScanner)
{
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// leggo la prossima linea
string sLine ;
if ( ! TheScanner.GetLine( sLine))
return false ;
// la divido in parametri
STRVECTOR vsParams ;
Tokenize( sLine, ";", vsParams) ;
// 3 parametri : flag chiuso num vertici e num tria
if ( vsParams.size() != 3)
return false ;
// recupero il flag
bool bClosed ;
if ( ! FromString( vsParams[0], bClosed))
return false ;
// recupero il numero di vertici
int nNumVert ;
if ( ! FromString( vsParams[1], nNumVert))
return false ;
// recupero il numero di triangoli
int nNumTria ;
if ( ! FromString( vsParams[2], nNumTria))
return false ;
// inizializzo la superficie TriMesh
if ( ! Init( nNumVert, nNumTria))
return false ;
m_bClosed = bClosed ;
// lettura dei vertici
int nInd ;
StmVert vV ;
for ( int i = 0 ; i < nNumVert ; ++ i) {
// leggo la prossima linea
if ( ! TheScanner.GetLine( sLine))
return false ;
// la divido in parametri
Tokenize( sLine, ";", vsParams) ;
// 4 parametri : Indice, Punto, IdTria, Flag
if ( vsParams.size() != 4)
return false ;
// la interpreto e imposto il vertice
if ( ! FromString( vsParams[0], nInd) ||
! FromString( vsParams[1], vV.ptP) ||
! FromString( vsParams[2], vV.nIdTria) ||
! FromString( vsParams[3], vV.nFlag) ||
! SetVertex( nInd, vV))
return false ;
}
// lettura dei triangoli
StmTria tT ;
for ( int i = 0 ; i < nNumTria ; ++ i) {
// leggo la prossima linea
if ( ! TheScanner.GetLine( sLine))
return false ;
// la divido in parametri
Tokenize( sLine, ";", vsParams) ;
// 6 parametri : Indice, Punto, IdTria, Flag
if ( vsParams.size() != 6)
return false ;
// la interpreto e imposto il vertice
if ( ! FromString( vsParams[0], nInd) ||
! FromString( vsParams[1], tT.nIdVert) ||
! FromString( vsParams[2], tT.nIdAdjac) ||
! FromString( vsParams[3], tT.vtN) ||
! FromString( vsParams[4], tT.nTFlag) ||
! FromString( vsParams[5], tT.nEFlag) ||
! SetTriangle( nInd, tT))
return false ;
}
// eseguo validazione
return Validate() ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Validate( void)
{
// !!! DA FARE !!!
if ( m_nStatus == TO_VERIFY)
m_nStatus = OK ;
return ( m_nStatus == OK) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetLocalBBox( BBox3d& b3Loc) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// assegno il box in locale
b3Loc.Reset() ;
for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
if ( m_vVert[i].nIdTria != VT_DEL)
b3Loc.Add( m_vVert[i].ptP) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetBBox( const Frame3d& frRef, BBox3d& b3Ref) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// assegno il box nel riferimento
b3Ref.Reset() ;
for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
if ( m_vVert[i].nIdTria != VT_DEL) {
Point3d ptTemp = m_vVert[i].ptP ;
ptTemp.ToGlob( frRef) ;
b3Ref.Add( ptTemp) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Translate( const Vector3d& vtMove)
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// traslo i vertici
for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
if ( m_vVert[i].nIdTria != VT_DEL)
m_vVert[i].ptP.Translate( vtMove) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità dell'asse di rotazione
if ( vtAx.IsSmall())
return false ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// ruoto i vertici
for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
if ( m_vVert[i].nIdTria != VT_DEL)
m_vVert[i].ptP.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
}
// ruoto le normali delle facce
for ( int i = 0 ; i < GetTriangleNum() ; ++ i) {
if ( m_vTria[i].nIdVert[0] != VT_DEL)
m_vTria[i].vtN.Rotate( vtAx, dCosAng, dSinAng) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico non sia nulla
if ( fabs( dCoeffX) < EPS_ZERO && fabs( dCoeffY) < EPS_ZERO && fabs( dCoeffZ) < EPS_ZERO)
return false ;
// determino se contiene anche un mirror (numero dispari di coefficienti negativi)
bool bMirror = ( dCoeffX < 0) ;
bMirror = ( bMirror ? ( dCoeffY > 0) : ( dCoeffY < 0)) ;
bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// scalo i vertici
for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
if ( m_vVert[i].nIdTria != VT_DEL)
m_vVert[i].ptP.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
}
// aggiorno le facce
for ( int i = 0 ; i < GetTriangleNum() ; ++ i) {
if ( m_vTria[i].nIdVert[0] != VT_DEL) {
// se c'è mirror, devo invertire la faccia
if ( bMirror && ! InvertTriangle( i))
return false ;
// aggiorno la normale
if ( ! CalcTriangleNormal( i))
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::InvertTriangle( int nT)
{
// controllo validità triangolo
if ( m_vTria[nT].nIdVert[0] == VT_DEL)
return false ;
// scambio di due vertici
swap( m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]) ;
// scambio delle conseguenti due adiacenze
swap( m_vTria[nT].nIdAdjac[0], m_vTria[nT].nIdAdjac[2]) ;
// inversione della normale
m_vTria[nT].vtN *= - 1 ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::CalcTriangleNormal( int nT)
{
// controllo validità triangolo
if ( m_vTria[nT].nIdVert[0] == VT_DEL)
return false ;
// controllo validità vertici riferiti dal triangolo
if ( m_vTria[nT].nIdVert[0] >= GetVertexNum() ||
m_vVert[m_vTria[nT].nIdVert[0]].nIdTria == VT_DEL ||
m_vTria[nT].nIdVert[1] >= GetVertexNum() ||
m_vVert[m_vTria[nT].nIdVert[1]].nIdTria == VT_DEL ||
m_vTria[nT].nIdVert[2] >= GetVertexNum() ||
m_vVert[m_vTria[nT].nIdVert[2]].nIdTria == VT_DEL)
return false ;
// calcolo vettori come due lati consecutivi del triangolo
Vector3d vtV1 = m_vVert[m_vTria[nT].nIdVert[1]].ptP - m_vVert[m_vTria[nT].nIdVert[0]].ptP ;
Vector3d vtV2 = m_vVert[m_vTria[nT].nIdVert[2]].ptP - m_vVert[m_vTria[nT].nIdVert[1]].ptP ;
Vector3d vtN = vtV1 ^ vtV2 ;
// normale da prodotto vettoriale
if ( ! vtN.Normalize())
return false ;
m_vTria[nT].vtN = vtN ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del piano di specchiatura
if ( vtNorm.IsSmall())
return false ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
// specchio i vertici
for ( int i = 0 ; i < GetVertexNum() ; ++ i)
m_vVert[i].ptP.Mirror( ptOn, vtNorm) ;
// inverto le facce
for ( int i = 0 ; i < GetTriangleNum() ; ++ i) {
if ( m_vTria[i].nIdVert[0] != VT_DEL) {
if ( ! InvertTriangle( i))
return false ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::ToGlob( const Frame3d& frRef)
{
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// trasformo i vertici
for ( int i = 0 ; i < GetVertexNum() ; ++ i)
m_vVert[i].ptP.ToGlob( frRef) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::ToLoc( const Frame3d& frRef)
{
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// verifico validità del frame
if ( frRef.GetType() == Frame3d::ERR)
return false ;
// trasformo i vertici
for ( int i = 0 ; i < GetVertexNum() ; ++ i)
m_vVert[i].ptP.ToLoc( frRef) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
return true ;
}