diff --git a/BBox3d.cpp b/BBox3d.cpp index 1e8b0a1..8ae2e19 100644 --- a/BBox3d.cpp +++ b/BBox3d.cpp @@ -18,7 +18,7 @@ #include //---------------------------------------------------------------------------- -BBox3d::BBox3d( const Point3d ptP1, const Point3d ptP2) +BBox3d::BBox3d( const Point3d& ptP1, const Point3d& ptP2) { m_ptMin.Set( __min( ptP1.x, ptP2.x), __min( ptP1.y, ptP2.y), __min( ptP1.z, ptP2.z)) ; m_ptMax.Set( __max( ptP1.x, ptP2.x), __max( ptP1.y, ptP2.y), __max( ptP1.z, ptP2.z)) ; @@ -33,7 +33,7 @@ BBox3d::BBox3d( double dX1, double dY1, double dZ1, double dX2, double dY2, doub //---------------------------------------------------------------------------- void -BBox3d::Set( const Point3d ptP1, const Point3d ptP2) +BBox3d::Set( const Point3d& ptP1, const Point3d& ptP2) { m_ptMin.Set( __min( ptP1.x, ptP2.x), __min( ptP1.y, ptP2.y), __min( ptP1.z, ptP2.z)) ; m_ptMax.Set( __max( ptP1.x, ptP2.x), __max( ptP1.y, ptP2.y), __max( ptP1.z, ptP2.z)) ; diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index e2968cf..5d94542 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index faecb79..728ab73 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -257,6 +257,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -298,6 +299,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index b303089..36265ad 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -153,6 +153,9 @@ File di origine\Gdb + + File di origine\Base + @@ -395,6 +398,9 @@ File di intestazione + + File di intestazione + diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index 6d7bddf..4453120 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -1165,18 +1165,15 @@ GdbExecutor::CurveCompoMake( const STRVECTOR& vsParams) PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( ! IsValid( pCrvCompo)) return false ; - // per eventuale cancellazione curve di origine - bool bErase ; - INTVECTOR vnNames ; - INTVECTOR::iterator Iter ; - // 3 o 4 parametri + bool bErase ; switch ( vsParams.size()) { case 3 : bErase = false ; break ; case 4 : bErase = ( vsParams[3] != "0") ; break ; default : return false ; break ; } // recupero lista nomi + INTVECTOR vnNames ; if ( ! GetNamesParam( vsParams[2], vnNames)) return false ; // recupero il riferimento del gruppo destinazione @@ -1184,6 +1181,7 @@ GdbExecutor::CurveCompoMake( const STRVECTOR& vsParams) if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) return false ; // esecuzione + INTVECTOR::iterator Iter ; for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) { // recupero la curva int nIdCrv = *Iter ; @@ -1329,185 +1327,31 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) { // se inizio creazione con componenti elementari if ( sCmd2 == "BEGIN") { - // 4 parametri (2 opzionali) : Id, ParentId[, numero vertici e numero triangoli] - if ( vsParams.size() < 2) - return false ; - // recupero Id e ParentId - m_sId = vsParams[0] ; - m_sParentId = vsParams[1] ; - // recupero i parametri opzionali - int nNumVert = 3 ; - if ( vsParams.size() >= 3) - FromString( vsParams[2], nNumVert) ; - int nNumTria = 1 ; - if ( vsParams.size() >= 4) - FromString( vsParams[3], nNumTria) ; - // creo la superficie - ISurfTriMesh* pSTM = CreateSurfTriMesh() ; - if ( pSTM == nullptr) - return false ; - // la inizializzo - if ( ! pSTM->Init( nNumVert, nNumTria)) - return false ; - // salvo il puntatore - if ( m_pGeoObj != nullptr) - delete m_pGeoObj ; - m_pGeoObj = pSTM ; - return true ; + return SurfTriMeshBegin( vsParams) ; } // se nuovo vertice else if ( sCmd2 == "VERT" || sCmd2 == "ADDVERTEX") { - // 1 parametro : punto - if ( vsParams.size() != 1) - return false ; - // recupero il riferimento in cui va inserito - Frame3d frRef ; - if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( m_sParentId), frRef)) - return false ; - // recupero il punto - Point3d ptP ; - if ( ! GetPointParam( vsParams[0], frRef, ptP)) - return false ; - // recupero la superficie - ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ; - if ( pSTM == nullptr) - return false ; - // aggiungo il vertice - return ( pSTM->AddVertex( ptP) != -1) ; + return SurfTriMeshAddVertex( vsParams) ; } // se nuovo triangolo else if ( sCmd2 == "TRIA" || sCmd2 == "ADDTRIANGLE") { - // 3 parametri : IdV1, IdV2, IdV3 - if ( vsParams.size() != 3) - return false ; - // recupero gli indici dei 3 vertici - int nIdVert[3] ; - if ( ! FromString( vsParams[0], nIdVert[0]) || - ! FromString( vsParams[1], nIdVert[1]) || - ! FromString( vsParams[2], nIdVert[2])) - return false ; - // recupero la superficie - ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ; - if ( pSTM == nullptr) - return false ; - // aggiungo il triangolo definito con gli indici dei 3 vertici - return ( pSTM->AddTriangle( nIdVert) != -1) ; + return SurfTriMeshAddTriangle( vsParams) ; } // se fine creazione else if ( sCmd2 == "END") { - // nessun parametro - if ( vsParams.size() != 0) - return false ; - // recupero la superficie - ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ; - if ( pSTM == nullptr) - return false ; - // valido la superficie e calcolo le adiacenze - if ( ! pSTM->AdjustTopology()) - return false ; - // inserisco la superficie trimesh nel DB - m_pGeoObj = nullptr ; - bool bOk = AddGeoObj( m_sId, m_sParentId, pSTM) ; - m_sId.clear() ; - m_sParentId.clear() ; - return bOk ; + return SurfTriMeshEnd( vsParams) ; } // se creazione per triangolazione di un contorno chiuso e piano else if ( sCmd2 == "CONT" || sCmd2 == "BYCONTOUR") { - // 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() == 4) - FromString( vsParams[3], dLinTol) ; - // recupero l'identificativo della curva - int nIdCrv = GetIdParam( vsParams[2]) ; - // 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 ; - if ( ! GetPolylineFromCurve( nIdCrv, frDest, dLinTol, PL)) - return false ; - // creo la superficie - PtrOwner pSTM( CreateSurfTriMesh()) ; - if ( ! IsValid( pSTM)) - return false ; - // costruisco la triangolazione - if ( ! pSTM->CreateByFlatContour( PL)) - return false ; - // inserisco la superficie trimesh nel DB - return AddGeoObj( vsParams[0], vsParams[1], Release( pSTM)) ; + return SurfTriMeshByContour( vsParams) ; } // se creazione per estrusione else if ( sCmd2 == "EXTR" || sCmd2 == "BYEXTRUSION") { - // 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]) ; - // 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 ; - if ( ! GetPolylineFromCurve( nIdCrv, frDest, dLinTol, PL)) - return false ; - // recupero il vettore di estrusione - Vector3d vtExtr ; - if ( ! GetVectorParam( vsParams[3], frDest, vtExtr)) - return false ; - // creo la superficie - PtrOwner pSTM( CreateSurfTriMesh()) ; - if ( ! IsValid( pSTM)) - return false ; - // costruisco l'estrusione - if ( ! pSTM->CreateByExtrusion( PL, vtExtr)) - return false ; - // inserisco la superficie trimesh nel DB - return AddGeoObj( vsParams[0], vsParams[1], Release( pSTM)) ; + return SurfTriMeshByExtrusion( vsParams) ; } // se creazione da 2 percorsi else if ( sCmd2 == "2P" || sCmd2 == "BY2PATHS") { - // 4 o 5 parametri : Id, ParentId, IdCurve1, IdCurve2[, 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 il riferimento del gruppo destinazione - Frame3d frDest ; - if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) - return false ; - // recupero l'identificativo della prima curva - int nIdCrv1 = GetIdParam( vsParams[2]) ; - // calcolo la polilinea che approssima la prima curva - PolyLine PL1 ; - if ( ! GetPolylineFromCurve( nIdCrv1, frDest, dLinTol, PL1)) - return false ; - // recupero l'identificativo della seconda curva - int nIdCrv2 = GetIdParam( vsParams[3]) ; - // calcolo la polilinea che approssima la seconda curva - PolyLine PL2 ; - if ( ! GetPolylineFromCurve( nIdCrv2, frDest, dLinTol, PL2)) - return false ; - // creo la superficie - PtrOwner pSTM( CreateSurfTriMesh()) ; - if ( ! IsValid( pSTM)) - return false ; - // costruisco la rigata tra le due curve - if ( ! pSTM->CreateByTwoCurves( PL1, PL2)) - return false ; - // inserisco la superficie trimesh nel DB - return AddGeoObj( vsParams[0], vsParams[1], Release( pSTM)) ; + return SurfTriMeshByTwoPaths( vsParams) ; } // se creazione per rivoluzione else if ( sCmd2 == "REV" || sCmd2 == "BYREVOLUTION") { @@ -1517,10 +1361,225 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) else if ( sCmd2 == "SCR" || sCmd2 == "BYSCREWING") { return SurfTriMeshByScrewing( true, vsParams) ; } + // imposto angolo limite per mediare normali in un vertice + else if ( sCmd2 == "SMA" || sCmd2 == "SMOOTHANG") { + return SurfTriMeshChangeSmoothAng( vsParams) ; + } + // compattazione per unione di vertici con posizioni coincidenti + else if ( sCmd2 == "COMP" || sCmd2 == "DOCOMPACTING") { + return SurfTriMeshDoCompacting( vsParams) ; + } + // se unione di due o più superfici per cucitura + else if ( sCmd2 == "SEW" || sCmd2 == "DOSEWING") { + return SurfTriMeshDoSewing( vsParams) ; + } else return false ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::SurfTriMeshBegin( const STRVECTOR& vsParams) +{ + // 4 parametri (2 opzionali) : Id, ParentId[, numero vertici e numero triangoli] + if ( vsParams.size() < 2) + return false ; + // recupero Id e ParentId + m_sId = vsParams[0] ; + m_sParentId = vsParams[1] ; + // recupero i parametri opzionali + int nNumVert = 3 ; + if ( vsParams.size() >= 3) + FromString( vsParams[2], nNumVert) ; + int nNumTria = 1 ; + if ( vsParams.size() >= 4) + FromString( vsParams[3], nNumTria) ; + // creo la superficie + ISurfTriMesh* pSTM = CreateSurfTriMesh() ; + if ( pSTM == nullptr) + return false ; + // la inizializzo + if ( ! pSTM->Init( nNumVert, nNumTria)) + return false ; + // salvo il puntatore + if ( m_pGeoObj != nullptr) + delete m_pGeoObj ; + m_pGeoObj = pSTM ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SurfTriMeshAddVertex( const STRVECTOR& vsParams) +{ + // 1 parametro : punto + if ( vsParams.size() != 1) + return false ; + // recupero il riferimento in cui va inserito + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( m_sParentId), frRef)) + return false ; + // recupero il punto + Point3d ptP ; + if ( ! GetPointParam( vsParams[0], frRef, ptP)) + return false ; + // recupero la superficie + ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ; + if ( pSTM == nullptr) + return false ; + // aggiungo il vertice + return ( pSTM->AddVertex( ptP) != -1) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SurfTriMeshAddTriangle( const STRVECTOR& vsParams) +{ + // 3 parametri : IdV1, IdV2, IdV3 + if ( vsParams.size() != 3) + return false ; + // recupero gli indici dei 3 vertici + int nIdVert[3] ; + if ( ! FromString( vsParams[0], nIdVert[0]) || + ! FromString( vsParams[1], nIdVert[1]) || + ! FromString( vsParams[2], nIdVert[2])) + return false ; + // recupero la superficie + ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ; + if ( pSTM == nullptr) + return false ; + // aggiungo il triangolo definito con gli indici dei 3 vertici + return ( pSTM->AddTriangle( nIdVert) != -1) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SurfTriMeshEnd( const STRVECTOR& vsParams) +{ + // nessun parametro + if ( vsParams.size() != 0) + return false ; + // recupero la superficie + ISurfTriMesh* pSTM = GetSurfTriMesh( m_pGeoObj) ; + if ( pSTM == nullptr) + return false ; + // valido la superficie e calcolo le adiacenze + if ( ! pSTM->AdjustTopology()) + return false ; + // inserisco la superficie trimesh nel DB + m_pGeoObj = nullptr ; + bool bOk = AddGeoObj( m_sId, m_sParentId, pSTM) ; + m_sId.clear() ; + m_sParentId.clear() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SurfTriMeshByContour( const STRVECTOR& vsParams) +{ + // 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() == 4) + FromString( vsParams[3], dLinTol) ; + // recupero l'identificativo della curva + int nIdCrv = GetIdParam( vsParams[2]) ; + // 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 ; + if ( ! GetPolylineFromCurve( nIdCrv, frDest, dLinTol, PL)) + return false ; + // creo la superficie + PtrOwner pSTM( CreateSurfTriMesh()) ; + if ( ! IsValid( pSTM)) + return false ; + // costruisco la triangolazione + if ( ! pSTM->CreateByFlatContour( PL)) + return false ; + // inserisco la superficie trimesh nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pSTM)) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SurfTriMeshByExtrusion( const STRVECTOR& vsParams) +{ + // 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]) ; + // 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 ; + if ( ! GetPolylineFromCurve( nIdCrv, frDest, dLinTol, PL)) + return false ; + // recupero il vettore di estrusione + Vector3d vtExtr ; + if ( ! GetVectorParam( vsParams[3], frDest, vtExtr)) + return false ; + // creo la superficie + PtrOwner pSTM( CreateSurfTriMesh()) ; + if ( ! IsValid( pSTM)) + return false ; + // costruisco l'estrusione + if ( ! pSTM->CreateByExtrusion( PL, vtExtr)) + return false ; + // inserisco la superficie trimesh nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pSTM)) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SurfTriMeshByTwoPaths( const STRVECTOR& vsParams) +{ + // 4 o 5 parametri : Id, ParentId, IdCurve1, IdCurve2[, 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 il riferimento del gruppo destinazione + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) + return false ; + // recupero l'identificativo della prima curva + int nIdCrv1 = GetIdParam( vsParams[2]) ; + // calcolo la polilinea che approssima la prima curva + PolyLine PL1 ; + if ( ! GetPolylineFromCurve( nIdCrv1, frDest, dLinTol, PL1)) + return false ; + // recupero l'identificativo della seconda curva + int nIdCrv2 = GetIdParam( vsParams[3]) ; + // calcolo la polilinea che approssima la seconda curva + PolyLine PL2 ; + if ( ! GetPolylineFromCurve( nIdCrv2, frDest, dLinTol, PL2)) + return false ; + // creo la superficie + PtrOwner pSTM( CreateSurfTriMesh()) ; + if ( ! IsValid( pSTM)) + return false ; + // costruisco la rigata tra le due curve + if ( ! pSTM->CreateByTwoCurves( PL1, PL2)) + return false ; + // inserisco la superficie trimesh nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pSTM)) ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::SurfTriMeshByScrewing( bool bMove, const STRVECTOR& vsParams) @@ -1624,6 +1683,90 @@ GdbExecutor::GetPolylineFromCurve( int nId, const Frame3d& frDest, double dLinTo return true ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::SurfTriMeshChangeSmoothAng( const STRVECTOR& vsParams) +{ + // 2 parametri : Id, dSmoothAngDeg + if ( vsParams.size() != 2) + return false ; + // recupero la superficie + ISurfTriMesh* pStm = GetSurfTriMesh( m_pGDB->GetGeoObj( GetIdParam( vsParams[0]))) ; + if ( pStm == nullptr) + return false ; + // recupero il valore dell'angolo + double dSmoothAng ; + if ( ! FromString( vsParams[1], dSmoothAng)) + return false ; + // imposto l'angolo + pStm->SetSmoothAngle( dSmoothAng) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SurfTriMeshDoCompacting( const STRVECTOR& vsParams) +{ + // 1 parametro : Id + if ( vsParams.size() != 1) + return false ; + // recupero la superficie + ISurfTriMesh* pStm = GetSurfTriMesh( m_pGDB->GetGeoObj( GetIdParam( vsParams[0]))) ; + if ( pStm == nullptr) + return false ; + // eseguo la compattazione + return pStm->DoCompacting() ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SurfTriMeshDoSewing( const STRVECTOR& vsParams) +{ + // 2 o 3 parametri : Id, IdOther[, bErase] + if ( vsParams.size() != 2 && vsParams.size() != 3) + return false ; + // eventuale flag per cancellazione delle superfici cucite alla prima + bool bErase = false ; + if ( vsParams.size() >= 3 && vsParams[2] != "0") + bErase = true ; + // recupero la prima superficie + int nIdStm = GetIdParam( vsParams[0]) ; + ISurfTriMesh* pStm = GetSurfTriMesh( m_pGDB->GetGeoObj( nIdStm)) ; + if ( pStm == nullptr) + return false ; + // ne recupero il riferimento + Frame3d frStm ; + if ( ! m_pGDB->GetGlobFrame( nIdStm, frStm)) + return false ; + // recupero lista nomi delle altre superfici + INTVECTOR vnNames ; + if ( ! GetNamesParam( vsParams[1], vnNames)) + return false ; + // esecuzione + INTVECTOR::iterator Iter ; + for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) { + // recupero la superficie da cucire + const ISurfTriMesh* pStmS = GetSurfTriMesh( m_pGDB->GetGeoObj( *Iter)) ; + if ( pStmS == nullptr) + return false ; + // recupero il riferimento + Frame3d frStmS ; + if ( ! m_pGDB->GetGlobFrame( *Iter, frStmS)) + return false ; + // lo esprimo rispetto a quello della prima superficie + frStmS.ToLoc( frStm) ; + // eseguo la cucitura + if ( ! pStm->DoSewing( *pStmS, frStm)) + return false ; + } + // se richiesto, cancello le superfici cucite alla prima + if ( bErase) { + for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) + m_pGDB->Erase( *Iter) ; + } + return true ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::AddGeoObj( const string& sId, const string& sIdParent, IGeoObj* pGeoObj) diff --git a/GdbExecutor.h b/GdbExecutor.h index 5993c4b..71e4b57 100644 --- a/GdbExecutor.h +++ b/GdbExecutor.h @@ -77,7 +77,17 @@ class GdbExecutor : public IGdbExecutor bool CurveCompoFromSplit( const STRVECTOR& vsParams) ; bool CurveCompoAddCurve( const STRVECTOR& vsParams) ; bool ExecuteSurfTriMesh( const std::string& sCmd2, const STRVECTOR& vsParams) ; + bool SurfTriMeshBegin( const STRVECTOR& vsParams) ; + bool SurfTriMeshAddVertex( const STRVECTOR& vsParams) ; + bool SurfTriMeshAddTriangle( const STRVECTOR& vsParams) ; + bool SurfTriMeshEnd( const STRVECTOR& vsParams) ; + bool SurfTriMeshByContour( const STRVECTOR& vsParams) ; + bool SurfTriMeshByExtrusion( const STRVECTOR& vsParams) ; + bool SurfTriMeshByTwoPaths( const STRVECTOR& vsParams) ; bool SurfTriMeshByScrewing( bool bMove, const STRVECTOR& vsParams) ; + bool SurfTriMeshChangeSmoothAng( const STRVECTOR& vsParams) ; + bool SurfTriMeshDoCompacting( const STRVECTOR& vsParams) ; + bool SurfTriMeshDoSewing( const STRVECTOR& vsParams) ; bool ExecuteLevel( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteMode( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteStatus( const std::string& sCmd2, const STRVECTOR& vsParams) ; diff --git a/GeoConst.h b/GeoConst.h index e4e89f4..05c44c5 100644 --- a/GeoConst.h +++ b/GeoConst.h @@ -35,4 +35,10 @@ 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 -static const double BEZARC_ANG_CEN_MAX = 90 ; \ No newline at end of file +static const double BEZARC_ANG_CEN_MAX = 90 ; + +//----------------- Costanti per superfici TriMesh --------------------------- +// tolleranza lineare standard +static const double STM_STD_LIN_TOL = 0.1 ; +// angolo limite per mediare le normali in un vertice +static const double STM_STD_SMOOTH_ANG = 25.0 ; diff --git a/NgeConst.h b/NgeConst.h index 63afad6..18375d8 100644 --- a/NgeConst.h +++ b/NgeConst.h @@ -21,7 +21,7 @@ // versione const int NGE_MAJOR_VER = 1 ; const int NGE_MINOR_VER = 5 ; -const int NGE_PATCH_VER = 5 ; +const int NGE_PATCH_VER = 6 ; // nome GDB const std::string NGE_GEOMDB = "GeomDB" ; // indici KeyWord diff --git a/PointGrid3d.cpp b/PointGrid3d.cpp new file mode 100644 index 0000000..d82c21d --- /dev/null +++ b/PointGrid3d.cpp @@ -0,0 +1,111 @@ +//---------------------------------------------------------------------------- +// EgalTech 2014-2014 +//---------------------------------------------------------------------------- +// File : PointGrid3d.cpp Data : 15.05.14 Versione : 1.5e5 +// Contenuto : Implementazione della classe PointGrid3d. +// Indicizzazione spaziale di Point3d mediante hash grid. +// +// +// Modifiche : 15.05.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "\EgtDev\Include\EGkPointGrid3d.h" +#include + +using namespace std ; + +//---------------------------------------------------------------------------- +bool +PointGrid3d::Init( int nBuckets, double dCellDim) +{ + m_dCellDim = dCellDim ; + m_MMap.rehash( nBuckets) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +PointGrid3d::InsertPoint( const Point3d& ptP, int nId) +{ + int nKey = PointHash( Get1dCellNbr( ptP.x), Get1dCellNbr( ptP.y), Get1dCellNbr( ptP.z)) ; + m_MMap.insert( make_pair( nKey, make_pair( ptP, nId))) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +PointGrid3d::Find( const Point3d& ptTest, double dTol, INTVECTOR& vnIds) +{ + // ricavo gli indici sui tre assi degli estremi del box + int nXmin = Get1dCellNbr( ptTest.x - dTol) ; + int nXmax = Get1dCellNbr( ptTest.x + dTol) ; + int nYmin = Get1dCellNbr( ptTest.y - dTol) ; + int nYmax = Get1dCellNbr( ptTest.y + dTol) ; + int nZmin = Get1dCellNbr( ptTest.z - dTol) ; + int nZmax = Get1dCellNbr( ptTest.z + dTol) ; + // pulisco il risultato + vnIds.clear() ; + // ciclo su tutte le celle comprese tra gli estremi + for ( int i = nXmin ; i <= nXmax ; ++ i) { + for ( int j = nYmin ; j <= nYmax ; ++ j) { + for ( int k = nZmin ; k <= nZmax ; ++ k) { + pair MMrange = + m_MMap.equal_range( PointHash( i, j, k)) ; + for ( ; MMrange.first != MMrange.second ; ++ MMrange.first) { + if ( SqDist( (*MMrange.first).second.first, ptTest) < ( dTol * dTol)) + vnIds.push_back( (*MMrange.first).second.second) ; + } + } + } + } + + return ( vnIds.size() > 0) ; +} + +//---------------------------------------------------------------------------- +bool +PointGrid3d::Find( const Point3d& ptTest, double dTol, int& nId) +{ + // ricavo gli indici sui tre assi degli estremi del box + int nXmin = Get1dCellNbr( ptTest.x - dTol) ; + int nXmax = Get1dCellNbr( ptTest.x + dTol) ; + int nYmin = Get1dCellNbr( ptTest.y - dTol) ; + int nYmax = Get1dCellNbr( ptTest.y + dTol) ; + int nZmin = Get1dCellNbr( ptTest.z - dTol) ; + int nZmax = Get1dCellNbr( ptTest.z + dTol) ; + // ciclo su tutte le celle comprese tra gli estremi + for ( int i = nXmin ; i <= nXmax ; ++ i) { + for ( int j = nYmin ; j <= nYmax ; ++ j) { + for ( int k = nZmin ; k <= nZmax ; ++ k) { + pair MMrange = + m_MMap.equal_range( PointHash( i, j, k)) ; + for ( ; MMrange.first != MMrange.second ; ++ MMrange.first) { + if ( SqDist( (*MMrange.first).second.first, ptTest) < ( dTol * dTol)) { + nId = (*MMrange.first).second.second ; + return true ; + } + } + } + } + } + + return false ; +} + +//---------------------------------------------------------------------------- +int +PointGrid3d::Get1dCellNbr( double dCoord) +{ + return static_cast( floor( dCoord / m_dCellDim)) ; +} + +//---------------------------------------------------------------------------- +int +PointGrid3d::PointHash( int nX, int nY, int nZ) +{ + return ( nX * 73856093 ^ nY * 19349663 ^ nZ * 83492791) ; +} diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 6fb94e2..a86984a 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -19,7 +19,9 @@ #include "NgeReader.h" #include "DistPointLine.h" #include "Triangulate.h" +#include "GeoConst.h" #include "\EgtDev\Include\EGkStringUtils3d.h" +#include "\EgtDev\Include\EGkPointGrid3d.h" #include "\EgtDev\Include\EGkPolyLine.h" #include @@ -30,8 +32,9 @@ GEOOBJ_REGISTER( SRF_TRIMESH, NGE_S_TRM, SurfTriMesh) ; //---------------------------------------------------------------------------- SurfTriMesh::SurfTriMesh( void) - : m_nStatus( TO_VERIFY), m_bClosed( false) + : m_nStatus( TO_VERIFY), m_dLinTol( STM_STD_LIN_TOL), m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bClosed( false) { + m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ; } //---------------------------------------------------------------------------- @@ -169,6 +172,34 @@ SurfTriMesh::SetTriangle( int nInd, const StmTria& tT) return true ; } +//---------------------------------------------------------------------------- +int +SurfTriMesh::GetVertexNum( void) const +{ + // calcolo il numero dei vertici cancellati + int nErased = 0 ; + for ( int nId = 0 ; nId < GetVertexSize() ; ++ nId) { + if ( m_vVert[nId].nIdTria == SVT_DEL) + ++ nErased ; + } + + return ( GetVertexSize() - nErased) ; +} + +//---------------------------------------------------------------------------- +int +SurfTriMesh::GetTriangleNum( void) const +{ + // calcolo il numero dei triangoli cancellati + int nErased = 0 ; + for ( int nId = 0 ; nId < GetTriangleSize() ; ++ nId) { + if ( m_vTria[nId].nIdVert[0] == SVT_DEL) + ++ nErased ; + } + + return ( GetTriangleSize() - nErased) ; +} + //---------------------------------------------------------------------------- int SurfTriMesh::GetFirstVertex( Point3d& ptP) const @@ -183,9 +214,9 @@ SurfTriMesh::GetNextVertex( int nId, Point3d& ptP) const // cerco il primo successivo valido do { nId ++ ; - } while ( nId < GetVertexNum() && m_vVert[nId].nIdTria == SVT_DEL) ; + } while ( nId < GetVertexSize() && m_vVert[nId].nIdTria == SVT_DEL) ; // se oltrepassata fine - if ( nId >= GetVertexNum()) + if ( nId >= GetVertexSize()) return SVT_NULL ; // recupero i dati ptP = m_vVert[nId].ptP ; @@ -207,9 +238,9 @@ SurfTriMesh::GetNextTriangle( int nId, Triangle3d& Tria) const // cerco il primo successivo valido do { nId ++ ; - } while ( nId < GetTriangleNum() && m_vTria[nId].nIdVert[0] == SVT_DEL) ; + } while ( nId < GetTriangleSize() && m_vTria[nId].nIdVert[0] == SVT_DEL) ; // se oltrepassata fine - if ( nId >= GetTriangleNum()) + if ( nId >= GetTriangleSize()) return SVT_NULL ; // recupero i dati Tria.Set( m_vVert[m_vTria[nId].nIdVert[0]].ptP, @@ -225,7 +256,7 @@ bool SurfTriMesh::GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const { // verifico esistenza del triangolo - if ( nId >= GetTriangleNum() || m_vTria[nId].nIdVert[0] == SVT_DEL) + if ( nId >= GetTriangleSize() || m_vTria[nId].nIdVert[0] == SVT_DEL) return false ; // recupero le normali di ciascun vertice @@ -261,13 +292,12 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const // medio le normali, finché non incontro degli spigoli vtN = m_vTria[nT].vtN ; - const double COS_DEV_LIM = cos( 22.5 * DEGTORAD) ; // parto dal triangolo e vado in direzione positiva 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) + if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng) vtN += m_vTria[vT[i]].vtN ; else break ; @@ -277,26 +307,11 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const 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) + if ( m_vTria[vT[nPos]].vtN * m_vTria[vT[i]].vtN >= m_dCosSmAng) 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 ; @@ -334,11 +349,14 @@ SurfTriMesh::Copy( const SurfTriMesh& stmSrc) { if ( &stmSrc == this) return true ; - if ( ! Init( stmSrc.GetVertexNum(), stmSrc.GetTriangleNum())) + if ( ! Init( stmSrc.GetVertexSize(), stmSrc.GetTriangleSize())) return false ; m_vVert = stmSrc.m_vVert ; m_vTria = stmSrc.m_vTria ; m_bClosed = stmSrc.m_bClosed ; + m_dLinTol = stmSrc.m_dLinTol ; + m_dSmoothAng = stmSrc.m_dSmoothAng ; + m_dCosSmAng = stmSrc.m_dCosSmAng ; m_nStatus = stmSrc.m_nStatus ; return true ; } @@ -363,11 +381,13 @@ bool SurfTriMesh::Dump( string& sOut, const char* szNewLine) const { // se superficie aperta o chiusa - sOut += ( m_bClosed ? "Closed" : "Open") ; + sOut += ( m_bClosed ? "Closed" : "Open") + string( szNewLine) ; // numero di vertici - sOut += " VertNbr=" + ToString( GetVertexNum()) ; + sOut += "Vert : Nbr=" + ToString( GetVertexNum()) + + " Size=" + ToString( GetVertexSize()) + szNewLine ; // numero di triangoli - sOut += " TriaNbr=" + ToString( GetTriangleNum()) ; + sOut += "Tria : Nbr=" + ToString( GetTriangleNum()) + + " Size=" + ToString( GetTriangleSize()) + szNewLine ; return true ; } @@ -383,12 +403,16 @@ SurfTriMesh::GetNgeId( void) const bool SurfTriMesh::Save( NgeWriter& ngeOut) const { + // tolleranza lineare di costruzione + ngeOut.WriteDouble( m_dLinTol, ";") ; + // angolo limite per mediare le normali + ngeOut.WriteDouble( m_dSmoothAng, ";", true) ; // flag aperta/chiusa ngeOut.WriteBool( m_bClosed, ";") ; // numero di vertici - ngeOut.WriteInt( GetVertexNum(), ";") ; + ngeOut.WriteInt( GetVertexSize(), ";") ; // numero di triangoli - ngeOut.WriteInt( GetTriangleNum(), ";", true) ; + ngeOut.WriteInt( GetTriangleSize(), ";", true) ; // ciclo sui vertici for ( int i = 0 ; i < int( m_vVert.size()) ; ++ i) { ngeOut.WriteInt( i, ";") ; @@ -419,6 +443,15 @@ SurfTriMesh::Load( NgeReader& ngeIn) { // imposto ricalcolo della grafica m_OGrMgr.Reset() ; + // leggo la prossima linea ( 2 parametri : dLinTol e dSmoothAng) + // tolleranza lineare di costruzione + double dLinTol ; + if ( ! ngeIn.ReadDouble( dLinTol, ";")) + return false ; + // angolo limite per mediare le normali + double dSmoothAng ; + if ( ! ngeIn.ReadDouble( dSmoothAng, ";", true)) + return false ; // leggo la prossima linea ( 3 parametri : flag chiuso num vertici e num tria) // recupero il flag bool bClosed ; @@ -432,10 +465,13 @@ SurfTriMesh::Load( NgeReader& ngeIn) int nNumTria ; if ( ! ngeIn.ReadInt( nNumTria, ";", true)) return false ; - // inizializzo la superficie TriMesh + // preparo la superficie if ( ! Init( nNumVert, nNumTria)) return false ; m_bClosed = bClosed ; + m_dLinTol = dLinTol ; + m_dSmoothAng = dSmoothAng ; + m_dCosSmAng = cos( dSmoothAng * DEGTORAD) ; // lettura dei vertici int nInd ; StmVert vV ; @@ -480,12 +516,12 @@ SurfTriMesh::Validate( void) // Verifico che i vertici riferiti dai triangoli esistano m_nStatus = OK ; - for ( int i = 0 ; i < GetTriangleNum() && m_nStatus == OK ; ++ i) { + for ( int i = 0 ; i < GetTriangleSize() && m_nStatus == OK ; ++ i) { // se triangolo non cancellato if ( m_vTria[i].nIdVert[0] != SVT_DEL) { for ( int j = 0 ; j < 3 && m_nStatus == OK ; ++ j) { if ( m_vTria[i].nIdVert[j] < 0 || - m_vTria[i].nIdVert[j] >= GetVertexNum() || + m_vTria[i].nIdVert[j] >= GetVertexSize() || m_vVert[ m_vTria[i].nIdVert[j]].nIdTria == SVT_DEL) m_nStatus = ERR ; } @@ -496,11 +532,11 @@ SurfTriMesh::Validate( void) } // Verifico che i triangoli riferiti dai vertici esistano - for ( int i = 0 ; i < GetVertexNum() && m_nStatus == OK ; ++ i) { + for ( int i = 0 ; i < GetVertexSize() && m_nStatus == OK ; ++ i) { // se vertice non cancellato e con riferimento assegnato if ( m_vVert[i].nIdTria != SVT_DEL && m_vVert[i].nIdTria != SVT_NULL) { if ( m_vVert[i].nIdTria < SVT_DEL || - m_vVert[i].nIdTria >= GetTriangleNum() || + m_vVert[i].nIdTria >= GetTriangleSize() || m_vTria[ m_vVert[i].nIdTria].nIdVert[0] == SVT_DEL) m_nStatus = ERR ; } @@ -604,7 +640,7 @@ bool SurfTriMesh::AdjustAdjacencies( void) { // sistemo i puntatori dai vertici ai triangoli - for ( int i = 0 ; i < GetTriangleNum() ; ++ i) { + for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { // se triangolo non cancellato if ( m_vTria[i].nIdVert[0] != SVT_DEL) { for ( int j = 0 ; j < 3 ; ++ j) { @@ -618,7 +654,7 @@ SurfTriMesh::AdjustAdjacencies( void) bool bModif ; do { bModif = false ; - for ( int i = 0 ; i < GetTriangleNum() ; ++ i) { + for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { // se triangolo non cancellato if ( m_vTria[i].nIdVert[0] != SVT_DEL) { for ( int j = 0 ; j < 3 ; ++ j) { @@ -686,7 +722,7 @@ SurfTriMesh::AdjustOrientations( int nLev, bool& bSomeWrong) // inizializzo parametro di ritorno bSomeWrong = false ; // ciclo sui triangoli - for ( int i = 0 ; i < GetTriangleNum() ; ++ i) { + for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { // flags int nNull = 0 ; int nWrong = 0 ; @@ -727,7 +763,7 @@ SurfTriMesh::TestClosure( void) { // ciclo sui triangoli bool bClosed = true ; - for ( int i = 0 ; i < GetTriangleNum() ; ++ i) { + for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { if ( m_vTria[i].nIdAdjac[0] == SVT_NULL || m_vTria[i].nIdAdjac[1] == SVT_NULL || m_vTria[i].nIdAdjac[2] == SVT_NULL) @@ -812,6 +848,10 @@ SurfTriMesh::CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) if ( PL.GetPointNbr() < 2) return false ; + // imposto ricalcolo + m_nStatus = ERR ; + m_OGrMgr.Reset() ; + // verifico se la polilinea è chiusa bool bClosed = PL.IsClosed() ; @@ -856,6 +896,7 @@ SurfTriMesh::CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) } // sistemo la topologia + m_nStatus = TO_VERIFY ; return AdjustTopology() ; } @@ -866,6 +907,11 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2) // verifico validità polilinee (devono avere almeno 2 punti e non coincidere se non agli estremi aperti) if ( ! VerifyPolylinesForTwoCurves( PL1, PL2)) return false ; + + // imposto ricalcolo + m_nStatus = ERR ; + m_OGrMgr.Reset() ; + // flag di curve chiuse bool bClosed = PL1.IsClosed() && PL2.IsClosed() ; // recupero i parametri delle due polilinee @@ -1022,6 +1068,7 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2) } // sistemo la topologia + m_nStatus = TO_VERIFY ; return AdjustTopology() ; } @@ -1150,6 +1197,10 @@ SurfTriMesh::CreateByScrewing( const PolyLine& PL, const Point3d& ptAx, const Ve return false ; } + // imposto ricalcolo + m_nStatus = ERR ; + m_OGrMgr.Reset() ; + // verifico se la polilinea è chiusa bool bClosed = PL.IsClosed() ; @@ -1287,6 +1338,7 @@ SurfTriMesh::CreateByScrewing( const PolyLine& PL, const Point3d& ptAx, const Ve } // sistemo la topologia + m_nStatus = TO_VERIFY ; return AdjustTopology() ; } @@ -1375,6 +1427,156 @@ SurfTriMesh::AddBiTriangle( const int nIdVert[4]) return true ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::DoCompacting( void) +{ + // imposto ricalcolo + m_nStatus = ERR ; + m_OGrMgr.Reset() ; + + // definisco un Grid per i vertici della superficie + PointGrid3d VertGrid ; + int nBuckets = GetVertexSize() ; + VertGrid.Init( nBuckets) ; + + // inserisco i vertici della trimesh (evitando ripetizioni coi precedenti), + // salvando in un vettore di reindirizzo i nuovi Id + INTVECTOR vVId ; + vVId.reserve( GetVertexSize()) ; + for ( int nId = 0 ; nId < GetVertexSize() ; ++ nId) { + // salto i vertici cancellati (ma ne occupo il posto nel vettore di reindirizzo) + if ( m_vVert[nId].nIdTria == SVT_DEL) { + vVId.push_back( SVT_DEL) ; + continue ; + } + // recupero la posizione geometrica del vertice + Point3d ptP = m_vVert[nId].ptP ; + // se non c'è già un vertice con la stessa posizione lo inserisco nel grid + int nAliasId ; + if ( ! VertGrid.Find( ptP, 2 * EPS_SMALL, nAliasId)) { + VertGrid.InsertPoint( ptP, nId) ; + // salvo l'Id nel vettore di reindirizzo + vVId.push_back( nId) ; + } + // c'e un vertice coincidente + else { + // salvo l'Id alias nel vettore di reindirizzo + vVId.push_back( nAliasId) ; + // marco il vertice come cancellato + m_vVert[nId].nIdTria = SVT_DEL ; + } + } + int nVIdSize = int( vVId.size()) ; + + // sistemo gli indici dei vertici nei triangoli + for ( int nId = 0 ; nId < GetTriangleSize() ; ++ nId) { + // recupero gli indici dei vertici del triangolo + int vOId[3] ; + vOId[0] = m_vTria[nId].nIdVert[0] ; + vOId[1] = m_vTria[nId].nIdVert[1] ; + vOId[2] = m_vTria[nId].nIdVert[2] ; + // salto i triangoli cancellati + if ( vOId[0] == SVT_DEL) + continue ; + // verifico la validità degli indici + if ( vOId[0] < 0 || vOId[0] >= nVIdSize || + vOId[1] < 0 || vOId[1] >= nVIdSize || + vOId[2] < 0 || vOId[2] >= nVIdSize) + return false ; + // aggiorno il triangolo + m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ; + m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ; + m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ; + } + + // ricalcolo le adiacenze + m_nStatus = TO_VERIFY ; + return AdjustTopology() ; +} + +//---------------------------------------------------------------------------- +bool +SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther) +{ + // recupero l'altra superficie + const SurfTriMesh* pOther = dynamic_cast( &stmOther) ; + if ( pOther == nullptr) + return false ; + + // imposto ricalcolo + m_nStatus = ERR ; + m_OGrMgr.Reset() ; + + // definisco un Grid per i vertici delle due superfici + PointGrid3d VertGrid ; + int nBuckets = GetVertexSize() + pOther->GetVertexSize() ; + VertGrid.Init( nBuckets) ; + + // inserisco i vertici della trimesh corrente (li considero tutti diversi tra loro) + for ( int nId = 0 ; nId < GetVertexSize() ; ++ nId) { + // salto i vertici cancellati + if ( m_vVert[nId].nIdTria == SVT_DEL) + continue ; + // inserisco il vertice nella griglia + VertGrid.InsertPoint( m_vVert[nId].ptP, nId) ; + } + + // inserisco i vertici dell'altra trimesh (evitando ripetizioni coi precedenti), + // salvando in un vettore di reindirizzo i nuovi Id + INTVECTOR vVId ; + vVId.reserve( pOther->GetVertexSize()) ; + for ( int nOId = 0 ; nOId < pOther->GetVertexSize() ; ++ nOId) { + // salto i vertici cancellati (ma ne occupo il posto nel vettore di reindirizzo) + if ( pOther->m_vVert[nOId].nIdTria == SVT_DEL) { + vVId.push_back( SVT_DEL) ; + continue ; + } + // recupero la posizione geometrica del vertice + Point3d ptOP = pOther->m_vVert[nOId].ptP ; + // la porto nel riferimento della prima superficie + ptOP.ToGlob( frOther) ; + // se non c'è già un vertice con la stessa posizione lo inserisco + int nNewId ; + if ( ! VertGrid.Find( ptOP, 2 * EPS_SMALL, nNewId)) { + if ( ( nNewId = AddVertex( ptOP)) == SVT_NULL) + return false ; + VertGrid.InsertPoint( ptOP, nNewId) ; + } + // salvo il nuovo Id nel vettore di reindirizzo + vVId.push_back( nNewId) ; + } + int nVIdSize = int( vVId.size()) ; + + // inserisco i triangoli dell'altra trimesh + for ( int nOtId = 0 ; nOtId < pOther->GetTriangleSize() ; ++ nOtId) { + // recupero gli indici dei vertici del triangolo + int vOId[3] ; + vOId[0] = pOther->m_vTria[nOtId].nIdVert[0] ; + vOId[1] = pOther->m_vTria[nOtId].nIdVert[1] ; + vOId[2] = pOther->m_vTria[nOtId].nIdVert[2] ; + // salto i triangoli cancellati + if ( vOId[0] == SVT_DEL) + continue ; + // verifico la validità degli indici + if ( vOId[0] < 0 || vOId[0] >= nVIdSize || + vOId[1] < 0 || vOId[1] >= nVIdSize || + vOId[2] < 0 || vOId[2] >= nVIdSize) + return false ; + int vId[3] ; + vId[0] = vVId[vOId[0]] ; + vId[1] = vVId[vOId[1]] ; + vId[2] = vVId[vOId[2]] ; + // inserisco il triangolo + if ( AddTriangle( vId) == SVT_NULL) + return false ; + } + + // ricalcolo le adiacenze + m_nStatus = TO_VERIFY ; + return AdjustTopology() ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::GetLocalBBox( BBox3d& b3Loc) const @@ -1384,7 +1586,7 @@ SurfTriMesh::GetLocalBBox( BBox3d& b3Loc) const return false ; // assegno il box in locale b3Loc.Reset() ; - for ( int i = 0 ; i < GetVertexNum() ; ++ i) { + for ( int i = 0 ; i < GetVertexSize() ; ++ i) { if ( m_vVert[i].nIdTria != SVT_DEL) b3Loc.Add( m_vVert[i].ptP) ; } @@ -1403,7 +1605,7 @@ SurfTriMesh::GetBBox( const Frame3d& frRef, BBox3d& b3Ref) const return false ; // assegno il box nel riferimento b3Ref.Reset() ; - for ( int i = 0 ; i < GetVertexNum() ; ++ i) { + for ( int i = 0 ; i < GetVertexSize() ; ++ i) { if ( m_vVert[i].nIdTria != SVT_DEL) { Point3d ptTemp = m_vVert[i].ptP ; ptTemp.ToGlob( frRef) ; @@ -1426,7 +1628,7 @@ SurfTriMesh::Translate( const Vector3d& vtMove) m_OGrMgr.Reset() ; // traslo i vertici - for ( int i = 0 ; i < GetVertexNum() ; ++ i) { + for ( int i = 0 ; i < GetVertexSize() ; ++ i) { if ( m_vVert[i].nIdTria != SVT_DEL) m_vVert[i].ptP.Translate( vtMove) ; } @@ -1450,13 +1652,13 @@ SurfTriMesh::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, m_OGrMgr.Reset() ; // ruoto i vertici - for ( int i = 0 ; i < GetVertexNum() ; ++ i) { + for ( int i = 0 ; i < GetVertexSize() ; ++ i) { if ( m_vVert[i].nIdTria != SVT_DEL) m_vVert[i].ptP.Rotate( ptAx, vtAx, dCosAng, dSinAng) ; } // ruoto le normali delle facce - for ( int i = 0 ; i < GetTriangleNum() ; ++ i) { + for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { if ( m_vTria[i].nIdVert[0] != SVT_DEL) m_vTria[i].vtN.Rotate( vtAx, dCosAng, dSinAng) ; } @@ -1485,13 +1687,13 @@ SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double m_OGrMgr.Reset() ; // scalo i vertici - for ( int i = 0 ; i < GetVertexNum() ; ++ i) { + for ( int i = 0 ; i < GetVertexSize() ; ++ i) { if ( m_vVert[i].nIdTria != SVT_DEL) m_vVert[i].ptP.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; } // aggiorno le facce - for ( int i = 0 ; i < GetTriangleNum() ; ++ i) { + for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { if ( m_vTria[i].nIdVert[0] != SVT_DEL) { // se c'è mirror, devo invertire la faccia if ( bMirror && ! InvertTriangle( i)) @@ -1530,13 +1732,13 @@ SurfTriMesh::CalcTriangleNormal( int nT) return false ; // controllo validità vertici riferiti dal triangolo if ( m_vTria[nT].nIdVert[0] < 0 || - m_vTria[nT].nIdVert[0] >= GetVertexNum() || + m_vTria[nT].nIdVert[0] >= GetVertexSize() || m_vVert[m_vTria[nT].nIdVert[0]].nIdTria == SVT_DEL || m_vTria[nT].nIdVert[1] < 0 || - m_vTria[nT].nIdVert[1] >= GetVertexNum() || + m_vTria[nT].nIdVert[1] >= GetVertexSize() || m_vVert[m_vTria[nT].nIdVert[1]].nIdTria == SVT_DEL || m_vTria[nT].nIdVert[2] < 0 || - m_vTria[nT].nIdVert[2] >= GetVertexNum() || + m_vTria[nT].nIdVert[2] >= GetVertexSize() || m_vVert[m_vTria[nT].nIdVert[2]].nIdTria == SVT_DEL) return false ; // calcolo vettori come due lati consecutivi del triangolo @@ -1566,11 +1768,11 @@ SurfTriMesh::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) m_OGrMgr.Reset() ; // specchio i vertici - for ( int i = 0 ; i < GetVertexNum() ; ++ i) + for ( int i = 0 ; i < GetVertexSize() ; ++ i) m_vVert[i].ptP.Mirror( ptOn, vtNorm) ; // inverto le facce - for ( int i = 0 ; i < GetTriangleNum() ; ++ i) { + for ( int i = 0 ; i < GetTriangleSize() ; ++ i) { if ( m_vTria[i].nIdVert[0] != SVT_DEL) { // inverto la faccia if ( ! InvertTriangle( i)) @@ -1597,7 +1799,7 @@ SurfTriMesh::ToGlob( const Frame3d& frRef) return false ; // trasformo i vertici - for ( int i = 0 ; i < GetVertexNum() ; ++ i) { + for ( int i = 0 ; i < GetVertexSize() ; ++ i) { if ( m_vVert[i].nIdTria != SVT_DEL) m_vVert[i].ptP.ToGlob( frRef) ; } @@ -1621,7 +1823,7 @@ SurfTriMesh::ToLoc( const Frame3d& frRef) return false ; // trasformo i vertici - for ( int i = 0 ; i < GetVertexNum() ; ++ i) { + for ( int i = 0 ; i < GetVertexSize() ; ++ i) { if ( m_vVert[i].nIdTria != SVT_DEL) m_vVert[i].ptP.ToLoc( frRef) ; } @@ -1641,7 +1843,7 @@ SurfTriMesh::Invert( void) return false ; // inverto i triangoli - for ( int i = 0 ; i < GetTriangleNum() ; ++ i) + for ( int i = 0 ; i < GetTriangleSize() ; ++ i) InvertTriangle( i) ; // imposto ricalcolo della grafica diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 7b1ed28..e3dbce3 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -92,8 +92,14 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW public : // ISurfTriMesh virtual bool Copy( const IGeoObj* pGObjSrc) ; virtual bool Init( int nNumVert, int nNumTria) ; - virtual int AddVertex( const Point3d& ptVert) ; - virtual int AddTriangle( const int nIdVert[3]) ; + virtual void SetLinearTolerance( double dLinTol) + { m_dLinTol = std::max( dLinTol, EPS_SMALL) ; } + virtual void SetSmoothAngle( double dSmoothAngDeg) + { m_dSmoothAng = std::max( dSmoothAngDeg, EPS_ANG_SMALL) ; + m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ; + m_OGrMgr.Reset() ; } + virtual int AddVertex( const Point3d& ptVert) ; + virtual int AddTriangle( const int nIdVert[3]) ; virtual bool AdjustTopology( void) ; virtual bool CreateByFlatContour( const PolyLine& PL) ; virtual bool CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) ; @@ -102,14 +108,22 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW double dAngRot, double dStepRot) ; virtual bool CreateByScrewing( const PolyLine& PL, const Point3d& ptAx, const Vector3d& vtAx, double dAngRot, double dStepRot, double dMove) ; - virtual int GetVertexNum( void) const - { return int( m_vVert.size()) ; } - virtual int GetTriangleNum( void) const - { return int( m_vTria.size()) ; } - virtual int GetFirstVertex( Point3d& ptP) const ; - virtual int GetNextVertex( int nId, Point3d& ptP) const ; - virtual int GetFirstTriangle( Triangle3d& Tria) const ; - virtual int GetNextTriangle( int nId, Triangle3d& Tria) const ; + virtual bool DoCompacting( void) ; + virtual bool DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther = GLOB_FRM) ; + virtual int GetVertexNum( void) const ; + virtual int GetTriangleNum( void) const ; + virtual int GetVertexSize( void) const + { return int( m_vVert.size()) ; } + virtual int GetTriangleSize( void) const + { return int( m_vTria.size()) ; } + virtual double GetLinearTolerance( void) + { return m_dLinTol ; } + virtual double GetSmoothAngle( void) + { return m_dSmoothAng ; } + virtual int GetFirstVertex( Point3d& ptP) const ; + virtual int GetNextVertex( int nId, Point3d& ptP) const ; + virtual int GetFirstTriangle( Triangle3d& Tria) const ; + virtual int GetNextTriangle( int nId, Triangle3d& Tria) const ; virtual bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const ; public : // IGeoObjRW @@ -157,6 +171,9 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto Status m_nStatus ; // stato + double m_dLinTol ; // tolleranza lineare di costruzione + double m_dSmoothAng ; // angolo limite per mediare le normali (in gradi) + double m_dCosSmAng ; // coseno dell'angolo precedente bool m_bClosed ; // la superficie racchiude un volume VERTVECTOR m_vVert ; // vettore dei vertici TRIAVECTOR m_vTria ; // vettore dei triangoli