EgtGeomKernel 1.5g4 :
- aggiunto calcolo Biarchi da condizioni tipo Hermite - aggiunta AngleInSpan - migliorata gestione riferimento di gruppi - corrette trasformazioni GeoVector3d per punto base.
This commit is contained in:
+139
@@ -0,0 +1,139 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// 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 false ;
|
||||
|
||||
// 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 false ;
|
||||
|
||||
// preparo la curva composita per i biarchi
|
||||
PtrOwner<ICurveComposite> pBiArc( CreateCurveComposite()) ;
|
||||
if ( ! IsValid( pBiArc))
|
||||
return false ;
|
||||
|
||||
// calcolo la curva dal punto iniziale alla giunzione
|
||||
if ( ! AreSamePointApprox( ptP0, ptJ)) {
|
||||
ICurve* pCrv = GetArc2PD( ptP0, ptJ, dDir0Deg) ;
|
||||
if ( pCrv == nullptr)
|
||||
return false ;
|
||||
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 false ;
|
||||
// inverto la curva
|
||||
pCrv->Invert() ;
|
||||
pBiArc->AddCurve( pCrv) ;
|
||||
}
|
||||
|
||||
// se il biarco non esiste
|
||||
if ( pBiArc->GetCurveNumber() == 0)
|
||||
return nullptr ;
|
||||
|
||||
return ::Release( pBiArc) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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) ;
|
||||
}
|
||||
Reference in New Issue
Block a user