//---------------------------------------------------------------------------- // EgalTech 2013-2013 //---------------------------------------------------------------------------- // File : DistPointCurve.cpp Data : 02.01.14 Versione : 1.5a1 // Contenuto : Implementazione della classe distanza punto da Curva. // // // // Modifiche : 02.01.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "DistPointArc.h" #include "DistPointCrvBezier.h" #include "DistPointCrvComposite.h" #include "/EgtDev/Include/EGkDistPointLine.h" #include "/EgtDev/Include/EGkDistPointCurve.h" //---------------------------------------------------------------------------- DistPointCurve::DistPointCurve( const Point3d& ptP, const ICurve& Curve, bool bIsSegment) { // Il flag bIsSegment vale solo per linee. // distanza non calcolata e curva sconosciuta m_dDist = - 1 ; m_pCurve = nullptr ; // curva non valida if ( &Curve == nullptr || ! Curve.IsValid()) return ; // chiamo calcolatore opportuno switch ( Curve.GetType()) { case CRV_LINE : LineCalculate( ptP, Curve, bIsSegment) ; break ; case CRV_ARC : ArcCalculate( ptP, Curve) ; break ; case CRV_BEZIER : CrvBezierCalculate( ptP, Curve) ; break ; case CRV_COMPO : CrvCompositeCalculate( ptP, Curve) ; break ; default : break ; } // salvo il punto m_ptP = ptP ; // salvo il puntatore alla curva m_pCurve = &Curve ; } //---------------------------------------------------------------------------- void DistPointCurve::LineCalculate( const Point3d& ptP, const ICurve& Curve, bool bIsSegment) { DistPointLine dstPtLn( ptP, *GetCurveLine( &Curve), bIsSegment) ; if ( dstPtLn.m_dSqDist >= 0) { m_dDist = sqrt( dstPtLn.m_dSqDist) ; m_Info.emplace_back( MDPCI_NORMAL, dstPtLn.m_dParam, dstPtLn.m_ptMinDist) ; } } //---------------------------------------------------------------------------- void DistPointCurve::ArcCalculate( const Point3d& ptP, const ICurve& Curve) { DistPointArc dstPtArc( ptP, *GetCurveArc( &Curve)) ; m_dDist = dstPtArc.m_dDist ; m_Info = dstPtArc.m_Info ; } //---------------------------------------------------------------------------- void DistPointCurve::CrvBezierCalculate( const Point3d& ptP, const ICurve& Curve) { DistPointCrvBezier dstPtCBez( ptP, *GetCurveBezier( &Curve)) ; m_dDist = dstPtCBez.m_dDist ; m_Info = dstPtCBez.m_Info ; } //---------------------------------------------------------------------------- void DistPointCurve::CrvCompositeCalculate( const Point3d& ptP, const ICurve& Curve) { DistPointCrvComposite dstPtCCompo( ptP, *GetCurveComposite( &Curve)) ; m_dDist = dstPtCCompo.m_dDist ; m_Info = dstPtCCompo.m_Info ; } //---------------------------------------------------------------------------- bool DistPointCurve::GetSqDist( double& dSqDist) const { if ( m_dDist < 0) return false ; dSqDist = m_dDist * m_dDist ; return true ; } //---------------------------------------------------------------------------- bool DistPointCurve::GetDist( double& dDist) const { if ( m_dDist < 0) return false ; dDist = m_dDist ; return true ; } //---------------------------------------------------------------------------- bool DistPointCurve::GetMinDistPoint( int nInd, Point3d& ptMinDist, int& nFlag) const { if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size()) return false ; ptMinDist = m_Info[nInd].ptQ ; nFlag = m_Info[nInd].nFlag ; return true ; } //---------------------------------------------------------------------------- bool DistPointCurve::GetMinDistPoint( double dNearParam, Point3d& ptMinDist, int& nFlag) const { if ( m_dDist < 0 || m_Info.empty()) return false ; // verifico se cade in una zona continua for ( int i = 1 ; i < (int) m_Info.size() ; ++ i) { if ( m_Info[i-1].nFlag == MDPCI_START_CONT && m_Info[i].nFlag == MDPCI_END_CONT) { if ( dNearParam > m_Info[i-1].dPar && dNearParam < m_Info[i].dPar) { nFlag = MDPCI_START_CONT ; if ( m_pCurve != nullptr && m_pCurve->GetPointD1D2( dNearParam, ICurve::FROM_MINUS, ptMinDist)) return true ; } } } // cerco punto discreto più vicino (anche estremi di zone continue) double dParam ; for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) { if ( i == 0 || abs( m_Info[i].dPar - dNearParam) < abs( dParam - dNearParam)) { dParam = m_Info[i].dPar ; ptMinDist = m_Info[i].ptQ ; nFlag = m_Info[i].nFlag ; } } return true ; } //---------------------------------------------------------------------------- bool DistPointCurve::GetParamAtMinDistPoint( int nInd, double& dParam, int& nFlag) const { if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size()) return false ; dParam = m_Info[nInd].dPar ; nFlag = m_Info[nInd].nFlag ; return true ; } //---------------------------------------------------------------------------- bool DistPointCurve::GetParamAtMinDistPoint( double dNearParam, double& dParam, int& nFlag) const { if ( m_dDist < 0 || m_Info.empty()) return false ; // verifico se cade in una zona continua for ( int i = 1 ; i < (int) m_Info.size() ; ++ i) { if ( m_Info[i-1].nFlag == MDPCI_START_CONT && m_Info[i].nFlag == MDPCI_END_CONT) { if ( dNearParam > m_Info[i-1].dPar && dNearParam < m_Info[i].dPar) { dParam = dNearParam ; nFlag = MDPCI_START_CONT ; return true ; } } } // cerco punto discreto più vicino (anche estremi di zone continue) for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) { if ( i == 0 || abs( m_Info[i].dPar - dNearParam) < abs( dParam - dNearParam)) { dParam = m_Info[i].dPar ; nFlag = m_Info[i].nFlag ; } } return true ; } //---------------------------------------------------------------------------- bool DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide, double dTol) const { if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size()) return false ; // se distanza nulla, il punto giace sulla curva if ( m_dDist <= dTol) { nSide = MDS_ON ; return true ; } // determino la tangente nell'intorno del punto Point3d ptQ ; Vector3d vtPreTg, vtPostTg ; if ( m_pCurve == nullptr || ! m_pCurve->GetPointTang( m_Info[nInd].dPar, ICurve::FROM_MINUS, ptQ, vtPreTg) || ! m_pCurve->GetPointTang( m_Info[nInd].dPar, ICurve::FROM_PLUS, ptQ, vtPostTg)) return false ; Vector3d vtTg = 0.5 * ( vtPreTg + vtPostTg) ; // se tangenti opposte, si deve ricalcolare spostandosi un poco if ( ! vtTg.Normalize()) { double dDeltaU = 1000 * EPS_PARAM ; double dParPre = m_Info[nInd].dPar - dDeltaU ; double dParPost = m_Info[nInd].dPar + dDeltaU ; // verifico se il parametro deve essere modificato per adattarsi a curva chiusa if ( m_pCurve->IsClosed()) { double dParS, dParE ; m_pCurve->GetDomain( dParS, dParE) ; if ( dParPre < dParS) dParPre = dParE - dDeltaU ; if ( dParPost > dParE) dParPost = dParS + dDeltaU ; } if ( ! m_pCurve->GetPointTang( dParPre, ICurve::FROM_MINUS, ptQ, vtPreTg) || ! m_pCurve->GetPointTang( dParPost, ICurve::FROM_PLUS, ptQ, vtPostTg)) return false ; vtTg = 0.5 * ( vtPreTg + vtPostTg) ; if ( ! vtTg.Normalize( EPS_ZERO)) return false ; } // determino la direzione di riferimento Vector3d vtRef = vtN ^ vtTg ; if ( ! vtRef.Normalize()) return false ; // determino il lato di giacitura del punto double dSide = vtRef * ( m_ptP - ptQ) ; if ( abs( dSide) < dTol) nSide = MDS_ON ; else if ( dSide > 0) nSide = MDS_LEFT ; else nSide = MDS_RIGHT ; return true ; } //---------------------------------------------------------------------------- bool DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide, double dTol) const { if ( m_dDist < 0 || m_Info.empty()) return false ; // cerco punto discreto più vicino (anche estremi di zone continue) int nInd ; double dParam ; for ( int i = 0 ; i < (int) m_Info.size() ; ++ i) { if ( i == 0 || abs( m_Info[i].dPar - dNearParam) < abs( dParam - dNearParam)) { nInd = i ; dParam = m_Info[i].dPar ; } } // mi sono ricondotto al caso precedente return GetSideAtMinDistPoint( nInd, vtN, nSide, dTol) ; } //---------------------------------------------------------------------------- bool DistPointCurve::GetMinDistInfo( int nInd, MinDistPCInfo& aInfo) const { if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size()) return false ; aInfo = m_Info[nInd] ; return true ; }