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:
+209
@@ -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 ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user