Files
EgtGeomKernel/LinePntTgCurve.cpp
T
DarioS 4410a83631 EgtGeomKernel :
- piccole modifiche per nuovo Set di PtrOwner.
2023-03-27 18:41:16 +02:00

203 lines
7.5 KiB
C++

//----------------------------------------------------------------------------
// 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<CurveLine> 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<CurveLine> 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<CurveComposite> pCrvCompo( CreateBasicCurveComposite()) ;
if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyArc( PA))
return nullptr ;
// calcolo la linea tangente a questa approssimazione
PtrOwner<CurveLine> 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<CurveLine> pCrvLine ;
for ( const ICurve* pCrv = crvCompo.GetFirstCurve() ;
pCrv != nullptr ;
pCrv = crvCompo.GetNextCurve()) {
// recupero la linea tangente alla curva elementare
PtrOwner<CurveLine> 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) ;
}