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:
+54
-39
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user