EgtGeomKernel 1.6b3 :

- aggiunta gestione buchi alle triangolazione di poligoni
- creazione suerfici trimesh da regioni con buchi.
This commit is contained in:
Dario Sassi
2015-02-11 11:38:50 +00:00
parent 48df8ea18c
commit 07405f7de6
25 changed files with 1056 additions and 166 deletions
+158 -16
View File
@@ -20,16 +20,20 @@
using namespace std ;
//-------------------------------------------------------------------------------
static bool CalcRegionPolyLines( const ICURVEPVECTOR& vpCurve, double dLinTol,
POLYLINEVECTOR& vPL, Vector3d& vtN) ;
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshByContour( const ICurve& Curve, double dLinTol)
GetSurfTriMeshByFlatContour( const ICurve* pCurve, double dLinTol)
{
// verifica parametri
if ( &Curve == nullptr)
if ( pCurve == nullptr)
return nullptr ;
// calcolo la polilinea che approssima la curva
PolyLine PL ;
if ( ! Curve.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL))
if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL))
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<ISurfTriMesh> pSTM( CreateSurfTriMesh()) ;
@@ -41,15 +45,35 @@ GetSurfTriMeshByContour( const ICurve& Curve, double dLinTol)
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshByExtrusion( const ICurve& Curve, const Vector3d& vtExtr,
GetSurfTriMeshByRegion( const ICURVEPVECTOR& vpCurve, double dLinTol)
{
// verifica parametri
if ( &vpCurve == nullptr || vpCurve.empty())
return nullptr ;
// calcolo le polilinee che approssimano le curve della regione
POLYLINEVECTOR vPL ;
Vector3d vtN ;
if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<ISurfTriMesh> pSTM( CreateSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
return nullptr ;
// restituisco la superficie
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr,
bool bCapEnds, double dLinTol)
{
// verifica parametri
if ( &Curve == nullptr || &vtExtr == nullptr)
if ( pCurve == nullptr || &vtExtr == nullptr)
return nullptr ;
// calcolo la polilinea che approssima la curva
PolyLine PL ;
if ( ! Curve.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL))
if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL))
return nullptr ;
// se richiesta chiusura agli estremi
bool bDoCapEnds = false ;
@@ -62,6 +86,7 @@ GetSurfTriMeshByExtrusion( const ICurve& Curve, const Vector3d& vtExtr,
double dOrthoExtr = plPlane.vtN * vtExtr ;
if ( ( fabs( dOrthoExtr) > EPS_SMALL)) {
bDoCapEnds = true ;
// se negativa, inverto il senso del contorno
if ( dOrthoExtr < 0)
PL.Invert() ;
}
@@ -95,17 +120,75 @@ GetSurfTriMeshByExtrusion( const ICurve& Curve, const Vector3d& vtExtr,
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshByRevolve( const ICurve& Curve, const Point3d& ptAx, const Vector3d& vtAx,
GetSurfTriMeshByRegionExtrusion( const ICURVEPVECTOR& vpCurve, const Vector3d& vtExtr, double dLinTol)
{
// verifica parametri
if ( &vpCurve == nullptr || vpCurve.empty() || &vtExtr == nullptr)
return nullptr ;
// se una sola curva, uso la funzione precedente
if ( vpCurve.size() == 1 )
return GetSurfTriMeshByExtrusion( vpCurve[0], vtExtr, true, dLinTol) ;
// calcolo le polilinee che approssimano le curve della regione
POLYLINEVECTOR vPL ;
Vector3d vtN ;
if ( ! CalcRegionPolyLines( vpCurve, dLinTol, vPL, vtN))
return nullptr ;
// verifico la direzione di estrusione
double dOrthoExtr = vtN * vtExtr ;
if ( ( fabs( dOrthoExtr) < EPS_SMALL))
return nullptr ;
// se componente estrusione negativa, inverto tutti i percorsi
if ( dOrthoExtr < 0) {
for ( int i = 0 ; i < int( vPL.size()) ; ++ i)
vPL[i].Invert() ;
}
// creo la prima superficie di estremità
PtrOwner<ISurfTriMesh> pSTM( CreateSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
return nullptr ;
// creo la seconda superficie e la unisco alla prima
{ // copio la prima superficie
PtrOwner<ISurfTriMesh> pSTM2( GetSurfTriMesh( pSTM->Clone())) ;
if ( IsNull( pSTM2))
return nullptr ;
// inverto la prima superficie
pSTM->Invert() ;
// traslo la seconda
pSTM2->Translate( vtExtr) ;
// la unisco alla prima
if ( ! pSTM->DoSewing( *pSTM2))
return nullptr ;
}
// creo e unisco le diverse superfici di estrusione
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// estrusione
PtrOwner<ISurfTriMesh> pSTM2( CreateSurfTriMesh()) ;
if ( IsNull( pSTM2) || ! pSTM2->CreateByExtrusion( vPL[i], vtExtr))
return nullptr ;
// la unisco alla superficie principale
if ( ! pSTM->DoSewing( *pSTM2))
return nullptr ;
}
// compatto la superficie
if ( ! pSTM->DoCompacting())
return nullptr ;
// restituisco la superficie
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshByRevolve( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx,
bool bCapEnds, double dLinTol)
{
// verifica parametri
if ( &Curve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
return nullptr ;
// limite minimo su tolleranza
dLinTol = max( dLinTol, EPS_SMALL) ;
// calcolo la polilinea che approssima la curva
PolyLine PL ;
if ( ! Curve.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL))
if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL))
return nullptr ;
// calcolo lo step di rotazione
double dMaxRad = 0 ;
@@ -156,17 +239,17 @@ GetSurfTriMeshByRevolve( const ICurve& Curve, const Point3d& ptAx, const Vector3
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshByScrewing( const ICurve& Curve, const Point3d& ptAx, const Vector3d& vtAx,
GetSurfTriMeshByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx,
double dAngRotDeg, double dMove, double dLinTol)
{
// verifica parametri
if ( &Curve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
if ( pCurve == nullptr || &ptAx == nullptr || &vtAx == nullptr)
return nullptr ;
// limite minimo su tolleranza
dLinTol = max( dLinTol, EPS_SMALL) ;
// calcolo la polilinea che approssima la curva
PolyLine PL ;
if ( ! Curve.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL))
if ( ! pCurve->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL))
return nullptr ;
// calcolo lo step di rotazione
double dMaxRad = 0 ;
@@ -189,18 +272,18 @@ GetSurfTriMeshByScrewing( const ICurve& Curve, const Point3d& ptAx, const Vector
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshRuled( const ICurve& Curve1, const ICurve& Curve2, double dLinTol)
GetSurfTriMeshRuled( const ICurve* pCurve1, const ICurve* pCurve2, double dLinTol)
{
// verifica parametri
if ( &Curve1 == nullptr || &Curve2 == nullptr)
if ( pCurve1 == nullptr || pCurve2 == nullptr)
return nullptr ;
// calcolo la polilinea che approssima la prima curva
PolyLine PL1 ;
if ( ! Curve1.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL1))
if ( ! pCurve1->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL1))
return nullptr ;
// calcolo la polilinea che approssima la seconda curva
PolyLine PL2 ;
if ( ! Curve2.ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL2))
if ( ! pCurve2->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL2))
return nullptr ;
// creo e setto la superficie trimesh
PtrOwner<ISurfTriMesh> pSTM( CreateSurfTriMesh()) ;
@@ -209,3 +292,62 @@ GetSurfTriMeshRuled( const ICurve& Curve1, const ICurve& Curve2, double dLinTol)
// restituisco la superficie
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
bool
CalcRegionPolyLines( const ICURVEPVECTOR& vpCurve, double dLinTol,
POLYLINEVECTOR& vPL, Vector3d& vtN)
{
// calcolo le polilinee che approssimano le curve
POLYLINEVECTOR vPLtmp ;
vPLtmp.resize( vpCurve.size()) ;
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, vPLtmp[i]))
return nullptr ;
}
// ne calcolo l'area e genero un ordine in senso decrescente
typedef std::pair<int,double> INDAREA ; // coppia indice, area
typedef std::vector<INDAREA> INDAREAVECTOR ; // vettore di coppie indice, area
INDAREAVECTOR vArea ;
vArea.reserve( vPLtmp.size()) ;
Vector3d vtN0 ;
for ( int i = 0 ; i < int( vPLtmp.size()) ; ++ i) {
// verifico chiusura, calcolo piano medio e area
Plane3d plPlane ;
double dArea ;
if ( ! vPLtmp[i].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
// imposto la normale del primo contorno come riferimento
if ( i == 0)
vtN0 = plPlane.vtN ;
// verifico che le normali siano molto vicine
if ( ! AreSameOrOppositeVectorApprox( plPlane.vtN, vtN0))
return false ;
// assegno il segno all'area secondo il verso della normale
if ( ( plPlane.vtN * vtN0) > 0)
vArea.emplace_back( i, dArea) ;
else
vArea.emplace_back( i, - dArea) ;
}
sort( vArea.begin(), vArea.end(),
[]( const INDAREA& a, const INDAREA&b) { return fabs( a.second) > fabs( b.second) ; }) ;
// sposto le polilinee nel vettore da restituire secondo l'ordine
vPL.clear() ;
vPL.resize( vPLtmp.size()) ;
bool bCCW = true ;
for ( int i = 0 ; i < int( vPLtmp.size()) ; ++ i) {
// scambio
swap( vPL[i], vPLtmp[vArea[i].first]) ;
// verifico senso di rotazione del contorno esterno
if ( i == 0)
bCCW = ( vArea[i].second > 0) ;
// aggiusto gli altri contorni
else {
if ( ( bCCW && vArea[i].second > 0) || ( ! bCCW && vArea[i].second < 0))
vPL[i].Invert() ;
}
}
// restituisco la normale positiva alla regione
vtN = ( bCCW ? vtN0 : - vtN0) ;
return true ;
}