EgtGeomKernel 1.5h3 :

- aggiunta IsFlat a tutte le Curve 
- aggiunta ApproxWithArcs a tutte le Curve 
- aggiunto oggetto PolyArc (raccolta ordinata di linee e archi con bulge)
- aggiunto oggetto PointsPCA per stima componenti principali di un insieme di punti
- FromSpheriical e FromPolar di Vector3d sono diventati funzioni e aggiunto FromUprightOrtho
- aggiunte Invert e a Vector3d.
This commit is contained in:
Dario Sassi
2014-08-15 17:36:08 +00:00
parent 1a42207365
commit 77e74ccf4e
27 changed files with 986 additions and 113 deletions
+54 -39
View File
@@ -14,6 +14,8 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "DistPointLine.h"
#include "PolygonPlane.h"
#include "PointsPCA.h"
#include "\EgtDev\Include\EGkPolyLine.h"
#include "\EgtDev\Include\EGkPlane3d.h"
@@ -379,57 +381,70 @@ PolyLine::GetPrevULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d*
//----------------------------------------------------------------------------
bool
PolyLine::NewellPlane( Plane3d& plPlane, double& dArea) const
PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) 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 ;
// cerco le componenti principali (tramite PCA)
Point3d ptP ;
PointsPCA ptsPCA ;
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP))
ptsPCA.AddPoint( ptP) ;
// recupero il rango, ovvero la dimensionalità dell'insieme di punti
nRank = ptsPCA.GetRank() ;
// se dimensione nulla, o non ci sono punti o sono tutti praticamente coincidenti
if ( nRank == 0)
return ptsPCA.GetCenter( ptCen) ;
// se dimensione 1, allora i punti sono distribuiti su una linea
if ( nRank == 1) {
// assegno il centro e la direzione della linea (il verso è indifferente)
ptsPCA.GetCenter( ptCen) ;
ptsPCA.GetPrincipalComponent( 0, vtDir) ;
return true ;
}
// 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 ;
// altrimenti dimensione 2 o 3, allora è determinato un piano principale, verifico se tutti i punti vi giacciono
// Center and normal vector
ptsPCA.GetCenter( ptCen) ;
Vector3d vtX, vtY ;
ptsPCA.GetPrincipalComponent( 0, vtX) ;
ptsPCA.GetPrincipalComponent( 1, vtY) ;
vtDir = vtX ^ vtY ;
if ( ! vtDir.Normalize()) {
// riduco la dimensionalità a lineare
nRank = 1 ;
// assegno il centro e la direzione della linea (il verso è indifferente)
ptsPCA.GetCenter( ptCen) ;
vtDir = vtX ;
return true ;
}
if ( vtDir.z < 0)
vtDir.Invert() ;
// Plane calculation
Plane3d plPlane ;
plPlane.vtN = vtDir ;
plPlane.dDist = ( ptCen - ORIG) * plPlane.vtN ;
// Test each vertex to see if it is farther from plane than allowed max distance
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP)) {
double dDist = ( ( ptP - ORIG) * plPlane.vtN) - plPlane.dDist ;
if ( fabs( dDist) > dToler)
return false ;
}
// At least 3 sides
if ( nNumSide < 3)
return false ;
// Normal must be normalizable (the length of the normal is the double of the area of the polygon)
double dLenN = vtN.Len() ;
if ( dLenN < EPS_SMALL)
return false ;
vtN /= dLenN ;
// Fill in the plane equation fields
plPlane.vtN = vtN ;
plPlane.dDist = ( ( ptCen - ORIG) * plPlane.vtN) / nNumSide ; // “centroid / n” is the true centroid point
// Set area
dArea = 0.5 * dLenN ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::IsFlat( Plane3d& plPlane, double& dArea, double dToler) const
PolyLine::IsClosedAndFlat( Plane3d& plPlane, double& dArea, double dToler) const
{
// Test if closed
if ( ! IsClosed())
return false ;
// Compute a representative plane for the polygon
if ( ! NewellPlane( plPlane, dArea))
Point3d ptP ;
PolygonPlane PolyPlane ;
for ( bool bFound = GetFirstPoint( ptP) ; bFound ; bFound = GetNextPoint( ptP))
PolyPlane.AddPoint( ptP) ;
if ( ! PolyPlane.GetPlane( plPlane) || ! PolyPlane.GetArea( dArea))
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)