EgtGeomKernel 1.6c2 :

- aggiunte funzioni per circonferenze e archi tangenti.
This commit is contained in:
Dario Sassi
2015-03-16 07:38:43 +00:00
parent 3dd5d63a65
commit 6c14e51ef6
16 changed files with 1054 additions and 317 deletions
+178
View File
@@ -0,0 +1,178 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : ArcCenTgCurvePnt.cpp Data : 15.03.15 Versione : 1.6c2
// Contenuto : Implementazione funzioni per calcolo arco dati centro,
// tangente a curva e punto vicino a finale.
//
//
// Modifiche : 15.03.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CurveBezier.h"
#include "CurveComposite.h"
#include "CreateCurveAux.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EgkArcCenTgCurvePnt.h"
#include "/EgtDev/Include/EgkArcSpecial.h"
#include "/EgtDev/Include/EgkCircleCenTgCurve.h"
#include "/EgtDev/Include/EgkDistPointCurve.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
//----------------------------------------------------------------------------
static CurveArc* GetArcCenTgCurvePnt( const Point3d& ptCen, const ICurve& cCrv, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN, Point3d* pPtTg) ;
static CurveArc* GetArcCenTgLinePnt( const Point3d& ptCen, const CurveLine& crvLine, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN, Point3d* pPtTg) ;
static CurveArc* GetArcCenTgArcPnt( const Point3d& ptCen, const CurveArc& crvArc, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN, Point3d* pPtTg) ;
static CurveArc* GetArcCenTgBezierPnt( const Point3d& ptCen, const CurveBezier& crvBezier, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN, Point3d* pPtTg) ;
static CurveArc* GetArcCenTgCompoPnt( const Point3d& ptCen, const CurveComposite& crvCompo, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN, Point3d* pPtTg) ;
//----------------------------------------------------------------------------
ICurveArc*
GetArcCenTgCurvePnt( const Point3d& pCen, const ICurve& cCrv, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN)
{
return GetArcCenTgCurvePnt( pCen, cCrv, ptNearStart, ptNearEnd, vtN, nullptr) ;
}
//----------------------------------------------------------------------------
CurveArc*
GetArcCenTgCurvePnt( const Point3d& ptCen, const ICurve& cCrv, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN, Point3d* pPtTg)
{
// verifica dei parametri
if ( &ptCen == nullptr || &cCrv == nullptr || &ptNearStart == nullptr ||
&ptNearEnd == nullptr || &vtN == nullptr)
return nullptr ;
// eseguo calcoli a seconda della curva tg
switch ( cCrv.GetType()) {
case CRV_LINE :
{ const CurveLine& crvLine = *GetBasicCurveLine( &cCrv) ;
return GetArcCenTgLinePnt( ptCen, crvLine, ptNearStart, ptNearEnd, vtN, pPtTg) ; }
case CRV_ARC :
{ const CurveArc& crvArc = *GetBasicCurveArc( &cCrv) ;
return GetArcCenTgArcPnt( ptCen, crvArc, ptNearStart, ptNearEnd, vtN, pPtTg) ; }
case CRV_BEZ :
{ const CurveBezier& crvBezier = *GetBasicCurveBezier( &cCrv) ;
return GetArcCenTgBezierPnt( ptCen, crvBezier, ptNearStart, ptNearEnd, vtN, pPtTg) ; }
case CRV_COMPO :
{ const CurveComposite& crvCompo = *GetBasicCurveComposite( &cCrv) ;
return GetArcCenTgCompoPnt( ptCen, crvCompo, ptNearStart, ptNearEnd, vtN, pPtTg) ; }
default :
return nullptr ;
}
}
//----------------------------------------------------------------------------
CurveArc* GetArcCenTgLinePnt( const Point3d& ptCen, const CurveLine& crvLine, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN, Point3d* pPtTg)
{
// ricavo circonferenza con medesimo centro e tangente alla stessa linea
Point3d ptTg ;
PtrOwner<ICurveArc> pCirc( GetCircleCenTgCurve( ptCen, vtN, crvLine, ptNearStart, &ptTg)) ;
if ( IsNull( pCirc))
return nullptr ;
// costruisco l'arco voluto con i dati di quuesta circonferenza
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
if ( pArc->SetC2PN( ptCen, ptTg, ptNearEnd, vtN)) {
if ( pPtTg != nullptr)
*pPtTg = ptTg ;
return Release( pArc) ;
}
else
return nullptr ;
}
//----------------------------------------------------------------------------
CurveArc* GetArcCenTgArcPnt( const Point3d& ptCen, const CurveArc& crvArc, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN, Point3d* pPtTg)
{
// ricavo circonferenza con medesimo centro e tangente allo stesso arco
Point3d ptTg ;
PtrOwner<ICurveArc> pCirc( GetCircleCenTgCurve( ptCen, vtN, crvArc, ptNearStart, &ptTg)) ;
if ( IsNull( pCirc))
return nullptr ;
// costruisco l'arco voluto con i dati di quuesta circonferenza
PtrOwner<CurveArc> pArc( CreateBasicCurveArc()) ;
if ( pArc->SetC2PN( ptCen, ptTg, ptNearEnd, vtN)) {
if ( pPtTg != nullptr)
*pPtTg = ptTg ;
return Release( pArc) ;
}
else
return nullptr ;
}
//----------------------------------------------------------------------------
CurveArc*
GetArcCenTgBezierPnt( const Point3d& ptCen, const CurveBezier& crvBezier, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN, Point3d* pPtTg)
{
// 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 circonferenza tangente a questa approssimazione
Point3d ptTg ;
PtrOwner<CurveArc> pCrvArc( GetBasicCurveArc( GetArcCenTgCurvePnt( ptCen, *pCrvCompo, ptNearStart,
ptNearEnd, vtN, &ptTg))) ;
if ( IsNull( pCrvArc))
return nullptr ;
// porto il punto di tangenza della circonferenza esattamente sulla curva di Bezier
DistPointCurve dstPtCurve( ptTg, crvBezier) ;
Point3d ptTg2 ;
int nFlag ;
if ( ! dstPtCurve.GetMinDistPoint( 0, ptTg2, nFlag))
return nullptr ;
// calcolo il nuovo arco
if ( ! pCrvArc->SetC2PN( ptCen, ptTg2, ptNearEnd, vtN))
return nullptr ;
// se richiesto, assegno il punto di tg
if ( pPtTg != nullptr)
*pPtTg = ptTg2 ;
// restituisco la circonferenza
return Release( pCrvArc) ;
}
//----------------------------------------------------------------------------
CurveArc* GetArcCenTgCompoPnt( const Point3d& ptCen, const CurveComposite& crvCompo, const Point3d& ptNearStart,
const Point3d& ptNearEnd, const Vector3d& vtN, Point3d* pPtTg)
{
// ciclo sulla curva composita
double dMinSqDist = INFINITO * INFINITO ;
PtrOwner<CurveArc> pCrvArc ;
for ( const ICurve* pCrv = crvCompo.GetFirstCurve() ;
pCrv != nullptr ;
pCrv = crvCompo.GetNextCurve()) {
// recupero la circonferenza tangente alla curva elementare
Point3d ptTg ;
PtrOwner<CurveArc> pCrvAtmp( GetBasicCurveArc( GetArcCenTgCurvePnt( ptCen, *pCrv, ptNearStart,
ptNearEnd, vtN, &ptTg))) ;
if ( IsNull( pCrvAtmp))
continue ;
// verifico se è la più vicina al punto desiderato
double dSqDist = SqDist( ptNearStart, ptTg) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
pCrvArc.Set( Release( pCrvAtmp)) ;
if ( pPtTg != nullptr)
*pPtTg = ptTg ;
}
}
return Release( pCrvArc) ;
}
+347
View File
@@ -0,0 +1,347 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : ArcPntDirTgCurve.cpp Data : 13.03.15 Versione : 1.6c2
// Contenuto : Implementazione funzioni per calcolo arco dato punto iniziale
// direzione e tangente a curva.
//
//
// Modifiche : 13.03.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CurveBezier.h"
#include "CurveComposite.h"
#include "CreateCurveAux.h"
#include "DistPointLine.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EgkArcPntDirTgCurve.h"
#include "/EgtDev/Include/EgkDistPointCurve.h"
#include "/EgtDev/Include/EgkArcSpecial.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
//----------------------------------------------------------------------------
static ICurve* GetArcPntDirTgCurve( const Point3d& ptP, const Vector3d& vtDir, const ICurve& cCrv,
const Point3d& ptNear, const Vector3d& vtN, Point3d* pPtTg) ;
static ICurve* GetArcPntDirTgLine( const Point3d& ptP, const Vector3d& vtDir, const CurveLine& crvLine,
const Point3d& ptNear, const Vector3d& vtN, Point3d* pPtTg) ;
static ICurve* GetArcPntDirTgArc( const Point3d& ptP, const Vector3d& vtDir, const CurveArc& crvArc,
const Point3d& ptNear, const Vector3d& vtN, Point3d* pPtTg) ;
static ICurve* GetArcPntDirTgBezier( const Point3d& ptP, const Vector3d& vtDir, const CurveBezier& crvBezier,
const Point3d& ptNear, const Vector3d& vtN, Point3d* pPtTg) ;
static ICurve* GetArcPntDirTgCompo( const Point3d& ptP, const Vector3d& vtDir, const CurveComposite& crvCompo,
const Point3d& ptNear, const Vector3d& vtN, Point3d* pPtTg) ;
//----------------------------------------------------------------------------
ICurve*
GetArcPntDirTgCurve( const Point3d& ptP, const Vector3d& vtDir, const ICurve& cCrv,
const Point3d& ptNear, const Vector3d& vtN)
{
return GetArcPntDirTgCurve( ptP, vtDir, cCrv, ptNear, vtN, nullptr) ;
}
//----------------------------------------------------------------------------
ICurve*
GetArcPntDirTgCurve( const Point3d& ptP, const Vector3d& vtDir, const ICurve& cCrv,
const Point3d& ptNear, const Vector3d& vtN, Point3d* pPtTg)
{
// verifica dei parametri
if ( &ptP == nullptr || &vtDir == nullptr || &vtN == nullptr || &cCrv == nullptr || &ptNear == nullptr)
return nullptr ;
// eseguo calcoli a seconda della curva tg
switch ( cCrv.GetType()) {
case CRV_LINE :
{ const CurveLine& crvLine = *GetBasicCurveLine( &cCrv) ;
return GetArcPntDirTgLine( ptP, vtDir, crvLine, ptNear, vtN, pPtTg) ; }
case CRV_ARC :
{ const CurveArc& crvArc = *GetBasicCurveArc( &cCrv) ;
return GetArcPntDirTgArc( ptP, vtDir, crvArc, ptNear, vtN, pPtTg) ; }
case CRV_BEZ :
{ const CurveBezier& crvBezier = *GetBasicCurveBezier( &cCrv) ;
return GetArcPntDirTgBezier( ptP, vtDir, crvBezier, ptNear, vtN, pPtTg) ; }
case CRV_COMPO :
{ const CurveComposite& crvCompo = *GetBasicCurveComposite( &cCrv) ;
return GetArcPntDirTgCompo( ptP, vtDir, crvCompo, ptNear, vtN, pPtTg) ; }
default :
return nullptr ;
}
}
//----------------------------------------------------------------------------
ICurve*
GetArcPntDirTgLine( const Point3d& ptP, const Vector3d& vtDir, const CurveLine& crvLine,
const Point3d& ptNear, const Vector3d& vtN, Point3d* pPtTg)
{
// calcolo il riferimento intrinseco dell'arco da creare (DirNorm->Z e DirStart->X)
Frame3d frIntr ;
if ( ! frIntr.Set( ptP, vtN, vtDir))
return nullptr ;
// porto la linea di tangenza in questo riferimento
CurveLine crvLineL = crvLine ;
crvLineL.ToLoc( frIntr) ;
// inclinazione della linea
Point3d ptP1 = crvLineL.GetStart() ;
Point3d ptP2 = crvLineL.GetEnd() ;
// se linea perpendicolare al piano XY
if ( AreSamePointXYApprox( ptP1, ptP2)) {
Point3d ptTg( ptP1.x, ptP1.y, 0) ;
PtrOwner<ICurve> pCrv( GetArc2PD( ORIG, ptTg, 0)) ;
if ( ! IsNull( pCrv) && pCrv->ToGlob( frIntr)) {
if ( pPtTg != nullptr) {
ptTg.ToGlob( frIntr) ;
*pPtTg = ptTg ;
}
return Release( pCrv) ;
}
else
return nullptr ;
}
// se linea parallela all'asse X
else if ( fabs( ptP2.y - ptP1.y) < EPS_SMALL) {
Point3d ptTg( 0, ptP1.y, ptP1.z + ( 0 - ptP1.x) * ( ptP2.z - ptP1.z) / ( ptP2.x - ptP1.x)) ;
PtrOwner<ICurve> pCrv( GetArc2PD( ORIG, ptTg, 0)) ;
if ( ! IsNull( pCrv) && pCrv->ToGlob( frIntr)) {
if ( pPtTg != nullptr) {
ptTg.ToGlob( frIntr) ;
*pPtTg = ptTg ;
}
return Release( pCrv) ;
}
else
return nullptr ;
}
// altrimenti linea inclinata
else {
// intersezione con asse X (linea di direzione nel riferimento intrinseco)
double dCoeff = ( 0 - ptP1.y) / ( ptP2.y - ptP1.y) ;
Point3d ptInt( ptP1.x + dCoeff * ( ptP2.x - ptP1.x), 0, ptP1.z + dCoeff * ( ptP2.z - ptP1.z)) ;
// punto distante da intersezione in XY come intersezione da origine
double dLenXY = fabs( ptInt.x) ;
Vector3d vtDir = ptP2 - ptP1 ;
vtDir.Normalize() ;
double dLen = dLenXY * vtDir.Len() / vtDir.LenXY() ;
// con segno +
Point3d PtTg1 = ptInt + dLen * vtDir ;
PtrOwner<ICurve> pCrv1( GetArc2PD( ORIG, PtTg1, 0)) ;
bool bOk1 = ( ! IsNull( pCrv1)) ;
// porto l'arco nel riferimento locale
bOk1 = bOk1 && pCrv1->ToGlob( frIntr) ;
// recupero il punto finale (è quello di tangenza)
Point3d ptEnd1 ;
bOk1 = bOk1 && pCrv1->GetEndPoint( ptEnd1) ;
// verifico se il punto di tangenza sta sul segmento
bOk1 = bOk1 && crvLine.IsPointOn( ptEnd1) ;
// con segno -
Point3d PtTg2 = ptInt - dLen * vtDir ;
PtrOwner<ICurve> pCrv2( GetArc2PD( ORIG, PtTg2, 0)) ;
bool bOk2 = ( ! IsNull( pCrv2)) ;
// porto l'arco nel riferimento locale
bOk2 = bOk2 && pCrv2->ToGlob( frIntr) ;
// recupero il punto finale (è quello di tangenza)
Point3d ptEnd2 ;
bOk2 = bOk2 && pCrv2->GetEndPoint( ptEnd2) ;
// verifico se il punto di tangenza sta sul segmento
bOk2 = bOk2 && crvLine.IsPointOn( ptEnd2) ;
// se due soluzioni, verifico quale ha il punto di tg più vicino al richiesto
if ( bOk1 && bOk2) {
if ( SqDist( ptEnd1, ptNear) <= SqDist( ptEnd2, ptNear))
bOk2 = false ;
else
bOk1 = false ;
}
// restituisco la soluzione
if ( bOk1) {
if ( pPtTg != nullptr)
*pPtTg = ptEnd1 ;
return Release( pCrv1) ;
}
else if ( bOk2) {
if ( pPtTg != nullptr)
*pPtTg = ptEnd2 ;
return Release( pCrv2) ;
}
else
return nullptr ;
}
}
//----------------------------------------------------------------------------
ICurve*
GetArcPntDirTgArc( const Point3d& ptP, const Vector3d& vtDir, const CurveArc& crvArc,
const Point3d& ptNear, const Vector3d& vtN, Point3d* pPtTg)
{
// verifico che la normale della circonferenza coincida con quella dell'arco di tg
if ( ! AreSameOrOppositeVectorApprox( vtN, crvArc.GetNormVersor()))
return nullptr ;
// calcolo il riferimento intrinseco dell'arco da creare (DirNorm->Z e DirStart->X)
Frame3d frIntr ;
if ( ! frIntr.Set( ptP, vtN, vtDir))
return nullptr ;
// porto l'arco di tangenza in questo riferimento
CurveArc crvArcL = crvArc ;
crvArcL.ToLoc( frIntr) ;
// versore ortogonale alla direzione iniziale (ora si lavora nel piano XY locale)
Vector3d vtOrtho = Y_AX ;
// angolo direzione iniziale
bool bOutSide = ( DistXY( ORIG, crvArcL.GetCenter()) >= crvArcL.GetRadius()) ;
// calcolo arco spostando il punto iniziale di + raggio in direzione ortogonale
Point3d ptP1 = ORIG + vtOrtho * crvArcL.GetRadius() ;
PtrOwner<ICurve> pCrv1( GetArc2PD( ptP1, crvArcL.GetCenter(), ( bOutSide ? 0 : 180))) ;
bool bOk1 = ( ! IsNull( pCrv1)) ;
// compenso lo spostamento ( più -> offset a destra)
if ( bOk1) {
double dOffset = ( bOutSide ? crvArcL.GetRadius() : - crvArcL.GetRadius()) ;
if ( pCrv1->GetType() == CRV_ARC)
bOk1 = (dynamic_cast<CurveArc*>(Get(pCrv1)))->ExtendedOffset( dOffset) ;
else
bOk1 = pCrv1->SimpleOffset( dOffset) ;
}
// porto l'arco nel riferimento locale
bOk1 = bOk1 && pCrv1->ToGlob( frIntr) ;
// recupero il punto finale (è quello di tangenza)
Point3d ptEnd1 ;
bOk1 = bOk1 && pCrv1->GetEndPoint( ptEnd1) ;
// se l'arco di tangenza ha deltaN, devo considerarne quota parte
if ( bOk1 && fabs( crvArc.GetDeltaN()) > EPS_SMALL) {
double dAngDeg ;
if ( crvArc.CalcPointAngle( ptEnd1, dAngDeg)) {
ptEnd1 += crvArc.GetNormVersor() * crvArc.GetDeltaN() * dAngDeg / crvArc.GetAngCenter() ;
bOk1 = bOk1 && pCrv1->ModifyEnd( ptEnd1) ;
}
else
bOk1 = false ;
}
// verifico se il punto di tangenza sta sull'arco
else
bOk1 = bOk1 && crvArc.IsPointOn( ptEnd1) ;
// calcolo arco spostando il punto iniziale di - raggio in direzione ortogonale
Point3d ptP2 = ORIG - vtOrtho * crvArcL.GetRadius() ;
PtrOwner<ICurve> pCrv2( GetArc2PD( ptP2, crvArcL.GetCenter(), ( bOutSide ? 0 : 180))) ;
bool bOk2 = ( ! IsNull( pCrv2)) ;
// compenso lo spostamento ( meno -> offset a sinistra)
if ( bOk2) {
double dOffset = ( bOutSide ? - crvArcL.GetRadius() : crvArcL.GetRadius()) ;
if ( pCrv2->GetType() == CRV_ARC)
bOk2 = (dynamic_cast<CurveArc*>(Get(pCrv2)))->ExtendedOffset( dOffset) ;
else
bOk2 = pCrv2->SimpleOffset( dOffset) ;
}
// porto l'arco nel riferimento locale
bOk2 = bOk2 && pCrv2->ToGlob( frIntr) ;
// recupero il punto finale (è quello di tangenza)
Point3d ptEnd2 ;
bOk2 = bOk2 && pCrv2->GetEndPoint( ptEnd2) ;
// se l'arco di tangenza ha deltaN, devo considerarne quota parte
if ( bOk2 && fabs( crvArc.GetDeltaN()) > EPS_SMALL) {
double dAngDeg ;
if ( crvArc.CalcPointAngle( ptEnd2, dAngDeg)) {
ptEnd2 += crvArc.GetNormVersor() * crvArc.GetDeltaN() * dAngDeg / crvArc.GetAngCenter() ;
bOk2 = bOk2 && pCrv2->ModifyEnd( ptEnd2) ;
}
else
bOk2 = false ;
}
// verifico se il punto di tangenza sta sull'arco
else
bOk2 = bOk2 && crvArc.IsPointOn( ptEnd2) ;
// se due soluzioni, verifico quale ha il punto di tg più vicino al richiesto
if ( bOk1 && bOk2) {
if ( SqDist( ptEnd1, ptNear) <= SqDist( ptEnd2, ptNear))
bOk2 = false ;
else
bOk1 = false ;
}
// restituisco la soluzione
if ( bOk1) {
if ( pPtTg != nullptr)
*pPtTg = ptEnd1 ;
return Release( pCrv1) ;
}
else if ( bOk2) {
if ( pPtTg != nullptr)
*pPtTg = ptEnd2 ;
return Release( pCrv2) ;
}
else
return nullptr ;
}
//----------------------------------------------------------------------------
ICurve*
GetArcPntDirTgBezier( const Point3d& ptP, const Vector3d& vtDir, const CurveBezier& crvBezier,
const Point3d& ptNear, const Vector3d& vtN, Point3d* pPtTg)
{
// 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 circonferenza tangente a questa approssimazione
Point3d ptTg ;
PtrOwner<ICurve> pCrv( GetCurve( GetArcPntDirTgCurve( ptP, vtDir, *pCrvCompo, ptNear, vtN, &ptTg))) ;
if ( IsNull( pCrv))
return nullptr ;
// porto il punto di tangenza della circonferenza esattamente sulla curva di Bezier
DistPointCurve dstPtCurve( ptTg, crvBezier) ;
Point3d ptTg2 ;
int nFlag ;
if ( ! dstPtCurve.GetMinDistPoint( 0, ptTg2, nFlag))
return nullptr ;
// calcolo il nuovo arco
pCrv.Set( GetArc2PVN( ptP, ptTg2, vtDir, vtN)) ;
if ( IsNull( pCrv))
return nullptr ;
// se richiesto, assegno il punto di tg
if ( pPtTg != nullptr)
*pPtTg = ptTg2 ;
// restituisco la circonferenza
return Release( pCrv) ;
}
//----------------------------------------------------------------------------
ICurve*
GetArcPntDirTgCompo( const Point3d& ptP, const Vector3d& vtDir, const CurveComposite& crvCompo,
const Point3d& ptNear, const Vector3d& vtN, Point3d* pPtTg)
{
// ciclo sulla curva composita
double dMinSqDist = INFINITO * INFINITO ;
PtrOwner<ICurve> pCrvNew ;
for ( const ICurve* pCrv = crvCompo.GetFirstCurve() ;
pCrv != nullptr ;
pCrv = crvCompo.GetNextCurve()) {
// recupero la circonferenza tangente alla curva elementare
Point3d ptTg ;
PtrOwner<ICurve> pCrvTmp( GetCurve( GetArcPntDirTgCurve( ptP, vtDir, *pCrv, ptNear, vtN, &ptTg))) ;
if ( IsNull( pCrvTmp))
continue ;
// verifico se è la più vicina al punto desiderato
double dSqDist = SqDist( ptNear, ptTg) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
pCrvNew.Set( Release( pCrvTmp)) ;
if ( pPtTg != nullptr)
*pPtTg = ptTg ;
}
}
return Release( pCrvNew) ;
}
+133
View File
@@ -0,0 +1,133 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2015
//----------------------------------------------------------------------------
// File : ArcSpecial.cpp Data : 15.03.15 Versione : 1.6c2
// Contenuto : Implementazione funzioni per calcoli speciali archi.
//
//
//
// Modifiche : 12.06.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CreateCurveAux.h"
#include "/EgtDev/Include/EgkCurveLine.h"
#include "/EgtDev/Include/EgkArcSpecial.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
// Come la CurveArc::Set2PD, ma se raggio infinito restituisce una retta
//----------------------------------------------------------------------------
ICurve*
GetArc2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStartDeg)
{
// creo l'oggetto arco
ICurveArc* pArc = CreateCurveArc() ;
if ( pArc == nullptr)
return nullptr ;
// inizializzo il puntatore a curva con l'arco
PtrOwner<ICurve> pCrv( pArc) ;
// calcolo l'arco, se ok lo restituisco ed esco
if ( pArc->Set2PD( ptStart, ptEnd, dDirStartDeg))
return Release( pCrv) ;
// calcolo arco non riuscito, verifico se retta va bene
Vector3d vtDiff = ptEnd - ptStart ;
vtDiff.z = 0 ;
Vector3d vtDir = FromPolar( 1, dDirStartDeg) ;
// verifico se i punti sono allineati con la direzione e nel giusto verso
if ( fabs( CrossXY( vtDiff, vtDir)) < EPS_SMALL && ScalarXY( vtDiff, vtDir) > EPS_SMALL) {
// creo l'oggetto retta
ICurveLine* pLine = CreateCurveLine() ;
if ( pLine == nullptr)
return nullptr ;
// inizializzo il puntatore a curva con la retta
pCrv.Set( pLine) ;
// calcolo retta, se ok la restituisco ed esco
if ( pLine->Set( ptStart, ptEnd))
return Release( pCrv) ;
}
return nullptr ;
}
//----------------------------------------------------------------------------
// Come la CurveArc::Set2PVN, ma se raggio infinito restituisce una retta
//----------------------------------------------------------------------------
ICurve*
GetArc2PVN( const Point3d& ptStart, const Point3d& ptEnd, const Vector3d& vtDirS, const Vector3d& vtN)
{
// creo l'oggetto arco
ICurveArc* pArc = CreateCurveArc() ;
if ( pArc == nullptr)
return nullptr ;
// inizializzo il puntatore a curva con l'arco
PtrOwner<ICurve> pCrv( pArc) ;
// calcolo l'arco, se ok lo restituisco ed esco
if ( pArc->Set2PVN( ptStart, ptEnd, vtDirS, vtN))
return Release( pCrv) ;
// calcolo arco non riuscito, verifico se retta va bene
Vector3d vtDiff = ptEnd - ptStart ;
vtDiff.z = 0 ;
// verifico se i punti sono allineati con la direzione e nel giusto verso
if ( fabs( CrossXY( vtDiff, vtDirS)) < EPS_SMALL && ScalarXY( vtDiff, vtDirS) > EPS_SMALL) {
// creo l'oggetto retta
ICurveLine* pLine = CreateCurveLine() ;
if ( pLine == nullptr)
return nullptr ;
// inizializzo il puntatore a curva con la retta
pCrv.Set( pLine) ;
// calcolo retta, se ok la restituisco ed esco
if ( pLine->Set( ptStart, ptEnd))
return Release( pCrv) ;
}
return nullptr ;
}
//----------------------------------------------------------------------------
// Come la CurveArc::Set3P, ma se raggio infinito restituisce una retta
//----------------------------------------------------------------------------
ICurve*
GetArc3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& ptEnd, bool bCirc)
{
// creo l'oggetto arco
ICurveArc* pArc = CreateCurveArc() ;
if ( pArc == nullptr)
return nullptr ;
// inizializzo il puntatore a curva con l'arco
PtrOwner<ICurve> pCrv( pArc) ;
// calcolo l'arco, se ok lo restituisco ed esco
if ( pArc->Set3P( ptStart, ptOther, ptEnd, bCirc))
return Release( pCrv) ;
// se era richiesta una circonferenza, errore
if ( bCirc)
return nullptr ;
// calcolo arco non riuscito, se i punti sono allineati nel giusto verso per essere una retta
// verifico se i punti sono allineati nel giusto verso
if ( ( ptOther - ptStart) * ( ptEnd - ptOther) > EPS_ZERO) {
// creo l'oggetto retta
ICurveLine* pLine = CreateCurveLine() ;
if ( pLine == nullptr)
return nullptr ;
// inizializzo il puntatore a curva con la retta
pCrv.Set( pLine) ;
// calcolo retta, se ok la restituisco ed esco
if ( pLine->Set( ptStart, ptEnd))
return Release( pCrv) ;
}
return nullptr ;
}
-291
View File
@@ -1,291 +0,0 @@
//----------------------------------------------------------------------------
// EgalTech 2013-2014
//----------------------------------------------------------------------------
// File : ArcXxTgArc.cpp Data : 12.06.14 Versione : 1.5f4
// Contenuto : Implementazione funzioni per calcolo archi tangenti a archi.
//
//
//
// Modifiche : 12.06.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "/EgtDev/Include/EgkCurveLine.h"
#include "/EgtDev/Include/EgkArcXxTgArc.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
static int CalcCircleCenTgCircle( const Point3d& ptC, const Point3d& ptCen, double dRad, BIPNTVECTOR& vCenPtg) ;
//----------------------------------------------------------------------------
ICurveArc*
GetCircleCenTgArc( const Point3d& ptCen, const ICurveArc& 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 ptCLoc = ptCen ;
ptCLoc.ToLoc( frIntr) ;
// calcolo le circonferenze tangenti alla circonferenza
BIPNTVECTOR vCenPtg( 2) ;
int nSol = CalcCircleCenTgCircle( ptCLoc, ORIG, crvArc.GetRadius(), vCenPtg) ;
if ( nSol == 0)
return nullptr ;
// porto i punti nel riferimento standard dell'arco
for ( size_t i = 0 ; i < vCenPtg.size() ; ++ i) {
vCenPtg[i].first.ToGlob( frIntr) ;
vCenPtg[i].second.ToGlob( frIntr) ;
}
// elimino le soluzioni che non stanno sull'arco
for ( int i = 1 ; i >= 0 ; -- i) {
if ( nSol > i) {
if ( ! crvArc.IsPointOn( vCenPtg[i].second)) {
-- nSol ;
for ( int j = i ; j < nSol ; ++ j)
vCenPtg[j] = vCenPtg[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 = INFINITO * INFINITO ;
for ( int i = 0 ; i < nSol ; ++ i) {
double dSqDist = SqDist( vCenPtg[i].second, ptNear) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
nIdOk = i ;
}
}
// creo l'arco
PtrOwner<ICurveArc> pCrvArc( CreateCurveArc()) ;
if ( IsNull( pCrvArc))
return nullptr ;
// costruisco la circonferenza corrispondente alla soluzione scelta
double dRad = DistXY( vCenPtg[nIdOk].first, vCenPtg[nIdOk].second) ;
if ( pCrvArc->Set( vCenPtg[nIdOk].first, crvArc.GetNormVersor(), dRad))
return Release( pCrvArc) ;
else
return nullptr ;
}
//----------------------------------------------------------------------------
ICurveArc*
GetArcCenTgArcPnt( const Point3d& ptCen, const ICurveArc& crvArc,
const Point3d& ptNearTg, const Point3d& ptNearEnd)
{
// 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 centro nel riferimento intrinseco
Point3d ptCLoc = ptCen ;
ptCLoc.ToLoc( frIntr) ;
// calcolo le circonferenze tangenti alla circonferenza
BIPNTVECTOR vCenPtg( 2) ;
int nSol = CalcCircleCenTgCircle( ptCLoc, ORIG, crvArc.GetRadius(), vCenPtg) ;
if ( nSol == 0)
return nullptr ;
// porto i punti nel riferimento standard dell'arco
for ( size_t i = 0 ; i < vCenPtg.size() ; ++ i) {
vCenPtg[i].first.ToGlob( frIntr) ;
vCenPtg[i].second.ToGlob( frIntr) ;
}
// elimino le soluzioni che non stanno sull'arco
for ( int i = 1 ; i >= 0 ; -- i) {
if ( nSol > i) {
if ( ! crvArc.IsPointOn( vCenPtg[i].second)) {
-- nSol ;
for ( int j = i ; j < nSol ; ++ j)
vCenPtg[j] = vCenPtg[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 = INFINITO * INFINITO ;
for ( int i = 0 ; i < nSol ; ++ i) {
double dSqDist = SqDist( vCenPtg[i].second, ptNearTg) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
nIdOk = i ;
}
}
// creo l'arco
PtrOwner<ICurveArc> pCrvArc( CreateCurveArc()) ;
if ( IsNull( pCrvArc))
return nullptr ;
// posso costruire l'arco solo nel riferimento intrinseco e poi portarlo in quello standard
vCenPtg[nIdOk].first.ToLoc( frIntr) ;
vCenPtg[nIdOk].second.ToLoc( frIntr) ;
Point3d ptNEloc = ptNearEnd ;
ptNEloc.ToLoc( frIntr) ;
if ( pCrvArc->SetC2P( vCenPtg[nIdOk].first, vCenPtg[nIdOk].second, ptNEloc) &&
pCrvArc->ToGlob( frIntr))
return Release( pCrvArc) ;
else
return nullptr ;
}
//----------------------------------------------------------------------------
// Come la CurveArc::Set2PD, ma se raggio infinito restituisce una retta
//----------------------------------------------------------------------------
ICurve*
GetArc2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStartDeg)
{
// creo l'oggetto arco
ICurveArc* pArc = CreateCurveArc() ;
if ( pArc == nullptr)
return nullptr ;
// inizializzo il puntatore a curva con l'arco
PtrOwner<ICurve> pCrv( pArc) ;
// calcolo l'arco, se ok lo restituisco ed esco
if ( pArc->Set2PD( ptStart, ptEnd, dDirStartDeg))
return Release( pCrv) ;
// calcolo arco non riuscito, verifico se retta va bene
Vector3d vtDiff = ptEnd - ptStart ;
vtDiff.z = 0 ;
Vector3d vtDir = FromPolar( 1, dDirStartDeg) ;
// verifico se i punti sono allineati con la direzione e nel giusto verso
if ( fabs( CrossXY( vtDiff, vtDir)) < EPS_SMALL && ScalarXY( vtDiff, vtDir) > EPS_SMALL) {
// creo l'oggetto retta
ICurveLine* pLine = CreateCurveLine() ;
if ( pLine == nullptr)
return nullptr ;
// inizializzo il puntatore a curva con la retta
pCrv.Set( pLine) ;
// calcolo retta, se ok la restituisco ed esco
if ( pLine->Set( ptStart, ptEnd))
return Release( pCrv) ;
}
return nullptr ;
}
//----------------------------------------------------------------------------
ICurve*
GetArcPntDirTgArc( const Point3d& ptP, double dDirStartDeg, const ICurveArc& crvArc, const Point3d& ptNearTg)
{
// se il raggio è praticamente nullo
if ( crvArc.GetRadius() < EPS_SMALL) {
return GetArc2PD( ptP, crvArc.GetCenter(), dDirStartDeg) ;
}
// versore ortogonale alla direzione iniziale (si lavora nel piano XY locale)
Vector3d vtOrtho = FromPolar( 1, dDirStartDeg) ;
vtOrtho.Rotate( Z_AX, 0, 1) ;
// calcolo arco spostando il punto iniziale di + raggio in direzione ortogonale
Point3d ptP1 = ptP + vtOrtho * crvArc.GetRadius() ;
PtrOwner<ICurve> pCrv1( GetArc2PD( ptP1, crvArc.GetCenter(), dDirStartDeg)) ;
bool bOk1 = ( ! IsNull( pCrv1)) ;
// compenso lo spostamento ( più -> offset a destra)
bOk1 = bOk1 && pCrv1->SimpleOffset( crvArc.GetRadius()) ;
// verifico se il punto di tangenza sta sull'arco
Point3d ptEnd1 ;
bOk1 = bOk1 && pCrv1->GetEndPoint( ptEnd1) && crvArc.IsPointOn( ptEnd1) ;
// calcolo arco spostando il punto iniziale di - raggio in direzione ortogonale
Point3d ptP2 = ptP - vtOrtho * crvArc.GetRadius() ;
PtrOwner<ICurve> pCrv2( GetArc2PD( ptP2, crvArc.GetCenter(), dDirStartDeg)) ;
bool bOk2 = ( ! IsNull( pCrv2)) ;
// compenso lo spostamento ( meno -> offset a sinistra)
bOk2 = bOk2 && pCrv2->SimpleOffset( - crvArc.GetRadius()) ;
// verifico se il punto di tangenza sta sull'arco
Point3d ptEnd2 ;
bOk2 = bOk2 && pCrv2->GetEndPoint( ptEnd2) && crvArc.IsPointOn( ptEnd2) ;
// se due soluzioni, verifico quale ha il punto di tg più vicino al richiesto
if ( bOk1 && bOk2) {
if ( SqDist( ptEnd1, ptNearTg) <= SqDist( ptEnd2, ptNearTg))
bOk2 = false ;
else
bOk1 = false ;
}
// restituisco la soluzione
if ( bOk1)
return Release( pCrv1) ;
else if ( bOk2)
return Release( pCrv2) ;
else
return nullptr ;
}
//----------------------------------------------------------------------------
static int
CalcCircleCenTgCircle( const Point3d& ptC, const Point3d& ptCen, double dRad, BIPNTVECTOR& vCenPtg)
{
// --- si lavora nel piano XY ---
// svuoto il vettore dei risultati (sono coppie centro-punto di tangenza)
vCenPtg.clear() ;
// se il raggio è negativo non ci sono soluzioni
if ( dRad < - EPS_SMALL)
return 0 ;
// versore e distanza tra i centri nel piano XY
Vector3d vtDir = ptCen - ptC ;
vtDir.z = 0 ;
double dDist = vtDir.Len() ;
vtDir /= dDist ;
// se il raggio è nullo ...
if ( dRad < EPS_SMALL) {
// se la distanza tra i punti è significativa, c'è una soluzione
if ( dDist > EPS_SMALL) {
vCenPtg.emplace_back( ptC, ptCen) ;
return 1 ;
}
// altrimenti, nessuna soluzione
else
return 0 ;
}
// se questa distanza è uguale al raggio, non ci sono soluzioni
if ( fabs( dDist - dRad) < EPS_SMALL)
return 0 ;
// se è minore del raggio, c'è una sola soluzione
else if ( dDist < dRad) {
vCenPtg.emplace_back( ptC, ptCen - vtDir * dRad) ;
return 1 ;
}
// altrimenti ci sono due soluzioni
else {
vCenPtg.emplace_back( ptC, ptCen - vtDir * dRad) ;
vCenPtg.emplace_back( ptC, ptCen + vtDir * dRad) ;
return 2 ;
}
}
+1 -1
View File
@@ -18,7 +18,7 @@
#include "/EgtDev/Include/EGkAngle.h"
#include "/EgtDev/Include/EgkCurveLine.h"
#include "/EgtDev/Include/EgkCurveComposite.h"
#include "/EgtDev/Include/EgkArcXxTgArc.h"
#include "/EgtDev/Include/EgkArcSpecial.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
+250
View File
@@ -0,0 +1,250 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : CircleCenTgCurve.cpp Data : 12.03.15 Versione : 1.6c2
// Contenuto : Implementazione funzioni per calcolo circonferenze di centro
// dato tangenti a curve.
//
//
// Modifiche : 12.03.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "CurveBezier.h"
#include "CurveComposite.h"
#include "CreateCurveAux.h"
#include "DistPointLine.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EgkCircleCenTgCurve.h"
#include "/EgtDev/Include/EgkDistPointCurve.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
using namespace std ;
//----------------------------------------------------------------------------
static CurveArc* GetCircleCenTgLine( const Point3d& ptCen, const Vector3d& vtN, const CurveLine& crvLine,
const Point3d& ptNear, Point3d* pPtTg) ;
static CurveArc* GetCircleCenTgArc( const Point3d& ptCen, const Vector3d& vtN, const CurveArc& crvArc,
const Point3d& ptNear, Point3d* pPtTg) ;
static CurveArc* GetCircleCenTgBezier( const Point3d& ptCen, const Vector3d& vtN, const CurveBezier& crvBezier,
const Point3d& ptNear, Point3d* pPtTg) ;
static CurveArc* GetCircleCenTgCompo( const Point3d& ptCen, const Vector3d& vtN, const CurveComposite& crvCompo,
const Point3d& ptNear, Point3d* pPtTg) ;
//----------------------------------------------------------------------------
ICurveArc*
GetCircleCenTgCurve( const Point3d& ptCen, const Vector3d& vtN, const ICurve& cCrv, const Point3d& ptNear)
{
return GetCircleCenTgCurve( ptCen, vtN, cCrv, ptNear, nullptr) ;
}
//----------------------------------------------------------------------------
ICurveArc*
GetCircleCenTgCurve( const Point3d& ptCen, const Vector3d& vtN, const ICurve& cCrv, const Point3d& ptNear,
Point3d* pPtTg)
{
// verifica dei parametri
if ( &ptCen == nullptr || &vtN == nullptr || &cCrv == nullptr || &ptNear == nullptr)
return nullptr ;
// eseguo calcoli a seconda della curva tg
switch ( cCrv.GetType()) {
case CRV_LINE :
{ const CurveLine& crvLine = *GetBasicCurveLine( &cCrv) ;
return GetCircleCenTgLine( ptCen, vtN, crvLine, ptNear, pPtTg) ; }
case CRV_ARC :
{ const CurveArc& crvArc = *GetBasicCurveArc( &cCrv) ;
return GetCircleCenTgArc( ptCen, vtN, crvArc, ptNear, pPtTg) ; }
case CRV_BEZ :
{ const CurveBezier& crvBezier = *GetBasicCurveBezier( &cCrv) ;
return GetCircleCenTgBezier( ptCen, vtN, crvBezier, ptNear, pPtTg) ; }
case CRV_COMPO :
{ const CurveComposite& crvCompo = *GetBasicCurveComposite( &cCrv) ;
return GetCircleCenTgCompo( ptCen, vtN, crvCompo, ptNear, pPtTg) ; }
default :
return nullptr ;
}
}
//----------------------------------------------------------------------------
CurveArc*
GetCircleCenTgLine( const Point3d& ptCen, const Vector3d& vtN, const CurveLine& crvLine,
const Point3d& ptNear, Point3d* pPtTg)
{
// devo considerare sempre la proiezione della linea sul piano della circonferenza
Point3d ptP1 = crvLine.GetStart() ;
Point3d ptP2 = crvLine.GetEnd() ;
ptP2 -= (( ptP2 - ptP1) * vtN) * vtN ;
// calcolo la proiezione perpendicolare del centro sulla linea
Point3d ptTg ;
if ( ! DistPointLine( ptCen, ptP1, ptP2, false).GetMinDistPoint( ptTg))
return nullptr ;
// verifico che stia sul segmento
double dSqDist ;
if ( ! DistPointLine( ptTg, ptP1, ptP2).GetSqDist( dSqDist) || dSqDist > EPS_SMALL * EPS_SMALL)
return nullptr ;
// creo l'arco
PtrOwner<CurveArc> pCrvArc( CreateBasicCurveArc()) ;
if ( IsNull( pCrvArc))
return nullptr ;
// costruisco la circonferenza corrispondente alla soluzione scelta
double dRad = (( ptTg - ptCen) ^ vtN).Len() ;
if ( pCrvArc->Set( ptCen, vtN, dRad)) {
if ( pPtTg != nullptr)
*pPtTg = ptTg ;
return Release( pCrvArc) ;
}
else
return nullptr ;
}
//----------------------------------------------------------------------------
CurveArc*
GetCircleCenTgArc( const Point3d& ptCen, const Vector3d& vtN, const CurveArc& crvArc,
const Point3d& ptNear, Point3d* pPtTg)
{
// verifico che la normale della circonferenza coincida con quella dell'arco di tg
if ( ! AreSameOrOppositeVectorApprox( vtN, crvArc.GetNormVersor()))
return nullptr ;
// 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 ptCLoc = ptCen ;
ptCLoc.ToLoc( frIntr) ;
// calcolo le circonferenze tangenti alla circonferenza
BIPNTVECTOR vCenPtg( 2) ;
int nSol = CalcCircleCenTgCircle( ptCLoc, ORIG, crvArc.GetRadius(), vCenPtg) ;
if ( nSol == 0)
return nullptr ;
// porto i punti nel riferimento standard dell'arco
for ( size_t i = 0 ; i < vCenPtg.size() ; ++ i) {
vCenPtg[i].first.ToGlob( frIntr) ;
vCenPtg[i].second.ToGlob( frIntr) ;
}
// se l'arco di tangenza ha deltaN, devo applicarlo in proporzione a questi punti
if ( fabs( crvArc.GetDeltaN()) > EPS_SMALL) {
for ( size_t i = 0 ; i < vCenPtg.size() ; ++ i) {
double dAngDeg ;
if ( crvArc.CalcPointAngle( vCenPtg[i].second, dAngDeg))
vCenPtg[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( vCenPtg[i].second)) {
-- nSol ;
for ( int j = i ; j < nSol ; ++ j)
vCenPtg[j] = vCenPtg[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 = INFINITO * INFINITO ;
for ( int i = 0 ; i < nSol ; ++ i) {
double dSqDist = SqDist( vCenPtg[i].second, ptNear) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
nIdOk = i ;
}
}
// creo l'arco
PtrOwner<CurveArc> pCrvArc( CreateBasicCurveArc()) ;
if ( IsNull( pCrvArc))
return nullptr ;
// costruisco la circonferenza corrispondente alla soluzione scelta
double dRad = (( vCenPtg[nIdOk].second - vCenPtg[nIdOk].first) ^ vtN).Len() ;
if ( pCrvArc->Set( vCenPtg[nIdOk].first, vtN, dRad)) {
if ( pPtTg != nullptr)
*pPtTg = vCenPtg[nIdOk].second ;
return Release( pCrvArc) ;
}
else
return nullptr ;
}
//----------------------------------------------------------------------------
CurveArc*
GetCircleCenTgBezier( const Point3d& ptCen, const Vector3d& vtN, const CurveBezier& crvBezier,
const Point3d& ptNear, Point3d* pPtTg)
{
// 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 circonferenza tangente a questa approssimazione
Point3d ptTg ;
PtrOwner<CurveArc> pCrvArc( GetBasicCurveArc( GetCircleCenTgCurve( ptCen, vtN, *pCrvCompo, ptNear, &ptTg))) ;
if ( IsNull( pCrvArc))
return nullptr ;
// porto il punto di tangenza della circonferenza esattamente sulla curva di Bezier
DistPointCurve dstPtCurve( ptTg, crvBezier) ;
Point3d ptTg2 ;
int nFlag ;
if ( ! dstPtCurve.GetMinDistPoint( 0, ptTg2, nFlag))
return nullptr ;
// calcolo il nuovo raggio
double dRad = (( ptTg2 - ptCen) ^ vtN).Len() ;
// imposto il nuovo raggio
if ( ! pCrvArc->Set( ptCen, vtN, dRad))
return nullptr ;
// se richiesto, assegno il punto di tg
if ( pPtTg != nullptr)
*pPtTg = ptTg2 ;
// restituisco la circonferenza
return Release( pCrvArc) ;
}
//----------------------------------------------------------------------------
CurveArc*
GetCircleCenTgCompo( const Point3d& ptCen, const Vector3d& vtN, const CurveComposite& crvCompo,
const Point3d& ptNear, Point3d* pPtTg)
{
// ciclo sulla curva composita
double dMinSqDist = INFINITO * INFINITO ;
PtrOwner<CurveArc> pCrvArc ;
for ( const ICurve* pCrv = crvCompo.GetFirstCurve() ;
pCrv != nullptr ;
pCrv = crvCompo.GetNextCurve()) {
// recupero la circonferenza tangente alla curva elementare
Point3d ptTg ;
PtrOwner<CurveArc> pCrvAtmp( GetBasicCurveArc( GetCircleCenTgCurve( ptCen, vtN, *pCrv, ptNear, &ptTg))) ;
if ( IsNull( pCrvAtmp))
continue ;
// verifico se è la più vicina al punto desiderato
double dSqDist = SqDist( ptNear, ptTg) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
pCrvArc.Set( Release( pCrvAtmp)) ;
if ( pPtTg != nullptr)
*pPtTg = ptTg ;
}
}
return Release( pCrvArc) ;
}
+47
View File
@@ -74,6 +74,53 @@ CalcLinePointTgCircle( const Point3d& ptP, const Point3d& ptCen, double dRad, BI
return 2 ;
}
//----------------------------------------------------------------------------
int
CalcCircleCenTgCircle( const Point3d& ptC, const Point3d& ptCen, double dRad, BIPNTVECTOR& vCenPtg)
{
// --- si lavora nel piano XY ---
// svuoto il vettore dei risultati (sono coppie centro-punto di tangenza)
vCenPtg.clear() ;
// se il raggio è negativo non ci sono soluzioni
if ( dRad < - EPS_SMALL)
return 0 ;
// versore e distanza tra i centri nel piano XY
Vector3d vtDir = ptCen - ptC ;
vtDir.z = 0 ;
double dDist = vtDir.Len() ;
vtDir /= dDist ;
// se il raggio è nullo ...
if ( dRad < EPS_SMALL) {
// se la distanza tra i punti è significativa, c'è una soluzione
if ( dDist > EPS_SMALL) {
vCenPtg.emplace_back( ptC, ptCen) ;
return 1 ;
}
// altrimenti, nessuna soluzione
else
return 0 ;
}
// se questa distanza è uguale al raggio, non ci sono soluzioni
if ( fabs( dDist - dRad) < EPS_SMALL)
return 0 ;
// se è minore del raggio, c'è una sola soluzione
else if ( dDist < dRad) {
vCenPtg.emplace_back( ptC, ptCen - vtDir * dRad) ;
return 1 ;
}
// altrimenti ci sono due soluzioni
else {
vCenPtg.emplace_back( ptC, ptCen - vtDir * dRad) ;
vCenPtg.emplace_back( ptC, ptCen + vtDir * dRad) ;
return 2 ;
}
}
//----------------------------------------------------------------------------
bool
FindPointOnArc( const CurveArc& crvArc, const Vector3d& vtDirP, const Point3d& ptNear, Point3d& ptP)
+1
View File
@@ -19,6 +19,7 @@
//----------------------------------------------------------------------------
int CalcLinePointTgCircle( const Point3d& ptP, const Point3d& ptCen, double dRad, BIPNTVECTOR& vBiPnt) ;
int CalcCircleCenTgCircle( const Point3d& ptC, const Point3d& ptCen, double dRad, BIPNTVECTOR& vCenPtg) ;
bool FindPointOnArc( const CurveArc& crvArc, const Vector3d& vtDirP, const Point3d& ptNear, Point3d& ptP) ;
+37
View File
@@ -1136,6 +1136,43 @@ CurveArc::SimpleOffset( double dDist, int nType)
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::ExtendedOffset( double dDist, int nType)
{
// la curva deve essere validata
if ( m_nStatus != OK)
return false ;
// determinazione versore normale al piano di offset
Vector3d vtNref = Z_AX ;
if ( ! m_VtExtr.IsSmall())
vtNref = m_VtExtr ;
// la normale deve coincidere con il versore del piano di offset
if ( ! AreSameOrOppositeVectorApprox( m_VtN, vtNref))
return false ;
// calcolo il nuovo raggio e lo valido
bool bCCW = ( ( m_dAngCenDeg > 0 && m_VtN * vtNref > 0) ||
( m_dAngCenDeg < 0 && m_VtN * vtNref < 0)) ;
double dNewRad = m_dRad + ( bCCW ? + dDist : - dDist) ;
if ( fabs( dNewRad) < EPS_SMALL)
return false ;
if ( dNewRad < 0) {
dNewRad = - dNewRad ;
m_VtS = - m_VtS ;
}
// aggiorno il raggio
m_dRad = dNewRad ;
// con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata
m_OGrMgr.Reset() ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveArc::ModifyStart( const Point3d& ptNewStart)
+1
View File
@@ -155,6 +155,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
virtual bool InvertN( void) ;
virtual bool ChangeRadius( double dNewRadius) ;
virtual bool ChangeDeltaN( double dNewDeltaN) ;
virtual bool ExtendedOffset( double dDist, int nType = OFF_FILLET) ;
virtual bool ToAdditional( void) ;
virtual bool Flip( void) ;
BIN
View File
Binary file not shown.
+7 -2
View File
@@ -248,11 +248,14 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Angle.cpp" />
<ClCompile Include="ArcXxTgArc.cpp" />
<ClCompile Include="ArcCenTgCurvePnt.cpp" />
<ClCompile Include="ArcPntDirTgCurve.cpp" />
<ClCompile Include="ArcSpecial.cpp" />
<ClCompile Include="Attribs.cpp" />
<ClCompile Include="BBox3d.cpp" />
<ClCompile Include="BiArcs.cpp" />
<ClCompile Include="ChainCurves.cpp" />
<ClCompile Include="CircleCenTgCurve.cpp" />
<ClCompile Include="Color.cpp" />
<ClCompile Include="CreateCurveAux.cpp" />
<ClCompile Include="CurveByInterp.cpp" />
@@ -334,10 +337,12 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\Include\EGkAngle.h" />
<ClInclude Include="..\Include\EGkArcXxTgArc.h" />
<ClInclude Include="..\Include\EGkArcPntDirTgCurve.h" />
<ClInclude Include="..\Include\EgkArcSpecial.h" />
<ClInclude Include="..\Include\EGkBBox3d.h" />
<ClInclude Include="..\Include\EGkBiArcs.h" />
<ClInclude Include="..\Include\EGkChainCurves.h" />
<ClInclude Include="..\Include\EGkCircleCenTgCurve.h" />
<ClInclude Include="..\Include\EGkColor.h" />
<ClInclude Include="..\Include\EgkCurve.h" />
<ClInclude Include="..\Include\EgkCurveArc.h" />
+21 -6
View File
@@ -186,9 +186,6 @@
<ClCompile Include="LinePntTgCurve.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
<ClCompile Include="ArcXxTgArc.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
<ClCompile Include="IntersLineLine.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
@@ -264,6 +261,18 @@
<ClCompile Include="IntersLineSurfTm.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="CircleCenTgCurve.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
<ClCompile Include="ArcPntDirTgCurve.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
<ClCompile Include="ArcCenTgCurvePnt.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
<ClCompile Include="ArcSpecial.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@@ -425,9 +434,6 @@
<ClInclude Include="..\Include\EGkAngle.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkArcXxTgArc.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkBBox3d.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
@@ -614,6 +620,15 @@
<ClInclude Include="ProjPlane.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkCircleCenTgCurve.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkArcPntDirTgCurve.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EgkArcSpecial.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc">
+7 -4
View File
@@ -28,7 +28,10 @@
#include "/EgtDev/Include/EgkLinePntTgCurve.h"
#include "/EgtDev/Include/EgkLineTgTwoCurves.h"
#include "/EgtDev/Include/EgkCurveArc.h"
#include "/EgtDev/Include/EgkArcXxTgArc.h"
#include "/EgtDev/Include/EgkCircleCenTgCurve.h"
#include "/EgtDev/Include/EgkArcPntDirTgCurve.h"
#include "/EgtDev/Include/EgkArcCenTgCurvePnt.h"
#include "/EgtDev/Include/EgkArcSpecial.h"
#include "/EgtDev/Include/EgkCurveBezier.h"
#include "/EgtDev/Include/EgkCurveComposite.h"
#include "/EgtDev/Include/EgkDistPointCurve.h"
@@ -1268,7 +1271,7 @@ GdbExecutor::CurveCircleCenterTgArc( const STRVECTOR& vsParams)
Point3d ptNloc = ptNear ;
ptNloc.LocToLoc( frDest, frTgArc) ;
// calcolo la circonferenza tangente all'arco
ICurveArc* pNewArc = GetCircleCenTgArc( ptCloc, *pTgArc, ptNloc) ;
ICurveArc* pNewArc = GetCircleCenTgCurve( ptCloc, pTgArc->GetNormVersor(), *pTgArc, ptNloc) ;
if ( pNewArc == nullptr)
return false ;
// porto il nuovo arco nel riferimento del gruppo destinazione
@@ -1320,7 +1323,7 @@ GdbExecutor::CurveArcCenterTgArcP( const STRVECTOR& vsParams)
Point3d ptNeloc = ptNear ;
ptNeloc.LocToLoc( frDest, frTgArc) ;
// calcolo la circonferenza tangente all'arco
ICurveArc* pNewArc = GetArcCenTgArcPnt( ptCloc, *pTgArc, ptNtloc, ptNeloc) ;
ICurveArc* pNewArc = GetArcCenTgCurvePnt( ptCloc, *pTgArc, ptNtloc, ptNeloc, Z_AX) ;
if ( pNewArc == nullptr)
return false ;
// porto il nuovo arco nel riferimento del gruppo destinazione
@@ -1370,7 +1373,7 @@ GdbExecutor::CurveArcPDiTgArc( const STRVECTOR& vsParams)
Point3d ptNtloc = ptNear ;
ptNtloc.LocToLoc( frDest, frTgArc) ;
// calcolo l'arco (in casi particolari può essere una linea)
ICurve* pCurve = GetArcPntDirTgArc( ptSloc, dDirI, *pTgArc, ptNtloc) ;
ICurve* pCurve = GetArcPntDirTgCurve( ptSloc, FromPolar( 1, dDirI), *pTgArc, ptNtloc, Z_AX) ;
if ( pCurve == nullptr)
return false ;
// porto il nuovo arco nel riferimento del gruppo destinazione
+9
View File
@@ -105,6 +105,15 @@ GetLinePointTgArc( const Point3d& ptP, const CurveArc& crvArc, const Point3d& pt
vBiPnt[i].second.ToGlob( frIntr) ;
}
// se l'arco di tangenza ha deltaN, devo applicarlo in proporzione a questi punti
if ( fabs( 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) {
+15 -13
View File
@@ -232,10 +232,11 @@ SurfTriMesh::GetFacetNearestEndPoint( int nF, const Point3d& ptNear, Point3d& pt
dMinSqDist = dSqDist ;
ptEnd = ptTest ;
bFound = true ;
// recupero la normale
Vector3d vtN1, vtN2 ;
if ( ! GetTriangleSmoothNormal( nT, j, vtN))
vtN = m_vTria[nT].vtN ;
// recupero la normale della faccia (non quella mediata del vertice)
vtN = m_vTria[nT].vtN ;
//Vector3d vtN1, vtN2 ;
//if ( ! GetTriangleSmoothNormal( nT, j, vtN))
// vtN = m_vTria[nT].vtN ;
}
}
}
@@ -269,15 +270,16 @@ SurfTriMesh::GetFacetNearestMidPoint( int nF, const Point3d& ptNear, Point3d& pt
dMinSqDist = dSqDist ;
ptMid = ptTest ;
bFound = true ;
// calcolo la normale
Vector3d vtN1, vtN2 ;
if ( GetTriangleSmoothNormal( nT, j, vtN1) &&
GetTriangleSmoothNormal( nT, k, vtN2)) {
vtN = Media( vtN1, vtN2, 0.5) ;
vtN.Normalize() ;
}
else
vtN = m_vTria[nT].vtN ;
// recupero la normale della faccia (non quella mediata del vertice)
vtN = m_vTria[nT].vtN ;
//Vector3d vtN1, vtN2 ;
//if ( GetTriangleSmoothNormal( nT, j, vtN1) &&
// GetTriangleSmoothNormal( nT, k, vtN2)) {
// vtN = Media( vtN1, vtN2, 0.5) ;
// vtN.Normalize() ;
//}
//else
// vtN = m_vTria[nT].vtN ;
}
}
}