//---------------------------------------------------------------------------- // 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 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( 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 ; }