//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : LinePntTgCurve.cpp Data : 09.06.14 Versione : 1.5f4 // Contenuto : Implementazione funzioni per calcolo rette tangenti a curve. // // // // Modifiche : 09.06.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/EGkLinePntTgCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- static CurveLine* GetLinePointTgLine( const Point3d& ptP, const CurveLine& crvLine, const Point3d& ptNear) ; static CurveLine* GetLinePointTgArc( const Point3d& ptP, const CurveArc& crvArc, const Point3d& ptNear) ; static CurveLine* GetLinePointTgBezier( const Point3d& ptP, const CurveBezier& crvBezier, const Point3d& ptNear) ; static CurveLine* GetLinePointTgCompo( const Point3d& ptP, const CurveComposite& crvCompo, const Point3d& ptNear) ; //---------------------------------------------------------------------------- ICurveLine* GetLinePointTgCurve( const Point3d& ptP, const ICurve& cCrv, const Point3d& ptNear) { switch ( cCrv.GetType()) { case CRV_LINE : { const CurveLine& crvLine = *GetBasicCurveLine( &cCrv) ; return GetLinePointTgLine( ptP, crvLine, ptNear) ; } case CRV_ARC : { const CurveArc& crvArc = *GetBasicCurveArc( &cCrv) ; return GetLinePointTgArc( ptP, crvArc, ptNear) ; } case CRV_BEZIER : { const CurveBezier& crvBezier = *GetBasicCurveBezier( &cCrv) ; return GetLinePointTgBezier( ptP, crvBezier, ptNear) ; } case CRV_COMPO : { const CurveComposite& crvCompo = *GetBasicCurveComposite( &cCrv) ; return GetLinePointTgCompo( ptP, crvCompo, ptNear) ; } default : return nullptr ; } } //---------------------------------------------------------------------------- CurveLine* GetLinePointTgLine( const Point3d& ptP, const CurveLine& crvLine, const Point3d& ptNear) { // verifico che il punto giaccia sulla linea estesa DistPointCurve dstPtCurve( ptP, crvLine, false) ; double dSqDist ; if ( ! dstPtCurve.GetSqDist( dSqDist) || dSqDist > SQ_EPS_SMALL) return nullptr ; // recupero il punto sulla linea pių vicino al punto near Point3d ptP2 ; int nFlag ; DistPointCurve dstNearCurve( ptNear, crvLine) ; if ( ! dstNearCurve.GetMinDistPoint( 0, ptP2, nFlag)) return nullptr ; // creo la linea PtrOwner pCrvLine( CreateBasicCurveLine()) ; if ( IsNull( pCrvLine)) return nullptr ; // setto la linea if ( ! pCrvLine->Set( ptP, ptP2)) return nullptr ; // la restituisco return Release( pCrvLine) ; } //---------------------------------------------------------------------------- CurveLine* GetLinePointTgArc( const Point3d& ptP, const CurveArc& crvArc, const Point3d& ptNear) { // calcolo il riferimento intrinseco dell'arco (DirNorm->Z e DirStart->X) Frame3d frIntr ; if ( ! frIntr.Set( crvArc.GetCenter(), crvArc.GetNormVersor(), crvArc.GetStartVersor())) return nullptr ; // porto il punto nel riferimento intrinseco Point3d ptPLoc = ptP ; ptPLoc.ToLoc( frIntr) ; // calcolo le linee tangenti alla circonferenza BIPNTVECTOR vBiPnt( 2) ; int nSol = CalcLinePointTgCircle( ptPLoc, ORIG, crvArc.GetRadius(), vBiPnt) ; if ( nSol == 0) return nullptr ; // porto i punti nel riferimento standard dell'arco for ( size_t i = 0 ; i < vBiPnt.size() ; ++ i) { vBiPnt[i].first.ToGlob( frIntr) ; vBiPnt[i].second.ToGlob( frIntr) ; } // se l'arco di tangenza ha deltaN, devo applicarlo in proporzione a questi punti if ( abs( crvArc.GetDeltaN()) > EPS_SMALL) { for ( size_t i = 0 ; i < vBiPnt.size() ; ++ i) { double dAngDeg ; if ( crvArc.CalcPointAngle( vBiPnt[i].second, dAngDeg)) vBiPnt[i].second += crvArc.GetNormVersor() * crvArc.GetDeltaN() * dAngDeg / crvArc.GetAngCenter() ; } } // elimino le soluzioni che non stanno sull'arco for ( int i = 1 ; i >= 0 ; -- i) { if ( nSol > i) { if ( ! crvArc.IsPointOn( vBiPnt[i].second)) { -- nSol ; for ( int j = i ; j < nSol ; ++ j) vBiPnt[j] = vBiPnt[j+1] ; } } } // se non sono rimaste soluzioni, esco if ( nSol == 0) return nullptr ; // scelgo la soluzione pių vicina al punto di riferimento int nIdOk = 0 ; double dMinSqDist = SQ_INFINITO ; for ( int i = 0 ; i < nSol ; ++ i) { double dSqDist = SqDist( vBiPnt[i].second, ptNear) ; if ( dSqDist < dMinSqDist) { dMinSqDist = dSqDist ; nIdOk = i ; } } // creo la linea PtrOwner pCrvLine( CreateBasicCurveLine()) ; if ( IsNull( pCrvLine)) return nullptr ; // costruisco la linea corrispondente alla soluzione scelta if ( ! pCrvLine->Set( vBiPnt[nIdOk].first, vBiPnt[nIdOk].second)) return nullptr ; // restituisco la linea return Release( pCrvLine) ; } //---------------------------------------------------------------------------- CurveLine* GetLinePointTgBezier( 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 tangente a questa approssimazione PtrOwner pCrvLine( GetBasicCurveLine( GetLinePointTgCurve( 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* GetLinePointTgCompo( 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 tangente alla curva elementare PtrOwner pCrvLtmp( GetBasicCurveLine( GetLinePointTgCurve( 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) ; }