diff --git a/CurveArc.cpp b/CurveArc.cpp
index 43db995..df25b04 100644
--- a/CurveArc.cpp
+++ b/CurveArc.cpp
@@ -402,6 +402,14 @@ CurveArc::GetLength( double& dLen) const
bool
CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const
{
+ // pulisco la polilinea
+ PL.Clear() ;
+
+ // la curva deve essere validata
+ if ( m_nStatus != OK)
+ return false ;
+
+ // eseguo approssimazione
ArcApproxer aAppr( dLinTol, dAngTolDeg, true, *this) ;
double dU ;
Point3d ptPos ;
diff --git a/CurveBezier.cpp b/CurveBezier.cpp
index 55635e6..2ca595b 100644
--- a/CurveBezier.cpp
+++ b/CurveBezier.cpp
@@ -1133,6 +1133,9 @@ CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart,
bool
CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const
{
+ // pulisco la polilinea
+ PL.Clear() ;
+
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
diff --git a/CurveComposite.cpp b/CurveComposite.cpp
index 546c30f..c529e3a 100644
--- a/CurveComposite.cpp
+++ b/CurveComposite.cpp
@@ -536,15 +536,18 @@ CurveComposite::GetLength( double& dLen) const
bool
CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const
{
- bool bFirst ;
- double dStartPar ;
- Point3d ptP ;
+ // pulisco la polilinea
+ PL.Clear() ;
+
+ // la curva deve essere validata
+ if ( m_nStatus != OK)
+ return false ;
+
+ // eseguo approssimazione
+ bool bFirst = true ;
+ double dStartPar = 0 ;
PolyLine PLSmpl ;
PCRVSMPL_LIST::const_iterator Iter ;
-
-
- bFirst = true ;
- dStartPar = 0 ;
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
// recupero approssimazione per curva semplice
if ( ! (*Iter)->ApproxWithLines( dLinTol, dAngTolDeg, PLSmpl))
diff --git a/CurveLine.cpp b/CurveLine.cpp
index 03a9044..518ab6b 100644
--- a/CurveLine.cpp
+++ b/CurveLine.cpp
@@ -264,6 +264,9 @@ CurveLine::GetLength( double& dLen) const
bool
CurveLine::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const
{
+ // pulisco la polilinea
+ PL.Clear() ;
+
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc
index 4403278..d3db20e 100644
Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ
diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj
index cb532af..27e99bd 100644
--- a/EgtGeomKernel.vcxproj
+++ b/EgtGeomKernel.vcxproj
@@ -264,6 +264,7 @@ copy $(TargetPath) \EgtProg\Dll64
+
@@ -290,6 +291,7 @@ copy $(TargetPath) \EgtProg\Dll64
+
@@ -337,6 +339,7 @@ copy $(TargetPath) \EgtProg\Dll64
+
diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters
index fa22283..56eca04 100644
--- a/EgtGeomKernel.vcxproj.filters
+++ b/EgtGeomKernel.vcxproj.filters
@@ -138,6 +138,9 @@
File di origine\Geo
+
+ File di origine\Base
+
@@ -350,6 +353,12 @@
File di intestazione
+
+ File di intestazione
+
+
+ File di intestazione
+
diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp
index 0af297f..1f1bc4c 100644
--- a/GdbExecutor.cpp
+++ b/GdbExecutor.cpp
@@ -100,6 +100,8 @@ GdbExecutor::GdbExecutor( void)
m_ExecMgr.Insert( "MIRROR", &GdbExecutor::ExecuteMirror) ;
m_ExecMgr.Insert( "INVC", &GdbExecutor::ExecuteInvertCurve) ;
m_ExecMgr.Insert( "INVERTCURVE", &GdbExecutor::ExecuteInvertCurve) ;
+ m_ExecMgr.Insert( "INVS", &GdbExecutor::ExecuteInvertSurf) ;
+ m_ExecMgr.Insert( "INVERTSURF", &GdbExecutor::ExecuteInvertSurf) ;
m_ExecMgr.Insert( "TRC", &GdbExecutor::ExecuteTrimCurve) ;
m_ExecMgr.Insert( "TRIMCURVE", &GdbExecutor::ExecuteTrimCurve) ;
m_ExecMgr.Insert( "NEW", &GdbExecutor::ExecuteNew) ;
@@ -697,6 +699,7 @@ GdbExecutor::ExecuteCurveCompo( const string& sCmd2, const STRVECTOR& vsParams)
bool
GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams)
{
+ // se inizio creazione con componenti elementari
if ( sCmd2 == "BEGIN") {
// 2 parametri opzionali : numero vertici e numero triangoli
if ( vsParams.size() > 2)
@@ -719,6 +722,7 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams)
m_pGeoObj = pSTM ;
return true ;
}
+ // se nuovo vertice
else if ( sCmd2 == "VERT" || sCmd2 == "ADDVERTEX") {
// 1 parametro : punto
if ( vsParams.size() != 1)
@@ -734,6 +738,7 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams)
// aggiungo il vertice
return ( pSTM->AddVertex( ptP) != -1) ;
}
+ // se nuovo triangolo
else if ( sCmd2 == "TRIA" || sCmd2 == "ADDTRIANGLE") {
// 3 parametri : IdV1, IdV2, IdV3
if ( vsParams.size() != 3)
@@ -751,6 +756,7 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams)
// aggiungo il triangolo definito con gli indici dei 3 vertici
return ( pSTM->AddTriangle( nIdVert) != -1) ;
}
+ // se fine creazione
else if ( sCmd2 == "END") {
// 2 parametri : Id e ParentId
if ( vsParams.size() != 2)
@@ -766,6 +772,108 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams)
m_pGeoObj = nullptr ;
return AddGeoObj( vsParams[0], vsParams[1], pSTM) ;
}
+ // se creazione per triangolazione di un contorno chiuso e piano
+ else if ( sCmd2 == "CONT" || sCmd2 == "BYCONTOUR") {
+ // 3 parametri : Id, ParentId, IdCurve
+ if ( vsParams.size() != 3)
+ return false ;
+ // recupero la curva
+ int nIdCrv = GetIdParam( vsParams[2]) ;
+ const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ;
+ if ( pCrv == nullptr)
+ return false ;
+ // recupero il riferimento della curva
+ Frame3d frCrv ;
+ if ( ! m_pGDB->GetGlobFrame( nIdCrv, frCrv))
+ return false ;
+ // recupero il riferimento del gruppo destinazione
+ Frame3d frDest ;
+ if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest))
+ return false ;
+ // calcolo la polilinea che approssima la curva
+ PolyLine PL ;
+ // se i riferimenti sono uguali
+ if ( AreSameFrame( frCrv, frDest)) {
+ // ricavo l'approssimazione
+ if ( ! pCrv->ApproxWithLines( 0.01, 15, PL))
+ return false ;
+ }
+ // altrimenti devo prima trasformare la curva
+ else {
+ // creo una copia della curva (da buttare alla fine)
+ PtrOwner pModCrv( GetCurve( pCrv->Clone())) ;
+ if ( ! IsValid( pModCrv))
+ return false ;
+ // eseguo la trasformazione
+ pModCrv->ToGlob( frCrv) ;
+ pModCrv->ToLoc( frDest) ;
+ // ricavo l'approssimazione
+ if ( ! pCrv->ApproxWithLines( 0.01, 15, PL))
+ return false ;
+ }
+ // creo la superficie
+ PtrOwner pSTM( CreateSurfTriMesh()) ;
+ if ( ! IsValid( pSTM))
+ return false ;
+ // costruisco la triangolazione
+ if ( ! pSTM->CreateByTriangulation( PL))
+ return false ;
+ // inserisco la superficie trimesh nel DB
+ return AddGeoObj( vsParams[0], vsParams[1], Release( pSTM)) ;
+ }
+ // se creazione per estrusione
+ else if ( sCmd2 == "EXTR" || sCmd2 == "BYEXTRUSION") {
+ // 4 parametri : Id, ParentId, IdCurve, vtExtr
+ if ( vsParams.size() != 4)
+ return false ;
+ // recupero la curva
+ int nIdCrv = GetIdParam( vsParams[2]) ;
+ const ICurve* pCrv = GetCurve( m_pGDB->GetGeoObj( nIdCrv)) ;
+ if ( pCrv == nullptr)
+ return false ;
+ // recupero il riferimento della curva
+ Frame3d frCrv ;
+ if ( ! m_pGDB->GetGlobFrame( nIdCrv, frCrv))
+ return false ;
+ // recupero il riferimento del gruppo destinazione
+ Frame3d frDest ;
+ if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest))
+ return false ;
+ // calcolo la polilinea che approssima la curva
+ PolyLine PL ;
+ // se i riferimenti sono uguali
+ if ( AreSameFrame( frCrv, frDest)) {
+ // ricavo l'approssimazione
+ if ( ! pCrv->ApproxWithLines( 0.01, 15, PL))
+ return false ;
+ }
+ // altrimenti devo prima trasformare la curva
+ else {
+ // creo una copia della curva (da buttare alla fine)
+ PtrOwner pModCrv( GetCurve( pCrv->Clone())) ;
+ if ( ! IsValid( pModCrv))
+ return false ;
+ // eseguo la trasformazione
+ pModCrv->ToGlob( frCrv) ;
+ pModCrv->ToLoc( frDest) ;
+ // ricavo l'approssimazione
+ if ( ! pCrv->ApproxWithLines( 0.01, 15, PL))
+ return false ;
+ }
+ // recupero il vettore di estrusione
+ Vector3d vtExtr ;
+ if ( ! GetVectorParam( vsParams[3], vtExtr))
+ return false ;
+ // creo la superficie
+ PtrOwner pSTM( CreateSurfTriMesh()) ;
+ if ( ! IsValid( pSTM))
+ return false ;
+ // costruisco l'estrusione
+ if ( ! pSTM->CreateByExtrusion( PL, vtExtr))
+ return false ;
+ // inserisco la superficie trimesh nel DB
+ return AddGeoObj( vsParams[0], vsParams[1], Release( pSTM)) ;
+ }
else
return false ;
}
@@ -1598,6 +1706,28 @@ GdbExecutor::ExecuteInvertCurve( const std::string& sCmd2, const STRVECTOR& vsPa
return true ;
}
+//----------------------------------------------------------------------------
+bool
+GdbExecutor::ExecuteInvertSurf( const std::string& sCmd2, const STRVECTOR& vsParams)
+{
+ // 1 parametro ( Nome/i)
+ if ( vsParams.size() != 1)
+ return false ;
+ // recupero lista nomi
+ INTVECTOR vnNames ;
+ if ( ! GetNamesParam( vsParams[0], vnNames))
+ return false ;
+ // esecuzione inversione normale superficie
+ INTVECTOR::iterator Iter ;
+ for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) {
+ ISurf* pSurf = GetSurf( m_pGDB->GetGeoObj( *Iter)) ;
+ if ( pSurf == nullptr || ! pSurf->Invert())
+ return false ;
+ }
+
+ return true ;
+}
+
//----------------------------------------------------------------------------
bool
GdbExecutor::ExecuteTrimCurve( const std::string& sCmd2, const STRVECTOR& vsParams)
diff --git a/GdbExecutor.h b/GdbExecutor.h
index 5c5b4a7..d83c33e 100644
--- a/GdbExecutor.h
+++ b/GdbExecutor.h
@@ -67,6 +67,7 @@ class GdbExecutor : public IGdbExecutor
bool ExecuteScale( const std::string& sCmd2, const STRVECTOR& vsParams) ;
bool ExecuteMirror( const std::string& sCmd2, const STRVECTOR& vsParams) ;
bool ExecuteInvertCurve( const std::string& sCmd2, const STRVECTOR& vsParams) ;
+ bool ExecuteInvertSurf( const std::string& sCmd2, const STRVECTOR& vsParams) ;
bool ExecuteTrimCurve( const std::string& sCmd2, const STRVECTOR& vsParams) ;
bool ExecuteNew( const std::string& sCmd2, const STRVECTOR& vsParams) ;
bool ExecuteLoad( const std::string& sCmd2, const STRVECTOR& vsParams) ;
diff --git a/PolyLine.cpp b/PolyLine.cpp
index bd28f29..3b811f7 100644
--- a/PolyLine.cpp
+++ b/PolyLine.cpp
@@ -14,6 +14,7 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "\EgtDev\Include\EGkPolyLine.h"
+#include "\EgtDev\Include\EGkPlane3d.h"
//----------------------------------------------------------------------------
@@ -28,6 +29,16 @@ PolyLine::~PolyLine( void)
{
}
+//----------------------------------------------------------------------------
+bool
+PolyLine::Clear( void)
+{
+ m_nCount = 0 ;
+ m_lUPoints.clear() ;
+ m_iter = m_lUPoints.end() ;
+ return true ;
+}
+
//----------------------------------------------------------------------------
bool
PolyLine::AddUPoint( double dPar, const Point3d& ptP)
@@ -48,7 +59,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP)
bool
PolyLine::EraseFirstUPoint( void)
{
- if ( m_lUPoints.begin() == m_lUPoints.end())
+ if ( m_lUPoints.empty())
return false ;
m_lUPoints.pop_front() ;
@@ -57,6 +68,19 @@ PolyLine::EraseFirstUPoint( void)
return true ;
}
+//----------------------------------------------------------------------------
+bool
+PolyLine::EraseLastUPoint( void)
+{
+ if ( m_lUPoints.empty())
+ return false ;
+
+ m_lUPoints.pop_back() ;
+ m_nCount -- ;
+
+ return true ;
+}
+
//----------------------------------------------------------------------------
bool
PolyLine::AddOffsetToU( double dOffset)
@@ -76,10 +100,21 @@ PolyLine::Splice( PolyLine& PL)
{
m_lUPoints.splice( m_lUPoints.end(), PL.m_lUPoints) ;
m_nCount += PL.GetPointNbr() ;
+ PL.m_nCount = 0 ;
return true ;
}
+//----------------------------------------------------------------------------
+bool
+PolyLine::IsClosed( void) const
+{
+ if ( m_lUPoints.empty())
+ return false ;
+
+ return ( AreSamePointNear( m_lUPoints.front().second, m_lUPoints.back().second)) ;
+}
+
//----------------------------------------------------------------------------
bool
PolyLine::GetFirstUPoint( double* pdPar, Point3d* pptP) const
@@ -116,7 +151,12 @@ PolyLine::GetNextUPoint( double* pdPar, Point3d* pptP) const
bool
PolyLine::GetLastUPoint( double* pdPar, Point3d* pptP) const
{
- if ( m_lUPoints.begin() == m_lUPoints.end())
+ m_iter = m_lUPoints.end() ;
+ if ( m_iter == m_lUPoints.begin())
+ return false ;
+ -- m_iter ;
+
+ if ( m_iter == m_lUPoints.end())
return false ;
if ( pdPar != nullptr)
@@ -127,6 +167,22 @@ PolyLine::GetLastUPoint( double* pdPar, Point3d* pptP) const
return true ;
}
+//----------------------------------------------------------------------------
+bool
+PolyLine::GetPrevUPoint( double* pdPar, Point3d* pptP) const
+{
+ if ( m_iter == m_lUPoints.begin())
+ return false ;
+ -- m_iter ;
+
+ if ( pdPar != nullptr)
+ *pdPar = m_iter->first ;
+ if ( pptP != nullptr)
+ *pptP = m_iter->second ;
+
+ return true ;
+}
+
//----------------------------------------------------------------------------
bool
PolyLine::GetFirstULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* pptFin) const
@@ -176,3 +232,60 @@ PolyLine::GetNextULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d*
return true ;
}
+//----------------------------------------------------------------------------
+bool
+PolyLine::NewellPlane( Plane3d& plPlane) const
+{
+ // Compute normal as being proportional to projected areas of polygon onto the yz,
+ // xz, and xy planes. Also compute centroid as representative point on the plane
+ Vector3d vtN ;
+ Point3d ptCen ;
+ int nNumSide = 0 ;
+ Point3d ptIni, ptFin ;
+ for ( bool bFound = GetFirstLine( ptIni, ptFin) ; bFound ; bFound = GetNextLine( ptIni, ptFin)) {
+ vtN.x += ( ptIni.y - ptFin.y) * ( ptIni.z + ptFin.z) ; // projection on yz
+ vtN.y += ( ptIni.z - ptFin.z) * ( ptIni.x + ptFin.x) ; // projection on xz
+ vtN.z += ( ptIni.x - ptFin.x) * ( ptIni.y + ptFin.y) ; // projection on xy
+ ptCen += ptFin ;
+ ++ nNumSide ;
+ }
+ // If open and existent, add segment from last to first points
+ if ( ! IsClosed() && nNumSide > 0) {
+ ptIni = ptFin ;
+ GetFirstPoint( ptFin) ;
+ vtN.x += ( ptIni.y - ptFin.y) * ( ptIni.z + ptFin.z) ; // projection on yz
+ vtN.y += ( ptIni.z - ptFin.z) * ( ptIni.x + ptFin.x) ; // projection on xz
+ vtN.z += ( ptIni.x - ptFin.x) * ( ptIni.y + ptFin.y) ; // projection on xy
+ ptCen += ptFin ;
+ ++ nNumSide ;
+ }
+ // At least 3 sides
+ if ( nNumSide < 3)
+ return false ;
+ // Normal must be normalizable
+ if ( ! vtN.Normalize())
+ return false ;
+ // Normalize normal and fill in the plane equation fields
+ plPlane.vtN = vtN ;
+ plPlane.dDist = ( ( ptCen - ORIG) * plPlane.vtN) / nNumSide ; // “centroid / n” is the true centroid point
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+PolyLine::IsPlanar( Plane3d& plPlane, double dToler) const
+{
+ // Compute a representative plane for the polygon
+ if ( ! NewellPlane( plPlane))
+ return false ;
+ // Test each vertex to see if it is farther from plane than allowed max distance
+ Point3d ptP ;
+ for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP)) {
+ double dDist = ( ( ptP - ORIG) * plPlane.vtN) - plPlane.dDist ;
+ if ( fabs( dDist) > dToler)
+ return false ;
+ }
+ // All points passed distance test, so polygon is considered planar
+ return true ;
+}
diff --git a/StringUtils3d.cpp b/StringUtils3d.cpp
index 17756fd..bf6dca5 100644
--- a/StringUtils3d.cpp
+++ b/StringUtils3d.cpp
@@ -17,89 +17,44 @@
using namespace std ;
-//----------------------------------------------------------------------------
-bool
-FromString( const string& sVal, Vector3d& vtVal)
-{
- // divido la stringa in parametri
- STRVECTOR vsParams ;
- Tokenize( sVal, ",", vsParams) ;
- // devono essere 3 parametri : x, y, z
- if ( vsParams.size() != 3)
- return false ;
- // recupero il punto
- return ( FromString( vsParams[0], vtVal.x) &&
- FromString( vsParams[1], vtVal.y) &&
- FromString( vsParams[2], vtVal.z)) ;
-}
-
-//----------------------------------------------------------------------------
-bool
-FromString( const string& sVal, Point3d& ptVal)
-{
- // divido la stringa in parametri
- STRVECTOR vsParams ;
- Tokenize( sVal, ",", vsParams) ;
- // devono essere 3 parametri : x, y, z
- if ( vsParams.size() != 3)
- return false ;
- // recupero il punto
- return ( FromString( vsParams[0], ptVal.x) &&
- FromString( vsParams[1], ptVal.y) &&
- FromString( vsParams[2], ptVal.z)) ;
-}
-
//----------------------------------------------------------------------------
bool
FromString( const string& sVal, Point3d& ptVal, double& dW)
{
- // divido la stringa in parametri
- STRVECTOR vsParams ;
- Tokenize( sVal, ",", vsParams) ;
- // devono essere 4 parametri : x, y, z, w
- if ( vsParams.size() != 4)
+ double vdVal[4] ;
+ if ( ! FromString( sVal, vdVal))
return false ;
- // recupero il punto
- return ( FromString( vsParams[0], ptVal.x) &&
- FromString( vsParams[1], ptVal.y) &&
- FromString( vsParams[2], ptVal.z) &&
- FromString( vsParams[3], dW)) ;
+ ptVal.x = vdVal[0] ;
+ ptVal.y = vdVal[1] ;
+ ptVal.z = vdVal[2] ;
+ dW = vdVal[3] ;
+ return true ;
}
//----------------------------------------------------------------------------
bool
FromString( const string& sVal, Frame3d& frFrame)
{
- // divido la stringa in parametri
- STRVECTOR vsParams ;
- Tokenize( sVal, ",", vsParams) ;
// devono essere 12 parametri : Ox, Oy, Oz, Xx, Xy, Xz, Yx, Yy, Yz, Zx, Zy, Zz
- if ( vsParams.size() != 12)
+ double vdVal[12] ;
+ if ( ! FromString( sVal, vdVal))
return false ;
- // recupero l'origine
Point3d ptOrig ;
- if ( ! FromString( vsParams[0], ptOrig.x) ||
- ! FromString( vsParams[1], ptOrig.y) ||
- ! FromString( vsParams[2], ptOrig.z))
- return false ;
- // recupero il versore X
+ ptOrig.x = vdVal[0] ;
+ ptOrig.y = vdVal[1] ;
+ ptOrig.z = vdVal[2] ;
Vector3d vtDirX ;
- if ( ! FromString( vsParams[3], vtDirX.x) ||
- ! FromString( vsParams[4], vtDirX.y) ||
- ! FromString( vsParams[5], vtDirX.z))
- return false ;
- // recupero il versore Y
+ vtDirX.x = vdVal[3] ;
+ vtDirX.y = vdVal[4] ;
+ vtDirX.z = vdVal[5] ;
Vector3d vtDirY ;
- if ( ! FromString( vsParams[6], vtDirY.x) ||
- ! FromString( vsParams[7], vtDirY.y) ||
- ! FromString( vsParams[8], vtDirY.z))
- return false ;
- // recupero il versore Z
+ vtDirY.x = vdVal[6] ;
+ vtDirY.y = vdVal[7] ;
+ vtDirY.z = vdVal[8] ;
Vector3d vtDirZ ;
- if ( ! FromString( vsParams[9], vtDirZ.x) ||
- ! FromString( vsParams[10], vtDirZ.y) ||
- ! FromString( vsParams[11], vtDirZ.z))
- return false ;
+ vtDirZ.x = vdVal[9] ;
+ vtDirZ.y = vdVal[10] ;
+ vtDirZ.z = vdVal[11] ;
// imposto il riferimento
return frFrame.Set( ptOrig, vtDirX, vtDirY, vtDirZ) ;
}
@@ -108,20 +63,11 @@ FromString( const string& sVal, Frame3d& frFrame)
bool
FromString( const string& sVal, Color& cCol)
{
- // divido la stringa in parametri
- STRVECTOR vsParams ;
- Tokenize( sVal, ",", vsParams) ;
// devono essere 4 parametri : Red, Green, Blue, Alpha
- if ( vsParams.size() != 4)
- return false ;
- // recupero i parametri
- int nRed, nGreen, nBlue, nAlpha ;
- if ( ! FromString( vsParams[0], nRed) ||
- ! FromString( vsParams[1], nGreen) ||
- ! FromString( vsParams[2], nBlue) ||
- ! FromString( vsParams[3], nAlpha))
+ int vnVal[4] ;
+ if ( ! FromString( sVal, vnVal))
return false ;
// assegno il colore
- cCol.Set( nRed, nGreen, nBlue, nAlpha) ;
+ cCol.Set( vnVal[0], vnVal[1], vnVal[2], vnVal[3]) ;
return true ;
}
diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp
index 6233b59..e356b0b 100644
--- a/SurfTriMesh.cpp
+++ b/SurfTriMesh.cpp
@@ -13,15 +13,11 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
-#include "DllMain.h"
#include "SurfTriMesh.h"
-#include "GeoConst.h"
-#include "DistPointLine.h"
#include "GeoObjFactory.h"
-#include "PolynomialPoint3d.h"
-#include "\EgtDev\Include\EGkCurveArc.h"
-#include "\EgtDev\Include\ENkPolynomial.h"
+#include "Triangulate.h"
#include "\EgtDev\Include\EGkStringUtils3d.h"
+#include "\EgtDev\Include\EGkPolyLine.h"
#include
using namespace std ;
@@ -73,7 +69,7 @@ SurfTriMesh::AddVertex( const Point3d& ptVert)
m_OGrMgr.Reset() ;
// inserisco il vertice
try { m_vVert.push_back( StmVert( ptVert)) ;}
- catch(...) { return - 1 ;}
+ catch(...) { return VT_NULL ;}
// ne determino l'indice
return int( m_vVert.size() - 1) ;
}
@@ -95,9 +91,11 @@ SurfTriMesh::SetVertex( int nInd, const StmVert& vV)
try { m_vVert.resize( nNewSize) ; }
catch (...) { return false ; }
// inizializzo a cancellati gli eventuali vertici intermedi
- StmVert vEmpty( Point3d(), VT_DEL, 0) ;
- for ( int i = nPrevSize ; i < nNewSize ; ++ i)
- m_vVert[i] = vEmpty ;
+ if ( ( nNewSize - nPrevSize) > 1) {
+ StmVert vEmpty( Point3d(), VT_DEL, 0) ;
+ for ( int i = nPrevSize ; i < nNewSize ; ++ i)
+ m_vVert[i] = vEmpty ;
+ }
}
// inserisco il vertice
m_vVert[nInd] = vV ;
@@ -112,7 +110,8 @@ SurfTriMesh::AddTriangle( const int nIdVert[3])
m_nStatus = TO_VERIFY ;
m_OGrMgr.Reset() ;
// inserisco il triangolo
- m_vTria.push_back( StmTria( nIdVert)) ;
+ try { m_vTria.push_back( StmTria( nIdVert)) ;}
+ catch(...) { return VT_NULL ;}
// ne determino l'indice
return int( m_vTria.size() - 1) ;
}
@@ -134,10 +133,12 @@ SurfTriMesh::SetTriangle( int nInd, const StmTria& tT)
try { m_vTria.resize( nNewSize) ; }
catch (...) { return false ; }
// inizializzo a cancellati gli eventuali triangoli intermedi
- StmTria tEmpty ;
- tEmpty.nIdVert[0] = VT_DEL ;
- for ( int i = nPrevSize ; i < nNewSize ; ++ i)
- m_vTria[i] = tEmpty ;
+ if ( ( nNewSize - nPrevSize) > 1) {
+ StmTria tEmpty ;
+ tEmpty.nIdVert[0] = VT_DEL ;
+ for ( int i = nPrevSize ; i < nNewSize ; ++ i)
+ m_vTria[i] = tEmpty ;
+ }
}
// inserisco il vertice
m_vTria[nInd] = tT ;
@@ -148,7 +149,7 @@ SurfTriMesh::SetTriangle( int nInd, const StmTria& tT)
int
SurfTriMesh::GetFirstVertex( Point3d& ptP) const
{
- return GetNextVertex( -1, ptP) ;
+ return GetNextVertex( VT_NULL, ptP) ;
}
//----------------------------------------------------------------------------
@@ -161,7 +162,7 @@ SurfTriMesh::GetNextVertex( int nId, Point3d& ptP) const
} while ( nId < GetVertexNum() && m_vVert[nId].nIdTria == VT_DEL) ;
// se oltrepassata fine
if ( nId >= GetVertexNum())
- return -1 ;
+ return VT_NULL ;
// recupero i dati
ptP = m_vVert[nId].ptP ;
// ritorno indice triangolo corrente
@@ -172,7 +173,7 @@ SurfTriMesh::GetNextVertex( int nId, Point3d& ptP) const
int
SurfTriMesh::GetFirstTriangle( Triangle3d& Tria) const
{
- return GetNextTriangle( -1, Tria) ;
+ return GetNextTriangle( VT_NULL, Tria) ;
}
//----------------------------------------------------------------------------
@@ -185,7 +186,7 @@ SurfTriMesh::GetNextTriangle( int nId, Triangle3d& Tria) const
} while ( nId < GetTriangleNum() && m_vTria[nId].nIdVert[0] == VT_DEL) ;
// se oltrepassata fine
if ( nId >= GetTriangleNum())
- return -1 ;
+ return VT_NULL ;
// recupero i dati
Tria.Set( m_vVert[m_vTria[nId].nIdVert[0]].ptP,
m_vVert[m_vTria[nId].nIdVert[1]].ptP,
@@ -195,6 +196,66 @@ SurfTriMesh::GetNextTriangle( int nId, Triangle3d& Tria) const
return nId ;
}
+//----------------------------------------------------------------------------
+bool
+SurfTriMesh::GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const
+{
+ // verifico esistenza del triangolo
+ if ( nId >= GetTriangleNum() || m_vTria[nId].nIdVert[0] == VT_DEL)
+ return false ;
+
+ // recupero le normali di ciascun vertice
+ for ( int i = 0 ; i < 3 ; ++ i) {
+ if ( ! GetTriangleSmoothNormal( nId, i, TNrms.vtN[i]))
+ TNrms.vtN[i] = m_vTria[nId].vtN ;
+ }
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const
+{
+ // recupero tutti i triangoli attorno al vertice
+ INTVECTOR vT ;
+ int nTria = GetAllTriaAroundVertex( m_vTria[nT].nIdVert[nV], vT) ;
+ if ( nTria < 1)
+ return false ;
+
+ // cerco indice del triangolo corrente
+ int nPos = - 1 ;
+ for ( int i = 0 ; i < int( vT.size()) ; ++ i) {
+ if ( vT[i] == nT) {
+ nPos = i ;
+ break ;
+ }
+ }
+ if ( nPos == -1)
+ return false ;
+
+ // medio le normali, finché non incontro degli spigoli
+ vtN = m_vTria[nT].vtN ;
+ const double COS_DEV_LIM = cos( 18 * DEGTORAD) ;
+ // 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 ;
+ }
+
//----------------------------------------------------------------------------
SurfTriMesh*
SurfTriMesh::Clone( void) const
@@ -359,7 +420,7 @@ SurfTriMesh::Load( Scanner& TheScanner)
return false ;
// la divido in parametri
Tokenize( sLine, ";", vsParams) ;
- // 6 parametri : Indice, Punto, IdTria, Flag
+ // 6 parametri : Indice, IdVertici, IdAdiacenze, Normale, TFlag, EFlag
if ( vsParams.size() != 6)
return false ;
// la interpreto e imposto il vertice
@@ -414,7 +475,7 @@ SurfTriMesh::Validate( void)
//----------------------------------------------------------------------------
bool
-SurfTriMesh::FindVertexInTria( int nV, int nT, int& nK)
+SurfTriMesh::FindVertexInTria( int nV, int nT, int& nK) const
{
nK = - 1 ;
for ( int k = 0 ; k < 3 ; k ++) {
@@ -428,7 +489,7 @@ SurfTriMesh::FindVertexInTria( int nV, int nT, int& nK)
//----------------------------------------------------------------------------
int
-SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT)
+SurfTriMesh::GetAllTriaAroundVertex( int nV, INTVECTOR& vT) const
{
const int MAX_VT_SIZE = 512 ;
@@ -642,6 +703,107 @@ SurfTriMesh::AdjustTopology( void)
return true ;
}
+//----------------------------------------------------------------------------
+bool
+SurfTriMesh::CreateByTriangulation( const PolyLine& PL)
+{
+ // eseguo la triangolazione
+ PNTVECTOR vPnt ;
+ INTVECTOR vTria ;
+ Triangulate Tri ;
+ if ( ! Tri.Make( PL, vPnt, vTria))
+ return false ;
+
+ // inizializzo la superficie
+ int nVert = int( vPnt.size()) ;
+ int nTria = int( vTria.size()) / 3 ;
+ if ( ! Init( nVert, nTria))
+ return false ;
+
+ // inserisco i vertici nella superficie
+ for ( int i = 0 ; i < int( vPnt.size()) ; ++ i) {
+ if ( AddVertex( vPnt[i]) == VT_NULL)
+ return false ;
+ }
+
+ // recupero i triangoli e li inserisco nella superficie
+ int vV[3] ;
+ for ( int i = 0 ; i < nTria ; ++i) {
+ vV[0] = vTria[3*i] ;
+ vV[1] = vTria[3*i+1] ;
+ vV[2] = vTria[3*i+2] ;
+ if ( AddTriangle( vV) == VT_NULL)
+ return false ;
+ }
+
+ // sistemo la topologia
+ return AdjustTopology() ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfTriMesh::CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr)
+{
+ // verifico che il vettore di estrusione sia non nullo
+ if ( vtExtr.IsSmall())
+ return false ;
+
+ // verifico se la polilinea è chiusa
+ bool bClosed = PL.IsClosed() ;
+
+ // costruisco la mesh
+ int nPointNbr = PL.GetPointNbr() ;
+ if ( ! Init( 2 * nPointNbr, 2 * nPointNbr))
+ return false ;
+
+ // inserisco il primo vertice della polilinea e il suo estruso
+ int nP = 0 ;
+ int nV = -1 ;
+ Point3d ptP ;
+ if ( ! PL.GetFirstPoint( ptP))
+ return false ;
+ ++ nP ;
+ if ( AddVertex( ptP) == VT_NULL || AddVertex( ptP + vtExtr) == VT_NULL)
+ return false ;
+ nV += 2 ;
+ // ciclo sui punti della polilinea (per inserire vertice e suo estruso + 2 triangoli per ogni punto)
+ int nIdV[3] ;
+ while ( PL.GetNextPoint( ptP)) {
+ // incremento numero punto
+ ++ nP ;
+ // se polilinea aperta o non è l'ultimo punto
+ if ( ! bClosed || nP < nPointNbr) {
+ // aggiungo due nuovi vertici
+ if ( AddVertex( ptP) == VT_NULL || AddVertex( ptP + vtExtr) == VT_NULL)
+ return false ;
+ nV += 2 ;
+ // aggiungo triangolo in basso a sinistra
+ nIdV[0] = nV - 3 ; nIdV[1] = nV - 1 ; nIdV[2] = nV - 2 ;
+ if ( AddTriangle( nIdV) == VT_NULL)
+ return false ;
+ // aggiungo triangolo in alto a destra
+ nIdV[0] = nV - 2 ; nIdV[1] = nV - 1 ; nIdV[2] = nV ;
+ if ( AddTriangle( nIdV) == VT_NULL)
+ return false ;
+ }
+ // altrimenti ultimo punto di polilinea chiusa
+ else {
+ // non devo aggiungere i vertici, perchè coincidono con quelli iniziali
+ // aggiungo triangolo in basso a sinistra
+ nIdV[0] = nV - 1 ; nIdV[1] = 0 ; nIdV[2] = nV ;
+ if ( AddTriangle( nIdV) == VT_NULL)
+ return false ;
+ // aggiungo triangolo in alto a destra
+ nIdV[0] = nV ; nIdV[1] = 0 ; nIdV[2] = 1 ;
+ if ( AddTriangle( nIdV) == VT_NULL)
+ return false ;
+ }
+ }
+
+ // sistemo la topologia
+ return AdjustTopology() ;
+}
+
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetLocalBBox( BBox3d& b3Loc) const
@@ -852,7 +1014,7 @@ SurfTriMesh::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
bool
SurfTriMesh::ToGlob( const Frame3d& frRef)
{
- // la curva deve essere validata
+ // la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
@@ -861,8 +1023,10 @@ SurfTriMesh::ToGlob( const Frame3d& frRef)
return false ;
// trasformo i vertici
- for ( int i = 0 ; i < GetVertexNum() ; ++ i)
- m_vVert[i].ptP.ToGlob( frRef) ;
+ for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
+ if ( m_vVert[i].nIdTria != VT_DEL)
+ m_vVert[i].ptP.ToGlob( frRef) ;
+ }
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -874,7 +1038,7 @@ SurfTriMesh::ToGlob( const Frame3d& frRef)
bool
SurfTriMesh::ToLoc( const Frame3d& frRef)
{
- // la curva deve essere validata
+ // la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
@@ -883,8 +1047,28 @@ SurfTriMesh::ToLoc( const Frame3d& frRef)
return false ;
// trasformo i vertici
- for ( int i = 0 ; i < GetVertexNum() ; ++ i)
- m_vVert[i].ptP.ToLoc( frRef) ;
+ for ( int i = 0 ; i < GetVertexNum() ; ++ i) {
+ if ( m_vVert[i].nIdTria != VT_DEL)
+ m_vVert[i].ptP.ToLoc( frRef) ;
+ }
+
+ // imposto ricalcolo della grafica
+ m_OGrMgr.Reset() ;
+
+ return true ;
+}
+
+//----------------------------------------------------------------------------
+bool
+SurfTriMesh::Invert( void)
+{
+ // la superficie deve essere validata
+ if ( m_nStatus != OK)
+ return false ;
+
+ // inverto i triangoli
+ for ( int i = 0 ; i < GetTriangleNum() ; ++ i)
+ InvertTriangle( i) ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
diff --git a/SurfTriMesh.h b/SurfTriMesh.h
index 009cb20..ff7947c 100644
--- a/SurfTriMesh.h
+++ b/SurfTriMesh.h
@@ -94,6 +94,7 @@ class SurfTriMesh : public ISurfTriMesh
{ return true ; }
virtual bool IsClosed( void) const
{ return m_bClosed ; }
+ virtual bool Invert( void) ;
public : // ISurfTriMesh
virtual bool Copy( const IGeoObj* pGObjSrc) ;
@@ -101,6 +102,8 @@ class SurfTriMesh : public ISurfTriMesh
virtual int AddVertex( const Point3d& ptVert) ;
virtual int AddTriangle( const int nIdVert[3]) ;
virtual bool AdjustTopology( void) ;
+ virtual bool CreateByTriangulation( const PolyLine& PL) ;
+ virtual bool CreateByExtrusion( const PolyLine& PL, const Vector3d& vtExtr) ;
virtual int GetVertexNum( void) const
{ return int( m_vVert.size()) ; }
virtual int GetTriangleNum( void) const
@@ -109,6 +112,7 @@ class SurfTriMesh : public ISurfTriMesh
virtual int GetNextVertex( int nId, Point3d& ptP) const ;
virtual int GetFirstTriangle( Triangle3d& Tria) const ;
virtual int GetNextTriangle( int nId, Triangle3d& Tria) const ;
+ virtual bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const ;
public :
SurfTriMesh( void) ;
@@ -127,12 +131,13 @@ class SurfTriMesh : public ISurfTriMesh
bool SetTriangle( int nInd, const StmTria& tT) ;
bool CalcTriangleNormal( int nT) ;
bool InvertTriangle( int nT) ;
- int Next( int i)
+ int Next( int i) const
{ return (( i + 1) % 3) ; }
- int Prev( int i)
+ int Prev( int i) const
{ return (( i + 2) % 3) ; }
- bool FindVertexInTria( int nV, int nT, int& nK) ;
- int GetAllTriaAroundVertex( int nV, INTVECTOR& vT) ;
+ bool FindVertexInTria( int nV, int nT, int& nK) const ;
+ int GetAllTriaAroundVertex( int nV, INTVECTOR& vT) const ;
+ bool GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const ;
private :
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
diff --git a/Triangulate.cpp b/Triangulate.cpp
new file mode 100644
index 0000000..a18f412
--- /dev/null
+++ b/Triangulate.cpp
@@ -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 ;
+}
+
diff --git a/Triangulate.h b/Triangulate.h
new file mode 100644
index 0000000..24ac50c
--- /dev/null
+++ b/Triangulate.h
@@ -0,0 +1,35 @@
+//----------------------------------------------------------------------------
+// EgalTech 2014-2014
+//----------------------------------------------------------------------------
+// File : SurfTriMesh.h Data : 26.03.14 Versione : 1.5c9
+// Contenuto : Dichiarazione della classe Superfici TriMesh.
+//
+//
+//
+// Modifiche : 26.03.14 DS Creazione modulo.
+//
+//
+//----------------------------------------------------------------------------
+
+#pragma once
+#include "/EgtDev/Include/EGkGeoCollection.h"
+
+class PolyLine ;
+
+//----------------------------------------------------------------------------
+enum { PL_XY = 1, PL_YZ = 2, PL_ZX = 3} ;
+
+//----------------------------------------------------------------------------
+class Triangulate
+{
+ public :
+ bool Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
+ bool MakeByEC( const PNTVECTOR& vPt, int nPlane, INTVECTOR& vTr) ;
+
+ private :
+ bool TriangleIsCCW( const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ;
+ bool TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) ;
+
+ private :
+ int m_nPlane ;
+} ;
\ No newline at end of file