From 6c14e51ef6c8c2b2d444aa863b8034efa00f60fc Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 16 Mar 2015 07:38:43 +0000 Subject: [PATCH] EgtGeomKernel 1.6c2 : - aggiunte funzioni per circonferenze e archi tangenti. --- ArcCenTgCurvePnt.cpp | 178 +++++++++++++++++ ArcPntDirTgCurve.cpp | 347 ++++++++++++++++++++++++++++++++++ ArcSpecial.cpp | 133 +++++++++++++ ArcXxTgArc.cpp | 291 ---------------------------- BiArcs.cpp | 2 +- CircleCenTgCurve.cpp | 250 ++++++++++++++++++++++++ CreateCurveAux.cpp | 47 +++++ CreateCurveAux.h | 1 + CurveArc.cpp | 37 ++++ CurveArc.h | 1 + EgtGeomKernel.rc | Bin 11710 -> 11710 bytes EgtGeomKernel.vcxproj | 9 +- EgtGeomKernel.vcxproj.filters | 27 ++- GdbExecutor.cpp | 11 +- LinePntTgCurve.cpp | 9 + SurfTriMeshFaceting.cpp | 28 +-- 16 files changed, 1054 insertions(+), 317 deletions(-) create mode 100644 ArcCenTgCurvePnt.cpp create mode 100644 ArcPntDirTgCurve.cpp create mode 100644 ArcSpecial.cpp delete mode 100644 ArcXxTgArc.cpp create mode 100644 CircleCenTgCurve.cpp diff --git a/ArcCenTgCurvePnt.cpp b/ArcCenTgCurvePnt.cpp new file mode 100644 index 0000000..e6fff01 --- /dev/null +++ b/ArcCenTgCurvePnt.cpp @@ -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 pCirc( GetCircleCenTgCurve( ptCen, vtN, crvLine, ptNearStart, &ptTg)) ; + if ( IsNull( pCirc)) + return nullptr ; + // costruisco l'arco voluto con i dati di quuesta circonferenza + PtrOwner 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 pCirc( GetCircleCenTgCurve( ptCen, vtN, crvArc, ptNearStart, &ptTg)) ; + if ( IsNull( pCirc)) + return nullptr ; + // costruisco l'arco voluto con i dati di quuesta circonferenza + PtrOwner 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 pCrvCompo( CreateBasicCurveComposite()) ; + if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyArc( PA)) + return nullptr ; + // calcolo la circonferenza tangente a questa approssimazione + Point3d ptTg ; + PtrOwner 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 pCrvArc ; + for ( const ICurve* pCrv = crvCompo.GetFirstCurve() ; + pCrv != nullptr ; + pCrv = crvCompo.GetNextCurve()) { + // recupero la circonferenza tangente alla curva elementare + Point3d ptTg ; + PtrOwner 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) ; +} \ No newline at end of file diff --git a/ArcPntDirTgCurve.cpp b/ArcPntDirTgCurve.cpp new file mode 100644 index 0000000..4ac9db0 --- /dev/null +++ b/ArcPntDirTgCurve.cpp @@ -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 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 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 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 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 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(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 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(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 pCrvCompo( CreateBasicCurveComposite()) ; + if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyArc( PA)) + return nullptr ; + // calcolo la circonferenza tangente a questa approssimazione + Point3d ptTg ; + PtrOwner 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 pCrvNew ; + for ( const ICurve* pCrv = crvCompo.GetFirstCurve() ; + pCrv != nullptr ; + pCrv = crvCompo.GetNextCurve()) { + // recupero la circonferenza tangente alla curva elementare + Point3d ptTg ; + PtrOwner 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) ; +} \ No newline at end of file diff --git a/ArcSpecial.cpp b/ArcSpecial.cpp new file mode 100644 index 0000000..a3d0a0a --- /dev/null +++ b/ArcSpecial.cpp @@ -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 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 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 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 ; +} diff --git a/ArcXxTgArc.cpp b/ArcXxTgArc.cpp deleted file mode 100644 index f098c3f..0000000 --- a/ArcXxTgArc.cpp +++ /dev/null @@ -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 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 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 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 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 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 ; - } -} diff --git a/BiArcs.cpp b/BiArcs.cpp index ece737b..5ebe256 100644 --- a/BiArcs.cpp +++ b/BiArcs.cpp @@ -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" diff --git a/CircleCenTgCurve.cpp b/CircleCenTgCurve.cpp new file mode 100644 index 0000000..418ba68 --- /dev/null +++ b/CircleCenTgCurve.cpp @@ -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 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 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 pCrvCompo( CreateBasicCurveComposite()) ; + if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyArc( PA)) + return nullptr ; + // calcolo la circonferenza tangente a questa approssimazione + Point3d ptTg ; + PtrOwner 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 pCrvArc ; + for ( const ICurve* pCrv = crvCompo.GetFirstCurve() ; + pCrv != nullptr ; + pCrv = crvCompo.GetNextCurve()) { + // recupero la circonferenza tangente alla curva elementare + Point3d ptTg ; + PtrOwner 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) ; +} diff --git a/CreateCurveAux.cpp b/CreateCurveAux.cpp index e5251a4..031cd59 100644 --- a/CreateCurveAux.cpp +++ b/CreateCurveAux.cpp @@ -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) diff --git a/CreateCurveAux.h b/CreateCurveAux.h index 0c9e153..b09123d 100644 --- a/CreateCurveAux.h +++ b/CreateCurveAux.h @@ -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) ; diff --git a/CurveArc.cpp b/CurveArc.cpp index 7cbc2d7..b7a9ce0 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -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) diff --git a/CurveArc.h b/CurveArc.h index c42602a..850e465 100644 --- a/CurveArc.h +++ b/CurveArc.h @@ -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) ; diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 2cfc002e93ebdd03640d5a2164560f95b61ae833..3c4bd9998aa05ac1b2ed5dd5b8da8d8c4d829e59 100644 GIT binary patch delta 94 zcmdlNy)SyhFE&P_&A-_cnHh~HD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-Vf-5U delta 94 zcmdlNy)SyhFE&QQ&A-_cnHdcyD{|{@_Trkr0u;H;XNwSVW8B;$>;>dw2zN+>g;Df- LFmBFL4&ed-U|t&X diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 2c6f601..cf7f12c 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -248,11 +248,14 @@ copy $(TargetPath) \EgtProg\Dll64 - + + + + @@ -334,10 +337,12 @@ copy $(TargetPath) \EgtProg\Dll64 - + + + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index adae979..a03a628 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -186,9 +186,6 @@ File di origine\GeoCreate - - File di origine\GeoCreate - File di origine\GeoInters @@ -264,6 +261,18 @@ File di origine\GeoInters + + File di origine\GeoCreate + + + File di origine\GeoCreate + + + File di origine\GeoCreate + + + File di origine\GeoCreate + @@ -425,9 +434,6 @@ File di intestazione\Include - - File di intestazione\Include - File di intestazione\Include @@ -614,6 +620,15 @@ File di intestazione + + File di intestazione\Include + + + File di intestazione\Include + + + File di intestazione\Include + diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index ca21f97..7875c0c 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -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 diff --git a/LinePntTgCurve.cpp b/LinePntTgCurve.cpp index 7279c5c..730ef2b 100644 --- a/LinePntTgCurve.cpp +++ b/LinePntTgCurve.cpp @@ -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) { diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index aa73fef..927744a 100644 --- a/SurfTriMeshFaceting.cpp +++ b/SurfTriMeshFaceting.cpp @@ -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 ; } } }