From 79978655d3e2fa33d2b1df6a2df75446c69648ed Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Thu, 27 Mar 2014 22:15:42 +0000 Subject: [PATCH] EgtGeomKernel : - prima versione delle superfici trimesh. --- CurveArc.cpp | 12 +- CurveBezier.cpp | 4 +- CurveLine.cpp | 4 +- EgtGeomKernel.vcxproj | 7 +- GeomDB.cpp | 8 +- SurfTriMesh.cpp | 1470 ++++++++++------------------------------- SurfTriMesh.h | 93 ++- 7 files changed, 419 insertions(+), 1179 deletions(-) diff --git a/CurveArc.cpp b/CurveArc.cpp index d207e09..43db995 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -197,17 +197,17 @@ bool CurveArc::Save( ostream& osOut) const { // centro - osOut << ToString( m_PtCen) ; + osOut << ToString( m_PtCen) << ";" ; // versore Normale - osOut << ";" << ToString( m_VtN) ; + osOut << ToString( m_VtN) << ";" ; // raggio - osOut << ";" << ToString( m_dRad) ; + osOut << ToString( m_dRad) << ";" ; // versore Iniziale - osOut << ";" << ToString( m_VtS) ; + osOut << ToString( m_VtS) << ";" ; // angolo al centro - osOut << ";" << ToString( m_dAngCenDeg) ; + osOut << ToString( m_dAngCenDeg) << ";" ; // deltaN - osOut << ";" << ToString( m_dDeltaN) << ";" << endl ; + osOut << ToString( m_dDeltaN) << ";" << endl ; return true ; } diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 1f4edec..55635e6 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -342,9 +342,9 @@ bool CurveBezier::Save( ostream& osOut) const { // flag razionale - osOut << m_bRat ; + osOut << ToString( m_bRat) << ";" ; // grado - osOut << ";" << ToString( m_nDeg) << ";" << endl ; + osOut << ToString( m_nDeg) << ";" << endl ; // ciclo sui punti di controllo ( con pesi se razionale) for ( int i = 0 ; i <= m_nDeg ; ++ i) { if ( ! m_bRat) diff --git a/CurveLine.cpp b/CurveLine.cpp index c3672ee..03a9044 100644 --- a/CurveLine.cpp +++ b/CurveLine.cpp @@ -115,8 +115,8 @@ bool CurveLine::Save( ostream& osOut) const { // parametri : punti iniziale e finale - osOut << ToString( m_PtStart) ; - osOut << ";" << ToString( m_PtEnd) << ";" << endl ; + osOut << ToString( m_PtStart) << ";"; + osOut << ToString( m_PtEnd) << ";" << endl ; return true ; } diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index d62e98d..e1eca63 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -263,12 +263,7 @@ copy $(TargetPath) \EgtProg\Dll64 Create - - true - true - true - true - + diff --git a/GeomDB.cpp b/GeomDB.cpp index 88ff9e5..753ab3d 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -256,10 +256,10 @@ GeomDB::SaveHeader( ostream& osOut) const osOut << "MAT_DEF" << endl ; Color colDef( 0, 0, 0, 0) ; GetDefaultMaterial( colDef) ; - osOut << ToString( colDef.GetIntRed()) ; - osOut << "," << ToString( colDef.GetIntGreen()) ; - osOut << "," << ToString( colDef.GetIntBlue()) ; - osOut << "," << ToString( colDef.GetIntAlpha()) << ";" << endl ; + osOut << ToString( colDef.GetIntRed()) << "," ; + osOut << ToString( colDef.GetIntGreen()) << "," ; + osOut << ToString( colDef.GetIntBlue()) << "," ; + osOut << ToString( colDef.GetIntAlpha()) << ";" << endl ; return true ; } diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index ab751f0..cbf469c 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -14,7 +14,7 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "DllMain.h" -#include "CurveBezier.h" +#include "SurfTriMesh.h" #include "GeoConst.h" #include "DistPointLine.h" #include "GeoObjFactory.h" @@ -30,301 +30,241 @@ using namespace std ; GEOOBJ_REGISTER( SRF_TRIMESH, "S_TRM", SurfTriMesh) ; //---------------------------------------------------------------------------- -CurveBezier::CurveBezier( void) - : m_nStatus( TO_VERIFY), m_nDeg( 0), m_bRat( false), m_dParSing( -2), - m_nDimArr( 0), m_aPtCtrl( nullptr), m_aWeCtrl( nullptr) +SurfTriMesh::SurfTriMesh( void) + : m_nStatus( TO_VERIFY), m_bClosed( false) { } //---------------------------------------------------------------------------- -CurveBezier::~CurveBezier( void) +SurfTriMesh::~SurfTriMesh( void) { - if ( m_nDimArr > 0) { - delete [] m_aPtCtrl ; - delete [] m_aWeCtrl ; - } - m_nDimArr = 0 ; } //---------------------------------------------------------------------------- bool -CurveBezier::Init( int nDeg, bool bIsRational) +SurfTriMesh::Init( int nNumVert, int nNumTria) { - - // verifico validità grado - if ( nDeg < 1 || nDeg > MAXDEG) + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + // verifico validità parametri + if ( nNumVert < 3 || nNumTria < 1) return false ; - - // se spazio dinamico sufficiente - if ( ( nDeg + 1) <= m_nDimArr) - ; - // se altrimenti spazio statico sufficiente - else if ( ( nDeg + 1) <= ST_PTC) { - m_aPtCtrl = m_aStPtCtrl ; - if ( bIsRational) - m_aWeCtrl = m_aStWeCtrl ; + // prealloco la memoria + try { + m_vVert.reserve( nNumVert) ; + m_vTria.reserve( nNumTria) ; } - // altrimenti - else { - // se necessaria, pulizia - if ( m_nDimArr > 0) { - delete [] m_aPtCtrl ; - delete [] m_aWeCtrl ; - } - // alloco punti - m_aPtCtrl = new Point3d [ nDeg + 1] ; - if ( m_aPtCtrl == nullptr) - return false ; - // se razionale, alloco pesi - if ( bIsRational) { - m_aWeCtrl = new double [ nDeg + 1] ; - if ( m_aWeCtrl == nullptr) { - delete [] m_aPtCtrl ; - return false ; - } - } - // salvo dimensione array allocati - m_nDimArr = nDeg + 1 ; - } - - // salvo il grado - m_nDeg = nDeg ; - - // salvo flag di razionale - m_bRat = bIsRational ; - - // dichiaro non si è ancora fatta analisi presenza singolarità - m_dParSing = - 2 ; - - // pulisco, assegnando 0 ai punti e 1 ai pesi - memset( m_aPtCtrl, 0, sizeof( Point3d) * ( m_nDeg + 1)) ; - if ( m_bRat) { - for ( int i = 0 ; i <= m_nDeg ; ++ i) - m_aWeCtrl[i] = 1 ; + catch (...) { + return false ; } + // completo inizializzazione m_nStatus = TO_VERIFY ; - - // imposto ricalcolo della grafica - m_OGrMgr.Reset() ; - - return Validate() ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl) -{ - // verifico validità indice - if ( m_nStatus != OK || m_bRat || nInd < 0 || nInd > m_nDeg) - return false ; - - // assegno il valore - m_aPtCtrl[nInd] = ptCtrl ; - - // se razionale, metto il peso a 1 - if ( m_bRat) - m_aWeCtrl[nInd] = 1 ; - - // annullo analisi presenza singolarità - m_dParSing = - 2 ; - - // imposto ricalcolo della grafica - m_OGrMgr.Reset() ; + m_bClosed = false ; return true ; } //---------------------------------------------------------------------------- -bool -CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) +int +SurfTriMesh::AddVertex( const Point3d& ptVert) { - // verifico validità, razionalità e indice - if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg) - return false ; - - // verifico che il peso non sia nullo o negativo - if ( dW < EPS_SMALL) - return false ; - - // assegno il valore e il peso - m_aPtCtrl[nInd] = ptCtrl ; - m_aWeCtrl[nInd] = dW ; - - // annullo analisi presenza singolarità - m_dParSing = - 2 ; - // imposto ricalcolo della grafica m_OGrMgr.Reset() ; - - return true ; + // inserisco il vertice + try { m_vVert.push_back( StmVert( ptVert)) ;} + catch(...) { return - 1 ;} + // ne determino l'indice + return int( m_vVert.size() - 1) ; } //---------------------------------------------------------------------------- bool -CurveBezier::FromArc( const ICurveArc& crArc) +SurfTriMesh::SetVertex( int nInd, const StmVert& vV) { - const double MAX_ANG_CEN_DEG = 120 ; - double dAngCen ; - double dCosAhalf ; - double dW ; - Point3d ptStart ; - Point3d ptEnd ; - Point3d ptEndNoDN ; - Point3d ptMed ; - Point3d ptNew ; - Point3d ptNew1 ; - Point3d ptNew2 ; - Vector3d vtDeltaN ; - Vector3d vtDir ; - - - if ( ! crArc.IsValid()) - return false ; - dAngCen = crArc.GetAngCenter() ; - if ( fabs( dAngCen) > MAX_ANG_CEN_DEG) - return false ; - dCosAhalf = cos( 0.5 * dAngCen * DEGTORAD) ; - - // se arco piatto, basta quadrica razionale - // algoritmo di Sederberg (BYU) CAGD cap. 2 pag. 33 - if ( fabs( crArc.GetDeltaN()) < EPS_ZERO) { - // peso del punto di controllo intermedio - dW = dCosAhalf ; - // calcolo dei punti di controllo - crArc.GetStartPoint( ptStart) ; - crArc.GetEndPoint( ptEnd) ; - ptMed = Media( ptStart, ptEnd, 0.5) ; - vtDir = ptMed - crArc.GetCenter() ; - ptNew = crArc.GetCenter() + vtDir / ( dCosAhalf * dCosAhalf) ; - // inserimento nella curva dei punti di controllo con i pesi - Init( 2, true) ; - SetControlPoint( 0, ptStart, 1) ; - SetControlPoint( 1, ptNew, dW) ; - SetControlPoint( 2, ptEnd, 1) ; + // 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 ; } - // altrimenti per elica serve cubica razionale - // algoritmo di Juhasz HelixApproxByCubicBezier CAD 1995 - else { - // peso dei punti di controllo intermedi - dW = ( 1 + 2 * dCosAhalf) / 3 ; - // calcolo dei punti di controllo - crArc.GetStartPoint( ptStart) ; - crArc.GetEndPoint( ptEnd) ; - vtDeltaN = crArc.GetDeltaN() * crArc.GetNormVersor() ; - ptEndNoDN = ptEnd - vtDeltaN ; - ptMed = Media( ptStart, ptEndNoDN, 0.5) ; - vtDir = ptMed - crArc.GetCenter() ; - ptNew = crArc.GetCenter() + vtDir / ( dCosAhalf * dCosAhalf) ; - ptNew1 = ( ptStart + 2 * dCosAhalf * ptNew) / ( 1 + 2 * dCosAhalf) + - 0.5 * ( 1 - dCosAhalf / ( 2 + dCosAhalf)) * vtDeltaN ; - ptNew2 = ( ptEndNoDN + 2 * dCosAhalf * ptNew) / ( 1 + 2 * dCosAhalf) + - 0.5 * ( 1 + ( dCosAhalf / ( 2 + dCosAhalf))) * vtDeltaN ; - // inserimento nella curva dei punti di controllo con i pesi - Init( 3, true) ; - SetControlPoint( 0, ptStart, 1) ; - SetControlPoint( 1, ptNew1, dW) ; - SetControlPoint( 2, ptNew2, dW) ; - SetControlPoint( 3, ptEnd, 1) ; - } - + // inserisco il vertice + m_vVert[nInd] = vV ; return true ; } //---------------------------------------------------------------------------- -const Point3d& -CurveBezier::GetControlPoint( int nInd, bool* pbOk) const +int +SurfTriMesh::AddTriangle( const int nIdVert[3]) { - // verifico validità e indice - if ( m_nStatus != OK || nInd < 0 || nInd > m_nDeg) { - if ( pbOk != NULL) - *pbOk = false ; - return ORIG ; - } - // ritorno i dati - if ( pbOk != NULL) - *pbOk = true ; - return m_aPtCtrl[nInd] ; + // 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) ; } //---------------------------------------------------------------------------- -double -CurveBezier::GetControlWeight( int nInd, bool* pbOk) const +bool +SurfTriMesh::SetTriangle( int nInd, const StmTria& tT) { - // verifico validità, razionalità e indice - if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg) { - if ( pbOk != NULL) - *pbOk = false ; - return 0 ; + // 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 ; } - // ritorno i dati - if ( pbOk != NULL) - *pbOk = true ; - return m_aWeCtrl[nInd] ; + // inserisco il vertice + m_vTria[nInd] = tT ; + return true ; } //---------------------------------------------------------------------------- -CurveBezier* -CurveBezier::Clone( void) const +int +SurfTriMesh::GetFirstTriangle( Point3d& ptP0, Point3d& ptP1, Point3d& ptP2) const { - CurveBezier* pCrv ; + 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 - pCrv = new(nothrow) CurveBezier ; - if ( pCrv != nullptr) - *pCrv = *(const_cast(this)) ; + SurfTriMesh* pStm = new(nothrow) SurfTriMesh ; + if ( pStm != nullptr) { + if ( ! pStm->Copy( *this)) { + delete pStm ; + return nullptr ; + } + } - return pCrv ; + 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& -CurveBezier::GetTitle( void) const +SurfTriMesh::GetTitle( void) const { - static const string sTitle = "CBezier" ; + static const string sTitle = "TriMesh" ; return sTitle ; } //---------------------------------------------------------------------------- bool -CurveBezier::Dump( string& sOut, const char* szNewLine) const +SurfTriMesh::Dump( string& sOut, const char* szNewLine) const { - // flag razionale - sOut += ( m_bRat ? "Rat " : "Int ") ; - // grado - sOut += "Deg=" + ToString( m_nDeg) + szNewLine ; - // ciclo sui punti di controllo ( con pesi se razionale) - for ( int i = 0 ; i <= m_nDeg ; ++ i) { - sOut += "PC(" + ToString( m_aPtCtrl[i]) ; - if ( m_bRat) - sOut += "," + ToString( m_aWeCtrl[i]) ; - sOut += string( ")") + szNewLine ; - } + // 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& -CurveBezier::GetKey( void) const +SurfTriMesh::GetKey( void) const { - return GEOOBJ_GETKEY( CurveBezier) ; + return GEOOBJ_GETKEY( SurfTriMesh) ; } //---------------------------------------------------------------------------- bool -CurveBezier::Save( ostream& osOut) const +SurfTriMesh::Save( ostream& osOut) const { - // flag razionale - osOut << m_bRat ; - // grado - osOut << ";" << ToString( m_nDeg) << ";" << endl ; - // ciclo sui punti di controllo ( con pesi se razionale) - for ( int i = 0 ; i <= m_nDeg ; ++ i) { - if ( ! m_bRat) - osOut << ToString( m_aPtCtrl[i]) << ";" << endl ; - else - osOut << ToString( m_aPtCtrl[i], m_aWeCtrl[i]) << ";" << endl ; + // 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 ; @@ -332,7 +272,7 @@ CurveBezier::Save( ostream& osOut) const //---------------------------------------------------------------------------- bool -CurveBezier::Load( Scanner& TheScanner) +SurfTriMesh::Load( Scanner& TheScanner) { // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -343,52 +283,65 @@ CurveBezier::Load( Scanner& TheScanner) // la divido in parametri STRVECTOR vsParams ; Tokenize( sLine, ";", vsParams) ; - // 2 parametri : flag razionale e grado - if ( vsParams.size() != 2) + // 3 parametri : flag chiuso num vertici e num tria + if ( vsParams.size() != 3) return false ; // recupero il flag - bool bIsRat ; - if ( ! FromString( vsParams[0], bIsRat)) + bool bClosed ; + if ( ! FromString( vsParams[0], bClosed)) return false ; - // recupero il grado - int nDeg ; - if ( ! FromString( vsParams[1], nDeg)) + // recupero il numero di vertici + int nNumVert ; + if ( ! FromString( vsParams[1], nNumVert)) return false ; - // inizializzo la curva di Bezier - if ( ! Init( nDeg, bIsRat)) + // recupero il numero di triangoli + int nNumTria ; + if ( ! FromString( vsParams[2], nNumTria)) return false ; - // se integrale - if ( ! bIsRat) { - // recupero e setto punti di controllo - string sLine ; - Point3d ptP ; - for ( int i = 0 ; i <= nDeg ; ++ i) { - // leggo la prossima linea - if ( ! TheScanner.GetLine( sLine)) - return false ; - TrimRight( sLine, ";") ; - // la interpreto - if ( ! FromString( sLine, ptP) || - ! SetControlPoint( i, ptP)) - 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 ; } - // altrimenti razionale - else { - // recupero e setto punti di controllo - string sLine ; - Point3d ptP ; - double dW ; - for ( int i = 0 ; i <= nDeg ; ++ i) { - // leggo la prossima linea - if ( ! TheScanner.GetLine( sLine)) - return false ; - TrimRight( sLine, ";") ; - // la interpreto - if ( ! FromString( sLine, ptP, dW) || - ! SetControlPoint( i, ptP, dW)) - 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() ; @@ -396,31 +349,35 @@ CurveBezier::Load( Scanner& TheScanner) //---------------------------------------------------------------------------- bool -CurveBezier::Validate( void) +SurfTriMesh::Validate( void) { + // !!! DA FARE !!! + if ( m_nStatus == TO_VERIFY) - m_nStatus = ( ( m_nDeg > 0 && m_aPtCtrl != nullptr) ? OK : ERR) ; + m_nStatus = OK ; return ( m_nStatus == OK) ; } //---------------------------------------------------------------------------- bool -CurveBezier::GetLocalBBox( BBox3d& b3Loc) const +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 <= m_nDeg ; ++ i) - b3Loc.Add( m_aPtCtrl[i]) ; + for ( int i = 0 ; i < GetVertexNum() ; ++ i) { + if ( m_vVert[i].nIdTria != VT_DEL) + b3Loc.Add( m_vVert[i].ptP) ; + } return true ; } //---------------------------------------------------------------------------- bool -CurveBezier::GetBBox( const Frame3d& frRef, BBox3d& b3Ref) const +SurfTriMesh::GetBBox( const Frame3d& frRef, BBox3d& b3Ref) const { // verifico lo stato if ( m_nStatus != OK) @@ -430,10 +387,12 @@ CurveBezier::GetBBox( const Frame3d& frRef, BBox3d& b3Ref) const return false ; // assegno il box nel riferimento b3Ref.Reset() ; - for ( int i = 0 ; i <= m_nDeg ; ++ i) { - Point3d ptTemp = m_aPtCtrl[i] ; - ptTemp.ToGlob( frRef) ; - b3Ref.Add( ptTemp) ; + 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 ; @@ -441,845 +400,29 @@ CurveBezier::GetBBox( const Frame3d& frRef, BBox3d& b3Ref) const //---------------------------------------------------------------------------- bool -CurveBezier::GetStartPoint( Point3d& ptStart) const +SurfTriMesh::Translate( const Vector3d& vtMove) { - // verifico lo stato + // la superficie deve essere validata if ( m_nStatus != OK) return false ; - // assegno il punto - ptStart = m_aPtCtrl[0] ; - - return true ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::GetEndPoint( Point3d& ptEnd) const -{ - // verifico lo stato - if ( m_nStatus != OK) - return false ; - - // assegno il punto - ptEnd = m_aPtCtrl[m_nDeg] ; - - return true ; -} - -//---------------------------------------------------------------------------- -// Calcolo i polinomi di Bernstein e da questi il punto ( vedi Piegl-Tiller) -//---------------------------------------------------------------------------- -bool -CurveBezier::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, Vector3d* pvtDer2) const -{ - int i ; - double dBern[MAXDEG] ; - - - // la curva deve essere validata - if ( m_nStatus != OK) - return false ; - - // il parametro U deve essere compreso tra 0 e 1 - if ( dU < 0) - dU = 0 ; - else if ( dU > 1) - dU = 1 ; - - // se forma polinomiale (o integrale) - if ( ! m_bRat) { - - // calcolo dei polinomi di Bernstein di grado opportuno - dBern[0] = 1 ; - for ( i = 1 ; i <= m_nDeg - 2 ; ++ i) - IncreaseBernsteinOneDegree( dU, i, dBern) ; - - // se richiesto, calcolo della derivata seconda - if ( pvtDer2 != nullptr && pvtDer1 != nullptr) { - pvtDer2->Set( 0, 0, 0) ; - for ( i = 0 ; i <= m_nDeg - 2 ; ++ i) { - *pvtDer2 += dBern[i] * ( m_aPtCtrl[i+2] + m_aPtCtrl[i] - 2 * m_aPtCtrl[i+1]) ; - } - *pvtDer2 *= m_nDeg * ( m_nDeg - 1) ; - } - - // aumento il grado - IncreaseBernsteinOneDegree( dU, m_nDeg - 1, dBern) ; - - // se richiesto, calcolo della derivata prima - if ( pvtDer1 != nullptr) { - pvtDer1->Set( 0, 0, 0) ; - for ( i = 0 ; i <= m_nDeg - 1 ; ++ i) { - *pvtDer1 += dBern[i] * ( m_aPtCtrl[i+1] - m_aPtCtrl[i]) ; - } - *pvtDer1 *= m_nDeg ; - } - - // aumento il grado - IncreaseBernsteinOneDegree( dU, m_nDeg, dBern) ; - - // calcolo del punto - ptPos.Set( 0, 0, 0) ; - for ( i = 0 ; i <= m_nDeg ; ++ i) - ptPos += dBern[i] * m_aPtCtrl[i] ; - } - - // altrimenti forma razionale - else { - double dW ; - double dW1 ; - double dW2 ; - double dInvW ; - Point3d aPtWCtrl[MAXDEG] ; - Vector3d vtPos ; - - // porto i punti in forma omogenea moltiplicandoli per i pesi - for ( i = 0 ; i <= m_nDeg ; ++ i) - aPtWCtrl[i] = m_aWeCtrl[i] * m_aPtCtrl[i] ; - - // calcolo dei polinomi di Bernstein di grado opportuno - dBern[0] = 1 ; - for ( i = 1 ; i <= m_nDeg - 2 ; ++ i) - IncreaseBernsteinOneDegree( dU, i, dBern) ; - - // se richiesto, calcolo della derivata seconda - if ( pvtDer2 != nullptr && pvtDer1 != nullptr) { - pvtDer2->Set( 0, 0, 0) ; dW2 = 0 ; - for ( i = 0 ; i <= m_nDeg - 2 ; ++ i) { - *pvtDer2 += dBern[i] * ( aPtWCtrl[i+2] + aPtWCtrl[i] - 2 * aPtWCtrl[i+1]) ; - dW2 += dBern[i] * ( m_aWeCtrl[i+2] + m_aWeCtrl[i] - 2 * m_aWeCtrl[i+1]) ; - } - *pvtDer2 *= m_nDeg * ( m_nDeg - 1) ; - dW2 *= m_nDeg * ( m_nDeg - 1) ; - } - - // aumento il grado - IncreaseBernsteinOneDegree( dU, m_nDeg - 1, dBern) ; - - // se richiesto, calcolo della derivata prima - if ( pvtDer1 != nullptr) { - pvtDer1->Set( 0, 0, 0) ; dW1 = 0 ; - for ( i = 0 ; i <= m_nDeg - 1 ; ++ i) { - *pvtDer1 += dBern[i] * ( aPtWCtrl[i+1] - aPtWCtrl[i]) ; - dW1 += dBern[i] * ( m_aWeCtrl[i+1] - m_aWeCtrl[i]) ; - } - *pvtDer1 *= m_nDeg ; - dW1 *= m_nDeg ; - } - - // aumento il grado - IncreaseBernsteinOneDegree( dU, m_nDeg, dBern) ; - - // calcolo del punto - ptPos.Set( 0, 0, 0) ; dW = 0 ; - for ( i = 0 ; i <= m_nDeg ; ++ i) { - ptPos += dBern[i] * aPtWCtrl[i] ; - dW += dBern[i] * m_aWeCtrl[i] ; - } - - // ritrasformo da forma omogenea a forma standard - dInvW = 1 / ( ( dW > EPS_ZERO) ? dW : EPS_ZERO) ; - ptPos *= dInvW ; - if ( pvtDer1 != nullptr) { - vtPos.Set( ptPos.x, ptPos.y, ptPos.z) ; - *pvtDer1 = ( *pvtDer1 - dW1 * vtPos) * dInvW ; - if ( pvtDer2 != nullptr) - *pvtDer2 = ( *pvtDer2 - 2 * dW1 * *pvtDer1 - dW2 * vtPos) * dInvW ; - } - } - - return true ; -} - -//---------------------------------------------------------------------------- -void -CurveBezier::IncreaseBernsteinOneDegree( double dU, int nDeg, double dBern[]) const -{ - int j ; - double dU1 ; - double dTot ; - double dTmp ; - - - dU1 = 1 - dU ; - dTot = 0 ; - for ( j = 0 ; j < nDeg ; ++ j) { - dTmp = dBern[j] ; - dBern[j] = dTot + dU1 * dTmp ; - dTot = dU * dTmp ; - } - dBern[nDeg] = ( nDeg > 0 ? dTot : 1) ; - -} - -//---------------------------------------------------------------------------- -int -CurveBezier::GetSingularParam( double& dPar) const -{ - // se da calcolare, lo faccio - if ( m_dParSing < -1.5) - CalcSingularParam() ; - - // se esiste singolarità - if ( m_dParSing > 0 && m_dParSing < 1) { - dPar = m_dParSing ; - return 1 ; - } - // altrimenti, non esiste - else - return 0 ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::CalcSingularParam( void) const -{ - // non si considerano singolarità agli estremi ( non creano problemi) - - // le curve di grado 1 non possono avere singolarità - if ( m_nDeg <= 1) { - m_dParSing = -1 ; - return true ; - } - - // le curve di grado 2 possono avere singolarità solo se i punti sono allineati con ordine P0 P2 P1 - if ( m_nDeg == 2) { - Vector3d vtV1 = m_aPtCtrl[1] - m_aPtCtrl[0] ; - Vector3d vtV2 = m_aPtCtrl[2] - m_aPtCtrl[1] ; - if ( ( vtV1 * vtV2) > - EPS_ZERO) { - m_dParSing = -1 ; - return true ; - } - } - - // calcolo della derivata o del suo numeratore se curva razionale - PolynomialPoint3d pol3P ; - - // se polinomiale - if ( ! m_bRat) { - // derivata come curva di Bezier delle differenze tra i punti di controllo - CurveBezier cbDeriv ; - cbDeriv.Init( m_nDeg - 1, false) ; - for ( int i = 0 ; i < m_nDeg ; ++ i) - cbDeriv.SetControlPoint( i, m_nDeg * ( m_aPtCtrl[i+1] + ( - m_aPtCtrl[i]))) ; - // trasformo nella forma monomia - cbDeriv.ToPowerBase( pol3P) ; - } - // altrimenti razionale - else { - // numeratore e denominatore in forma monomia - PolynomialPoint3d pol3Num ; - Polynomial polDen ; - ToPowerBase( pol3Num, polDen) ; - // derivata del numeratore - PolynomialPoint3d pol3NumD ; - pol3NumD.Derive( pol3Num) ; - // derivata del denominatore - Polynomial polDenD ; - polDenD.Derive( polDen) ; - // numeratore della derivata complessiva ( NumD * Den - Num * DenD) - pol3P = pol3NumD * polDen - pol3Num * polDenD ; - pol3P.AdjustDegree() ; - } - - // calcolo gli zeri della componente più importante della derivata - DBLVECTOR vdRoot ; - int nZ = pol3P.FindMainComponentRoots( vdRoot) ; - // scarto gli zeri fuori dall'intervallo aperto 0-1 e quelli ripetuti - nZ = FilterMultipleAndOutOfRangeRoots( vdRoot, 0 + EPS_ZERO, 1 - EPS_ZERO, EPS_ZERO) ; - - // verifico se in corrispondenza di qualche zero si annulla la derivata - Point3d ptPos ; - Vector3d vtDer1 ; - for ( int i = 0 ; i < nZ ; ++ i) { - GetPointD1D2( vdRoot[i], FROM_MINUS, ptPos, &vtDer1) ; - if ( vtDer1.IsZero()) { - m_dParSing = vdRoot[i] ; - LOG_DBG_INFO( GetEGkLogger(), "INFO : Found Singularity in CurveBezier") - return true ; - } - } - - // non ci sono singolarità - m_dParSing = -1 ; - return true ; -} - -//---------------------------------------------------------------------------- -// i coefficienti sono ordinati dalla potenza più bassa alla più alta -// se razionale, ritorna la sola forma monomiale del numeratore -//---------------------------------------------------------------------------- -bool -CurveBezier::ToPowerBase( PolynomialPoint3d& pol3P) const -{ - // creo un vettore di punti ausiliario (pulito e di dimensioni adeguate) - PNTVECTOR vPow ; - vPow.clear() ; - vPow.reserve( m_nDeg + 1) ; - - // algoritmo di Sederberg (BYU) CAGD cap. 3 - // copio i punti di controllo - for ( int i = 0 ; i <= m_nDeg ; ++ i) - vPow.push_back( m_aPtCtrl[i]) ; - // se razionale, li moltiplico per i relativi pesi - if ( m_bRat) { - for ( int i = 0 ; i <= m_nDeg ; ++ i) - vPow[i] *= m_aWeCtrl[i] ; - } - // applico differenze successive, lasciando sul posto il risultato - for ( int i = 1 ; i <= m_nDeg ; ++ i) { - for ( int j = m_nDeg ; j >= i ; -- j) - vPow[j] += - vPow[j-1] ; - } - // calcolo i coefficienti binomiali - double dBinom[ MAXDEG+1] ; - dBinom[0] = 1 ; - for ( int i = 1 ; i <= m_nDeg ; ++ i) - dBinom[i] = 0 ; - for ( int i = 1 ; i <= m_nDeg ; ++ i) { - for ( int j = i ; j > 0 ; -- j) - dBinom[j] += dBinom[j-1] ; - } - // ottengo i coefficienti delle potenze - for ( int i = 1 ; i <= m_nDeg ; ++ i) - vPow[i] *= dBinom[i] ; - - // assegno il risultato al parametro di ritorno - pol3P.Set( m_nDeg, vPow) ; - - return true ; -} - -//---------------------------------------------------------------------------- -// i coefficienti sono ordinati dalla potenza più bassa alla più alta -// se polinomiale, la forma monomiale del denominatore è un 1 -//---------------------------------------------------------------------------- -bool -CurveBezier::ToPowerBase( PolynomialPoint3d& pol3Num, Polynomial& polDen) const -{ - // creo un vettore di punti ausiliario (pulito e di dimensioni adeguate) - PNTVECTOR vPow ; - vPow.reserve( m_nDeg + 1) ; - // creo un vettore di double ausiliario (pulito e di dimensioni adeguate) - DBLVECTOR dPow ; - if ( m_bRat) - dPow.reserve( m_nDeg + 1) ; - - // algoritmo di Sederberg (BYU) CAGD cap. 3 - // copio i punti di controllo - for ( int i = 0 ; i <= m_nDeg ; ++ i) - vPow.push_back( m_aPtCtrl[i]) ; - // se razionale - if ( m_bRat) { - // moltiplico i punti per i relativi pesi - for ( int i = 0 ; i <= m_nDeg ; ++ i) - vPow[i] *= m_aWeCtrl[i] ; - // copio i pesi - for ( int i = 0 ; i <= m_nDeg ; ++ i) - dPow.push_back( m_aWeCtrl[i]) ; - } - // applico differenze successive, lasciando sul posto il risultato - for ( int i = 1 ; i <= m_nDeg ; ++ i) { - for ( int j = m_nDeg ; j >= i ; -- j) { - vPow[j] += - vPow[j-1] ; - if ( m_bRat) - dPow[j] += - dPow[j-1] ; - } - } - // calcolo i coefficienti binomiali - double dBinom[ MAXDEG+1] ; - dBinom[0] = 1 ; - for ( int i = 1 ; i <= m_nDeg ; ++ i) - dBinom[i] = 0 ; - for ( int i = 1 ; i <= m_nDeg ; ++ i) { - for ( int j = i ; j > 0 ; -- j) - dBinom[j] += dBinom[j-1] ; - } - // ottengo i coefficienti delle potenze - for ( int i = 1 ; i <= m_nDeg ; ++ i) { - vPow[i] *= dBinom[i] ; - if ( m_bRat) - dPow[i] *= dBinom[i] ; - } - - // assegno i risultati ai parametri di ritorno - pol3Num.Set( m_nDeg, vPow) ; - if ( m_bRat) - polDen.Set( m_nDeg, dPow) ; - else - polDen.SetToConstant( 1) ; - - return true ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::GetControlPolygonLength( double& dLen) const -{ - // la curva deve essere valida - if ( m_nStatus != OK) - return false ; - - // ciclo sui punti di controllo - dLen = 0 ; - for ( int i = 1 ; i <= m_nDeg ; ++ i) - dLen += Dist( m_aPtCtrl[i], m_aPtCtrl[i-1]) ; - - return true ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::GetLength( double& dLen) const -{ - return ( GetLengthAtParam( 1, dLen) && dLen > EPS_SMALL) ; -} - -//---------------------------------------------------------------------------- -double -CurveBezier::GetSegmentLength( int nLev, double dU0, double dU1, double dU2, - const Point3d& ptP0, const Point3d& ptP1, const Point3d& ptP2) const -{ - const int MAX_LEV = 10 ; - const double MAX_ARC = 1.05 ; - const double LEN_RATIO = 1.2 ; - double dD1 ; - double dDa ; - double dDb ; - double dD2 ; - - - // algoritmo dell'approssimazione con arco per tre punti di S. Vincent e D. Forsey - - // verifica superamento del massimo livello di recursione per debug - if ( nLev >= MAX_LEV) - LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions") - - // calcolo delle distanze - dD1 = Dist( ptP0, ptP2) ; - dDa = Dist( ptP0, ptP1) ; - dDb = Dist( ptP1, ptP2) ; - dD2 = dDa + dDb ; - - // distanza piccola o massimo livello di recursione, approx arco ok - if ( dD2 < EPS_SMALL || nLev >= MAX_LEV) - return ( dD2 + ( dD2 - dD1) / 3) ; - - // se ci sono anomalie si suddivide - if ( dD1 < EPS_SMALL || dD2 / dD1 > MAX_ARC || - dDa < 0.1 * EPS_SMALL || dDb / dDa > LEN_RATIO || - dDb < 0.1 * EPS_SMALL || dDa / dDb > LEN_RATIO) { - - double dUMid ; - Point3d ptMid ; - - // prima metà - dUMid = 0.5 * ( dU0 + dU1) ; - GetPointD1D2( dUMid, ICurve::FROM_MINUS, ptMid) ; - double dD3 = GetSegmentLength( nLev +1, dU0, dUMid, dU1, - ptP0, ptMid, ptP1) ; - // seconda metà - dUMid = 0.5 * ( dU1 + dU2) ; - GetPointD1D2( dUMid, ICurve::FROM_MINUS, ptMid) ; - double dD4 = GetSegmentLength( nLev + 1, dU1, dUMid, dU2, - ptP1, ptMid, ptP2) ; - - // la lunghezza è la somma delle due - return ( dD3 + dD4) ; - } - - // caso normale - return ( dD2 + ( dD2 - dD1) / 3) ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::GetLengthAtParam( double dU, double& dLen) const -{ - const int NUM_SEG = 16 ; - double dUIni ; - double dUMid ; - double dUFin ; - Point3d ptIni ; - Point3d ptMid ; - Point3d ptFin ; - - - // la curva deve essere validata - if ( m_nStatus != OK) - return false ; - - // fuori dominio del parametro -> errore - if ( dU < 0 - EPS_ZERO) - return false ; - if ( dU > ( 1 + EPS_ZERO)) - return false ; - - // inizio - if ( dU < 0 + EPS_ZERO) { - dLen = 0 ; - return true ; - } - - // parto con un numero fisso di punti e poi affino dove serve - dLen = 0 ; - dUIni = 0 ; - GetPointD1D2( 0, ICurve::FROM_MINUS, ptIni) ; - for ( int i = 1 ; i <= NUM_SEG ; ++ i) { - // ricavo il punto - dUFin = i / (double) NUM_SEG * dU ; - GetPointD1D2( dUFin, ICurve::FROM_MINUS, ptFin) ; - // se punto dispari - if ( ( i % 2) == 1) { - // assegno nuovo medio - dUMid = dUFin ; - ptMid = ptFin ; - } - // se punto pari, calcolo la lunghezza - else { - dLen += GetSegmentLength( 0, dUIni, dUMid, dUFin, ptIni, ptMid, ptFin) ; - // nuovo iniziale prende i valori del finale - dUIni = dUFin ; - ptIni = ptFin ; - } - } - - return true ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::GetSegmentParam( double dLen, double& dCurrLen, double& dSegLen, - double& dUIni, double& dUFin) const -{ - const int NUM_SEG = 16 ; - double dUMid ; - Point3d ptIni ; - Point3d ptMid ; - Point3d ptFin ; - - - double dUStart = dUIni ; - double dUEnd = dUFin ; - GetPointD1D2( dUIni, ICurve::FROM_MINUS, ptIni) ; - for ( int i = 1 ; i <= NUM_SEG ; ++ i) { - // ricavo il punto - dUFin = dUStart + i / (double) NUM_SEG * ( dUEnd - dUStart) ; - GetPointD1D2( dUFin, ICurve::FROM_MINUS, ptFin) ; - // se punto dispari - if ( ( i % 2) == 1) { - // assegno nuovo medio - dUMid = dUFin ; - ptMid = ptFin ; - } - // se punto pari, calcolo la lunghezza - else { - dSegLen = GetSegmentLength( 0, dUIni, dUMid, dUFin, ptIni, ptMid, ptFin) ; - if ( ( dCurrLen + dSegLen) >= dLen) { - return true ; - } - else - dCurrLen += dSegLen ; - // nuovo iniziale prende i valori del finale - dUIni = dUFin ; - ptIni = ptFin ; - } - } - - return false ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::GetParamAtLength( double dLen, double& dU) const -{ - const double MAX_SEG_LEN = 0.2 ; - - // la curva deve essere validata - if ( m_nStatus != OK) - return false ; - - // inizio - if ( dLen < EPS_SMALL) { - dU = 0 ; - return true ; - } - - // approfondisco nell'intervallo di interesse - bool bOk ; - double dSegLen ; - double dCurrLen = 0 ; - double dUIni = 0 ; - double dUFin = 1 ; - while ( ( bOk = GetSegmentParam( dLen, dCurrLen, dSegLen, dUIni, dUFin)) && dSegLen > MAX_SEG_LEN) - ; - // aggiustamento finale parametro - if ( bOk) - dU = dUIni + ( dLen - dCurrLen) / dSegLen * ( dUFin - dUIni) ; - - return bOk ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParEnd, - double dLinTol, double dAngTolDeg, PolyLine& PL) const -{ - const int MAX_LEV = 10 ; - int i ; - double dMaxSqDist ; - double dSqDist ; - double dAngDeg ; - double dPolLen ; - double dLen ; - Point3d ptLast ; - Vector3d vtDirI ; - Vector3d vtDirF ; - Vector3d vtDir ; - - - // se raggiunto il massimo livello di recursione ... - if ( nLev >= MAX_LEV) { - // segnalo situazione per debug - LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions") - // considero la curva piatta (inserisco il punto se abbastanza lontano dal precedente) ed esco - PL.GetLastPoint( ptLast) ; - if ( SqDist( ptLast, crvBez.m_aPtCtrl[m_nDeg]) > ( dLinTol * dLinTol)) - PL.AddUPoint( dParEnd, crvBez.m_aPtCtrl[m_nDeg]) ; - return true ; - } - - // massima distanza al quadrato dei punti di controllo intermedi dalla linea tra primo e ultimo - dMaxSqDist = 0 ; - DirDist( crvBez.m_aPtCtrl[0], crvBez.m_aPtCtrl[m_nDeg], vtDir, dLen) ; - for ( i = 1 ; i < m_nDeg ; i ++) { - DistPointLine dstPL( crvBez.m_aPtCtrl[i], crvBez.m_aPtCtrl[0], vtDir, dLen) ; - if ( dstPL.GetSqDist( dSqDist) && dSqDist > dMaxSqDist) - dMaxSqDist = dSqDist ; - } - - // se distanza entro tolleranza - if ( dMaxSqDist <= ( dLinTol * dLinTol)) { - // deviazione angolare tra primo e ultimo tratto del poligono di controllo (grado >= 1) - vtDirI = crvBez.m_aPtCtrl[1] - crvBez.m_aPtCtrl[0] ; - vtDirF = crvBez.m_aPtCtrl[m_nDeg] - crvBez.m_aPtCtrl[m_nDeg-1] ; - vtDirI.GetAngle( vtDirF, dAngDeg) ; - // se deviazione angolare entro tolleranza oppure lunghezza poligono controllo entro tolleranza - if ( fabs( dAngDeg) <= dAngTolDeg || - ( crvBez.GetControlPolygonLength( dPolLen) && dPolLen <= dLinTol)) { - // considero la curva piatta (inserisco il punto se abbastanza lontano dal precedente) ed esco - PL.GetLastPoint( ptLast) ; - if ( SqDist( ptLast, crvBez.m_aPtCtrl[m_nDeg]) > ( dLinTol * dLinTol)) - PL.AddUPoint( dParEnd, crvBez.m_aPtCtrl[m_nDeg]) ; - return true ; - } - } - - // curva da dividere - { - double dParDiv ; - double dParMid ; - CurveBezier crvBez1 ; - // se prima suddivisione e c'è singolarità, divido su questa - if ( nLev == 0 && GetSingularParam( dParDiv) > 0) - ; - // altrimenti divido a metà - else - dParDiv = 0.5 ; - dParMid = dParDiv * ( dParStart + dParEnd) ; - // prima metà - crvBez1 = crvBez ; - crvBez1.TrimEndAtParam( dParDiv) ; - if ( ! FlatOrSplit( nLev + 1, crvBez1, dParStart, dParMid, dLinTol, dAngTolDeg, PL)) - return false ; - // seconda metà - crvBez1 = crvBez ; - crvBez1.TrimStartAtParam( dParDiv) ; - if ( ! FlatOrSplit( nLev + 1, crvBez1, dParMid, dParEnd, dLinTol, dAngTolDeg, PL)) - return false ; - } - - return true ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const -{ - // la curva deve essere validata - if ( m_nStatus != OK) - return false ; - - // se di primo grado, basta inserire gli estremi - if ( m_nDeg == 1) { - PL.AddUPoint( 0, m_aPtCtrl[0]) ; - PL.AddUPoint( 1, m_aPtCtrl[m_nDeg]) ; - return true ; - } - - // limiti minimi su tolleranza e deviazione angolare - dLinTol = max( dLinTol, LIN_TOL_MIN) ; - dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ; - - // inserisco il punto iniziale - PL.AddUPoint( 0, m_aPtCtrl[0]) ; - - // verifico se va divisa - FlatOrSplit( 0, *this, 0, 1, dLinTol, dAngTolDeg, PL) ; - - // se è stato inserito un solo punto, aggiungo il finale - if ( PL.GetPointNbr() == 1) - PL.AddUPoint( 1, m_aPtCtrl[m_nDeg]) ; - - return true ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::Invert( void) -{ - // la curva deve essere valida - if ( m_nStatus != OK) - return false ; - - // inverto i punti di controllo - int nMid = ( m_nDeg + 1) / 2 ; - for ( int i = 0 ; i < nMid ; ++ i) { - Point3d ptTemp = m_aPtCtrl[i] ; - m_aPtCtrl[i] = m_aPtCtrl[m_nDeg-i] ; - m_aPtCtrl[m_nDeg-i] = ptTemp ; - } - // imposto ricalcolo della grafica m_OGrMgr.Reset() ; - - return true ; -} -//---------------------------------------------------------------------------- -bool -CurveBezier::TrimStartAtParam( double dUTrim) -{ - // la curva deve essere valida - if ( m_nStatus != OK) - return false ; - - // se devo togliere dall'inizio o prima non tolgo niente - if ( dUTrim <= 0) - return true ; - // se devo togliere a partire dalla fine o dopo non rimane niente - if ( dUTrim >= 1) - return false ; - // eseguo il trim (algoritmo di de Casteljau) - for ( int k = 1 ; k <= m_nDeg ; k ++) { - for ( int i = 0 ; i <= m_nDeg - k ; i ++) { - if ( ! m_bRat) { - m_aPtCtrl[i] = ( 1 - dUTrim) * m_aPtCtrl[i] + dUTrim * m_aPtCtrl[i+1] ; - } - else { - m_aPtCtrl[i] = ( 1 - dUTrim) * m_aWeCtrl[i] * m_aPtCtrl[i] + dUTrim * m_aWeCtrl[i+1] * m_aPtCtrl[i+1] ; - m_aWeCtrl[i] = ( 1 - dUTrim) * m_aWeCtrl[i] + dUTrim * m_aWeCtrl[i+1] ; - m_aPtCtrl[i] = m_aPtCtrl[i] * ( 1 / m_aWeCtrl[i]) ; - } - } + // traslo i vertici + for ( int i = 0 ; i < GetVertexNum() ; ++ i) { + if ( m_vVert[i].nIdTria != VT_DEL) + m_vVert[i].ptP.Translate( vtMove) ; } - // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata - m_OGrMgr.Reset() ; - - return true ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::TrimEndAtParam( double dUTrim) -{ - // la curva deve essere valida - if ( m_nStatus != OK) - return false ; - - // se devo togliere a partire dall'inizio o prima non rimane niente - if ( dUTrim <= 0) - return false ; - // se devo togliere dalla fine o dopo non tolgo niente - if ( dUTrim >= 1) - return true ; - // eseguo il trim (algoritmo di de Casteljau) - for ( int k = 1 ; k <= m_nDeg ; k ++) { - for ( int i = m_nDeg ; i >= k ; i --) { - if ( ! m_bRat) { - m_aPtCtrl[i] = ( 1 - dUTrim) * m_aPtCtrl[i-1] + dUTrim * m_aPtCtrl[ i] ; - } - else { - m_aPtCtrl[i] = ( 1 - dUTrim) * m_aWeCtrl[i-1] * m_aPtCtrl[i-1] + dUTrim * m_aWeCtrl[ i] * m_aPtCtrl[ i] ; - m_aWeCtrl[i] = ( 1 - dUTrim) * m_aWeCtrl[i-1] + dUTrim * m_aWeCtrl[ i] ; - m_aPtCtrl[i] = m_aPtCtrl[i] * ( 1 / m_aWeCtrl[i]) ; - } - } - } - - // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata - m_OGrMgr.Reset() ; - - return true ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::TrimStartAtLen( double dLenTrim) -{ - // lunghezze negative vengono considerate nulle - dLenTrim = __max( dLenTrim, 0) ; - - // converto le lunghezze in valori parametrici - double dUTrim ; - if ( ! GetParamAtLength( dLenTrim, dUTrim)) - return false ; - - // utilizzo il trim sui parametri - return TrimStartAtParam( dUTrim) ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::TrimEndAtLen( double dLenTrim) -{ - // lunghezze negative vengono considerate nulle - dLenTrim = __max( dLenTrim, 0) ; - - // converto le lunghezze in valori parametrici - double dUTrim ; - if ( ! GetParamAtLength( dLenTrim, dUTrim)) - return false ; - - // utilizzo il trim sui parametri - return TrimEndAtParam( dUTrim) ; -} - -//---------------------------------------------------------------------------- -bool -CurveBezier::Translate( const Vector3d& vtMove) -{ - // la curva deve essere validata - if ( m_nStatus != OK) - return false ; - - // traslo i punti di controllo - for ( int i = 0 ; i <= m_nDeg ; ++ i) - m_aPtCtrl[i].Translate( vtMove) ; - - // imposto ricalcolo della grafica - m_OGrMgr.Reset() ; - return true ; } //---------------------------------------------------------------------------- bool -CurveBezier::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) +SurfTriMesh::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng) { - // la curva deve essere validata + // la superficie deve essere validata if ( m_nStatus != OK) return false ; @@ -1287,21 +430,29 @@ CurveBezier::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, if ( vtAx.IsSmall()) return false ; - // ruoto i punti di controllo - for ( int i = 0 ; i <= m_nDeg ; ++ i) - m_aPtCtrl[i].Rotate( ptAx, vtAx, dCosAng, dSinAng) ; - // 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 -CurveBezier::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ) +SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ) { - // la curva deve essere validata + // la superficie deve essere validata if ( m_nStatus != OK) return false ; @@ -1309,21 +460,82 @@ CurveBezier::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double if ( fabs( dCoeffX) < EPS_ZERO && fabs( dCoeffY) < EPS_ZERO && fabs( dCoeffZ) < EPS_ZERO) return false ; - // scalo i punti di controllo - for ( int i = 0 ; i <= m_nDeg ; ++ i) - m_aPtCtrl[i].Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; + // 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 -CurveBezier::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) +SurfTriMesh::InvertTriangle( int nT) { - // la curva deve essere validata + // 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 ; @@ -1331,19 +543,27 @@ CurveBezier::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) if ( vtNorm.IsSmall()) return false ; - // specchio i punti di controllo - for ( int i = 0 ; i <= m_nDeg ; ++ i) - m_aPtCtrl[i].Mirror( ptOn, vtNorm) ; - // 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 -CurveBezier::ToGlob( const Frame3d& frRef) +SurfTriMesh::ToGlob( const Frame3d& frRef) { // la curva deve essere validata if ( m_nStatus != OK) @@ -1353,9 +573,9 @@ CurveBezier::ToGlob( const Frame3d& frRef) if ( frRef.GetType() == Frame3d::ERR) return false ; - // trasformo i punti di controllo - for ( int i = 0 ; i <= m_nDeg ; ++ i) - m_aPtCtrl[i].ToGlob( frRef) ; + // trasformo i vertici + for ( int i = 0 ; i < GetVertexNum() ; ++ i) + m_vVert[i].ptP.ToGlob( frRef) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1365,7 +585,7 @@ CurveBezier::ToGlob( const Frame3d& frRef) //---------------------------------------------------------------------------- bool -CurveBezier::ToLoc( const Frame3d& frRef) +SurfTriMesh::ToLoc( const Frame3d& frRef) { // la curva deve essere validata if ( m_nStatus != OK) @@ -1375,9 +595,9 @@ CurveBezier::ToLoc( const Frame3d& frRef) if ( frRef.GetType() == Frame3d::ERR) return false ; - // trasformo i punti di controllo - for ( int i = 0 ; i <= m_nDeg ; ++ i) - m_aPtCtrl[i].ToLoc( frRef) ; + // trasformo i vertici + for ( int i = 0 ; i < GetVertexNum() ; ++ i) + m_vVert[i].ptP.ToLoc( frRef) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 22052d8..39b882b 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -14,9 +14,49 @@ #pragma once #include "ObjGraphicsMgr.h" +#include "DllMain.h" #include "/EgtDev/Include/EGkSurfTriMesh.h" #include +//---------------------------------------------------------------------------- +const int VT_NULL = - 1 ; // vertice o triangolo nullo +const int VT_DEL = - 2 ; // vertice o triangolo cancellato + +//---------------------------------------------------------------------------- +class StmVert +{ + public : + StmVert( void) : ptP(), nIdTria( VT_NULL), nFlag( 0) {} + StmVert( const Point3d& ptQ) : ptP( ptQ), nIdTria( VT_NULL), nFlag( 0) {} + StmVert( const Point3d& ptQ, int nIdT, int nF) : ptP( ptQ), nIdTria( nIdT), nFlag( nF) {} + public : + Point3d ptP ; + int nIdTria ; + int nFlag ; +} ; + +//---------------------------------------------------------------------------- +class StmTria +{ + public : + StmTria( void) : vtN(), nTFlag( 0), nEFlag( 0) + { nIdVert[0] = VT_NULL ; nIdVert[1] = VT_NULL ; nIdVert[2] = VT_NULL ; + nIdAdjac[0] = VT_NULL ; nIdAdjac[1] = VT_NULL ; nIdAdjac[2] = VT_NULL ; } + StmTria( const int nIdV[3]) : vtN(), nTFlag( 0), nEFlag( 0) + { nIdVert[0] = nIdV[0] ; nIdVert[1] = nIdV[1] ; nIdVert[2] = nIdV[2] ; + nIdAdjac[0] = VT_NULL ; nIdAdjac[1] = VT_NULL ; nIdAdjac[2] = VT_NULL ; } + StmTria( const int nIdV[3], const int nIdA[3], const Vector3d& vtV, int nTF, int nEF) + : vtN( vtV), nTFlag( nTF), nEFlag( nEF) + { nIdVert[0] = nIdV[0] ; nIdVert[1] = nIdV[1] ; nIdVert[2] = nIdV[2] ; + nIdAdjac[0] = nIdA[0] ; nIdAdjac[1] = nIdA[1] ; nIdAdjac[2] = nIdA[2] ; } + public : + int nIdVert[3] ; + int nIdAdjac[3] ; + Vector3d vtN ; + int nTFlag ; + int nEFlag ; +} ; + //---------------------------------------------------------------------------- class SurfTriMesh : public ISurfTriMesh { @@ -56,53 +96,38 @@ class SurfTriMesh : public ISurfTriMesh { return m_bClosed ; } public : // ISurfTriMesh + virtual bool Copy( const IGeoObj* pGObjSrc) ; virtual bool Init( int nNumVert, int nNumTria) ; - virtual bool AddVertex( const Point3d& ptVert) ; - virtual bool AddVertex( const Point3d& ptVert, int nTria, int nFlag) ; - virtual bool AddTriangle( - - virtual const Point3d& GetControlPoint( int nInd, bool* pbOk = NULL) const ; - virtual double GetControlWeight( int nInd, bool* pbOk = NULL) const ; - virtual bool GetControlPolygonLength( double& dLen) const ; - virtual int GetSingularParam( double& dPar) const ; + virtual int AddVertex( const Point3d& ptVert) ; + virtual int AddTriangle( const int nIdVert[3]) ; + virtual int GetFirstTriangle( Point3d& ptP0, Point3d& ptP1, Point3d& ptP2) const ; + virtual int GetNextTriangle( int nId, Point3d& ptP0, Point3d& ptP1, Point3d& ptP2) const ; public : SurfTriMesh( void) ; const SurfTriMesh& operator =( const SurfTriMesh& stSrc) - { if ( &stSrc != this && Init( m_vVert.size(), m_vTria.size())) { - m_nStatus = stSrc.m_nStatus ; - m_bClosed = stSrc.m_bClosed ; - m_vVert = stSrc.m_vVert ; - m_vTria = stSrc.m_vTria ; - } - return *this ; } + { if ( ! Copy( stSrc)) + LOG_ERROR( GetEGkLogger(), "SurfTriMesh : copy error") + return *this ; } private : + bool Copy( const SurfTriMesh& clSrc) ; bool Validate( void) ; + bool SetVertex( int nInd, const StmVert& vV) ; + bool SetTriangle( int nInd, const StmTria& tT) ; + int GetVertexNum( void) const + { return int( m_vVert.size()) ; } + int GetTriangleNum( void) const + { return int( m_vTria.size()) ; } + bool CalcTriangleNormal( int nT) ; + bool InvertTriangle( int nT) ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; private : - class Vertex { - public : - Vertex( void) : ptP(), nIdTria( 0), nFlag( 0) {} - Vertex( const Point3d& ptQ, int nIdT, int nF) : ptP( ptQ), nIdTria( nIdT), nFlag( nF) {} - public : - Point3d ptP ; - int nIdTria ; - int nFlag ; - } ; - class Tria { - public : - int nIdVert[3] ; - int nIdAdjac[3] ; - Vector3d vtN ; - int nFlag ; - int nAux ; - } ; - typedef std::vector VERTVECTOR ; - typedef std::vector TRIAVECTOR ; + typedef std::vector VERTVECTOR ; + typedef std::vector TRIAVECTOR ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto