//---------------------------------------------------------------------------- // 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 ; }