4410a83631
- piccole modifiche per nuovo Set di PtrOwner.
203 lines
7.5 KiB
C++
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) ;
|
|
} |