Files
EgtGeomKernel/DistPointArc.cpp
T

211 lines
6.7 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2014
//----------------------------------------------------------------------------
// File : DistPointArc.cpp Data : 13.01.14 Versione : 1.5a3
// Contenuto : Implementazione della classe distanza punto da circonferenza/arco.
//
//
//
// Modifiche : 28.12.13 DS Creazione modulo.
// 13.01.14 DS Implementata gestione elica.
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "DistPointArc.h"
#include "DistPointCrvAux.h"
#include "GeoConst.h"
//----------------------------------------------------------------------------
DistPointArc::DistPointArc( const Point3d& ptP, const ICurveArc& arArc)
{
// distanza non calcolata
m_dDist = - 1 ;
if ( ! arArc.IsValid())
return ;
// se circonferenza
if ( arArc.IsACircle())
DistPointCircle( ptP, arArc) ;
// se arco in un piano
else if ( arArc.IsFlat())
DistPointFlatArc( ptP, arArc) ;
// altrimenti caso generico
else
DistPointHelix( ptP, arArc) ;
}
//----------------------------------------------------------------------------
void
DistPointArc::DistPointCircle( const Point3d& ptP, const ICurveArc& arArc)
{
// vettori ausiliari
Vector3d vtDiff = ptP - arArc.GetCenter() ;
double dDistN = vtDiff * arArc.GetNormVersor() ;
Vector3d vtDiffPlane = vtDiff - dDistN * arArc.GetNormVersor() ;
double dDistPlane = fabs( vtDiffPlane.Len() - arArc.GetRadius()) ;
// calcolo della distanza
if ( fabs( dDistPlane) > EPS_ZERO && fabs( dDistN) > EPS_ZERO)
m_dDist = sqrt( dDistPlane * dDistPlane + dDistN * dDistN) ;
else if ( fabs( dDistPlane) > EPS_ZERO)
m_dDist = dDistPlane ;
else if ( fabs( dDistN) > EPS_ZERO)
m_dDist = fabs( dDistN) ;
else
m_dDist = 0 ;
// calcolo del parametro del punto a minima distanza
if ( vtDiffPlane.Normalize()) {
bool bDet ;
double dAngDeg ;
double dParam ;
Point3d ptMinDist ;
arArc.GetStartVersor().GetRotation( vtDiffPlane, arArc.GetNormVersor(), dAngDeg, bDet) ;
if ( arArc.GetAngCenter() > 0 && dAngDeg < 0)
dAngDeg += 360 ;
else if ( arArc.GetAngCenter() < 0 && dAngDeg > 0)
dAngDeg -= 360 ;
dParam = dAngDeg / arArc.GetAngCenter() ;
if ( dParam < 0)
dParam = 0 ;
else if ( dParam > 1)
dParam = 1 ;
// calcolo del punto di minima distanza
arArc.GetPointD1D2( dParam, ICurve::FROM_MINUS, ptMinDist) ;
// salvo i dati
m_Info.push_back( MinDistPCInfo( MDPCI_NORMAL, dParam, ptMinDist)) ;
}
else {
Point3d ptMinDist ;
// tutti i punti della circonferenza sono a minima distanza salvo iniziale e finale
arArc.GetStartPoint( ptMinDist) ;
m_Info.push_back( MinDistPCInfo( MDPCI_START_CONT, 0, ptMinDist)) ;
arArc.GetEndPoint( ptMinDist) ;
m_Info.push_back( MinDistPCInfo( MDPCI_END_CONT, 1, ptMinDist)) ;
}
}
//----------------------------------------------------------------------------
void
DistPointArc::DistPointFlatArc( const Point3d& ptP, const ICurveArc& arArc)
{
// calcolo come per il cerchio (ma angolo al centro corretto)
DistPointCircle( ptP, arArc) ;
// se non tutti i punti e il parametro è sui bordi, li verifico entrambi
if ( m_Info[0].nFlag != MDPCI_START_CONT &&
( fabs( m_Info[0].dPar) < EPS_ZERO || fabs( m_Info[0].dPar - 1) < EPS_ZERO)) {
for ( int i = 0 ; i <= 1 ; i ++) {
// eseguo il calcolo
double dU = i ;
Point3d ptTest ;
arArc.GetPointD1D2( dU, ICurve::FROM_MINUS, ptTest) ;
double dDist = Dist( ptP, ptTest) ;
// altro punto con la stessa minima distanza
if ( i == 1 && fabs( dDist - m_dDist) < EPS_SMALL) {
// lo aggiungo
m_Info.push_back( MinDistPCInfo( MDPCI_NORMAL, dU, ptTest)) ;
}
// primo punto o punto con minima distanza più bassa
else if ( i == 0 || dDist < m_dDist) {
// aggiorno i minimi
m_dDist = dDist ;
// il nuovo vettore deve contenere solo quest'ultimo minimo
m_Info.clear() ;
m_Info.push_back( MinDistPCInfo( MDPCI_NORMAL, dU, ptTest)) ;
}
}
}
}
//----------------------------------------------------------------------------
void
DistPointArc::DistPointHelix( const Point3d& ptP, const ICurveArc& arArc)
{
// creo una polilinea di approssimazione
PolyLine PL ;
if ( ! arArc.ApproxWithLines( LIN_TOL_APPROX, ANG_TOL_APPROX_DEG, PL))
return ;
// cerco la minima distanza per la polilinea
MDCVECTOR vApproxMin ;
MDCVECTOR::iterator Iter ;
if ( ! CalcMinDistPointPolyLine( ptP, PL, vApproxMin))
return ;
// raffino i punti trovati
double dPolishedPar ;
Point3d ptPolishedQ ;
for ( Iter = vApproxMin.begin() ; Iter != vApproxMin.end() ; ++Iter) {
// eseguo raffinamento
if ( PolishMinDistPointCurve( ptP, arArc, *Iter, dPolishedPar, ptPolishedQ)) {
(*Iter).dDist = Dist( ptP, ptPolishedQ) ;
(*Iter).dPar = dPolishedPar ;
(*Iter).ptQ = ptPolishedQ ;
}
else
(*Iter).dDist = INFINITO ;
}
// determino i minimi raffinati da tenere
double dMinDist ;
if ( FilterMinDistPointCurve( ptP, arArc, vApproxMin, dMinDist, m_Info))
m_dDist = dMinDist ;
}
//----------------------------------------------------------------------------
bool
DistPointArc::GetSqDist( double& dSqDist)
{
if ( m_dDist < 0)
return false ;
dSqDist = m_dDist * m_dDist ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointArc::GetDist( double& dDist)
{
if ( m_dDist < 0)
return false ;
dDist = m_dDist ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointArc::GetMinDistPoint( int nInd, Point3d& ptMinDist, int& nFlag)
{
if ( m_dDist < 0)
return false ;
if ( nInd < 0 || nInd >= (int) m_Info.size())
return false ;
ptMinDist = m_Info[nInd].ptQ ;
nFlag = m_Info[nInd].nFlag ;
return true ;
}
//----------------------------------------------------------------------------
bool
DistPointArc::GetParamAtMinDistPoint( int nInd, double& dParam, int& nFlag)
{
if ( m_dDist < 0)
return false ;
if ( nInd < 0 || nInd >= (int) m_Info.size())
return false ;
dParam = m_Info[nInd].dPar ;
nFlag = m_Info[nInd].nFlag ;
return true ;
}