EgtGeomKernel 1.8c2 :

- Validate e DoCompacting di SurfTrimesh eliminano i triangoli degeneri (punto o segmento di retta)
- a SurfTrimesh aggiunta Cut (taglio con un piano).
This commit is contained in:
Dario Sassi
2017-03-14 12:04:30 +00:00
parent 876e310289
commit 0b50dc348c
11 changed files with 243 additions and 19 deletions
+224 -7
View File
@@ -35,7 +35,8 @@ GEOOBJ_REGISTER( SRF_TRIMESH, NGE_S_TRM, SurfTriMesh) ;
//----------------------------------------------------------------------------
SurfTriMesh::SurfTriMesh( void)
: m_nStatus( TO_VERIFY), m_dLinTol( STM_STD_LIN_TOL), m_dBoundaryAng( STM_STD_BOUNDARY_ANG),
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bOriented( false), m_bClosed( false), m_bFaceted( false), m_nTimeStamp(), m_nTempProp()
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bOriented( false), m_bClosed( false), m_bFaceted( false),
m_nTimeStamp( 0), m_nTempProp( 0)
{
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
@@ -925,7 +926,7 @@ SurfTriMesh::GetType( void) const
const string&
SurfTriMesh::GetTitle( void) const
{
static const string sTitle = "TriMesh" ;
static const string sTitle = "SurfTm" ;
return sTitle ;
}
@@ -1146,8 +1147,10 @@ SurfTriMesh::Validate( void)
m_nStatus = ERR ;
}
// calcolo eventuale normale mancante
if ( m_nStatus == OK && m_vTria[i].vtN.IsSmall())
CalcTriangleNormal( i) ;
if ( m_nStatus == OK && m_vTria[i].vtN.IsSmall()) {
if ( ! CalcTriangleNormal( i))
RemoveTriangle( i) ;
}
}
}
@@ -2216,6 +2219,11 @@ SurfTriMesh::DoCompacting( void)
m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ;
m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ;
m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ;
// se due vertici coincidono, cancello il triangolo
if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1] ||
m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2] ||
m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2])
RemoveTriangle( nId) ;
}
// ricalcolo le adiacenze
@@ -2295,9 +2303,11 @@ SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther)
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 ;
// se triangolo ancora valido, lo inserisco
if ( vId[0] != vId[1] && vId[0] != vId[2] && vId[1] != vId[2]) {
if ( AddTriangle( vId) == SVT_NULL)
return false ;
}
}
// ricalcolo le adiacenze
@@ -2673,3 +2683,210 @@ SurfTriMesh::Invert( void)
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq)
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// classifico i vertici rispetto al piano
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
double dDist = DistPointPlane( m_vVert[i].ptP, plPlane) ;
if ( abs( dDist) < EPS_SMALL)
m_vVert[i].nTemp = 0 ;
else if ( dDist > 0)
m_vVert[i].nTemp = +1 ;
else
m_vVert[i].nTemp = -1 ;
}
// aggiorno timestamp dei triangoli
for ( auto& Tria : m_vTria)
Tria.nTemp = m_nTimeStamp ;
++ m_nTimeStamp ;
// sistemo i triangoli (eventualmente li elimino)
bool bModif = false ;
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
// salto i triangoli cancellati e quelli aggiunti
if ( m_vTria[i].nIdVert[0] == SVT_DEL || m_vTria[i].nTemp == m_nTimeStamp)
continue ;
// se flag abilita e giace sul piano ed equiverso, lo salvo
if ( bSaveOnEq &&
m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 0 &&
m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 0 &&
m_vVert[ m_vTria[i].nIdVert[2]].nTemp == 0 &&
AreSameVectorApprox( m_vTria[i].vtN, plPlane.vtN))
;
// se giace sul piano o dalla parte esterna del piano, lo cancello
else if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp != -1 &&
m_vVert[ m_vTria[i].nIdVert[1]].nTemp != -1 &&
m_vVert[ m_vTria[i].nIdVert[2]].nTemp != -1) {
bModif = true ;
RemoveTriangle( i) ;
}
// se giace dalla parte interna con al massimo un lato sul piano, lo conservo
else if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp != 1 &&
m_vVert[ m_vTria[i].nIdVert[1]].nTemp != 1 &&
m_vVert[ m_vTria[i].nIdVert[2]].nTemp != 1)
;
// altrimenti attraversa il piano, devo modificarlo
else {
bModif = true ;
int nDisc = m_vVert[ m_vTria[i].nIdVert[0]].nTemp +
m_vVert[ m_vTria[i].nIdVert[1]].nTemp +
m_vVert[ m_vTria[i].nIdVert[2]].nTemp ;
// se ha un vertice all'interno e uno sul piano -> 1 nuovo vertice e 1 nuovo triangolo
if ( nDisc == 0) {
// classifico i vertici
int nVertOn, nVertIn, nVertOut ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 0) {
nVertOn = 0 ;
nVertIn = 1 ;
nVertOut = 2 ;
if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 0) {
nVertOn = 1 ;
nVertIn = 2 ;
nVertOut = 0 ;
if ( m_vVert[ m_vTria[i].nIdVert[2]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
else {
nVertOn = 2 ;
nVertIn = 0 ;
nVertOut = 1 ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
// calcolo il punto di intersezione del lato che attraversa il piano
double dDistIn = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP, plPlane) ;
double dDistOut = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP, plPlane) ;
Point3d ptInt = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
dDistIn / ( dDistIn + dDistOut)) ;
// inserisco il nuovo vertice
int nNewV = AddVertex( ptInt) ;
// inserisco il nuovo triangolo
int nIdVert[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
nIdVert[nVertOut] = nNewV ;
int nIdTria = AddTriangle( nIdVert) ;
if ( ! IsValidSvt( nIdTria))
return false ;
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( i) ;
}
// se ha un vertice all'interno e due all'esterno -> 2 nuovi vertici e 1 nuovo triangolo
else if ( nDisc == 1) {
// classifico i vertici
int nVertIn, nVertOut1, nVertOut2 ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == -1) {
nVertIn = 0 ;
nVertOut1 = 1 ;
nVertOut2 = 2 ;
}
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == -1) {
nVertIn = 1 ;
nVertOut1 = 2 ;
nVertOut2 = 0 ;
}
else {
nVertIn = 2 ;
nVertOut1 = 0 ;
nVertOut2 = 1 ;
}
// calcolo i punti di intersezione dei lati che attraversano il piano
double dDistIn = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP, plPlane) ;
double dDistOut1 = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut1]].ptP, plPlane) ;
double dDistOut2 = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut2]].ptP, plPlane) ;
Point3d ptInt1 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut1]].ptP,
dDistIn / ( dDistIn + dDistOut1)) ;
Point3d ptInt2 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut2]].ptP,
dDistIn / ( dDistIn + dDistOut2)) ;
// inserisco i nuovi vertici
int nNewV1 = AddVertex( ptInt1) ;
int nNewV2 = AddVertex( ptInt2) ;
// inserisco il nuovo triangolo
int nIdVert[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
nIdVert[nVertOut1] = nNewV1 ;
nIdVert[nVertOut2] = nNewV2 ;
int nIdTria = AddTriangle( nIdVert) ;
if ( ! IsValidSvt( nIdTria))
return false ;
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( i) ;
}
// altrimenti ha due vertici allinterno e uno all'esterno -> 2 nuovi vertici e 2 nuovi triangoli
else {
// classifico i vertici
int nVertIn1, nVertIn2, nVertOut ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 1) {
nVertOut = 0 ;
nVertIn1 = 1 ;
nVertIn2 = 2 ;
}
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 1) {
nVertOut = 1 ;
nVertIn1 = 2 ;
nVertIn2 = 0 ;
}
else {
nVertOut = 2 ;
nVertIn1 = 0 ;
nVertIn2 = 1 ;
}
// calcolo i punti di intersezione dei lati che attraversano il piano
double dDistIn1 = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP, plPlane) ;
double dDistIn2 = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP, plPlane) ;
double dDistOut = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP, plPlane) ;
Point3d ptInt1 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
dDistIn1 / ( dDistIn1 + dDistOut)) ;
Point3d ptInt2 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
dDistIn2 / ( dDistIn2 + dDistOut)) ;
// inserisco i nuovi vertici
int nNewV1 = AddVertex( ptInt1) ;
int nNewV2 = AddVertex( ptInt2) ;
// inserisco i nuovi triangoli
int nIdVert1[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
int nIdVert2[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
double dSqDist1 = SqDist( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP, ptInt2) ;
double dSqDist2 = SqDist( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP, ptInt1) ;
if ( dSqDist1 <= dSqDist2) {
nIdVert1[nVertOut] = nNewV1 ;
nIdVert1[nVertIn2] = nNewV2 ;
nIdVert2[nVertOut] = nNewV2 ;
}
else {
nIdVert1[nVertOut] = nNewV1 ;
nIdVert2[nVertOut] = nNewV2 ;
nIdVert2[nVertIn1] = nNewV1 ;
}
int nIdTria1 = AddTriangle( nIdVert1) ;
int nIdTria2 = AddTriangle( nIdVert2) ;
if ( ! IsValidSvt( nIdTria1) || ! IsValidSvt( nIdTria2))
return false ;
m_vTria[nIdTria1].nTemp = m_nTimeStamp ;
m_vTria[nIdTria2].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( i) ;
}
}
}
// se necessario, aggiorno tutto
if ( bModif)
return DoCompacting() ;
return true ;
}