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
+2 -4
View File
@@ -176,8 +176,7 @@ GetArc2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStartDeg)
// calcolo arco non riuscito, verifico se retta va bene
Vector3d vtDiff = ptEnd - ptStart ;
vtDiff.z = 0 ;
Vector3d vtDir ;
vtDir.FromPolar( 1, dDirStartDeg) ;
Vector3d vtDir = FromPolar( 1, dDirStartDeg) ;
// verifico se i punti sono allineati con la direzione e nel giusto verso
if ( fabs( CrossXY( vtDiff, vtDir)) < EPS_SMALL && ScalarXY( vtDiff, vtDir) > EPS_SMALL) {
// creo l'oggetto retta
@@ -204,8 +203,7 @@ GetArcPntDirTgArc( const Point3d& ptP, double dDirStartDeg, const ICurveArc& crv
}
// versore ortogonale alla direzione iniziale (si lavora nel piano XY locale)
Vector3d vtOrtho ;
vtOrtho.FromPolar( 1, dDirStartDeg) ;
Vector3d vtOrtho = FromPolar( 1, dDirStartDeg) ;
vtOrtho.Rotate( Z_AX, 0, 1) ;
// calcolo arco spostando il punto iniziale di + raggio in direzione ortogonale
+2 -2
View File
@@ -88,7 +88,7 @@ CalcCircleStartDer( double dU0, const Point3d& ptP0, double dU1, const Point3d&
vtDer = ptP0 - ptCen ;
vtDer.Rotate( vtN, 0, 1) ;
if ( ( vtDer * vtA) < 0)
vtDer *= - 1 ;
vtDer.Invert() ;
// ne aggiusto il modulo
if ( ! vtDer.Normalize())
return false ;
@@ -120,7 +120,7 @@ CalcCircleEndDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& pt
vtDer = ptP2 - ptCen ;
vtDer.Rotate( vtN, 0, 1) ;
if ( ( vtDer * ( ptP2 - ptP1)) < 0)
vtDer *= - 1 ;
vtDer.Invert() ;
// ne aggiusto il modulo
if ( ! vtDer.Normalize())
return false ;
+60 -11
View File
@@ -124,7 +124,7 @@ CurveArc::SetXY( const Point3d& ptCen, double dRad, double dAngIniDeg, double dA
// assegno e calcolo i dati
m_PtCen = ptCen ;
m_VtN = Z_AX ;
m_VtS.FromPolar( 1, dAngIniDeg) ;
m_VtS = FromPolar( 1, dAngIniDeg) ;
m_dRad = dRad ;
m_dAngCenDeg = dAngCenDeg ;
m_dDeltaN = dDeltaZ ;
@@ -278,8 +278,7 @@ CurveArc::Set2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStart
m_nStatus = ERR ;
// vettore tangente iniziale ( nel piano XY)
Vector3d vtA ;
vtA.FromPolar( 1, dDirStartDeg) ;
Vector3d vtA = FromPolar( 1, dDirStartDeg) ;
// vettore da inizio a fine ( nel piano XY)
Vector3d vtB = ptEnd - ptStart ;
vtB.z = 0 ;
@@ -313,9 +312,9 @@ CurveArc::Set2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStart
// se normale con Z negativa, inverto senza modificare la geometria
if ( m_VtN.z < 0) {
m_VtN *= - 1 ;
m_dAngCenDeg *= - 1 ;
m_dDeltaN *= - 1 ;
m_VtN.Invert() ;
m_dAngCenDeg = - m_dAngCenDeg ;
m_dDeltaN = - m_dDeltaN ;
}
// imposto ricalcolo della grafica
@@ -605,6 +604,21 @@ CurveArc::Validate( void)
return ( m_nStatus == OK) ;
}
//----------------------------------------------------------------------------
bool
CurveArc::IsFlat( Plane3d& plPlane, double dToler) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// assegno dati possibile piano
plPlane.vtN = m_VtN ;
plPlane.dDist = ( m_PtCen - ORIG) * plPlane.vtN ;
// verifico piattezza
return IsFlat( dToler) ;
}
//----------------------------------------------------------------------------
bool
CurveArc::GetStartPoint( Point3d& ptStart) const
@@ -845,8 +859,43 @@ CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) cons
ArcApproxer aAppr( dLinTol, dAngTolDeg, true, *this) ;
double dU ;
Point3d ptPos ;
while ( aAppr.GetPoint( dU, ptPos))
PL.AddUPoint( dU, ptPos) ;
while ( aAppr.GetPoint( dU, ptPos)) {
if ( ! PL.AddUPoint( dU, ptPos))
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
{
// pulisco la polilinea
PA.Clear() ;
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// la curva deve avere normale coincidente con Z
if ( ! m_VtN.IsZplus() && ! m_VtN.IsZminus())
return false ;
// inserisco punto iniziale con bulge
Point3d ptStart ;
GetStartPoint( ptStart) ;
double dBulge = tan( m_dAngCenDeg / 4 * DEGTORAD) ;
if ( m_VtN.IsZminus())
dBulge = - dBulge ;
if ( ! PA.AddUPoint( 0, ptStart, dBulge))
return false ;
// inserisco punto finale senza bulge
Point3d ptEnd ;
GetEndPoint( ptEnd) ;
if ( ! PA.AddUPoint( 1, ptEnd, 0))
return false ;
return true ;
}
@@ -1357,9 +1406,9 @@ CurveArc::InvertN( void)
return false ;
// si inverte il verso della normale senza modificare la geometria dell'arco
m_VtN *= - 1 ;
m_dAngCenDeg *= - 1 ;
m_dDeltaN *= - 1 ;
m_VtN.Invert() ;
m_dAngCenDeg = - m_dAngCenDeg ;
m_dDeltaN = - m_dDeltaN ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
+16 -2
View File
@@ -55,6 +55,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
{ return true ; }
virtual bool IsClosed( void) const
{ return ::IsClosed( *this) ; }
virtual bool IsFlat( Plane3d& plPlane, double dToler = EPS_SMALL) const ;
virtual bool GetStartPoint( Point3d& ptStart) const ;
virtual bool GetEndPoint( Point3d& ptEnd) const ;
virtual bool GetMidPoint( Point3d& ptMid) const ;
@@ -85,6 +86,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
return ::GetPointDiffGeom( *this, dU, nS, oDiffG) ; }
virtual bool IsPointOn( const Point3d& ptP, double dTol = EPS_SMALL) const ;
virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ;
virtual bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const ;
virtual ICurve* CopyParamRange( double dUStart, double dUEnd) const ;
virtual bool Invert( void) ;
virtual bool Offset( double dDist, int nSide, int nType = OFF_FILLET) ;
@@ -108,8 +110,8 @@ class CurveArc : public ICurveArc, public IGeoObjRW
virtual bool Set2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStartDeg) ;
virtual bool Set2PRS( const Point3d& ptStart, const Point3d& ptEnd, double dRad, bool bCCW = true) ;
virtual bool SetC2P( const Point3d& ptCen, const Point3d& ptStart, const Point3d& ptNearEnd) ;
virtual bool IsFlat( void) const
{ return ( fabs( m_dDeltaN) < EPS_SMALL) ; }
virtual bool IsFlat( double dToler = EPS_SMALL) const
{ return ( fabs( m_dDeltaN) < dToler) ; }
virtual bool IsACircle( void) const
{ return ( IsFlat() && IsClosed()) ; }
virtual bool IsInPlaneXY( void) const
@@ -164,3 +166,15 @@ class CurveArc : public ICurveArc, public IGeoObjRW
double m_dAngCenDeg ; // angolo al centro in gradi (positivo se antiorario visto da VtN)
double m_dDeltaN ; // variazione di quota lungo VtN della fine rispetto all'inizio
} ;
//-----------------------------------------------------------------------------
inline CurveArc* CreateBasicCurveArc( void)
{ return (static_cast<CurveArc*>( CreateGeoObj( CRV_ARC))) ; }
inline CurveArc* CloneBasicCurveArc( const IGeoObj* pGObj)
{ if ( pGObj == nullptr || pGObj->GetType() != CRV_ARC)
return nullptr ;
return (static_cast<CurveArc*>(pGObj->Clone())) ; }
inline const CurveArc* GetBasicCurveArc( const IGeoObj* pGObj)
{ return (dynamic_cast<const CurveArc*>(pGObj)) ; }
inline CurveArc* GetBasicCurveArc( IGeoObj* pGObj)
{ return (dynamic_cast<CurveArc*>(pGObj)) ; }
+2 -2
View File
@@ -110,7 +110,7 @@ GetPointTang( const ICurve& crvC, double dU, ICurve::Side nS, Point3d& ptPos, Ve
if ( ! crvC.GetPointD1D2( dU, nS, ptDummy, &vtD1near))
return false ;
if ( ( vtTang * vtD1near) < 0)
vtTang *= - 1 ;
vtTang.Invert() ;
return true ;
}
@@ -152,7 +152,7 @@ GetPointDiffGeom( const ICurve& crvC, double dU, ICurve::Side nS, CrvPointDiffGe
dU += ( nS == ICurve::FROM_MINUS ? -1 : +1) * 100 * EPS_PARAM ;
if ( crvC.GetPointD1D2( dU, nS, ptDummy, &vtD1near)) {
if ( ( oDiffG.vtT * vtD1near) < 0)
oDiffG.vtT *= - 1 ;
oDiffG.vtT.Invert() ;
oDiffG.nStatus = CrvPointDiffGeom::TANG ;
}
else {
+62 -6
View File
@@ -473,6 +473,52 @@ CurveBezier::GetBBox( const Frame3d& frRef, BBox3d& b3Ref) const
return true ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::IsFlat( Plane3d& plPlane, double dToler) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// polilinea dei punti rappresentativi
PolyLine shPL ;
int nLastPC = m_nDeg ;
for ( int i = 0 ; i <= nLastPC ; ++ i) {
double dU = i / double( nLastPC) ;
if ( ! shPL.AddUPoint( dU, GetControlPoint( i)))
return false ;
}
// recupero dati sulla planarità
int nRank ;
Point3d ptCen ;
Vector3d vtDir ;
bool bFlat = shPL.IsFlat( nRank, ptCen, vtDir, dToler) ;
// se punto
switch ( nRank) {
case 0 : // punto
if ( bFlat) {
plPlane.vtN = Z_AX ;
plPlane.dDist = ( ptCen - ORIG) * plPlane.vtN ;
}
else {
plPlane.vtN = V_NULL ;
plPlane.dDist = 0 ;
}
break ;
case 1 : // linea
plPlane.vtN = FromUprightOrtho( vtDir) ;
plPlane.dDist = ( ptCen - ORIG) * plPlane.vtN ;
break ;
default : // piana o 3d
plPlane.vtN = vtDir ;
plPlane.dDist = ( ptCen - ORIG) * plPlane.vtN ;
break ;
}
return bFlat ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::GetStartPoint( Point3d& ptStart) const
@@ -1201,9 +1247,7 @@ CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) c
// se di primo grado, basta inserire gli estremi
if ( m_nDeg == 1) {
PL.AddUPoint( 0, m_aPtCtrl[0]) ;
PL.AddUPoint( 1, m_aPtCtrl[m_nDeg]) ;
return true ;
return ( PL.AddUPoint( 0, m_aPtCtrl[0]) && PL.AddUPoint( 1, m_aPtCtrl[m_nDeg])) ;
}
// limiti minimi su tolleranza e deviazione angolare
@@ -1211,18 +1255,30 @@ CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) c
dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ;
// inserisco il punto iniziale
PL.AddUPoint( 0, m_aPtCtrl[0]) ;
if ( ! PL.AddUPoint( 0, m_aPtCtrl[0]))
return false ;
// verifico se va divisa
FlatOrSplit( 0, *this, 0, 1, dLinTol, dAngTolDeg, PL) ;
if ( ! FlatOrSplit( 0, *this, 0, 1, dLinTol, dAngTolDeg, PL))
return false ;
// se è stato inserito un solo punto, aggiungo il finale
if ( PL.GetPointNbr() == 1)
PL.AddUPoint( 1, m_aPtCtrl[m_nDeg]) ;
return PL.AddUPoint( 1, m_aPtCtrl[m_nDeg]) ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
{
// pulisco la polilinea
PA.Clear() ;
return false ;
}
//----------------------------------------------------------------------------
ICurve*
CurveBezier::CopyParamRange( double dUStart, double dUEnd) const
+14
View File
@@ -56,6 +56,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
virtual bool IsSimple( void) const { return true ; }
virtual bool IsClosed( void) const
{ return ::IsClosed( *this) ; }
virtual bool IsFlat( Plane3d& plPlane, double dToler) const ;
virtual bool GetStartPoint( Point3d& ptStart) const ;
virtual bool GetEndPoint( Point3d& ptEnd) const ;
virtual bool GetMidPoint( Point3d& ptMid) const ;
@@ -87,6 +88,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
return ::GetPointDiffGeom( *this, dU, nS, oDiffG) ; }
virtual bool IsPointOn( const Point3d& ptP, double dTol = EPS_SMALL) const ;
virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ;
virtual bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const ;
virtual ICurve* CopyParamRange( double dUStart, double dUEnd) const ;
virtual bool Invert( void) ;
virtual bool Offset( double dDist, int nSide, int nType = OFF_FILLET)
@@ -159,3 +161,15 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
Point3d m_aStPtCtrl[ST_PTC] ; // array predefinito di 4 punti di controllo
double m_aStWeCtrl[ST_PTC] ; // array predefinito di 4 pesi di controllo
} ;
//-----------------------------------------------------------------------------
inline CurveBezier* CreateBasicCurveBezier( void)
{ return (static_cast<CurveBezier*>( CreateGeoObj( CRV_BEZ))) ; }
inline CurveBezier* CloneBasicCurveBezier( const IGeoObj* pGObj)
{ if ( pGObj == nullptr || pGObj->GetType() != CRV_BEZ)
return nullptr ;
return (static_cast<CurveBezier*>(pGObj->Clone())) ; }
inline const CurveBezier* GetBasicCurveBezier( const IGeoObj* pGObj)
{ return (dynamic_cast<const CurveBezier*>(pGObj)) ; }
inline CurveBezier* GetBasicCurveBezier( IGeoObj* pGObj)
{ return (dynamic_cast<CurveBezier*>(pGObj)) ; }
+132 -12
View File
@@ -15,14 +15,14 @@
#include "stdafx.h"
#include "CurveComposite.h"
#include "DistPointCrvComposite.h"
#include "CurveLine.h"
#include "CurveArc.h"
#include "CurveBezier.h"
#include "GeoConst.h"
#include "GeoObjFactory.h"
#include "NgeWriter.h"
#include "NgeReader.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkCurveLine.h"
#include "/EgtDev/Include/EGkCurveArc.h"
#include "/EgtDev/Include/EGkCurveBezier.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <algorithm>
@@ -325,7 +325,7 @@ CurveComposite::FromPointBulgeVector( const UPNTVECTOR& vUPnt, const Vector3d& v
// se retta
if ( fabs( vUPnt[i-1].first) < EPS_SMALL) {
// creo la retta
PtrOwner<ICurveLine> pCrvLine( CreateCurveLine()) ;
PtrOwner<CurveLine> pCrvLine( CreateBasicCurveLine()) ;
if ( ! ::IsValid( pCrvLine))
return false ;
// setto la linea
@@ -338,7 +338,7 @@ CurveComposite::FromPointBulgeVector( const UPNTVECTOR& vUPnt, const Vector3d& v
// altrimenti arco
else {
// creo l'arco
PtrOwner<ICurveArc> pCrvArc( CreateCurveArc()) ;
PtrOwner<CurveArc> pCrvArc( CreateBasicCurveArc()) ;
if ( ! ::IsValid( pCrvArc))
return false ;
// setto l'arco
@@ -384,7 +384,7 @@ CurveComposite::PolygonCenterCorner( int nSides, const Point3d& ptCen, const Poi
return false ;
}
// creo il segmento di retta
PtrOwner<ICurveLine> pCrvLine( CreateCurveLine()) ;
PtrOwner<CurveLine> pCrvLine( CreateBasicCurveLine()) ;
if ( ! ::IsValid( pCrvLine))
return false ;
// assegno i punti estremi
@@ -473,11 +473,11 @@ bool
CurveComposite::CopyFrom( const IGeoObj* pGObjSrc)
{
// se sorgente è una curva composita
const CurveComposite* pCC = dynamic_cast<const CurveComposite*>( pGObjSrc) ;
const CurveComposite* pCC = GetBasicCurveComposite( pGObjSrc) ;
if ( pCC != nullptr)
return CopyFrom( *pCC) ;
// se sorgente è un'altro tipo di curva
const ICurve* pCrv = dynamic_cast<const ICurve*>( pGObjSrc) ;
const ICurve* pCrv = GetCurve( pGObjSrc) ;
if ( pCrv != nullptr) {
Clear() ;
return AddCurve( *pCrv) ;
@@ -716,6 +716,89 @@ CurveComposite::Validate( void)
return ( m_nStatus == OK) ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::IsFlat( Plane3d& plPlane, double dToler) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// polilinea dei punti rappresentativi
PolyLine shPL ;
// punto iniziale
Point3d ptP ;
if ( ! GetStartPoint( ptP) ||
! shPL.AddUPoint( 0, ptP))
return false ;
// ciclo sulle curve semplici (aggiungo solo eventuali punti intermedi e finali)
int nCount = 0 ;
for ( const ICurve* pCrv = GetFirstCurve() ;
pCrv != nullptr ;
pCrv = GetNextCurve(), ++ nCount) {
switch ( pCrv->GetType()) {
case CRV_LINE :
// punto finale
if ( ! pCrv->GetEndPoint( ptP) ||
! shPL.AddUPoint( nCount + 1, ptP))
return false ;
break ;
case CRV_ARC :
// punto a 1/3
if ( ! pCrv->GetPointD1D2( 0.3333, ICurve::FROM_MINUS, ptP) ||
! shPL.AddUPoint( nCount + 0.3333, ptP))
return false ;
// punto a 7/11
if ( ! pCrv->GetPointD1D2( 0.6363, ICurve::FROM_MINUS, ptP) ||
! shPL.AddUPoint( nCount + 0.6363, ptP))
return false ;
// punto finale
if ( ! pCrv->GetEndPoint( ptP) ||
! shPL.AddUPoint( nCount + 1, ptP))
return false ;
break ;
case CRV_BEZ :
{ const CurveBezier* pBez = GetBasicCurveBezier( pCrv) ;
// inserisco tutti i punti di controllo tranne il primo
int nLastPC = pBez->GetDegree() ;
for ( int i = 1 ; i <= nLastPC ; ++ i) {
double dU = nCount + i / double( nLastPC) ;
if ( ! shPL.AddUPoint( dU, pBez->GetControlPoint( i)))
return false ;
}
} break ;
}
}
// recupero dati sulla planarità della polilinea
int nRank ;
Point3d ptCen ;
Vector3d vtDir ;
bool bFlat = shPL.IsFlat( nRank, ptCen, vtDir, dToler) ;
// se punto
switch ( nRank) {
case 0 : // punto
if ( bFlat) {
plPlane.vtN = Z_AX ;
plPlane.dDist = ( ptCen - ORIG) * plPlane.vtN ;
}
else {
plPlane.vtN = V_NULL ;
plPlane.dDist = 0 ;
}
break ;
case 1 : // linea
plPlane.vtN = FromUprightOrtho( vtDir) ;
plPlane.dDist = ( ptCen - ORIG) * plPlane.vtN ;
break ;
default : // piana o 3d
plPlane.vtN = vtDir ;
plPlane.dDist = ( ptCen - ORIG) * plPlane.vtN ;
break ;
}
return bFlat ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::GetStartPoint( Point3d& ptStart) const
@@ -999,6 +1082,43 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL
return true ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
{
// pulisco il poliarco
PA.Clear() ;
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// eseguo approssimazione
bool bFirst = true ;
double dStartPar = 0 ;
PolyArc PASmpl ;
PCRVSMPL_DEQUE::const_iterator Iter ;
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
// recupero approssimazione per curva semplice
if ( ! (*Iter)->ApproxWithArcs( dLinTol, dAngTolDeg, PASmpl))
return false ;
// la accodo opportunamente a quella della curva composita
if ( bFirst) {
PA.Splice( PASmpl) ;
bFirst = false ;
}
else {
PA.EraseLastUPoint() ;
PASmpl.AddOffsetToU( dStartPar) ;
PA.Splice( PASmpl) ;
}
// incremento inizio parametro per prossima curva semplice
dStartPar += 1 ;
}
return true ;
}
//----------------------------------------------------------------------------
ICurve*
CurveComposite::CopyParamRange( double dUStart, double dUEnd) const
@@ -1230,10 +1350,11 @@ CurveComposite::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
if ( dUStartTrim < - EPS_PARAM || dUStartTrim > m_nCounter + EPS_PARAM ||
dUEndTrim < - EPS_PARAM || dUEndTrim > m_nCounter + EPS_PARAM)
return false ;
#if 0
// verifico che i trim non cancellino interamente la curva
if ( dUStartTrim > dUEndTrim - EPS_PARAM)
return false ;
#if 0
#endif
// se il parametro start supera quello di end
if ( dUStartTrim > dUEndTrim - EPS_PARAM) {
// se curva aperta, il trim la cancella completamente quindi errore
@@ -1252,7 +1373,6 @@ CurveComposite::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
}
}
}
#endif
// per parametro start : determino la curva di appartenenza e il valore locale del parametro
int nCs ;
double dUcs ;
@@ -1757,11 +1877,11 @@ CurveComposite::ArcsToBezierCurves( void)
for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) {
// se arco, devo trasformare in una o più curve di Bezier
if ( (*Iter)->GetType() == CRV_ARC) {
const ICurveArc* pArc = GetCurveArc( (*Iter)) ;
const CurveArc* pArc = GetBasicCurveArc( (*Iter)) ;
// se angolo al centro sotto il limite, basta una curva
if ( fabs( pArc->GetAngCenter()) <= BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL) {
// creo la curva di Bezier
PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
PtrOwner<CurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
if ( ! ::IsValid( pCrvBez))
return false ;
if ( ! pCrvBez->FromArc( *pArc))
+14
View File
@@ -56,6 +56,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
virtual bool IsSimple( void) const { return false ; }
virtual bool IsClosed( void) const
{ return ( m_nStatus == OK && m_bClosed) ; }
virtual bool IsFlat( Plane3d& plPlane, double dToler = EPS_SMALL) const ;
virtual bool GetStartPoint( Point3d& ptStart) const ;
virtual bool GetEndPoint( Point3d& ptEnd) const ;
virtual bool GetMidPoint( Point3d& ptMid) const ;
@@ -86,6 +87,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
return ::GetPointDiffGeom( *this, dU, nS, oDiffG) ; }
virtual bool IsPointOn( const Point3d& ptP, double dTol = EPS_SMALL) const ;
virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ;
virtual bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const ;
virtual ICurve* CopyParamRange( double dUStart, double dUEnd) const ;
virtual bool Invert( void) ;
virtual bool Offset( double dDist, int nSide, int nType = OFF_FILLET)
@@ -154,3 +156,15 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool m_bClosed ; // flag per indicare che la curva è chiusa
mutable PCRVSMPL_DEQUE::const_iterator m_Iter ; // iteratore
} ;
//-----------------------------------------------------------------------------
inline CurveComposite* CreateBasicCurveComposite( void)
{ return (static_cast<CurveComposite*>( CreateGeoObj( CRV_COMPO))) ; }
inline CurveComposite* CloneBasicCurveComposite( const IGeoObj* pGObj)
{ if ( pGObj == nullptr || pGObj->GetType() != CRV_COMPO)
return nullptr ;
return (static_cast<CurveComposite*>(pGObj->Clone())) ; }
inline const CurveComposite* GetBasicCurveComposite( const IGeoObj* pGObj)
{ return (dynamic_cast<const CurveComposite*>(pGObj)) ; }
inline CurveComposite* GetBasicCurveComposite( IGeoObj* pGObj)
{ return (dynamic_cast<CurveComposite*>(pGObj)) ; }
+31 -1
View File
@@ -79,7 +79,7 @@ CurveLine::SetPDL( const Point3d& ptStart, double dDirAngDeg, double dLen)
// assegno i dati
m_PtStart = ptStart ;
Vector3d vtDelta ;
vtDelta.FromPolar( dLen, dDirAngDeg) ;
vtDelta = FromPolar( dLen, dDirAngDeg) ;
m_PtEnd = ptStart + vtDelta ;
m_nStatus = TO_VERIFY ;
@@ -229,6 +229,21 @@ CurveLine::Validate( void)
return ( m_nStatus == OK) ;
}
//----------------------------------------------------------------------------
bool
CurveLine::IsFlat( Plane3d& plPlane, double dToler) const
{
// verifico lo stato
if ( m_nStatus != OK)
return false ;
// assegno dati piano
plPlane.vtN = FromUprightOrtho( m_PtEnd - m_PtStart) ; ;
plPlane.dDist = ( m_PtStart - ORIG) * plPlane.vtN ;
// ritorno conferma
return true ;
}
//----------------------------------------------------------------------------
bool
CurveLine::GetStartPoint( Point3d& ptStart) const
@@ -422,6 +437,21 @@ CurveLine::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) con
return true ;
}
//----------------------------------------------------------------------------
bool
CurveLine::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
{
// pulisco la polilinea
PA.Clear() ;
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// inserisco gli estremi
return ( PA.AddUPoint( 0, m_PtStart, 0) && PA.AddUPoint( 1, m_PtEnd, 0)) ;
}
//----------------------------------------------------------------------------
ICurve*
CurveLine::CopyParamRange( double dUStart, double dUEnd) const
+14
View File
@@ -55,6 +55,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW
{ return true ; }
virtual bool IsClosed( void) const
{ return ::IsClosed( *this) ; }
virtual bool IsFlat( Plane3d& plPlane, double dToler) const ;
virtual bool GetStartPoint( Point3d& ptStart) const ;
virtual bool GetEndPoint( Point3d& ptEnd) const ;
virtual bool GetMidPoint( Point3d& ptMid) const ;
@@ -85,6 +86,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW
return ::GetPointDiffGeom( *this, dU, nS, oDiffG) ; }
virtual bool IsPointOn( const Point3d& ptP, double dTol = EPS_SMALL) const ;
virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ;
virtual bool ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const ;
virtual ICurve* CopyParamRange( double dUStart, double dUEnd) const ;
virtual bool Invert( void) ;
virtual bool Offset( double dDist, int nSide, int nType = OFF_FILLET) ;
@@ -132,3 +134,15 @@ class CurveLine : public ICurveLine, public IGeoObjRW
Point3d m_PtStart ; // punto iniziale
Point3d m_PtEnd ; // punto finale
} ;
//-----------------------------------------------------------------------------
inline CurveLine* CreateBasicCurveLine( void)
{ return (static_cast<CurveLine*>( CreateGeoObj( CRV_LINE))) ; }
inline CurveLine* CloneBasicCurveLine( const IGeoObj* pGObj)
{ if ( pGObj == nullptr || pGObj->GetType() != CRV_LINE)
return nullptr ;
return (static_cast<CurveLine*>(pGObj->Clone())) ; }
inline const CurveLine* GetBasicCurveLine( const IGeoObj* pGObj)
{ return (dynamic_cast<const CurveLine*>(pGObj)) ; }
inline CurveLine* GetBasicCurveLine( IGeoObj* pGObj)
{ return (dynamic_cast<CurveLine*>(pGObj)) ; }
BIN
View File
Binary file not shown.
+6
View File
@@ -277,6 +277,9 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="OutTsc.cpp" />
<ClCompile Include="Point3d.cpp" />
<ClCompile Include="PointGrid3d.cpp" />
<ClCompile Include="PointsPCA.cpp" />
<ClCompile Include="PolyArc.cpp" />
<ClCompile Include="PolygonPlane.cpp" />
<ClCompile Include="PolyLine.cpp" />
<ClCompile Include="PolynomialPoint3d.cpp" />
<ClCompile Include="stdafx.cpp">
@@ -330,6 +333,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="..\Include\EGkPlane3d.h" />
<ClInclude Include="..\Include\EGkPoint3d.h" />
<ClInclude Include="..\Include\EGkPointGrid3d.h" />
<ClInclude Include="..\Include\EGkPolyArc.h" />
<ClInclude Include="..\Include\EGkPolyLine.h" />
<ClInclude Include="..\Include\EGkStringUtils3d.h" />
<ClInclude Include="..\Include\EgkSurfTriMesh.h" />
@@ -388,6 +392,8 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="ObjGraphicsMgr.h" />
<ClInclude Include="FontOs.h" />
<ClInclude Include="OutTsc.h" />
<ClInclude Include="PointsPCA.h" />
<ClInclude Include="PolygonPlane.h" />
<ClInclude Include="PolynomialPoint3d.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="SelManager.h" />
+18
View File
@@ -216,6 +216,15 @@
<ClCompile Include="CurveByInterp.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
<ClCompile Include="PolygonPlane.cpp">
<Filter>File di origine\Base</Filter>
</ClCompile>
<ClCompile Include="PointsPCA.cpp">
<Filter>File di origine\Base</Filter>
</ClCompile>
<ClCompile Include="PolyArc.cpp">
<Filter>File di origine\Base</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@@ -524,6 +533,15 @@
<ClInclude Include="CalcDerivate.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="PolygonPlane.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="PointsPCA.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkPolyArc.h">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc">
+5 -5
View File
@@ -48,7 +48,7 @@ ExtText::Set( const string& sText, const Point3d& ptP, double dAngDeg, double dH
// assegno i dati
m_ptP = ptP ;
m_vtN = Z_AX ;
m_vtD.FromPolar( 1, dAngDeg) ;
m_vtD = FromPolar( 1, dAngDeg) ;
m_sText = sText ;
m_sFont.clear() ;
m_nWeight = 400 ;
@@ -79,7 +79,7 @@ ExtText::Set( const string& sText, const Point3d& ptP, double dAngDeg,
// assegno i dati
m_ptP = ptP ;
m_vtN = Z_AX ;
m_vtD.FromPolar( 1, dAngDeg) ;
m_vtD = FromPolar( 1, dAngDeg) ;
m_sText = sText ;
m_sFont = sFont ;
m_nWeight = nW ;
@@ -802,8 +802,8 @@ ExtText::Mir( bool bOnLen)
case ETXT_IPBR : m_nInsPos = ETXT_IPBL ; break ;
}
// inverto i versori
m_vtN *= - 1 ;
m_vtD *= - 1 ;
m_vtN.Invert() ;
m_vtD.Invert() ;
}
// altrimenti auto-mirror su altezza del testo
else {
@@ -817,7 +817,7 @@ ExtText::Mir( bool bOnLen)
case ETXT_IPBR : m_nInsPos = ETXT_IPTR ; break ;
}
// inverto il versore normale
m_vtN *= - 1 ;
m_vtN.Invert() ;
}
return true ;
+2 -2
View File
@@ -102,7 +102,7 @@ Frame3d::Set( const Point3d& ptOrig, const Vector3d& vtDirZ)
m_vtVersX = Z_AX ^ m_vtVersZ ;
if ( ! m_vtVersX.Normalize())
return false ;
// verzsore Y
// versore Y
m_vtVersY = m_vtVersZ ^ m_vtVersX ;
if ( ! m_vtVersY.Normalize())
return false ;
@@ -526,7 +526,7 @@ Frame3d::GetRotationsCAC1( double& dAngCDeg, double& dAngADeg, double& dAngC1Deg
m_vtVersX.ToSpherical( nullptr, nullptr, &dAngCDeg) ;
// calcolo l'asse X senza la rotazione attorno a C'
vtXnoC1.FromPolar( 1, dAngCDeg) ;
vtXnoC1 = FromPolar( 1, dAngCDeg) ;
// calcolo la rotazione attorno a C'
if ( ! vtXnoC1.GetRotation( m_vtVersX, m_vtVersZ, dAngC1Deg, bDet) || ! bDet)
+2 -4
View File
@@ -383,8 +383,7 @@ GdbExecutor::VectorFromSpherical( const STRVECTOR& vsParams)
IGeoVector3d* pGVect = CreateGeoVector3d() ;
if ( pGVect == nullptr)
return false ;
Vector3d vtV ;
vtV.FromSpherical( dLen, dAngVertDeg, dAngOrizzDeg) ;
Vector3d vtV = FromSpherical( dLen, dAngVertDeg, dAngOrizzDeg) ;
pGVect->Set( vtV) ;
return AddGeoObj( vsParams[0], vsParams[1], pGVect) ;
}
@@ -2461,8 +2460,7 @@ GdbExecutor::GetPolylineFromCurve( int nId, const Frame3d& frDest, double dLinTo
if ( ! IsValid( pModCrv))
return false ;
// eseguo la trasformazione
pModCrv->ToGlob( frCrv) ;
pModCrv->ToLoc( frDest) ;
pModCrv->LocToLoc( frCrv, frDest) ;
// ricavo l'approssimazione
if ( ! pModCrv->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, PL))
return false ;
+5 -5
View File
@@ -655,14 +655,14 @@ CalcATypeFromDisk( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
! CurveA.GetPointTang( dUAm, nSideA, ptP, vtADir))
return false ;
if ( nSideA == ICurve::FROM_MINUS)
vtADir *= - 1 ;
vtADir.Invert() ;
// direzioni di arrivo (prev) e partenza (next) curva B
Vector3d vtBpDir ;
double dUBp = dUB ;
if ( ! MoveParamToAvoidTg( dUBp, ICurve::FROM_MINUS, CurveB) ||
! CurveB.GetPointTang( dUBp, ICurve::FROM_MINUS, ptP, vtBpDir))
return false ;
vtBpDir *= - 1 ;
vtBpDir.Invert() ;
Vector3d vtBnDir ;
double dUBn = dUB ;
if ( ! MoveParamToAvoidTg( dUBn, ICurve::FROM_PLUS, CurveB) ||
@@ -702,14 +702,14 @@ CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
! CurveA.GetPointTang( dUAm, nSideA, ptP, vtADir))
return false ;
if ( nSideA == ICurve::FROM_MINUS)
vtADir *= - 1 ;
vtADir.Invert() ;
// direzioni di arrivo (prev) e partenza (next) curva B (P1)
Vector3d vtB1pDir ;
double dUB1p = dUB1 ;
if ( ! MoveParamToAvoidTg( dUB1p, ICurve::FROM_MINUS, CurveB) ||
! CurveB.GetPointTang( dUB1p, ICurve::FROM_MINUS, ptP, vtB1pDir))
return false ;
vtB1pDir *= - 1 ;
vtB1pDir.Invert() ;
Vector3d vtB1nDir ;
double dUB1n = dUB1 ;
if ( ! MoveParamToAvoidTg( dUB1n, ICurve::FROM_PLUS, CurveB) ||
@@ -721,7 +721,7 @@ CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
if ( ! MoveParamToAvoidTg( dUB2p, ICurve::FROM_MINUS, CurveB) ||
! CurveB.GetPointTang( dUB2p, ICurve::FROM_MINUS, ptP, vtB2pDir))
return false ;
vtB2pDir *= - 1 ;
vtB2pDir.Invert() ;
Vector3d vtB2nDir ;
double dUB2n = dUB2 ;
if ( ! MoveParamToAvoidTg( dUB2n, ICurve::FROM_PLUS, CurveB) ||
+164
View File
@@ -0,0 +1,164 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : PointsPCA.cpp Data : 12.08.14 Versione : 1.5h3
// Contenuto : Implementazione della classe PointsPCA,
// Principal Components Analysis di un insieme di punti.
//
//
// Modifiche : 12.08.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "PointsPCA.h"
//----------------------------------------------------------------------------
PointsPCA::PointsPCA( void)
{
// azzero numero punti
m_nPntNbr = 0 ;
// azzero il baricentro
m_ptCen.Set( 0, 0, 0) ;
// azzero matrice di covarianza
m_CovMat.setZero() ;
// inizializzo il rank ad un valore assurdo
m_nRank = - 1 ;
}
//----------------------------------------------------------------------------
void
PointsPCA::AddPoint( const Point3d& ptP)
{
// incremento numero punti
++ m_nPntNbr ;
// aggiorno il baricentro
m_ptCen += ptP ;
// aggiorno la matrice di covarianza (solo triangolo superiore perchè simmetrica)
m_CovMat(0,0) += ptP.x * ptP.x ;
m_CovMat(1,1) += ptP.y * ptP.y ;
m_CovMat(2,2) += ptP.z * ptP.z ;
m_CovMat(0,1) += ptP.x * ptP.y ;
m_CovMat(0,2) += ptP.x * ptP.z ;
m_CovMat(1,2) += ptP.y * ptP.z ;
}
//----------------------------------------------------------------------------
bool
PointsPCA::Finalize( void)
{
// se già eseguito il calcolo finale, esco
if ( m_nRank >= 0)
return true ;
// il rank viene annullato ( non sono ancora note direzioni principali)
m_nRank = 0 ;
// se non sono stati assegnati punti, esco
if ( m_nPntNbr == 0)
return false ;
// fattore di scala per numero di punti
double dScale = 1 / double( m_nPntNbr) ;
// calcolo del baricentro
m_ptCen *= dScale ;
// completo la matrice di covarianza
m_CovMat(0,0) = m_CovMat(0,0) * dScale - m_ptCen.x * m_ptCen.x ;
m_CovMat(1,1) = m_CovMat(1,1) * dScale - m_ptCen.y * m_ptCen.y ;
m_CovMat(2,2) = m_CovMat(2,2) * dScale - m_ptCen.z * m_ptCen.z ;
m_CovMat(0,1) = m_CovMat(0,1) * dScale - m_ptCen.x * m_ptCen.y ;
m_CovMat(0,2) = m_CovMat(0,2) * dScale - m_ptCen.x * m_ptCen.z ;
m_CovMat(1,2) = m_CovMat(1,2) * dScale - m_ptCen.y * m_ptCen.z ;
m_CovMat(1,0) = m_CovMat(0,1) ;
m_CovMat(2,0) = m_CovMat(0,2) ;
m_CovMat(2,1) = m_CovMat(1,2) ;
// calcolo gli autovalori e autovettori (essendo matrice 3x3 uso metodo diretto)
Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> es ;
es.compute( m_CovMat) ; // non usare computeDirect : errore nell'ordine degli autovettori
if ( es.info() == Eigen::NoConvergence)
return false ;
// recupero gli autovettori corrispondenti agli autovalori non nulli
for ( int i = 0 ; i < 3 ; ++ i) {
int j = ( i + 1) % 3 ;
int k = ( i + 2) % 3 ;
// se l'autovalore corrente è il più grande in modulo
if ( fabs( es.eigenvalues()(i)) >= fabs( es.eigenvalues()(j)) &&
fabs( es.eigenvalues()(i)) >= fabs( es.eigenvalues()(k)) &&
fabs( es.eigenvalues()(i)) > EPS_SMALL * EPS_SMALL) {
// il suo autovettore è il primo
++ m_nRank ;
m_vtPC[0].Set( es.eigenvectors()(0,i), es.eigenvectors()(1,i), es.eigenvectors()(2,i)) ;
// se il successivo autovalore è maggiore del rimanente in modulo
if ( fabs( es.eigenvalues()(j)) >= fabs(es.eigenvalues()(k)) &&
fabs( es.eigenvalues()(j)) > EPS_SMALL * EPS_SMALL) {
// il suo autovettore è il secondo
++ m_nRank ;
m_vtPC[1].Set( es.eigenvectors()(0,j), es.eigenvectors()(1,j), es.eigenvectors()(2,j)) ;
// se il rimanente autovalore è non nullo
if ( fabs( es.eigenvalues()(k)) > EPS_SMALL * EPS_SMALL) {
// il suo autovettore è il terzo
++ m_nRank ;
m_vtPC[2].Set( es.eigenvectors()(0,k), es.eigenvectors()(1,k), es.eigenvectors()(2,k)) ;
}
}
// altrimenti, se il rimanente autovalore è maggiore del successivo in modulo
else if ( fabs( es.eigenvalues()(k)) >= fabs( es.eigenvalues()(j)) &&
fabs( es.eigenvalues()(k)) > EPS_SMALL * EPS_SMALL) {
// il suo autovettore è il secondo
++ m_nRank ;
m_vtPC[1].Set( es.eigenvectors()(0,k), es.eigenvectors()(1,k), es.eigenvectors()(2,k)) ;
// se il rimanente autovalore è non nullo
if ( fabs( es.eigenvalues()(j)) > EPS_SMALL * EPS_SMALL) {
// il suo autovettore è il terzo
++ m_nRank ;
m_vtPC[2].Set( es.eigenvectors()(0,j), es.eigenvectors()(1,j), es.eigenvectors()(2,j)) ;
}
}
break ;
}
}
return true ;
}
//----------------------------------------------------------------------------
int
PointsPCA::GetRank( void)
{
// verifico completamento conti
Finalize() ;
return m_nRank ;
}
//----------------------------------------------------------------------------
bool
PointsPCA::GetCenter( Point3d& ptCen)
{
// verifico completamento conti
Finalize() ;
// assegno i dati
ptCen = m_ptCen ;
return ( m_nPntNbr > 0) ;
}
//----------------------------------------------------------------------------
bool
PointsPCA::GetPrincipalComponent( int nId, Vector3d& vtPC)
{
// verifico completamento conti
Finalize() ;
// verifico esistenza componente (indice 0-based)
if ( nId < 0 || nId >= m_nRank)
return false ;
// assegno dati
vtPC = m_vtPC[nId] ;
return true ;
}
+42
View File
@@ -0,0 +1,42 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : PointsPCA.h Data : 12.08.14 Versione : 1.5h3
// Contenuto : Dichiarazione della classe PointsPCA.
//
//
//
// Modifiche : 12.08.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Extern/Eigen/Dense"
//----------------------------------------------------------------------------
class PointsPCA
{
public :
PointsPCA( void) ;
void AddPoint( const Point3d& ptP) ;
int GetRank( void) ;
bool GetCenter( Point3d& ptCen) ;
bool GetPrincipalComponent( int nId, Vector3d& vtPC) ;
private :
bool Finalize( void) ;
private :
static const int MAX_RANK = 3 ;
private :
int m_nPntNbr ; // numero punti
Point3d m_ptCen ; // baricentro
Eigen::Matrix3d m_CovMat ; // matrice di covarianza
int m_nRank ; // numero delle componenti principali (MAX_RANK = 3)
Vector3d m_vtPC[MAX_RANK] ; // direzioni delle componenti principali
} ;
+176
View File
@@ -0,0 +1,176 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : PolyArc.cpp Data : 14.08.14 Versione : 1.5h3
// Contenuto : Implementazione della classe PolyArc.
//
//
//
// Modifiche : 14.08.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "\EgtDev\Include\EGkPolyArc.h"
//----------------------------------------------------------------------------
PolyArc::PolyArc( void)
{
m_nCount = 0 ;
m_iter = m_lUPointBs.end() ;
}
//----------------------------------------------------------------------------
PolyArc::~PolyArc( void)
{
}
//----------------------------------------------------------------------------
bool
PolyArc::Clear( void)
{
m_nCount = 0 ;
m_lUPointBs.clear() ;
m_iter = m_lUPointBs.end() ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::AddUPoint( double dPar, const Point3d& ptP, double dBulge)
{
try {
m_lUPointBs.push_back( UPointB( dPar, ptP, dBulge)) ;
}
catch (...) {
return false ;
}
m_nCount ++ ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::EraseFirstUPoint( void)
{
if ( m_lUPointBs.empty())
return false ;
m_lUPointBs.pop_front() ;
m_nCount -- ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::EraseLastUPoint( void)
{
if ( m_lUPointBs.empty())
return false ;
m_lUPointBs.pop_back() ;
m_nCount -- ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::AddOffsetToU( double dOffset)
{
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->dU += dOffset ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::ToGlob( const Frame3d& frRef)
{
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.ToGlob( frRef) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::ToLoc( const Frame3d& frRef)
{
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.ToLoc( frRef) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{
UPNTBLIST::iterator iter ;
for ( iter = m_lUPointBs.begin() ; iter != m_lUPointBs.end() ; ++ iter)
iter->ptP.LocToLoc( frOri, frDest) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::Splice( PolyArc& PA)
{
m_lUPointBs.splice( m_lUPointBs.end(), PA.m_lUPointBs) ;
m_nCount += PA.GetPointNbr() ;
PA.m_nCount = 0 ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::GetFirstUPoint( double* pdPar, Point3d* pptP, double* pdBulge) const
{
m_iter = m_lUPointBs.begin() ;
if ( m_iter == m_lUPointBs.end())
return false ;
if ( pdPar != nullptr)
*pdPar = m_iter->dU ;
if ( pptP != nullptr)
*pptP = m_iter->ptP ;
if ( pdBulge != nullptr)
*pdBulge = m_iter->dB ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolyArc::GetNextUPoint( double* pdPar, Point3d* pptP, double* pdBulge, bool bNotLast) const
{
if ( m_iter == m_lUPointBs.end())
return false ;
++ m_iter ;
if ( m_iter == m_lUPointBs.end())
return false ;
if ( bNotLast && m_iter == -- ( m_lUPointBs.end()))
return false ;
if ( pdPar != nullptr)
*pdPar = m_iter->dU ;
if ( pptP != nullptr)
*pptP = m_iter->ptP ;
if ( pdBulge != nullptr)
*pdBulge = m_iter->dB ;
return true ;
}
+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)
+89
View File
@@ -0,0 +1,89 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : PolygonPlane.cpp Data : 12.08.14 Versione : 1.5h3
// Contenuto : Implementazione della classe PolygonPlane.
// Calcolo della normale e delle aree con il metodo di Newell.
//
//
// Modifiche : 12.08.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "PolygonPlane.h"
//----------------------------------------------------------------------------
void
PolygonPlane::AddPoint( const Point3d& ptP)
{
// se è il primo punto (parto da -1 perchè verrà contato alla chiusura)
if ( m_nPntNbr == -1)
m_ptFirst = ptP ;
// dal secondo punto posso cominciare ad eseguire le somme parziali
else {
// 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
m_vtN.x += ( m_ptLast.y - ptP.y) * ( m_ptLast.z + ptP.z) ; // projection on yz
m_vtN.y += ( m_ptLast.z - ptP.z) * ( m_ptLast.x + ptP.x) ; // projection on xz
m_vtN.z += ( m_ptLast.x - ptP.x) * ( m_ptLast.y + ptP.y) ; // projection on xy
m_ptCen += ptP ;
}
// salvo punto e incremento numero di punti
m_ptLast = ptP ;
++ m_nPntNbr ;
}
//----------------------------------------------------------------------------
bool
PolygonPlane::Finalize( void)
{
// almeno 3 punti (il triangolo è il poligono con minimo numero di lati)
if ( m_nPntNbr < 3)
return false ;
// se il poligono non è stato chiuso, aggiungo calcolo per ultimo lato
if ( ! AreSamePointApprox( m_ptFirst, m_ptLast)) {
// aggiungo il primo punto per far eseguire i conti sul lato di chiusura
AddPoint( m_ptFirst) ;
}
// se non effettuato, eseguo il calcolo finale
if ( m_dLenN < EPS_SMALL) {
// lunghezza della normale (doppio dell'area del poligono)
m_dLenN = m_vtN.Len() ;
if ( m_dLenN < EPS_SMALL)
return false ;
// normalizzo
m_vtN /= m_dLenN ;
// sistemo baricentro
m_ptCen /= m_nPntNbr ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
PolygonPlane::GetPlane( Plane3d& plPlane)
{
// verifico completamento conti
if ( ! Finalize())
return false ;
// assegno i dati al piano
plPlane.vtN = m_vtN ;
plPlane.dDist = ( ( m_ptCen - ORIG) * plPlane.vtN) ;
return true ;
}
//----------------------------------------------------------------------------
bool
PolygonPlane::GetArea( double& dArea)
{
// verifico completamento conti
if ( ! Finalize())
return false ;
// assegno l'area
dArea = 0.5 * m_dLenN ;
return true ;
}
+38
View File
@@ -0,0 +1,38 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : PolygonPlane.h Data : 12.08.14 Versione : 1.5h3
// Contenuto : Dichiarazione della classe PolygonPlane.
//
//
//
// Modifiche : 12.08.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EGkPlane3d.h"
//----------------------------------------------------------------------------
class PolygonPlane
{
public :
PolygonPlane( void) : m_nPntNbr( -1), m_dLenN( 0) {}
void AddPoint( const Point3d& ptP) ;
bool GetPlane( Plane3d& plPlane) ;
bool GetArea( double& dArea) ;
private :
bool Finalize( void) ;
private :
int m_nPntNbr ; // numero punti aggiunti
double m_dLenN ; // lunghezza della normale
Point3d m_ptFirst ; // primo punto aggiunto
Point3d m_ptLast ; // ultimo punto aggiunto
Vector3d m_vtN ; // versore normale
Point3d m_ptCen ; // baricentro
} ;
+1 -1
View File
@@ -1752,7 +1752,7 @@ SurfTriMesh::InvertTriangle( int nT)
// scambio delle conseguenti due adiacenze
swap( m_vTria[nT].nIdAdjac[0], m_vTria[nT].nIdAdjac[2]) ;
// inversione della normale
m_vTria[nT].vtN *= - 1 ;
m_vTria[nT].vtN.Invert() ;
return true ;
}
+2 -5
View File
@@ -27,13 +27,10 @@ using namespace std ;
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
// verific che la polilinea sia chiusa e calcolo il piano medio del poligono
double dArea ;
Plane3d plPlane ;
if ( ! PL.IsFlat( plPlane, dArea, 50 * EPS_SMALL))
if ( ! PL.IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
bool bCCW ;
if ( fabs( plPlane.vtN.z) >= fabs( plPlane.vtN.x) &&
+33 -12
View File
@@ -13,7 +13,6 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "\EgtDev\Include\EGkGeoConst.h"
#include "\EgtDev\Include\EGkVector3d.h"
#include "\EgtDev\Include\EGKFrame3d.h"
@@ -21,27 +20,49 @@
//----------------------------------------------------------------------------
// Definizione a partire da coordinate sferiche
//----------------------------------------------------------------------------
void
Vector3d::FromSpherical( double dLen, double dAngVertDeg, double dAngOrizzDeg)
Vector3d
FromSpherical( double dLen, double dAngVertDeg, double dAngOrizzDeg)
{
double dAngVertRad = dAngVertDeg * DEGTORAD ;
double dAngOrizzRad = dAngOrizzDeg * DEGTORAD ;
double dSinAngVert = sin( dAngVertRad) ;
x = dLen * dSinAngVert * cos( dAngOrizzRad) ;
y = dLen * dSinAngVert * sin( dAngOrizzRad) ;
z = dLen * cos( dAngVertRad) ;
Vector3d vtV( dLen * dSinAngVert * cos( dAngOrizzRad),
dLen * dSinAngVert * sin( dAngOrizzRad),
dLen * cos( dAngVertRad)) ;
return vtV ;
}
//----------------------------------------------------------------------------
// Definizione a partire da coordinate polari
// Definizione a partire da coordinate polari ( nel piano XY, Z = 0)
//----------------------------------------------------------------------------
void
Vector3d::FromPolar( double dLen, double dAngDeg)
Vector3d
FromPolar( double dLen, double dAngDeg)
{
double dAngRad = dAngDeg * DEGTORAD ;
x = dLen * cos( dAngRad) ;
y = dLen * sin( dAngRad) ;
z = 0 ;
Vector3d vtV( dLen * cos( dAngRad),
dLen * sin( dAngRad),
0) ;
return vtV ;
}
//----------------------------------------------------------------------------
// Definizione dal più verticale dei vettori ortogonali a quello ricevuto
//----------------------------------------------------------------------------
Vector3d
FromUprightOrtho( const Vector3d& vtV)
{
// se vettore nullo, imposto asse Z+
if ( vtV.IsZero())
return Z_AX ;
// se vettore coincidente con asse Z, imposto asse X+
if ( vtV.IsZplus() || vtV.IsZminus())
return X_AX ;
// caso generico
Vector3d vtAx = vtV ;
vtAx.z = 0 ;
vtAx.Normalize( EPS_ZERO) ;
vtAx.Rotate( Z_AX, 0, 1) ;
return ( vtV ^ vtAx) ;
}
//----------------------------------------------------------------------------