EgtGeomKernel 1.5e1 :

- in TriMesh migliorato lo smooth delle normali
- in TriMesh aggiunta generazione per rivoluzione
- migliorati gestione e aggiornamento materiali.
This commit is contained in:
Dario Sassi
2014-05-02 06:57:24 +00:00
parent e080543b97
commit 1b767fe58e
12 changed files with 621 additions and 110 deletions
+322 -10
View File
@@ -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