//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : LinePntPerpCurve.cpp Data : 25.11.14 Versione : 1.5k5 // Contenuto : Implementazione funzioni per calcolo rette perpendicolari a curve. // // // // Modifiche : 25.11.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveLine.h" #include "CurveArc.h" #include "CurveBezier.h" #include "CurveComposite.h" #include "CreateCurveAux.h" #include "GeoConst.h" #include "/EgtDev/Include/EGkLinePntPerpCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- static CurveLine* GetLinePointPerpLine( const Point3d& ptP, const CurveLine& crvLine, const Point3d& ptNear) ; static CurveLine* GetLinePointPerpArc( const Point3d& ptP, const CurveArc& crvArc, const Point3d& ptNear) ; static CurveLine* GetLinePointPerpBezier( const Point3d& ptP, const CurveBezier& crvBezier, const Point3d& ptNear) ; static CurveLine* GetLinePointPerpCompo( const Point3d& ptP, const CurveComposite& crvCompo, const Point3d& ptNear) ; //---------------------------------------------------------------------------- ICurveLine* GetLinePointPerpCurve( const Point3d& ptP, const ICurve& cCrv, const Point3d& ptNear) { switch ( cCrv.GetType()) { case CRV_LINE : { const CurveLine& crvLine = *GetBasicCurveLine( &cCrv) ; return GetLinePointPerpLine( ptP, crvLine, ptNear) ; } case CRV_ARC : { const CurveArc& crvArc = *GetBasicCurveArc( &cCrv) ; return GetLinePointPerpArc( ptP, crvArc, ptNear) ; } case CRV_BEZIER : { const CurveBezier& crvBezier = *GetBasicCurveBezier( &cCrv) ; return GetLinePointPerpBezier( ptP, crvBezier, ptNear) ; } case CRV_COMPO : { const CurveComposite& crvCompo = *GetBasicCurveComposite( &cCrv) ; return GetLinePointPerpCompo( ptP, crvCompo, ptNear) ; } default : return nullptr ; } } //---------------------------------------------------------------------------- CurveLine* GetLinePointPerpLine( const Point3d& ptP, const CurveLine& crvLine, const Point3d& ptNear) { // direzione della linea Vector3d vtDir ; if ( ! crvLine.GetStartDir( vtDir)) return nullptr ; // lunghezza della linea double dLen ; if ( ! crvLine.GetLength( dLen)) return nullptr ; // piede della perpendicolare dal punto alla linea double dPerpLen = ( ptP - crvLine.GetStart()) * vtDir ; if ( dPerpLen < - EPS_ZERO || dPerpLen > dLen + EPS_ZERO) return nullptr ; if ( dPerpLen < 0) dPerpLen = 0 ; else if ( dPerpLen > dLen) dPerpLen = dLen ; Point3d ptFoot = crvLine.GetStart() + dPerpLen * vtDir ; // creo la linea PtrOwner pCrvLine( CreateBasicCurveLine()) ; if ( IsNull( pCrvLine)) return nullptr ; // costruisco la linea if ( ! pCrvLine->Set( ptP, ptFoot)) return nullptr ; // restituisco la linea return Release( pCrvLine) ; } //---------------------------------------------------------------------------- CurveLine* GetLinePointPerpArc( const Point3d& ptP, const CurveArc& crvArc, const Point3d& ptNear) { // l'arco deve essere piatto (no elica) if ( ! crvArc.IsPlane()) return nullptr ; // punti sull'arco su direzione della linea dal punto al centro dell'arco Point3d ptP2 ; Vector3d vtDirP = crvArc.GetCenter() - ptP ; vtDirP -= vtDirP * crvArc.GetNormVersor() * crvArc.GetNormVersor() ; if ( ! vtDirP.Normalize()) { // il punto è nel centro dell'arco, l'estremo sull'arco dipende solo da Near DistPointCurve dstPtCurve( ptNear, crvArc) ; int nFlag ; if ( ! dstPtCurve.GetMinDistPoint( 0, ptP2, nFlag)) return nullptr ; } else { if ( ! FindPointOnArc( crvArc, vtDirP, ptNear, ptP2)) return nullptr ; } // creo la linea PtrOwner pCrvLine( CreateBasicCurveLine()) ; if ( IsNull( pCrvLine)) return nullptr ; // costruisco la linea if ( ! pCrvLine->Set( ptP, ptP2)) return nullptr ; // restituisco la linea return Release( pCrvLine) ; } //---------------------------------------------------------------------------- CurveLine* GetLinePointPerpBezier( const Point3d& ptP, const CurveBezier& crvBezier, const Point3d& ptNear) { // calcolo approssimazione della curva di Bezier con archi e rette PolyArc PA ; if ( ! crvBezier.ApproxWithArcs( 10 * EPS_SMALL, ANG_TOL_STD_DEG, PA)) return nullptr ; // la trasformo in curva composita PtrOwner pCrvCompo( CreateBasicCurveComposite()) ; if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyArc( PA)) return nullptr ; // calcolo la linea perpendicolare a questa approssimazione PtrOwner pCrvLine( GetBasicCurveLine( GetLinePointPerpCurve( ptP, *pCrvCompo, ptNear))) ; if ( IsNull( pCrvLine)) return nullptr ; // porto il punto finale della linea esattamente sulla curva di Bezier DistPointCurve dstPtCurve( pCrvLine->GetEnd(), crvBezier) ; Point3d ptP2 ; int nFlag ; if ( ! dstPtCurve.GetMinDistPoint( 0, ptP2, nFlag) || ! pCrvLine->ModifyEnd( ptP2)) return nullptr ; // restituisco la linea return Release( pCrvLine) ; } //---------------------------------------------------------------------------- CurveLine* GetLinePointPerpCompo( const Point3d& ptP, const CurveComposite& crvCompo, const Point3d& ptNear) { // ciclo sulla curva composita double dMinSqDist = SQ_INFINITO ; PtrOwner pCrvLine ; for ( const ICurve* pCrv = crvCompo.GetFirstCurve() ; pCrv != nullptr ; pCrv = crvCompo.GetNextCurve()) { // recupero la linea perpendicolare alla curva elementare PtrOwner pCrvLtmp( GetBasicCurveLine( GetLinePointPerpCurve( ptP, *pCrv, ptNear))) ; if ( IsNull( pCrvLtmp)) continue ; // verifico se è la più vicina al punto desiderato double dSqDist = SqDist( ptNear, pCrvLtmp->GetEnd()) ; if ( dSqDist < dMinSqDist) { dMinSqDist = dSqDist ; pCrvLine.Set( pCrvLtmp) ; } } return Release( pCrvLine) ; }