de246fc3e7
- ricompilazione.
160 lines
6.2 KiB
C++
160 lines
6.2 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2013-2014
|
|
//----------------------------------------------------------------------------
|
|
// File : BiArcs.cpp Data : 30.07.14 Versione : 1.5g4
|
|
// Contenuto : Implementazione funzioni per calcolo biarchi.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 30.07.14 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "/EgtDev/Include/EGkAngle.h"
|
|
#include "/EgtDev/Include/EgkBiArcs.h"
|
|
#include "/EgtDev/Include/EgkCurveLine.h"
|
|
#include "/EgtDev/Include/EgkCurveComposite.h"
|
|
#include "/EgtDev/Include/EgkArcXxTgArc.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static ICurve* CalcJCurve( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg) ;
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg, double dU)
|
|
{
|
|
// calcolo la curva dove giacciono i punti di giunzione tra i due archi del biarco
|
|
PtrOwner<ICurve> pJCrv( CalcJCurve( ptP0, dDir0Deg, ptP1, dDir1Deg)) ;
|
|
if ( ! ::IsValid( pJCrv))
|
|
return nullptr ;
|
|
|
|
// limito il parametro nell'intervallo 0 - 1
|
|
if ( dU < 0)
|
|
dU = 0 ;
|
|
else if ( dU > 1)
|
|
dU = 1 ;
|
|
|
|
// recupero il punto di giunzione
|
|
Point3d ptJ ;
|
|
if ( ! pJCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptJ))
|
|
return nullptr ;
|
|
|
|
// preparo la curva composita per i biarchi
|
|
PtrOwner<ICurveComposite> pBiArc( CreateCurveComposite()) ;
|
|
if ( ! IsValid( pBiArc))
|
|
return nullptr ;
|
|
|
|
// calcolo la curva dal punto iniziale alla giunzione
|
|
if ( ! AreSamePointApprox( ptP0, ptJ)) {
|
|
ICurve* pCrv = GetArc2PD( ptP0, ptJ, dDir0Deg) ;
|
|
if ( pCrv == nullptr)
|
|
return nullptr ;
|
|
pBiArc->AddCurve( pCrv) ;
|
|
}
|
|
|
|
// calcolo la curva dalla giunzione al punto finale
|
|
if ( ! AreSamePointApprox( ptJ, ptP1)) {
|
|
// curva dal punto finale, direzione opposta alla giunzione
|
|
ICurve* pCrv = GetArc2PD( ptP1, ptJ, dDir1Deg + ANG_STRAIGHT) ;
|
|
if ( pCrv == nullptr)
|
|
return nullptr ;
|
|
// inverto la curva
|
|
pCrv->Invert() ;
|
|
pBiArc->AddCurve( pCrv) ;
|
|
}
|
|
|
|
// se il biarco non esiste
|
|
if ( pBiArc->GetCurveNumber() == 0)
|
|
return nullptr ;
|
|
|
|
return ::Release( pBiArc) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
GetBiArc( const PolyLine& PL, double dU0, double dDir0Deg, double dU1, double dDir1Deg)
|
|
{
|
|
// recupero i punti estremi della parte di interesse della polilinea
|
|
//double dU ;
|
|
//Point3d ptP, ptP0, ptP1 ;
|
|
//for ( bool bFound = PL.GetFirstUPoint( dU, &ptP) ;
|
|
// bFound ;
|
|
// bFound = PL.GetNextUPoint( dU, &ptP)) {
|
|
|
|
//}
|
|
// calcolo la curva dove giacciono i punti di giunzione tra i due archi del biarco
|
|
//PtrOwner<ICurve> pJCrv( CalcJCurve( ptP0, dDir0Deg, ptP1, dDir1Deg)) ;
|
|
//if ( ! ::IsValid( pJCrv))
|
|
// return nullptr ;
|
|
|
|
return nullptr ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static ICurve*
|
|
CalcJCurve( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir1Deg)
|
|
{
|
|
// se i due punti coincidono, non si può fare alcunché
|
|
if ( AreSamePointApprox( ptP0, ptP1))
|
|
return nullptr ;
|
|
|
|
// angolo di rotazione dalla prima direzione alla seconda -> angolo al centro
|
|
double dAngDeg = DiffAngle( dDir1Deg, dDir0Deg) ;
|
|
|
|
// se rotazione nulla, allora segmento di retta tra i due punti
|
|
if ( fabs( dAngDeg) < EPS_ANG_SMALL) {
|
|
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
|
if ( ! ::IsValid( pLine) || ! pLine->Set( ptP0, ptP1))
|
|
return nullptr ;
|
|
// inverto per avere parametrizzazione crescente allontanandosi da Dir0 e avvicinandosi a Dir1
|
|
pLine->Invert() ;
|
|
return ::Release( pLine) ;
|
|
}
|
|
|
|
// caso generico
|
|
Point3d ptMed = 0.5 * ( ptP0 + ptP1) ;
|
|
ptMed.z = ptP0.z ;
|
|
Vector3d vtDiff = ptMed - ptP0 ;
|
|
double dHalfDist = vtDiff.LenXY() ;
|
|
vtDiff /= dHalfDist ;
|
|
double dDirDiffDeg ;
|
|
vtDiff.ToSpherical( nullptr, nullptr, &dDirDiffDeg) ;
|
|
double dH = dHalfDist / tan( 0.5 * dAngDeg * DEGTORAD) ;
|
|
vtDiff.Rotate( Z_AX, 0, 1) ;
|
|
Point3d ptCen = ptMed + dH * vtDiff ;
|
|
Vector3d vtStart = ptP0 - ptCen ;
|
|
double dRad, dAngStart ;
|
|
vtStart.ToSpherical( &dRad, nullptr, &dAngStart) ;
|
|
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ;
|
|
if ( ! ::IsValid( pArc) || ! pArc->SetXY( ptCen, dRad, dAngStart, dAngDeg, ( ptP1.z - ptP0.z)))
|
|
return nullptr ;
|
|
double dDirStartDeg = dAngStart + ( dAngDeg > 0 ? ANG_RIGHT : - ANG_RIGHT) ;
|
|
// determinazione regione tra le curve estreme in cui contenere l'arco (tramite angoli su start)
|
|
// direzione iniziale arco rispetto a direzione P0->P1
|
|
double dDirStartRelDeg = DiffAngle( dDirStartDeg, dDirDiffDeg) ;
|
|
// direzione iniziale primo arco limite rispetto a direzione P0->P1
|
|
double dDir0RelDeg = DiffAngle( dDir0Deg, dDirDiffDeg) ;
|
|
// direzione iniziale secondo arco limite rispetto a direzione P0->P1 (dalla finale simmetrico e invert)
|
|
double dDir1RelDeg = - DiffAngle( dDir1Deg, dDirDiffDeg) ;
|
|
// nel caso di direzioni a 180deg si sceglie la più compatta
|
|
if ( fabs( fabs( dDir1RelDeg) - ANG_STRAIGHT) < EPS_SMALL)
|
|
dDir1RelDeg = ( dDir0RelDeg > 0 ? ANG_STRAIGHT : - ANG_STRAIGHT) ;
|
|
else if ( fabs( fabs( dDir0RelDeg) - ANG_STRAIGHT) < EPS_SMALL)
|
|
dDir0RelDeg = ( dDir1RelDeg > 0 ? ANG_STRAIGHT : - ANG_STRAIGHT) ;
|
|
// intervallo angolare ammissibile a partire da direzione iniziale primo arco ammissibile ( == Dir0)
|
|
double dDeltaAngDeg = - dDir0RelDeg + dDir1RelDeg ;
|
|
// se non è nella regione, prendo l'altra parte di arco
|
|
if ( ! AngleInSpan( dDirStartRelDeg, dDir0RelDeg, dDeltaAngDeg))
|
|
pArc->ToAdditional() ;
|
|
// inverto per avere parametrizzazione crescente allontanandosi da Dir0 e avvicinandosi a Dir1
|
|
pArc->Invert() ;
|
|
return ::Release( pArc) ;
|
|
}
|