From 1b767fe58e982e2c8a3d88eb65ede2cbfa8afe3b Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Fri, 2 May 2014 06:57:24 +0000 Subject: [PATCH] EgtGeomKernel 1.5e1 : - in TriMesh migliorato lo smooth delle normali - in TriMesh aggiunta generazione per rivoluzione - migliorati gestione e aggiornamento materiali. --- DistPointLine.h | 7 +- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes GdbExecutor.cpp | 315 ++++++++++++++++++++++++++++++------------ GdbExecutor.h | 3 + GdbMaterialMgr.cpp | 4 +- GdbMaterialMgr.h | 4 +- GeoConst.h | 10 +- GeomDB.cpp | 24 +++- GeomDB.h | 2 +- PolyLine.cpp | 22 +++ SurfTriMesh.cpp | 332 +++++++++++++++++++++++++++++++++++++++++++-- SurfTriMesh.h | 8 +- 12 files changed, 621 insertions(+), 110 deletions(-) diff --git a/DistPointLine.h b/DistPointLine.h index b89aa4e..cbe21e7 100644 --- a/DistPointLine.h +++ b/DistPointLine.h @@ -34,7 +34,12 @@ class DistPointLine public : bool GetSqDist( double& dSqDist) ; bool GetDist( double& dDist) ; - int GetNbrMinDist( void) { return (( m_dSqDist < 0) ? 0 : 1) ; } + bool IsSmall( void) + { double dSqDist ; return ( GetSqDist( dSqDist) && dSqDist < EPS_SMALL * EPS_SMALL) ; } + bool IsZero( void) + { double dSqDist ; return ( GetSqDist( dSqDist) && dSqDist < EPS_ZERO * EPS_ZERO) ; } + int GetNbrMinDist( void) + { return (( m_dSqDist < 0) ? 0 : 1) ; } bool GetMinDistPoint( Point3d& ptMinDist) ; bool GetParamAtMinDistPoint( double& dParam) ; diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 79a03184b94f9260c1949d52c8c5661d2f6e8e01..78eef9f6b9eb968b71c9eeedcccddb173a3ead68 100644 GIT binary patch delta 105 zcmdlNy)SyhCpK171|0^&&FAIhnVD08jE{$f}3`h8vwX?A6@_e delta 105 zcmdlNy)SyhCpK0S1|0^A&FAIhnVD07jE{$f}3`h8vwy pCrvCompo( CreateCurveComposite()) ; @@ -599,92 +618,50 @@ GdbExecutor::ExecuteCurveCompo( const string& sCmd2, const STRVECTOR& vsParams) INTVECTOR vnNames ; INTVECTOR::iterator Iter ; - // curva composita generica - if ( sCmd2 == "" || sCmd2 == "MAKE") { - // 3 o 4 parametri - switch ( vsParams.size()) { - case 3 : bErase = false ; break ; - case 4 : bErase = ( vsParams[3] != "0") ; break ; - default : return false ; break ; - } - // recupero lista nomi - if ( ! GetNamesParam( vsParams[2], vnNames)) - return false ; - // recupero il riferimento del gruppo destinazione - Frame3d frDest ; - if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) - return false ; - // esecuzione - for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) { - // recupero la curva - int nIdCrv = *Iter ; - const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ; - if ( pCrv == nullptr) - return false ; - // recupero il riferimento della curva - Frame3d frSou ; - if ( ! m_pGDB->GetGlobFrame( nIdCrv, frSou)) - return false ; - // se i riferimenti sono uguali - if ( AreSameFrame( frSou, frDest)) { - // aggiungo direttamente questa curva - if ( ! pCrvCompo->AddCurve( *pCrv)) - return false ; - } - // altrimenti devo prima trasformare la curva - else { - // creo una copia della curva (da buttare alla fine) - PtrOwner pModCrv( GetCurve( pCrv->Clone())) ; - if ( ! IsValid( pModCrv)) - return false ; - // eseguo la trasformazione - pModCrv->ToGlob( frSou) ; - pModCrv->ToLoc( frDest) ; - // aggiungo la curva modificata - if ( ! pCrvCompo->AddCurve( *pModCrv)) - return false ; - } - } + // 3 o 4 parametri + switch ( vsParams.size()) { + case 3 : bErase = false ; break ; + case 4 : bErase = ( vsParams[3] != "0") ; break ; + default : return false ; break ; } - // da split di curva semplice - else if ( sCmd2 == "S" || sCmd2 == "FROMSPLIT") { - // 4 o 5 parametri - switch ( vsParams.size()) { - case 4 : bErase = false ; break ; - case 5 : bErase = ( vsParams[4] != "0") ; break ; - default : return false ; break ; - } - // salvo nome curva originale per eventuale cancellazione - int nIdCrv = GetIdParam( vsParams[2]) ; - vnNames.push_back( nIdCrv) ; + // recupero lista nomi + if ( ! GetNamesParam( vsParams[2], vnNames)) + return false ; + // recupero il riferimento del gruppo destinazione + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) + return false ; + // esecuzione + for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) { // recupero la curva + int nIdCrv = *Iter ; const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ; if ( pCrv == nullptr) return false ; - // recupero il numero delle parti in cui spezzare - int nParts ; - if ( ! FromString( vsParams[3], nParts)) - return false ; - // ne deduco la curva composita - if ( ! pCrvCompo->FromSplit( *pCrv, nParts)) - return false ; // recupero il riferimento della curva Frame3d frSou ; if ( ! m_pGDB->GetGlobFrame( nIdCrv, frSou)) return false ; - // recupero il riferimento del gruppo destinazione - Frame3d frDest ; - if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) - return false ; - // porto la curva composita dal riferimento della sorgente a quello di inserimento - if ( ! AreSameFrame( frSou, frDest)) { - pCrvCompo->ToGlob( frSou) ; - pCrvCompo->ToLoc( frDest) ; + // se i riferimenti sono uguali + if ( AreSameFrame( frSou, frDest)) { + // aggiungo direttamente questa curva + if ( ! pCrvCompo->AddCurve( *pCrv)) + return false ; + } + // altrimenti devo prima trasformare la curva + else { + // creo una copia della curva (da buttare alla fine) + PtrOwner pModCrv( GetCurve( pCrv->Clone())) ; + if ( ! IsValid( pModCrv)) + return false ; + // eseguo la trasformazione + pModCrv->ToGlob( frSou) ; + pModCrv->ToLoc( frDest) ; + // aggiungo la curva modificata + if ( ! pCrvCompo->AddCurve( *pModCrv)) + return false ; } } - // altrimenti errore - else - return false ; // inserisco la curva composita nel DB if ( AddGeoObj( vsParams[0], vsParams[1], Release( pCrvCompo))) { @@ -701,6 +678,99 @@ GdbExecutor::ExecuteCurveCompo( const string& sCmd2, const STRVECTOR& vsParams) return false ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveCompoFromSplit( const STRVECTOR& vsParams) +{ + // per eventuale cancellazione curva di origine + bool bErase ; + // 4 o 5 parametri + switch ( vsParams.size()) { + case 4 : bErase = false ; break ; + case 5 : bErase = ( vsParams[4] != "0") ; break ; + default : return false ; break ; + } + + // creo la curva composita + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( ! IsValid( pCrvCompo)) + return false ; + + // salvo nome curva originale per eventuale cancellazione + int nIdCrv = GetIdParam( vsParams[2]) ; + // recupero la curva + const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ; + if ( pCrv == nullptr) + return false ; + + // recupero il numero delle parti in cui spezzare + int nParts ; + if ( ! FromString( vsParams[3], nParts)) + return false ; + + // ne deduco la curva composita + if ( ! pCrvCompo->FromSplit( *pCrv, nParts)) + return false ; + // recupero il riferimento della curva + Frame3d frSou ; + if ( ! m_pGDB->GetGlobFrame( nIdCrv, frSou)) + return false ; + // recupero il riferimento del gruppo destinazione + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) + return false ; + // porto la curva composita dal riferimento della sorgente a quello di inserimento + if ( ! AreSameFrame( frSou, frDest)) { + pCrvCompo->ToGlob( frSou) ; + pCrvCompo->ToLoc( frDest) ; + } + + // inserisco la curva composita nel DB + if ( AddGeoObj( vsParams[0], vsParams[1], Release( pCrvCompo))) { + // se richiesto, cancello la curva originale + if ( bErase) { + if ( ! m_pGDB->Erase( nIdCrv)) + return false ; + } + return true ; + } + else + return false ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveCompoAddCurve( const STRVECTOR& vsParams) +{ + // per eventuale cancellazione curva da accodare + bool bErase ; + // 2 o 3 parametri ( IdCurveCompo, IdCurveToAdd[, bEraseCurveToAdd]) + switch ( vsParams.size()) { + case 2 : bErase = false ; break ; + case 3 : bErase = ( vsParams[2] != "0") ; break ; + default : return false ; break ; + } + // recupero la curva composita + ICurveComposite* pCrvComp = GetCurveComposite( m_pGDB->GetGeoObj( GetIdParam( vsParams[0]))) ; + if ( pCrvComp == nullptr) + return false ; + // salvo nome curva da accodare per eventuale cancellazione + int nIdCrv = GetIdParam( vsParams[1]) ; + // recupero la curva + const ICurve* pCrvToAdd = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ; + if ( pCrvToAdd == nullptr) + return false ; + // eseguo l'accodamento + if ( ! pCrvComp->AddCurve( *pCrvToAdd)) + return false ; + // se richiesto, elimino la curva accodata + if ( bErase) { + if ( ! m_pGDB->Erase( nIdCrv)) + return false ; + } + return true ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) @@ -780,9 +850,13 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) } // se creazione per triangolazione di un contorno chiuso e piano else if ( sCmd2 == "CONT" || sCmd2 == "BYCONTOUR") { - // 3 parametri : Id, ParentId, IdCurve - if ( vsParams.size() != 3) + // 3 o 4 parametri : Id, ParentId, IdCurve[, dLinTol] + if ( vsParams.size() != 3 && vsParams.size() != 4) return false ; + // recupero la tolleranza lineare + double dLinTol = LIN_TOL_STD ; + if ( vsParams.size() == 5) + FromString( vsParams[3], dLinTol) ; // recupero la curva int nIdCrv = GetIdParam( vsParams[2]) ; const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ; @@ -801,7 +875,7 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) // se i riferimenti sono uguali if ( AreSameFrame( frCrv, frDest)) { // ricavo l'approssimazione - if ( ! pCrv->ApproxWithLines( 0.01, 15, PL)) + if ( ! pCrv->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL)) return false ; } // altrimenti devo prima trasformare la curva @@ -814,7 +888,7 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) pModCrv->ToGlob( frCrv) ; pModCrv->ToLoc( frDest) ; // ricavo l'approssimazione - if ( ! pModCrv->ApproxWithLines( 0.01, 15, PL)) + if ( ! pModCrv->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL)) return false ; } // creo la superficie @@ -829,9 +903,13 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) } // se creazione per estrusione else if ( sCmd2 == "EXTR" || sCmd2 == "BYEXTRUSION") { - // 4 parametri : Id, ParentId, IdCurve, vtExtr - if ( vsParams.size() != 4) + // 4 o 5 parametri : Id, ParentId, IdCurve, vtExtr[, dLinTol] + if ( vsParams.size() != 4 && vsParams.size() != 5) return false ; + // recupero la tolleranza lineare + double dLinTol = LIN_TOL_STD ; + if ( vsParams.size() == 5) + FromString( vsParams[4], dLinTol) ; // recupero la curva int nIdCrv = GetIdParam( vsParams[2]) ; const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ; @@ -850,7 +928,7 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) // se i riferimenti sono uguali if ( AreSameFrame( frCrv, frDest)) { // ricavo l'approssimazione - if ( ! pCrv->ApproxWithLines( 0.01, 15, PL)) + if ( ! pCrv->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL)) return false ; } // altrimenti devo prima trasformare la curva @@ -863,7 +941,7 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) pModCrv->ToGlob( frCrv) ; pModCrv->ToLoc( frDest) ; // ricavo l'approssimazione - if ( ! pModCrv->ApproxWithLines( 0.01, 15, PL)) + if ( ! pModCrv->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL)) return false ; } // recupero il vettore di estrusione @@ -880,6 +958,77 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) // inserisco la superficie trimesh nel DB return AddGeoObj( vsParams[0], vsParams[1], Release( pSTM)) ; } + // se creazione per rivoluzione + else if ( sCmd2 == "REV" || sCmd2 == "BYREVOLUTION") { + // 6 o 7 parametri : Id, ParentId, IdCurve, ptRev, vtRev, dAngRot[, dLinTol] + if ( vsParams.size() != 6 && vsParams.size() != 7) + return false ; + // recupero la tolleranza lineare + double dLinTol = LIN_TOL_STD ; + if ( vsParams.size() == 7) + FromString( vsParams[6], dLinTol) ; + // recupero la curva + int nIdCrv = GetIdParam( vsParams[2]) ; + const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ; + if ( pCrv == nullptr) + return false ; + // recupero il riferimento della curva + Frame3d frCrv ; + if ( ! m_pGDB->GetGlobFrame( nIdCrv, frCrv)) + return false ; + // recupero il riferimento del gruppo destinazione + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) + return false ; + // calcolo la polilinea che approssima la curva + PolyLine PL ; + // se i riferimenti sono uguali + if ( AreSameFrame( frCrv, frDest)) { + // ricavo l'approssimazione + if ( ! pCrv->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL)) + return false ; + } + // altrimenti devo prima trasformare la curva + else { + // creo una copia della curva (da buttare alla fine) + PtrOwner pModCrv( GetCurve( pCrv->Clone())) ; + if ( ! IsValid( pModCrv)) + return false ; + // eseguo la trasformazione + pModCrv->ToGlob( frCrv) ; + pModCrv->ToLoc( frDest) ; + // ricavo l'approssimazione + if ( ! pModCrv->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL)) + return false ; + } + // recupero il punto dell'asse di rivoluzione + Point3d ptAx ; + if ( ! GetPointParam( vsParams[3], ptAx)) + return false ; + // recupero il vettore dell'asse di rivoluzione + Vector3d vtAx ; + if ( ! GetVectorParam( vsParams[4], vtAx)) + return false ; + // recupero l'angolo di rotazione + double dAngRotDeg ; + if ( ! FromString( vsParams[5], dAngRotDeg)) + return false ; + // calcolo lo step di rotazione + double dMaxRad = 0 ; + PL.GetMaxDistanceFromLine( dMaxRad, ptAx, vtAx, 1, false) ; + if ( dMaxRad < EPS_SMALL) + return false ; + double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; + // creo la superficie + PtrOwner pSTM( CreateSurfTriMesh()) ; + if ( ! IsValid( pSTM)) + return false ; + // costruisco la rivoluzione + if ( ! pSTM->CreateByRevolution( PL, ptAx, vtAx, dAngRotDeg, dStepRotDeg)) + return false ; + // inserisco la superficie trimesh nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pSTM)) ; + } else return false ; } diff --git a/GdbExecutor.h b/GdbExecutor.h index f4cd040..5dbe2ae 100644 --- a/GdbExecutor.h +++ b/GdbExecutor.h @@ -51,6 +51,9 @@ class GdbExecutor : public IGdbExecutor bool ExecuteCurveArc( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteCurveBez( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteCurveCompo( const std::string& sCmd2, const STRVECTOR& vsParams) ; + bool CurveCompoMake( const STRVECTOR& vsParams) ; + bool CurveCompoFromSplit( const STRVECTOR& vsParams) ; + bool CurveCompoAddCurve( const STRVECTOR& vsParams) ; bool ExecuteSurfTriMesh( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteLevel( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteMode( const std::string& sCmd2, const STRVECTOR& vsParams) ; diff --git a/GdbMaterialMgr.cpp b/GdbMaterialMgr.cpp index 54cf90e..dd4d7d2 100644 --- a/GdbMaterialMgr.cpp +++ b/GdbMaterialMgr.cpp @@ -202,7 +202,7 @@ GdbMaterialMgr::FindMaterial( const string& sName) const //---------------------------------------------------------------------------- bool -GdbMaterialMgr::GetMaterial( int nId, Material& matM) const +GdbMaterialMgr::GetMaterialData( int nId, Material& matM) const { if ( ! ExistsMaterial( nId)) return false ; @@ -235,7 +235,7 @@ GdbMaterialMgr::IsCustomMaterial( int nId, bool& bCustom) const //---------------------------------------------------------------------------- bool -GdbMaterialMgr::ModifyMaterial( int nId, const Material& matM) +GdbMaterialMgr::ModifyMaterialData( int nId, const Material& matM) { if ( ! ExistsMaterial( nId)) return false ; diff --git a/GdbMaterialMgr.h b/GdbMaterialMgr.h index 290d415..dde8c3a 100644 --- a/GdbMaterialMgr.h +++ b/GdbMaterialMgr.h @@ -35,10 +35,10 @@ class GdbMaterialMgr { return int( m_GdbMats.size()) ; } bool ExistsMaterial( int nId) const { return ( nId > GDB_MT_NULL && nId <= int( m_GdbMats.size()) && ! m_GdbMats[nId-1].sName.empty()) ; } - bool GetMaterial( int nId, Material& matM) const ; + bool GetMaterialData( int nId, Material& matM) const ; bool GetMaterialName( int nId, std::string& sName) const ; bool IsCustomMaterial( int nId, bool& bCustom) const ; - bool ModifyMaterial( int nId, const Material& matM) ; + bool ModifyMaterialData( int nId, const Material& matM) ; bool ModifyMaterialName( int nId, const std::string& sName) ; private : diff --git a/GeoConst.h b/GeoConst.h index 475aebc..e4e89f4 100644 --- a/GeoConst.h +++ b/GeoConst.h @@ -19,15 +19,19 @@ //----------------- Costanti per approssimazioni con polilinee --------------- // tolleranza lineare minima in approssimazioni lineari -const double LIN_TOL_MIN = 0.01 ; +const double LIN_TOL_MIN = 0.001 ; // deviazione angolare minima (in gradi) in approssimazioni lineari const double ANG_TOL_MIN_DEG = 0.1 ; // deviazione angolare massima (in gradi) in approssimazioni lineari esterne const double ANG_TOL_EXT_MAX_DEG = 90 ; -// tolleranza lineare standard in approssimazioni lineari +// tolleranza lineare comune in approssimazioni lineari static const double LIN_TOL_APPROX = 1 ; -// deviazione angolare standard (in gradi) in approssimazioni lineari +// deviazione angolare comune (in gradi) in approssimazioni lineari static const double ANG_TOL_APPROX_DEG = 45 ; +// tolleranza lineare standard +static const double LIN_TOL_STD = 0.1 ; +// deviazione angolare standard (in gradi) +static const double ANG_TOL_STD_DEG = 15 ; //----------------- Costanti per archi come curve di Bezier ------------------ // massimo angolo al centro di un arco espresso tramite curva di Bezier diff --git a/GeomDB.cpp b/GeomDB.cpp index 4f5416b..e82bcf6 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -1408,7 +1408,7 @@ GeomDB::SetMaterial( GdbObj* pGdbObj, const string& sMatName) // recupero il materiale per assegnare anche il colore Material mMat ; - GetMaterial( nIdMat, mMat) ; + GetMaterialData( nIdMat, mMat) ; // assegno il materiale tramite indice return ( pGdbObj->SetMaterial( mMat.GetDiffuse()) && @@ -1580,7 +1580,7 @@ GeomDB::UsedMaterialInGroup( int nMat, const GdbGroup* pGdbGroup) const //---------------------------------------------------------------------------- bool -GeomDB::NotifyObjectsWithMaterialInGroup( int nMat, bool bByParent, GdbGroup* pGdbGroup) +GeomDB::NotifyObjectsWithMaterialInGroup( int nMat, Color cCol, bool bByParent, GdbGroup* pGdbGroup) { // verifico se il gruppo utilizza direttamente il materiale int nObjMat ; @@ -1589,6 +1589,11 @@ GeomDB::NotifyObjectsWithMaterialInGroup( int nMat, bool bByParent, GdbGroup* pG nObjMat = GDB_MT_PARENT ; // se il materiale è usato dal gruppo bByParent = ( nObjMat == nMat || ( nObjMat == GDB_MT_PARENT && bByParent)) ; + // eventuale aggiornamento del colore + if ( nObjMat == nMat) { + pGdbGroup->SetMaterial( cCol) ; + pGdbGroup->SetMaterial( nMat) ; + } // scandisco il gruppo bool bOk = true ; for ( GdbObj* pGdbObj = pGdbGroup->GetFirstObj() ; @@ -1597,7 +1602,7 @@ GeomDB::NotifyObjectsWithMaterialInGroup( int nMat, bool bByParent, GdbGroup* pG // se sottogruppo, devo cercare nei suoi figli GdbGroup* pGdbSubGrp ; if ( ( pGdbSubGrp = ::GetGdbGroup( pGdbObj)) != nullptr) { - if ( ! NotifyObjectsWithMaterialInGroup( nMat, bByParent, pGdbSubGrp)) + if ( ! NotifyObjectsWithMaterialInGroup( nMat, cCol, bByParent, pGdbSubGrp)) bOk = false ; } // altrimenti oggetto @@ -1611,6 +1616,11 @@ GeomDB::NotifyObjectsWithMaterialInGroup( int nMat, bool bByParent, GdbGroup* pG if ( ! pGdbObj->OnSetMaterial()) bOk = false ; } + // eventuale aggiornamento del colore + if ( nObjMat == nMat) { + pGdbObj->SetMaterial( cCol) ; + pGdbObj->SetMaterial( nMat) ; + } } } @@ -1739,7 +1749,7 @@ GeomDB::EraseMaterial( int nMat, bool& bInUse) bool GeomDB::GetMaterialData( int nMat, Material& matM) const { - return m_MatManager.GetMaterial( nMat, matM) ; + return m_MatManager.GetMaterialData( nMat, matM) ; } //---------------------------------------------------------------------------- @@ -1774,10 +1784,10 @@ GeomDB::IsCustomMaterial( int nMat, bool& bCustom) const bool GeomDB::ModifyMaterialData( int nMat, const Material& matM) { - if ( ! m_MatManager.ModifyMaterial( nMat, matM)) + if ( ! m_MatManager.ModifyMaterialData( nMat, matM)) return false ; - // notifico gli oggetti che usano questo materiale - NotifyObjectsWithMaterialInGroup( nMat, false, &m_GrpRadix) ; + // notifico gli oggetti che usano questo materiale (e gli aggiorno il colore) + NotifyObjectsWithMaterialInGroup( nMat, matM.GetDiffuse(), false, &m_GrpRadix) ; return true ; } diff --git a/GeomDB.h b/GeomDB.h index 34b554d..83ee371 100644 --- a/GeomDB.h +++ b/GeomDB.h @@ -160,7 +160,7 @@ class GeomDB : public IGeomDB bool GetMaterial( const GdbObj* pGdbObj, Material& mMat) const ; bool GetCalcMaterial( const GdbObj* pGdbObj, Material& mMat) const ; bool UsedMaterialInGroup( int nMat, const GdbGroup* pGdbGroup) const ; - bool NotifyObjectsWithMaterialInGroup( int nMat, bool bByParent, GdbGroup* pGdbGroup) ; + bool NotifyObjectsWithMaterialInGroup( int nMat, Color cCol, bool bByParent, GdbGroup* pGdbGroup) ; bool AddGdbIteratorToList( GdbIterator* pIter) { return m_IterManager.AddGdbIterator( pIter) ; } bool RemoveGdbIteratorFromList( GdbIterator* pIter) diff --git a/PolyLine.cpp b/PolyLine.cpp index 3b811f7..0ec53a1 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -13,6 +13,7 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" +#include "DistPointLine.h" #include "\EgtDev\Include\EGkPolyLine.h" #include "\EgtDev\Include\EGkPlane3d.h" @@ -289,3 +290,24 @@ PolyLine::IsPlanar( Plane3d& plPlane, double dToler) const // All points passed distance test, so polygon is considered planar return true ; } + +//---------------------------------------------------------------------------- +bool +PolyLine::GetMaxDistanceFromLine( double& dMaxDist, const Point3d& ptAx, + const Vector3d& vtAx, double dLen, bool bIsSegment) const +{ + // Verifico che la polilinea esista + if ( GetPointNbr() < 1) + return false ; + // Calcolo la distanza di ogni punto dalla linea + dMaxDist = 0 ; + Point3d ptP ; + for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP)) { + DistPointLine dstPL( ptP, ptAx, vtAx, dLen, bIsSegment) ; + double dDist ; + if ( dstPL.GetDist( dDist) && dDist > dMaxDist) + dMaxDist = dDist ; + } + + return true ; +} diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index bf96213..9f55e04 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -17,6 +17,7 @@ #include "GeoObjFactory.h" #include "NgeWriter.h" #include "NgeReader.h" +#include "DistPointLine.h" #include "Triangulate.h" #include "\EgtDev\Include\EGkStringUtils3d.h" #include "\EgtDev\Include\EGkPolyLine.h" @@ -225,8 +226,9 @@ bool SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const { // recupero tutti i triangoli attorno al vertice + bool bCirc ; INTVECTOR vT ; - int nTria = GetAllTriaAroundVertex( m_vTria[nT].nIdVert[nV], vT) ; + int nTria = GetAllTriaAroundVertex( m_vTria[nT].nIdVert[nV], vT, bCirc) ; if ( nTria < 1) return false ; @@ -241,23 +243,44 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const if ( nPos == -1) return false ; - // medio le normali, finché non incontro degli spigoli + // medio le normali, finché non incontro degli spigoli vtN = m_vTria[nT].vtN ; - const double COS_DEV_LIM = cos( 18 * DEGTORAD) ; + const double COS_DEV_LIM = cos( 22.5 * DEGTORAD) ; // parto dal triangolo e vado in direzione positiva - for ( int i = nPos + 1 ; i < int( vT.size()) ; ++ i) { + int nLim = nPos ; + for ( int i = NextIndAroundVertex( nPos, nTria, bCirc) ; + i != nPos && i < int( vT.size()) ; + i = NextIndAroundVertex( i, nTria, bCirc)) { if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= COS_DEV_LIM) vtN += m_vTria[vT[i]].vtN ; else break ; + nLim = i ; } // parto dal triangolo e vado in direzione negativa - for ( int i = nPos - 1 ; i >= 0 ; -- i) { + for ( int i = PrevIndAroundVertex( nPos, nTria, bCirc) ; + i != nLim && i >= 0 ; + i = PrevIndAroundVertex( i, nTria, bCirc)) { if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= COS_DEV_LIM) vtN += m_vTria[vT[i]].vtN ; else break ; } + + //// parto dal triangolo e vado in direzione positiva + //for ( int i = nPos + 1 ; i < int( vT.size()) ; ++ i) { + // if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= COS_DEV_LIM) + // vtN += m_vTria[vT[i]].vtN ; + // else + // break ; + //} + //// parto dal triangolo e vado in direzione negativa + //for ( int i = nPos - 1 ; i >= 0 ; -- i) { + // if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= COS_DEV_LIM) + // vtN += m_vTria[vT[i]].vtN ; + // else + // break ; + //} vtN.Normalize() ; return true ; @@ -486,7 +509,7 @@ SurfTriMesh::FindVertexInTria( int nV, int nT, int& nK) const //---------------------------------------------------------------------------- int -SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT) const +SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT, bool& bCirc) const { const int MAX_VT_SIZE = 512 ; @@ -516,8 +539,10 @@ SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT) const } while ( nTa != nT && nTa != SVT_NULL && vT.size() < MAX_VT_SIZE) ; // se sono ritornato al triangolo di partenza ho fatto un giro e concluso la ricerca - if ( nTa == nT) + if ( nTa == nT) { + bCirc = true ; return int( vT.size()) ; + } // altrimenti, devo cercare i triangoli adiacenti con lo stesso vertice in CW nTa = nT ; @@ -534,9 +559,30 @@ SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT) const vT.insert( vT.begin(), nTa) ; } while ( nTa != nT && nTa != SVT_NULL && vT.size() < MAX_VT_SIZE) ; + bCirc = ( nTa == nT) ; return int( vT.size()) ; } +//---------------------------------------------------------------------------- +int +SurfTriMesh::NextIndAroundVertex( int nInd, int nSize, bool bCirc) const +{ + nInd = nInd + 1 ; + if ( bCirc && nInd >= nSize) + nInd = nInd % nSize ; + return nInd ; +} + +//---------------------------------------------------------------------------- +int +SurfTriMesh::PrevIndAroundVertex( int nInd, int nSize, bool bCirc) const +{ + nInd = nInd - 1 ; + if ( bCirc && nInd < 0) + nInd = ( nInd + nSize) % nSize ; + return nInd ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::AdjustAdjacencies( void) @@ -567,10 +613,11 @@ SurfTriMesh::AdjustAdjacencies( void) int nVf = m_vTria[i].nIdVert[Next(j)] ; // indice altro vertice in altro triangolo int k ; - int nN ; + int nN ; + bool bCirc ; INTVECTOR vT ; // triangoli con il vertice all'inizio dello half-edge - nN = GetAllTriaAroundVertex( nVi, vT) ; + nN = GetAllTriaAroundVertex( nVi, vT, bCirc) ; for ( int l = 0 ; l < nN ; ++ l) { int nTi = vT[l] ; if ( nTi != i) { @@ -589,7 +636,7 @@ SurfTriMesh::AdjustAdjacencies( void) } } // triangoli con il vertice alla fine dello half-edge - nN = GetAllTriaAroundVertex( nVf, vT) ; + nN = GetAllTriaAroundVertex( nVf, vT, bCirc) ; for ( int l = 0 ; l < nN ; ++ l) { int nTf = vT[l] ; if ( nTf != i) { @@ -801,6 +848,271 @@ SurfTriMesh::CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) return AdjustTopology() ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::CreateByRevolution( const PolyLine& PL, const Point3d& ptAx, const Vector3d& vtAx, + double dAngRot, double dStepRot) +{ + // verifico che l'asse di rotazione sia non nullo + if ( vtAx.IsSmall()) + return false ; + // verifico che l'angolo di rotazione sia significativo e non superi un giro + if ( fabs( dAngRot) < EPS_ANG_SMALL) + return false ; + if ( fabs( dAngRot) > ANG_FULL) + dAngRot = _copysign( ANG_FULL, dAngRot) ; + // verifico se rotazione completa + bool bFullRev = ( fabs( fabs( dAngRot) - ANG_FULL) < EPS_ANG_SMALL) ; + // aggiusto il valore dell'angolo di step + const double MIN_STEP_ROT = 1 ; + const double MAX_STEP_ROT = 90 ; + if ( fabs( dStepRot) < MIN_STEP_ROT) + dStepRot = _copysign( MIN_STEP_ROT, dAngRot) ; + else if ( fabs( dStepRot) > MAX_STEP_ROT) + dStepRot = _copysign( MAX_STEP_ROT, dAngRot) ; + else + dStepRot = _copysign( dStepRot, dAngRot) ; + // calcolo il numero di step + int nStep = int( dAngRot / dStepRot) ; + nStep = max( nStep, 1) ; + dStepRot = dAngRot / nStep ; + if ( bFullRev) + -- nStep ; + + // verifico che la polilinea non attraversi l'asse di rivoluzione o lo tocchi in punti interni + if ( ! VeryfyPolylineForRevolution( PL, ptAx, vtAx)) { + LOG_ERROR( GetEGkLogger(), "StmCreateByRevolution : polyline inside meets axis") + return false ; + } + + // verifico se la polilinea è chiusa + bool bClosed = PL.IsClosed() ; + + // costruisco la mesh + int nPointNbr = PL.GetPointNbr() ; + if ( ! Init( ( 1 + nStep) * nPointNbr, ( 1 + nStep) * nPointNbr)) + return false ; + + // inserisco il primo punto della polilinea e i suoi ruotati + int nP = 0 ; + int nV = -1 ; + Point3d ptP ; + // recupero il punto + if ( ! PL.GetFirstPoint( ptP)) + return false ; + ++ nP ; + // inserisco il primo vertice + if ( AddVertex( ptP) == SVT_NULL) + return false ; + ++ nV ; + // verifico se il punto giace sull'asse + bool bPrevOnAx = DistPointLine( ptP, ptAx, vtAx, 1, false).IsSmall() ; + int nVPrevOnAx = nV ; + // se non è sull'asse, inserisco le copie ruotate + if ( ! bPrevOnAx) { + for ( int i = 1 ; i <= nStep ; ++i) { + ptP.Rotate( ptAx, vtAx, dStepRot * DEGTORAD) ; + if ( AddVertex( ptP) == SVT_NULL) + return false ; + ++ nV ; + } + } + // ciclo sui punti della polilinea (per inserire vertice e suoi ruotati + 2 triangoli per ogni punto) + int nIdV[4] ; + while ( PL.GetNextPoint( ptP)) { + // incremento numero punto + ++ nP ; + // se polilinea aperta o non è l'ultimo punto + if ( ! bClosed || nP < nPointNbr) { + // aggiungo il primo vertice + if ( AddVertex( ptP) == SVT_NULL) + return false ; + ++ nV ; + // verifico se il punto giace sull'asse + bool bOnAx = DistPointLine( ptP, ptAx, vtAx, 1, false).IsSmall() ; + // ciclo sugli step + for ( int i = 1 ; i <= nStep ; ++i) { + // se non è sull'asse, inserisco le copie ruotate + if ( ! bOnAx) { + ptP.Rotate( ptAx, vtAx, dStepRot * DEGTORAD) ; + if ( AddVertex( ptP) == SVT_NULL) + return false ; + ++ nV ; + } + // per i controlli già fatti non è possibile avere contemp. prec e corr su asse + // se il precedente è sull'asse, aggiungo un solo triangolo + if ( bPrevOnAx) { + nIdV[0] = nVPrevOnAx ; + nIdV[1] = nV ; + nIdV[2] = nV - 1 ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + } + // se il corrente è sull'asse, aggiungo un solo triangolo + else if ( bOnAx) { + nIdV[0] = nV - ( nStep + 2) + i ; + nIdV[1] = nIdV[0] + 1 ; + nIdV[2] = nV ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + } + // altrimenti aggiungo due triangoli + else { + nIdV[0] = nV - ( nStep + 2) ; + nIdV[1] = nIdV[0] + 1 ; + nIdV[2] = nV ; + nIdV[3] = nV - 1 ; + if ( ! AddBiTriangle( nIdV)) + return false ; + } + } + // se rivoluzione completa, aggiungo i due triangoli di chiusura + if ( bFullRev) { + // per i controlli già fatti non è possibile avere contemp. prec e corr su asse + // se il precedente è sull'asse, aggiungo un solo triangolo + if ( bPrevOnAx) { + nIdV[0] = nVPrevOnAx ; + nIdV[1] = nV - nStep ; + nIdV[2] = nV ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + } + // se il corrente è sull'asse, aggiungo un solo triangolo + else if ( bOnAx) { + nIdV[0] = nV - 1 ; + nIdV[1] = nV - ( nStep + 1) ; + nIdV[2] = nV ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + } + // altrimenti aggiungo due triangoli + else { + nIdV[0] = nV - ( nStep + 1) ; + nIdV[1] = nV - ( 2 * nStep + 1) ; + nIdV[2] = nV - nStep ; + nIdV[3] = nV ; + if ( ! AddBiTriangle( nIdV)) + return false ; + } + } + bPrevOnAx = false ; + } + // altrimenti ultimo punto di polilinea chiusa + else { + for ( int i = 1 ; i <= nStep ; ++i) { + // non devo aggiungere i vertici, perchè coincidono con quelli iniziali + // aggiungo triangolo in basso a sinistra + nIdV[0] = nV - nStep + i - 1 ; nIdV[1] = nV - nStep + i ; nIdV[2] = i ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + // aggiungo triangolo in alto a destra + nIdV[0] = nV - nStep + i - 1 ; nIdV[1] = i ; nIdV[2] = i - 1 ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + } + // se rivoluzione completa, aggiungo i due triangoli di chiusura + if ( bFullRev) { + // aggiungo triangolo in basso a sinistra + nIdV[0] = nV ; nIdV[1] = nV - nStep ; nIdV[2] = 0 ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + // aggiungo triangolo in alto a destra + nIdV[0] = nV ; nIdV[1] = 0 ; nIdV[2] = nStep ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + } + } + } + + // sistemo la topologia + return AdjustTopology() ; +} + +//---------------------------------------------------------------------------- +bool +SurfTriMesh::VeryfyPolylineForRevolution( const PolyLine& PL, const Point3d& ptAx, const Vector3d& vtAx) const +{ + // calcolo un riferimento con origine ptAx e asseZ vtAx + Frame3d frAx ; + if ( ! frAx.Set( ptAx, vtAx)) + return false ; + + // numero di segmenti della polilinea + int nTotSeg = PL.GetLineNbr() ; + // flag di chiusa + bool bClosed = PL.IsClosed() ; + + // recupero il primo punto e lo porto nel riferimento Ax e quindi lo proietto su XY + Point3d ptPp ; + if ( ! PL.GetFirstPoint( ptPp)) + return false ; + ptPp.ToLoc( frAx) ; + ptPp.z = 0 ; + + // calcolo la distanza tra i segmenti della polilinea portati nel piano XY del rif Ax e l'origine + int nSeg = 0 ; + Point3d ptPc ; + while ( PL.GetNextPoint( ptPc)) { + // punto corrente + ptPc.ToLoc( frAx) ; + ptPc.z = 0 ; + ++ nSeg ; + // verifico distanza + if ( DistPointLine( ORIG, ptPp, ptPc).IsSmall()) { + if ( bClosed || + ( ! ( nSeg == 1 && AreSamePointNear( ORIG, ptPp)) && + ! ( nSeg == nTotSeg && AreSamePointNear( ORIG, ptPc)))) + return false ; + } + // salvo punto + ptPp = ptPc ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfTriMesh::AddBiTriangle( const int nIdVert[4]) +{ + // 0 <- 3 + // | | + // 1 -> 2 + int nIdV[3] ; + // se la diagonale 0->2 è più corta della 1->3 + if ( SqDist( m_vVert[nIdVert[0]].ptP, m_vVert[nIdVert[2]].ptP) <= + SqDist( m_vVert[nIdVert[1]].ptP, m_vVert[nIdVert[3]].ptP)) { + // triangolo 0->1->2 + nIdV[0] = nIdVert[0] ; + nIdV[1] = nIdVert[1] ; + nIdV[2] = nIdVert[2] ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + // triangolo 0->2->3 + nIdV[0] = nIdVert[0] ; + nIdV[1] = nIdVert[2] ; + nIdV[2] = nIdVert[3] ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + } + // altrimenti uso la 1->3 + else { + // triangolo 0->1->3 + nIdV[0] = nIdVert[0] ; + nIdV[1] = nIdVert[1] ; + nIdV[2] = nIdVert[3] ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + // triangolo 1->2->3 + nIdV[0] = nIdVert[1] ; + nIdV[1] = nIdVert[2] ; + nIdV[2] = nIdVert[3] ; + if ( AddTriangle( nIdV) == SVT_NULL) + return false ; + } + + return true ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::GetLocalBBox( BBox3d& b3Loc) const diff --git a/SurfTriMesh.h b/SurfTriMesh.h index fc2ac91..111894b 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -97,6 +97,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW virtual bool AdjustTopology( void) ; virtual bool CreateByTriangulation( const PolyLine& PL) ; virtual bool CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) ; + virtual bool CreateByRevolution( const PolyLine& PL, const Point3d& ptAx, const Vector3d& vtAx, + double dAngRot, double dStepRot) ; virtual int GetVertexNum( void) const { return int( m_vVert.size()) ; } virtual int GetTriangleNum( void) const @@ -134,8 +136,12 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW int Prev( int i) const { return (( i + 2) % 3) ; } bool FindVertexInTria( int nV, int nT, int& nK) const ; - int GetAllTriaAroundVertex( int nV, INTVECTOR& vT) const ; + int GetAllTriaAroundVertex( int nV, INTVECTOR& vT, bool& bCirc) const ; + int NextIndAroundVertex( int nInd, int nSize, bool bCirc) const ; + int PrevIndAroundVertex( int nInd, int nSize, bool bCirc) const ; bool GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const ; + bool VeryfyPolylineForRevolution( const PolyLine& PL, const Point3d& ptAx, const Vector3d& vtAx) const ; + bool AddBiTriangle( const int nIdVert[4]) ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;