EgtGeomKernel 2.4i4 :
- a superficie trimesh aggiunta CloneTriangle - modifiche a Triangulate per gestione MinAngle di triangolo.
This commit is contained in:
+96
-40
@@ -20,6 +20,7 @@
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
@@ -73,10 +74,17 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
reverse( vPt.begin(), vPt.end()) ;
|
||||
|
||||
// eseguo la triangolazione
|
||||
if ( ! MakeByEC2( vPt, vTr) &&
|
||||
! MakeByEC3( vPt, vTr)) {
|
||||
LOG_INFO( GetEGkLogger(), "Info : problems in MakeByEC23(1)")
|
||||
return MakeByEC_HPP( PL, bCCW, vPt, vTr) ;
|
||||
double dMinMinAng2, dMinMinAng3 ;
|
||||
if ( ! MakeByEC2( vPt, vTr, dMinMinAng2)) {
|
||||
if ( ! MakeByEC3( vPt, vTr, dMinMinAng3)) {
|
||||
LOG_INFO( GetEGkLogger(), "Info : problems in MakeByEC23(1)")
|
||||
return MakeByEC_HPP( PL, bCCW, vPt, vTr) ;
|
||||
}
|
||||
}
|
||||
else if ( dMinMinAng2 < 5) {
|
||||
INTVECTOR vMyTr ;
|
||||
if ( MakeByEC3( vPt, vMyTr, dMinMinAng3) && dMinMinAng3 > dMinMinAng2)
|
||||
vTr = vMyTr ;
|
||||
}
|
||||
|
||||
// se era CW, devo invertire il senso dei triangoli
|
||||
@@ -187,10 +195,17 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
|
||||
|
||||
// eseguo la triangolazione
|
||||
if ( ! MakeByEC2( vPt, vTr) &&
|
||||
! MakeByEC3( vPt, vTr)) {
|
||||
LOG_INFO( GetEGkLogger(), "Info : problems in MakeByEC23(N)")
|
||||
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
|
||||
double dMinMinAng2, dMinMinAng3 ;
|
||||
if ( ! MakeByEC2( vPt, vTr, dMinMinAng2)) {
|
||||
if ( ! MakeByEC3( vPt, vTr, dMinMinAng3)) {
|
||||
LOG_INFO( GetEGkLogger(), "Info : problems in MakeByEC23(N)")
|
||||
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
|
||||
}
|
||||
}
|
||||
else if ( dMinMinAng2 < 5) {
|
||||
INTVECTOR vMyTr ;
|
||||
if ( MakeByEC3( vPt, vMyTr, dMinMinAng3) && dMinMinAng3 > dMinMinAng2)
|
||||
vTr = vMyTr ;
|
||||
}
|
||||
|
||||
// se era CW, devo invertire il senso dei triangoli
|
||||
@@ -393,10 +408,11 @@ Triangulate::MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
// Ear Clipping algorithm enhanced, choose smaller diagonal
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng)
|
||||
{
|
||||
// Clear triangle vector
|
||||
vTr.clear() ;
|
||||
dMinMinAng = ANG_STRAIGHT ;
|
||||
|
||||
// At least 3 points
|
||||
int n = int( vPt.size()) ;
|
||||
@@ -453,11 +469,11 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
int nLimN = min( 19, n / 2) ;
|
||||
for ( int h = 0 ; h < nLimN ; ++ h) {
|
||||
j = vNext[j] ;
|
||||
if ( vEar[j] == EAS_NULL)
|
||||
vEar[j] = ( TestTriangle( vPt, vPol, vPrev, vNext, j) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[j] == EAS_OK) {
|
||||
double dMySqDist = SqDist( vPt[vPol[vPrev[j]]], vPt[vPol[vNext[j]]]) ;
|
||||
if ( dMySqDist < 0.9 * dSqDist) {
|
||||
double dMySqDist = SqDist( vPt[vPol[vPrev[j]]], vPt[vPol[vNext[j]]]) ;
|
||||
if ( dMySqDist < 0.9 * dSqDist) {
|
||||
if ( vEar[j] == EAS_NULL)
|
||||
vEar[j] = ( TestTriangle( vPt, vPol, vPrev, vNext, j) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[j] == EAS_OK) {
|
||||
dSqDist = dMySqDist ;
|
||||
i = j ;
|
||||
}
|
||||
@@ -467,11 +483,11 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
int nLimP = min( 19, n / 2) ;
|
||||
for ( int h = 0 ; h < nLimP ; ++ h) {
|
||||
k = vPrev[k] ;
|
||||
if ( vEar[k] == EAS_NULL)
|
||||
vEar[k] = ( TestTriangle( vPt, vPol, vPrev, vNext, k) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[k] == EAS_OK) {
|
||||
double dMySqDist = SqDist( vPt[vPol[vPrev[k]]], vPt[vPol[vNext[k]]]) ;
|
||||
if ( dMySqDist < 0.9 * dSqDist) {
|
||||
double dMySqDist = SqDist( vPt[vPol[vPrev[k]]], vPt[vPol[vNext[k]]]) ;
|
||||
if ( dMySqDist < 0.9 * dSqDist) {
|
||||
if ( vEar[k] == EAS_NULL)
|
||||
vEar[k] = ( TestTriangle( vPt, vPol, vPrev, vNext, k) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[k] == EAS_OK) {
|
||||
dSqDist = dMySqDist ;
|
||||
i = k ;
|
||||
}
|
||||
@@ -491,6 +507,8 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
vTr.push_back( vPol[vPrev[i]]) ;
|
||||
vTr.push_back( vPol[i]) ;
|
||||
vTr.push_back( vPol[vNext[i]]) ;
|
||||
double dMinAng = CalcTriangleMinAngle( vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]]) ;
|
||||
dMinMinAng = min( dMinMinAng, dMinAng) ;
|
||||
}
|
||||
// Reset earity of diagonal endpoints
|
||||
vEar[vPrev[i]] = EAS_NULL ;
|
||||
@@ -516,14 +534,14 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0])
|
||||
// Ear Clipping algorithm enhanced, choose smaller triangle aspect ratio
|
||||
// AR = ( Lmax * Lmax) / ( 2 * Area) = SqLenMax / L1 * L2
|
||||
// Ear Clipping algorithm enhanced, choose max MinAng
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng)
|
||||
{
|
||||
// Clear triangle vector
|
||||
vTr.clear() ;
|
||||
dMinMinAng = ANG_STRAIGHT ;
|
||||
|
||||
// At least 3 points
|
||||
int n = int( vPt.size()) ;
|
||||
@@ -570,32 +588,50 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
vEar[i] = ( TestTriangle( vPt, vPol, vPrev, vNext, i) ? EAS_OK : EAS_NO) ;
|
||||
bool bIsEar = ( vEar[i] == EAS_OK) ;
|
||||
bool bSave = bIsEar ;
|
||||
double dMinAng = -1 ;
|
||||
if ( bIsEar) {
|
||||
// Square Length & Aspect Ratio
|
||||
// Square Length & MinAngle
|
||||
double dSqLen = SqDist(vPt[vPol[vPrev[i]]], vPt[vPol[vNext[i]]]) ;
|
||||
double dAR = CalcTriangleAspectRatio( vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]]) ;
|
||||
// Try with all other vertices
|
||||
int ii = i ;
|
||||
int j = vNext[i] ;
|
||||
while ( j != ii) {
|
||||
// New Square Length
|
||||
double dNewSqLen = SqDist(vPt[vPol[vPrev[j]]], vPt[vPol[vNext[j]]]) ;
|
||||
if ( dNewSqLen < 0.99 * dSqLen) {
|
||||
// New Aspect Ratio
|
||||
double dNewAR = CalcTriangleAspectRatio( vPt[vPol[vPrev[j]]], vPt[vPol[j]], vPt[vPol[vNext[j]]]) ;
|
||||
// if better, test if triangle ok
|
||||
if ( dNewAR < 30 || dNewAR < 1.2 * dAR) {
|
||||
dMinAng = CalcTriangleMinAngle( vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]]) ;
|
||||
// Start point for trials
|
||||
int j = i ;
|
||||
int k = i ;
|
||||
// Try with 29 next
|
||||
int nLimN = min( 29, n / 2) ;
|
||||
for ( int h = 0 ; h < nLimN ; ++ h) {
|
||||
j = vNext[j] ;
|
||||
double dMySqLen = SqDist( vPt[vPol[vPrev[j]]], vPt[vPol[vNext[j]]]) ;
|
||||
if ( dMySqLen < 2 * dSqLen) {
|
||||
double dMyMinAng = CalcTriangleMinAngle( vPt[vPol[vPrev[j]]], vPt[vPol[j]], vPt[vPol[vNext[j]]]) ;
|
||||
if ( dMyMinAng > 1.01 * dMinAng) {
|
||||
if ( vEar[j] == EAS_NULL)
|
||||
vEar[j] = ( TestTriangle( vPt, vPol, vPrev, vNext, j) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[j] == EAS_OK) {
|
||||
dSqLen = dNewSqLen ;
|
||||
dAR = min( dAR, dNewAR) ;
|
||||
dSqLen = dMySqLen ;
|
||||
dMinAng = dMyMinAng ;
|
||||
i = j ;
|
||||
}
|
||||
}
|
||||
}
|
||||
j = vNext[j] ;
|
||||
}
|
||||
}
|
||||
// Try with 29 prev
|
||||
int nLimP = min( 29, n / 2) ;
|
||||
for ( int h = 0 ; h < nLimP ; ++ h) {
|
||||
k = vPrev[k] ;
|
||||
double dMySqLen = SqDist( vPt[vPol[vPrev[k]]], vPt[vPol[vNext[k]]]) ;
|
||||
if ( dMySqLen < 2 * dSqLen) {
|
||||
double dMyMinAng = CalcTriangleMinAngle( vPt[vPol[vPrev[k]]], vPt[vPol[k]], vPt[vPol[vNext[k]]]) ;
|
||||
if ( dMyMinAng > 1.01 * dMinAng) {
|
||||
if ( vEar[k] == EAS_NULL)
|
||||
vEar[k] = ( TestTriangle( vPt, vPol, vPrev, vNext, k) ? EAS_OK : EAS_NO) ;
|
||||
if ( vEar[k] == EAS_OK) {
|
||||
dSqLen = dMySqLen ;
|
||||
dMinAng = dMyMinAng ;
|
||||
i = k ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Verify if triangle is null (accept to discard)
|
||||
else {
|
||||
@@ -610,6 +646,7 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
vTr.push_back( vPol[vPrev[i]]) ;
|
||||
vTr.push_back( vPol[i]) ;
|
||||
vTr.push_back( vPol[vNext[i]]) ;
|
||||
dMinMinAng = min( dMinMinAng, dMinAng) ;
|
||||
}
|
||||
// Reset earity of diagonal endpoints
|
||||
vEar[vPrev[i]] = EAS_NULL ;
|
||||
@@ -716,7 +753,7 @@ Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Ratio between max side and opposite height
|
||||
// Ratio between Circumcircle Radius and Incircle Diameter (minimum 1 for equilateral)
|
||||
double
|
||||
Triangulate::CalcTriangleAspectRatio( const Point3d& ptPa, const Point3d& ptPb, const Point3d& ptPc)
|
||||
{
|
||||
@@ -730,6 +767,25 @@ Triangulate::CalcTriangleAspectRatio( const Point3d& ptPa, const Point3d& ptPb,
|
||||
return ( max( { dSqDistA, dSqDistB, dSqDistC}) / dTwoArea) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
Triangulate::CalcTriangleMinAngle( const Point3d& ptPa, const Point3d& ptPb, const Point3d& ptPc)
|
||||
{
|
||||
double dSqLenA = SquareDist( ptPa, ptPb) ;
|
||||
double dSqLenB = SquareDist( ptPb, ptPc) ;
|
||||
double dSqLenC = SquareDist( ptPc, ptPa) ;
|
||||
if ( dSqLenA > dSqLenB)
|
||||
swap( dSqLenA, dSqLenB) ;
|
||||
if ( dSqLenA > dSqLenC)
|
||||
swap( dSqLenA, dSqLenC) ;
|
||||
double dLenB = sqrt( dSqLenB) ;
|
||||
double dLenC = sqrt( dSqLenC) ;
|
||||
double dCosA = ( dSqLenB + dSqLenC - dSqLenA) / ( 2 * dLenB * dLenC) ;
|
||||
dCosA = Clamp( dCosA, -1., +1.) ;
|
||||
double dAngA = acos( dCosA) * RADTODEG ;
|
||||
return dAngA ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
Triangulate::SquareDist( const Point3d& ptA, const Point3d& ptB)
|
||||
|
||||
Reference in New Issue
Block a user