EgtGeomKernel 1.5d2 :

- creazione di superfici trimesh da piani contornati e per estrusione
- migliorie a PolyLine
- migliorie a FromString
- modifiche a Vector3d e Point3d.
This commit is contained in:
Dario Sassi
2014-04-09 13:00:17 +00:00
parent d509417136
commit 9b564445cd
15 changed files with 771 additions and 119 deletions
+209
View File
@@ -0,0 +1,209 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : Triangulate.cpp Data : 08.04.14 Versione : 1.5d2
// Contenuto : Implementazione della classe Triangulate.
//
//
//
// Modifiche : 08.04.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "Triangulate.h"
#include "\EgtDev\Include\EGkPolyLine.h"
#include "\EgtDev\Include\EGkPlane3d.h"
//----------------------------------------------------------------------------
// In : PolyLine
// Out : PNTVECTOR (Point3d Vector) : points of the polyline
// INTVECTOR (int Vector) : 3*T indices of above points for T triangles
//----------------------------------------------------------------------------
bool
Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// verifico che la polilinea sia chiusa -> poligono
if ( ! PL.IsClosed())
return false ;
// calcolo il piano medio del poligono
Plane3d plPlane ;
if ( ! PL.IsPlanar( plPlane, 50 * EPS_SMALL))
return false ;
int nPlane ;
bool bCCW ;
if ( fabs( plPlane.vtN.z) >= fabs( plPlane.vtN.x) &&
fabs( plPlane.vtN.z) >= fabs( plPlane.vtN.y)) {
nPlane = PL_XY ;
bCCW = ( plPlane.vtN.z > 0) ;
}
else if ( fabs( plPlane.vtN.x) >= fabs( plPlane.vtN.y)) {
nPlane = PL_YZ ;
bCCW = ( plPlane.vtN.x > 0) ;
}
else {
nPlane = PL_ZX ;
bCCW = ( plPlane.vtN.y > 0) ;
}
// riempio il vettore con i vertici del poligono da triangolare
vPt.clear() ;
vPt.reserve( PL.GetPointNbr() - 1) ;
// se orientato correttamente (componente di N > 0)
if ( bCCW) {
// salto il primo punto (coincide con l'ultimo)
Point3d ptP ;
if ( ! PL.GetFirstPoint( ptP))
return false ;
// inserisco i punti
while ( PL.GetNextPoint( ptP))
vPt.push_back( ptP) ;
}
// altrimenti lo prendo al contrario
else {
// salto l'ultimo punto (coincide con il primo)
Point3d ptP ;
if ( ! PL.GetLastPoint( ptP))
return false ;
// inserisco i punti
while ( PL.GetPrevPoint( ptP))
vPt.push_back( ptP) ;
}
// eseguo la triangolazione
return MakeByEC( vPt, nPlane, vTr) ;
}
//----------------------------------------------------------------------------
// Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0])
// Ear Clipping algorithm
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC( const PNTVECTOR& vPt, int nPlane, INTVECTOR& vTr)
{
// At least 3 points
int n = int( vPt.size()) ;
if ( n < 3)
return false ;
// Save the plane
if ( nPlane != PL_XY && nPlane != PL_YZ && nPlane != PL_ZX)
return false ;
m_nPlane = nPlane ;
// Clear and preallocate triangle vector ( #triangles = n - 2)
vTr.clear() ;
vTr.reserve( 3 * ( n - 2)) ;
// Set up previous and next links to effectively form a double-linked vertex list
INTVECTOR prev( n) ;
INTVECTOR next( n) ;
for ( int i = 0 ; i < n ; ++ i) {
prev[i] = i - 1 ;
next[i] = i + 1 ;
}
prev[0] = n - 1 ;
next[n - 1] = 0 ;
// Start at vertex 0
int i = 0 ;
int nCount = n ;
// Keep removing vertices until just a triangle left
while ( n >= 3) {
// To avoid infinite loop
if ( nCount <= 0)
return false ;
-- nCount ;
// Test if current vertex, v[i], is an ear
bool bIsEar = true ;
// An ear must be convex (here counterclockwise)
if ( TriangleIsCCW( vPt[prev[i]], vPt[i], vPt[next[i]])) {
// Loop over all vertices not part of the tentative ear
int k = next[next[i]] ;
do {
// If vertex k is inside the ear triangle, then this is not an ear
if ( TestPointInTriangle( vPt[k], vPt[prev[i]], vPt[i], vPt[next[i]])) {
bIsEar = false ;
break;
}
k = next[k] ;
} while (k != prev[i]) ;
}
else {
// The ear triangle is clockwise so v[i] is not an ear
bIsEar = false ;
}
// If current vertex v[i] is an ear, delete it and visit the previous vertex
if ( bIsEar) {
// Triangle (v[prev[i]], v[i], v[next[i]]) is an ear
vTr.push_back( prev[i]) ;
vTr.push_back( i) ;
vTr.push_back( next[i]) ;
// Delete vertex v[i] by redirecting next and previous links
// of neighboring verts past it. Decrement vertex count
next[prev[i]] = next[i] ;
prev[next[i]] = prev[i] ;
n--;
// Visit the previous vertex next
i = prev[i] ;
// Reset Count
nCount = n ;
}
else {
// Current vertex is not an ear; visit the next vertex
i = next[i] ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
Triangulate::TriangleIsCCW( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC)
{
double dV11 ;
double dV12 ;
double dV21 ;
double dV22 ;
switch ( m_nPlane) {
default : // PL_XY
dV11 = ptB.x - ptA.x ;
dV12 = ptB.y - ptA.y ;
dV21 = ptC.x - ptB.x ;
dV22 = ptC.y - ptB.y ;
break ;
case PL_YZ :
dV11 = ptB.y - ptA.y ;
dV12 = ptB.z - ptA.z ;
dV21 = ptC.y - ptB.y ;
dV22 = ptC.z - ptB.z ;
break ;
case PL_ZX :
dV11 = ptB.z - ptA.z ;
dV12 = ptB.x - ptA.x ;
dV21 = ptC.z - ptB.z ;
dV22 = ptC.x - ptB.x ;
break ;
}
return ( ( dV11 * dV22 - dV12 * dV21) > 0) ;
}
//----------------------------------------------------------------------------
// Test if point p is contained in triangle (a, b, c)
bool
Triangulate::TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC)
{
if ( ! TriangleIsCCW( ptA, ptB, ptP))
return false ;
if ( ! TriangleIsCCW( ptB, ptC, ptP))
return false ;
if ( ! TriangleIsCCW( ptC, ptA, ptP))
return false ;
return true ;
}