From 26c2ad702aab81b15bad66e81cae5d3e391e56dc Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Sat, 14 Jun 2014 18:03:04 +0000 Subject: [PATCH] EgtGeomKernel 1.5f4 : - aggiunto punto base a GeoVector3d - aggiunta creazione linea Pt+TgArc e Tg2Arcs - aggiunta creazione arco Cen+TgArc e PDi + TgArc - aggiunta a tutte le curve funzione IsPointOn - aggiunta CurveLine e CurveArc la funzione Offset - ottimizzata rotazione Vector3d attorno ad assi canonici - corretta emissione Group e Frame in OutTsc. --- ArcXxTgArc.cpp | 295 +++++++++++++++ CurveArc.cpp | 42 +++ CurveArc.h | 5 +- CurveBezier.cpp | 10 + CurveBezier.h | 5 +- CurveComposite.cpp | 10 + CurveComposite.h | 5 +- CurveLine.cpp | 41 +- CurveLine.h | 4 +- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes EgtGeomKernel.vcxproj | 7 + EgtGeomKernel.vcxproj.filters | 39 +- GdbExecutor.cpp | 683 ++++++++++++++++++++++++++-------- GdbExecutor.h | 16 +- GeoVector3d.cpp | 61 ++- GeoVector3d.h | 13 +- LinePntTgCurve.cpp | 160 ++++++++ LinePntTgCurve.h | 20 + LineTgTwoArcs.cpp | 241 ++++++++++++ OutTsc.cpp | 8 +- Vector3d.cpp | 81 +++- 21 files changed, 1537 insertions(+), 209 deletions(-) create mode 100644 ArcXxTgArc.cpp create mode 100644 LinePntTgCurve.cpp create mode 100644 LinePntTgCurve.h create mode 100644 LineTgTwoArcs.cpp diff --git a/ArcXxTgArc.cpp b/ArcXxTgArc.cpp new file mode 100644 index 0000000..c5a7039 --- /dev/null +++ b/ArcXxTgArc.cpp @@ -0,0 +1,295 @@ +//---------------------------------------------------------------------------- +// 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 ( ! IsValid( 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 ( ! IsValid( 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 ; + vtDir.FromPolar( 1, dDirStartDeg) ; + // verifico se i punti sono allineati con la direzione + if ( ( vtDiff ^ vtDir).SqLen() < EPS_SMALL * 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 ; + 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 = IsValid( pCrv1) ; + // compenso lo spostamento + bOk1 = bOk1 && pCrv1->Offset( crvArc.GetRadius(), ICurve::OFF_RIGHT) ; + // 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 = IsValid( pCrv2) ; + // compenso lo spostamento + bOk2 = bOk2 && pCrv2->Offset( crvArc.GetRadius(), ICurve::OFF_LEFT) ; + // 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 ; +} + +//---------------------------------------------------------------------------- +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.push_back( make_pair( 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.push_back( make_pair( ptC, ptCen - vtDir * dRad)) ; + return 1 ; + } + // altrimenti ci sono due soluzioni + else { + vCenPtg.push_back( make_pair( ptC, ptCen - vtDir * dRad)) ; + vCenPtg.push_back( make_pair( ptC, ptCen + vtDir * dRad)) ; + return 2 ; + } +} diff --git a/CurveArc.cpp b/CurveArc.cpp index 2248957..48f9282 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -14,6 +14,7 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveArc.h" +#include "DistPointArc.h" #include "GeoConst.h" #include "GeoObjFactory.h" #include "NgeWriter.h" @@ -734,6 +735,15 @@ CurveArc::GetLength( double& dLen) const return ( dLen > EPS_SMALL) ; } +//---------------------------------------------------------------------------- +bool +CurveArc::IsPointOn( const Point3d& ptP, double dTol) const +{ + double dSqDist ; + dTol = max( dTol, EPS_ZERO) ; + return ( DistPointArc( ptP, *this).GetSqDist( dSqDist) && dSqDist < dTol * dTol) ; +} + //---------------------------------------------------------------------------- bool CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const @@ -782,6 +792,38 @@ CurveArc::Invert( void) return true ; } +//---------------------------------------------------------------------------- +bool +CurveArc::Offset( double dDist, int nSide, int nType) +{ + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; + + // la normale deve coincidere con l'asse Z (l'offset è sempre nel piano XY) + if ( ! ( m_VtN.IsZplus() || m_VtN.IsZminus())) + return false ; + + // calcolo il nuovo raggio e lo valido + bool bCCW = ( ( m_dAngCenDeg > 0 && m_VtN.z > 0) || + ( m_dAngCenDeg < 0 && m_VtN.z < 0)) ; + double dNewRad ; + if ( ( bCCW && nSide != OFF_LEFT) || ( ! bCCW && nSide == OFF_LEFT)) + dNewRad = m_dRad + dDist ; + else + dNewRad = m_dRad - dDist ; + if ( dNewRad < EPS_SMALL) + return false ; + + // 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::TrimStartAtParam( double dUTrim) diff --git a/CurveArc.h b/CurveArc.h index b86d011..8bad016 100644 --- a/CurveArc.h +++ b/CurveArc.h @@ -75,8 +75,10 @@ class CurveArc : public ICurveArc, public IGeoObjRW virtual bool GetPointDiffGeom( double dU, Side nS, CrvPointDiffGeom& oDiffG) const { oDiffG.nFlag = CrvPointDiffGeom::STD ; return ::GetPointDiffGeom( *this, dU, nS, oDiffG) ; } - virtual bool Invert( void) ; + virtual bool IsPointOn( const Point3d& ptP, double dTol = EPS_SMALL) const ; virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ; + virtual bool Invert( void) ; + virtual bool Offset( double dDist, int nSide, int nType = OFF_FILLET) ; virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; @@ -132,6 +134,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW private : bool Copy( const CurveArc& caSrc) ; + bool Copy( const ICurveArc& caSrc) ; bool Validate( void) ; bool GetDir( double dU, Vector3d& vtDir) const ; diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 24492ff..5644ade 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -14,6 +14,7 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveBezier.h" +#include "DistPointCrvBezier.h" #include "GeoConst.h" #include "DistPointLine.h" #include "GeoObjFactory.h" @@ -1163,6 +1164,15 @@ CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, return true ; } +//---------------------------------------------------------------------------- +bool +CurveBezier::IsPointOn( const Point3d& ptP, double dTol) const +{ + double dSqDist ; + dTol = max( dTol, EPS_ZERO) ; + return ( DistPointCrvBezier( ptP, *this).GetSqDist( dSqDist) && dSqDist < dTol * dTol) ; +} + //---------------------------------------------------------------------------- bool CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const diff --git a/CurveBezier.h b/CurveBezier.h index 1fa7bab..c5fdf0c 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -79,8 +79,11 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW virtual bool GetPointDiffGeom( double dU, Side nS, CrvPointDiffGeom& oDiffG) const { oDiffG.nFlag = CrvPointDiffGeom::STD ; return ::GetPointDiffGeom( *this, dU, nS, oDiffG) ; } - virtual bool Invert( void) ; + virtual bool IsPointOn( const Point3d& ptP, double dTol = EPS_SMALL) const ; virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ; + virtual bool Invert( void) ; + virtual bool Offset( double dDist, int nSide, int nType = OFF_FILLET) + { return false ; } virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; diff --git a/CurveComposite.cpp b/CurveComposite.cpp index 0e3f8e0..2a6189e 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -14,6 +14,7 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveComposite.h" +#include "DistPointCrvComposite.h" #include "GeoConst.h" #include "GeoObjFactory.h" #include "NgeWriter.h" @@ -678,6 +679,15 @@ CurveComposite::GetLength( double& dLen) const return true ; } +//---------------------------------------------------------------------------- +bool +CurveComposite::IsPointOn( const Point3d& ptP, double dTol) const +{ + double dSqDist ; + dTol = max( dTol, EPS_ZERO) ; + return ( DistPointCrvComposite( ptP, *this).GetSqDist( dSqDist) && dSqDist < dTol * dTol) ; +} + //---------------------------------------------------------------------------- bool CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const diff --git a/CurveComposite.h b/CurveComposite.h index dc9eec8..699c732 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -76,8 +76,11 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW virtual bool GetPointDiffGeom( double dU, Side nS, CrvPointDiffGeom& oDiffG) const { oDiffG.nFlag = ( IsParamAtJoint( dU) ? CrvPointDiffGeom::TO_VERIFY : CrvPointDiffGeom::STD) ; return ::GetPointDiffGeom( *this, dU, nS, oDiffG) ; } - virtual bool Invert( void) ; + virtual bool IsPointOn( const Point3d& ptP, double dTol = EPS_SMALL) const ; virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ; + virtual bool Invert( void) ; + virtual bool Offset( double dDist, int nSide, int nType = OFF_FILLET) + { return false ; } virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; diff --git a/CurveLine.cpp b/CurveLine.cpp index b5e11be..3cecb6c 100644 --- a/CurveLine.cpp +++ b/CurveLine.cpp @@ -14,6 +14,7 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveLine.h" +#include "DistPointLine.h" #include "GeoObjFactory.h" #include "NgeWriter.h" #include "NgeReader.h" @@ -325,6 +326,15 @@ CurveLine::GetLength( double& dLen) const return ( dLen > EPS_SMALL) ; } +//---------------------------------------------------------------------------- +bool +CurveLine::IsPointOn( const Point3d& ptP, double dTol) const +{ + double dSqDist ; + dTol = max( dTol, EPS_ZERO) ; + return ( DistPointLine( ptP, *this).GetSqDist( dSqDist) && dSqDist < dTol * dTol) ; +} + //---------------------------------------------------------------------------- bool CurveLine::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const @@ -352,7 +362,7 @@ CurveLine::Invert( void) return false ; // inverto i punti estremi - swap( m_PtStart, m_PtEnd) ; + swap( m_PtStart, m_PtEnd) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -360,6 +370,35 @@ CurveLine::Invert( void) return true ; } +//---------------------------------------------------------------------------- +bool +CurveLine::Offset( double dDist, int nSide, int nType) +{ + // verifico lo stato + if ( m_nStatus != OK) + return false ; + + // calcolo il versore direzione linea nel piano XY + Vector3d vtDir = m_PtEnd - m_PtStart ; + vtDir.z = 0 ; + if ( ! vtDir.Normalize()) + return false ; + // calcolo il versore ortogonale dal lato di offset + if ( nSide != OFF_LEFT) + vtDir.Rotate( Z_AX, 0, -1) ; // rotazione CW di 90 deg + else + vtDir.Rotate( Z_AX, 0, 1) ; // rotazione CCW di 90 deg + + // sposto i punti + m_PtStart += vtDir * dDist ; + m_PtEnd += vtDir * dDist ; + + // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata + m_OGrMgr.Reset() ; + + return true ; +} + //---------------------------------------------------------------------------- bool CurveLine::TrimStartAtParam( double dUTrim) diff --git a/CurveLine.h b/CurveLine.h index 7a64784..aaf9183 100644 --- a/CurveLine.h +++ b/CurveLine.h @@ -75,8 +75,10 @@ class CurveLine : public ICurveLine, public IGeoObjRW virtual bool GetPointDiffGeom( double dU, Side nS, CrvPointDiffGeom& oDiffG) const { oDiffG.nFlag = CrvPointDiffGeom::STD ; return ::GetPointDiffGeom( *this, dU, nS, oDiffG) ; } - virtual bool Invert( void) ; + virtual bool IsPointOn( const Point3d& ptP, double dTol = EPS_SMALL) const ; virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ; + virtual bool Invert( void) ; + virtual bool Offset( double dDist, int nSide, int nType = OFF_FILLET) ; virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index c0b7dc2d81f129a5924e6752bd90988b1029cc95..73a0e9640bf3b2bfb2a3b72af0413a30f79c3e7e 100644 GIT binary patch delta 81 zcmdlNy)SyhH#SC-&FAG5nSs + @@ -256,6 +257,8 @@ copy $(TargetPath) \EgtProg\Dll64 + + @@ -279,6 +282,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -303,6 +307,8 @@ copy $(TargetPath) \EgtProg\Dll64 + + @@ -352,6 +358,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 7c7f057..338ca4c 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -28,12 +28,12 @@ {a3fbb199-9e77-4b66-8f18-7d48b8d6a8e1} - - {cc84f71a-b149-4187-af26-736133e92672} - {c3d823d6-c3ba-45ac-b6c4-b8896e75404d} + + {cc84f71a-b149-4187-af26-736133e92672} + @@ -91,28 +91,28 @@ File di origine\Base - File di origine\Distanze + File di origine\GeoDist - File di origine\Distanze + File di origine\GeoDist - File di origine\Distanze + File di origine\GeoDist - File di origine\Distanze + File di origine\GeoDist File di origine\Base - File di origine\Distanze + File di origine\GeoDist File di origine\Base - File di origine\Distanze + File di origine\GeoDist File di origine\Base @@ -177,6 +177,15 @@ File di origine\Gdb + + File di origine\GeoCreate + + + File di origine\GeoCreate + + + File di origine\GeoCreate + @@ -443,6 +452,18 @@ File di intestazione + + File di intestazione + + + File di intestazione + + + File di intestazione + + + File di intestazione + diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index d960de9..d74be6b 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -26,7 +26,10 @@ #include "/EgtDev/Include/EgkGeoVector3d.h" #include "/EgtDev/Include/EgkGeoFrame3d.h" #include "/EgtDev/Include/EgkCurveLine.h" +#include "/EgtDev/Include/EgkLinePntTgCurve.h" +#include "/EgtDev/Include/EgkLineTgTwoArcs.h" #include "/EgtDev/Include/EgkCurveArc.h" +#include "/EgtDev/Include/EgkArcXxTgArc.h" #include "/EgtDev/Include/EgkCurveBezier.h" #include "/EgtDev/Include/EgkCurveComposite.h" #include "/EgtDev/Include/EgkDistPointCurve.h" @@ -66,6 +69,8 @@ GdbExecutor::GdbExecutor( void) m_ExecMgr.Insert( "FRAME", &GdbExecutor::ExecuteFrame) ; m_ExecMgr.Insert( "CL", &GdbExecutor::ExecuteCurveLine) ; m_ExecMgr.Insert( "CURVELINE", &GdbExecutor::ExecuteCurveLine) ; + m_ExecMgr.Insert( "CI", &GdbExecutor::ExecuteCurveCircle) ; + m_ExecMgr.Insert( "CURVECIRCLE", &GdbExecutor::ExecuteCurveCircle) ; m_ExecMgr.Insert( "CA", &GdbExecutor::ExecuteCurveArc) ; m_ExecMgr.Insert( "CURVEARC", &GdbExecutor::ExecuteCurveArc) ; m_ExecMgr.Insert( "CB", &GdbExecutor::ExecuteCurveBez) ; @@ -233,7 +238,7 @@ GdbExecutor::ExecuteGroup( const string& sCmd2, const STRVECTOR& vsParams) bool GdbExecutor::ExecutePoint( const string& sCmd2, const STRVECTOR& vsParams) { - // analisi ed esecuzione dei comandi + // definizione diretta if ( sCmd2 == "" || sCmd2 == "MAKE") { Point3d Pnt ; // 3 parametri : Id, IdParent e punto @@ -253,6 +258,30 @@ GdbExecutor::ExecutePoint( const string& sCmd2, const STRVECTOR& vsParams) pGPnt->Set( Pnt) ; return AddGeoObj( vsParams[0], vsParams[1], pGPnt) ; } + // definizione come somma di un punto e un vettore + else if ( sCmd2 == "S" || sCmd2 == "SUM") { + // 4 : Id, IdParent, ptP, vtV + if ( vsParams.size() != 4) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frPnt ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frPnt)) + return false ; + // recupero il punto + Point3d ptP ; + if ( ! GetPointParam( vsParams[2], frPnt, ptP)) + return false ; + // recupero il vettore + Vector3d vtV ; + if ( ! GetVectorParam( vsParams[3], frPnt, vtV)) + return false ; + // creo il punto + IGeoPoint3d* pGPnt = CreateGeoPoint3d() ; + if ( pGPnt == nullptr) + return false ; + pGPnt->Set( ptP+ vtV) ; + return AddGeoObj( vsParams[0], vsParams[1], pGPnt) ; + } return false ; } @@ -263,94 +292,144 @@ GdbExecutor::ExecuteVector( const string& sCmd2, const STRVECTOR& vsParams) { // definizione diretta if ( sCmd2 == "" || sCmd2 == "MAKE") { - Vector3d Vect ; - // 3 o 4 parametri : Id, IdParent, Vettore [, ScaleFactor] - if ( vsParams.size() != 3 && vsParams.size() != 4) - return false ; - // recupero il riferimento in cui è immerso - Frame3d frVect ; - if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect)) - return false ; - // recupero i tre componenti - if ( ! GetVectorParam( vsParams[2], frVect, Vect)) - return false ; - // recupero l'eventuale fattore di scala - double dScale = 1 ; - if ( vsParams.size() == 4 && ! FromString( vsParams[3], dScale)) - return false ; - // creo il vettore - IGeoVector3d* pGVect = CreateGeoVector3d() ; - if ( pGVect == nullptr) - return false ; - pGVect->Set( Vect * dScale) ; - return AddGeoObj( vsParams[0], vsParams[1], pGVect) ; + return VectorMake( vsParams) ; } // definizione come differenza di due punti else if ( sCmd2 == "D" || sCmd2 == "DIFF") { - // 4 o 5 parametri : Id, IdParent, ptP1, ptP2 [, bNorm] - if ( vsParams.size() != 4 && vsParams.size() != 5) - return false ; - // recupero il riferimento in cui è immerso - Frame3d frVect ; - if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect)) - return false ; - // recupero il primo punto - Point3d ptP1 ; - if ( ! GetPointParam( vsParams[2], frVect, ptP1)) - return false ; - // recupero il secondo punto - Point3d ptP2 ; - if ( ! GetPointParam( vsParams[3], frVect, ptP2)) - return false ; - // flag di normalizzazione - bool bNorm = false ; - if ( vsParams.size() >= 5) - bNorm = ( vsParams[4] == "N") ; - // creo il vettore - IGeoVector3d* pGVect = CreateGeoVector3d() ; - if ( pGVect == nullptr) - return false ; - Vector3d vtV = ptP2 - ptP1 ; - if ( bNorm) - vtV.Normalize() ; - pGVect->Set( vtV) ; - return AddGeoObj( vsParams[0], vsParams[1], pGVect) ; + return VectorDifference( vsParams) ; } // definizione come prodotto vettoriale di due vettori else if ( sCmd2 == "CP" || sCmd2 == "CROSSPROD") { - // 4 o 5 parametri : Id, IdParent, vtV1, vtV2 [, bNorm] - if ( vsParams.size() != 4 && vsParams.size() != 5) - return false ; - // recupero il riferimento in cui è immerso - Frame3d frVect ; - if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect)) - return false ; - // recupero il primo vettore - Vector3d vtV1 ; - if ( ! GetVectorParam( vsParams[2], frVect, vtV1)) - return false ; - // recupero il secondo vettore - Vector3d vtV2 ; - if ( ! GetVectorParam( vsParams[3], frVect, vtV2)) - return false ; - // flag di normalizzazione - bool bNorm = false ; - if ( vsParams.size() >= 5) - bNorm = ( vsParams[4] == "N") ; - // creo il vettore - IGeoVector3d* pGVect = CreateGeoVector3d() ; - if ( pGVect == nullptr) - return false ; - Vector3d vtCross = vtV1 ^ vtV2 ; - if ( bNorm) - vtCross.Normalize() ; - pGVect->Set( vtCross) ; - return AddGeoObj( vsParams[0], vsParams[1], pGVect) ; + return VectorCrossProduct( vsParams) ; + } + // impostazione del punto di base + else if ( sCmd2 == "B" || sCmd2 == "BASE") { + return VectorModifyBase( vsParams) ; } return false ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::VectorMake( const STRVECTOR& vsParams) +{ + // 3 o 4 parametri : Id, IdParent, Vettore [, ScaleFactor] + if ( vsParams.size() != 3 && vsParams.size() != 4) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frVect ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect)) + return false ; + // recupero i tre componenti + Vector3d Vect ; + if ( ! GetVectorParam( vsParams[2], frVect, Vect)) + return false ; + // recupero l'eventuale fattore di scala + double dScale = 1 ; + if ( vsParams.size() == 4 && ! FromString( vsParams[3], dScale)) + return false ; + // creo il vettore + IGeoVector3d* pGVect = CreateGeoVector3d() ; + if ( pGVect == nullptr) + return false ; + pGVect->Set( Vect * dScale) ; + return AddGeoObj( vsParams[0], vsParams[1], pGVect) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::VectorDifference( const STRVECTOR& vsParams) +{ + // 4 o 5 parametri : Id, IdParent, ptP1, ptP2 [, bNorm] + if ( vsParams.size() != 4 && vsParams.size() != 5) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frVect ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect)) + return false ; + // recupero il primo punto + Point3d ptP1 ; + if ( ! GetPointParam( vsParams[2], frVect, ptP1)) + return false ; + // recupero il secondo punto + Point3d ptP2 ; + if ( ! GetPointParam( vsParams[3], frVect, ptP2)) + return false ; + // flag di normalizzazione + bool bNorm = false ; + if ( vsParams.size() >= 5) + bNorm = ( vsParams[4] == "N") ; + // creo il vettore + IGeoVector3d* pGVect = CreateGeoVector3d() ; + if ( pGVect == nullptr) + return false ; + Vector3d vtV = ptP2 - ptP1 ; + if ( bNorm) + vtV.Normalize() ; + pGVect->Set( vtV) ; + return AddGeoObj( vsParams[0], vsParams[1], pGVect) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::VectorCrossProduct( const STRVECTOR& vsParams) +{ + // 4 o 5 parametri : Id, IdParent, vtV1, vtV2 [, bNorm] + if ( vsParams.size() != 4 && vsParams.size() != 5) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frVect ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect)) + return false ; + // recupero il primo vettore + Vector3d vtV1 ; + if ( ! GetVectorParam( vsParams[2], frVect, vtV1)) + return false ; + // recupero il secondo vettore + Vector3d vtV2 ; + if ( ! GetVectorParam( vsParams[3], frVect, vtV2)) + return false ; + // flag di normalizzazione + bool bNorm = false ; + if ( vsParams.size() >= 5) + bNorm = ( vsParams[4] == "N") ; + // creo il vettore + IGeoVector3d* pGVect = CreateGeoVector3d() ; + if ( pGVect == nullptr) + return false ; + Vector3d vtCross = vtV1 ^ vtV2 ; + if ( bNorm) + vtCross.Normalize() ; + pGVect->Set( vtCross) ; + return AddGeoObj( vsParams[0], vsParams[1], pGVect) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::VectorModifyBase( const STRVECTOR& vsParams) +{ + // 2 parametri : Id, ptBase + if ( vsParams.size() != 2) + return false ; + // indice dell'oggetto + int nId = GetIdParam( vsParams[0]) ; + // recupero il riferimento in cui è immerso + Frame3d frVect ; + if ( ! m_pGDB->GetGlobFrame( nId, frVect)) + return false ; + // recupero il punto di base + Point3d ptBase ; + if ( ! GetPointParam( vsParams[1], frVect, ptBase)) + return false ; + // recupero l'oggetto + IGeoVector3d* pGVect = GetGeoVector3d( m_pGDB->GetGeoObj( nId)) ; + if ( pGVect == nullptr) + return false ; + // imposto il nuovo punto di base + return pGVect->ChangeBase( ptBase) ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::ExecuteFrame( const string& sCmd2, const STRVECTOR& vsParams) @@ -436,6 +515,12 @@ GdbExecutor::ExecuteCurveLine( const string& sCmd2, const STRVECTOR& vsParams) // creazione linea da : ptStart, dDirAngDeg, dLen else if ( sCmd2 == "DL" || sCmd2 == "DirLength") return CurveLineDirLength( vsParams) ; + // creazione linea da punto tangente a curva + else if ( sCmd2 == "PTGC" || sCmd2 == "POINTTGCURVE") + return CurveLinePointTgCurve( vsParams) ; + // creazione linea tangente a 2 archi + else if ( sCmd2 == "TG2A" || sCmd2 == "TG2ARCS") + return CurveLineTgTwoArcs( vsParams) ; // creazione linea di minima distanza tra punto e curva else if ( sCmd2 == "MPC" || sCmd2 == "MINPOINTCURVE") return CurveLineMinPointCurve( vsParams) ; @@ -542,6 +627,115 @@ GdbExecutor::CurveLineDirLength( const STRVECTOR& vsParams) return AddGeoObj( vsParams[0], vsParams[1], Release( pCrvLine)) ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveLinePointTgCurve( const STRVECTOR& vsParams) +{ + // 5 parametri : Id, IdParent, ptP, IdCrv, ptNear + if ( vsParams.size() != 5) + return false ; + // recupero il riferimento del gruppo destinazione + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) + return false ; + // recupero il punto + Point3d ptStart ; + if ( ! GetPointParam( vsParams[2], frDest, ptStart)) + return false ; + // recupero l'identificativo della curva + int nId ; + if ( ( nId = GetIdParam( vsParams[3])) == CMD_ID_ERROR) + return false ; + // recupero il riferimento della curva + Frame3d frCurve ; + if ( ! m_pGDB->GetGlobFrame( nId, frCurve)) + return false ; + // recupero la curva + const ICurve* pCurve = GetCurve( m_pGDB->GetGeoObj( nId)) ; + if ( pCurve == nullptr) + return false ; + // porto il punto nel riferimento della curva + Point3d ptSloc = ptStart ; + ptSloc.LocToLoc( frDest, frCurve) ; + // recupero il punto vicino + Point3d ptNear ; + if ( ! GetPointParam( vsParams[4], frDest, ptNear)) + return false ; + Point3d ptNloc = ptNear ; + ptNloc.LocToLoc( frDest, frCurve) ; + // calcolo la retta tangente alla curva + ICurveLine* pCrvLine = GetLinePointTgCurve( ptSloc, *pCurve, ptNloc) ; + if ( pCrvLine == nullptr) + return false ; + // porto la linea nel riferimento del gruppo destinazione + pCrvLine->LocToLoc( frCurve, frDest) ; + // inserisco la linea nel DB + return AddGeoObj( vsParams[0], vsParams[1], pCrvLine) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveLineTgTwoArcs( const STRVECTOR& vsParams) +{ + // 6 parametri : Id, IdParent, IdArc1, ptNear1, IdArc2, ptNear2 + if ( vsParams.size() != 6) + return false ; + // recupero il riferimento del gruppo destinazione + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) + return false ; + // recupero l'identificativo del primo arco + int nId1 ; + if ( ( nId1 = GetIdParam( vsParams[2])) == CMD_ID_ERROR) + return false ; + // recupero il riferimento del primo arco + Frame3d frArc1 ; + if ( ! m_pGDB->GetGlobFrame( nId1, frArc1)) + return false ; + // recupero il primo arco + const ICurveArc* pArc1 = GetCurveArc( m_pGDB->GetGeoObj( nId1)) ; + if ( pArc1 == nullptr) + return false ; + // recupero il primo punto vicino e lo porto nel riferimento del primo arco + Point3d ptNear1 ; + if ( ! GetPointParam( vsParams[3], frDest, ptNear1)) + return false ; + Point3d ptN1loc = ptNear1 ; + ptN1loc.LocToLoc( frDest, frArc1) ; + // recupero l'identificativo del secondo arco + int nId2 ; + if ( ( nId2 = GetIdParam( vsParams[4])) == CMD_ID_ERROR) + return false ; + // recupero il riferimento del secondo arco + Frame3d frArc2 ; + if ( ! m_pGDB->GetGlobFrame( nId2, frArc2)) + return false ; + // recupero il secondo arco + const ICurveArc* pArc2 = GetCurveArc( m_pGDB->GetGeoObj( nId2)) ; + if ( pArc2 == nullptr) + return false ; + // porto il secondo arco nel riferimento del primo + PtrOwner pArc2Loc( CreateCurveArc()) ; + if ( ! IsValid( pArc2Loc)) + return false ; + pArc2Loc->Copy( pArc2) ; + pArc2Loc->LocToLoc( frArc2, frArc1) ; + // recupero il secondo punto vicino e lo porto nel riferimento del primo arco + Point3d ptNear2 ; + if ( ! GetPointParam( vsParams[5], frDest, ptNear2)) + return false ; + Point3d ptN2loc = ptNear2 ; + ptN2loc.LocToLoc( frDest, frArc1) ; + // calcolo la retta tangente ai due archi + ICurveLine* pCrvLine = GetLineTgTwoArcs( *pArc1, ptN1loc, *pArc2, ptN2loc) ; + if ( pCrvLine == nullptr) + return false ; + // porto la linea nel riferimento del gruppo destinazione + pCrvLine->LocToLoc( frArc1, frDest) ; + // inserisco la linea nel DB + return AddGeoObj( vsParams[0], vsParams[1], pCrvLine) ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::CurveLineMinPointCurve( const STRVECTOR& vsParams) @@ -595,6 +789,27 @@ GdbExecutor::CurveLineMinPointCurve( const STRVECTOR& vsParams) return AddGeoObj( vsParams[0], vsParams[1], Release( pCrvLine)) ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::ExecuteCurveCircle( const string& sCmd2, const STRVECTOR& vsParams) +{ + // creo circonferenza generica + if ( sCmd2 == "" || sCmd2 == "MAKE") + return CurveCircleMake( vsParams) ; + // creo circonferenza nel piano XY + else if ( sCmd2 == "XY" || sCmd2 == "PLANEXY") + return CurveCirclePlaneXY( vsParams) ; + // creo circonferenza passante per 3 punti + else if ( sCmd2 == "3P") + return CurveArcCircle3P( vsParams, true) ; + // creo circonferenza dato centro e tangente ad un arco + else if ( sCmd2 == "CTGA") + return CurveCircleCenterTgArc( vsParams) ; + // altrimenti errore + else + return false ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::ExecuteCurveArc( const string& sCmd2, const STRVECTOR& vsParams) @@ -602,18 +817,12 @@ GdbExecutor::ExecuteCurveArc( const string& sCmd2, const STRVECTOR& vsParams) // creo arco generico if ( sCmd2 == "" || sCmd2 == "MAKE") return CurveArcMake( vsParams) ; - // creo circonferenza - else if ( sCmd2 == "C" || sCmd2 == "CIRCLE") - return CurveArcCircle( vsParams) ; // creo arco nel piano XY else if ( sCmd2 == "XY" || sCmd2 == "PLANEXY") return CurveArcPlaneXY( vsParams) ; - // creo circonferenza nel piano XY - else if ( sCmd2 == "CXY" || sCmd2 == "CIRCLEXY") - return CurveArcCircleXY( vsParams) ; // creo arco o circonferenza passante per 3 punti - else if ( sCmd2 == "3P" || sCmd2 == "C3P") - return CurveArc3P( vsParams, ( sCmd2 == "C3P")) ; + else if ( sCmd2 == "3P") + return CurveArcCircle3P( vsParams, false) ; // creo arco per 2 punti e direzione iniziale else if ( sCmd2 == "2PDI") return CurveArc2PDi( vsParams) ; @@ -623,6 +832,12 @@ GdbExecutor::ExecuteCurveArc( const string& sCmd2, const STRVECTOR& vsParams) // creo arco dato centro, per primo punto e vicino al secondo else if ( sCmd2 == "C2P") return CurveArcC2P( vsParams) ; + // creo arco dato centro, tangente ad un arco e punto vicino alla fine + else if ( sCmd2 == "CTGAP") + return CurveArcCenterTgArcP( vsParams) ; + // creo arco dato punto e direzione iniziali e tangente ad altro arco + else if ( sCmd2 == "PDTGA") + return CurveArcPDiTgArc( vsParams) ; // inversione della normale else if ( sCmd2 == "INVN" || sCmd2 == "INVERTNORMAL") return CurveArcInvertNormal( vsParams) ; @@ -643,6 +858,70 @@ GdbExecutor::ExecuteCurveArc( const string& sCmd2, const STRVECTOR& vsParams) return false ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveCircleMake( const STRVECTOR& vsParams) +{ + // 5 parametri + if ( vsParams.size() != 5) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // centro + Point3d ptCen ; + if ( ! GetPointParam( vsParams[2], frRef, ptCen)) + return false ; + // versore ortogonale al piano della circonferenza + Vector3d vtN ; + if ( ! GetVectorParam( vsParams[3], frRef, vtN)) + return false ; + // raggio + double dRad ; + if ( ! GetLengthParam( vsParams[4], dRad)) + return false ; + // creo l'arco + PtrOwner pCrvArc( CreateCurveArc()) ; + if ( ! IsValid( pCrvArc)) + return false ; + // setto l'arco + if ( ! pCrvArc->Set( ptCen, vtN, dRad)) + return false ; + // inserisco l'arco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pCrvArc)) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveCirclePlaneXY( const STRVECTOR& vsParams) +{ + // 4 parametri + if ( vsParams.size() != 4) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // centro + Point3d ptCen ; + if ( ! GetPointParam( vsParams[2], frRef, ptCen)) + return false ; + // raggio + double dRad ; + if ( ! GetLengthParam( vsParams[3], dRad)) + return false ; + // creo l'arco + PtrOwner pCrvArc( CreateCurveArc()) ; + if ( ! IsValid( pCrvArc)) + return false ; + // setto l'arco + if ( ! pCrvArc->SetXY( ptCen, dRad)) + return false ; + // inserisco l'arco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pCrvArc)) ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::CurveArcMake( const STRVECTOR& vsParams) @@ -733,71 +1012,7 @@ GdbExecutor::CurveArcPlaneXY( const STRVECTOR& vsParams) //---------------------------------------------------------------------------- bool -GdbExecutor::CurveArcCircle( const STRVECTOR& vsParams) -{ - // 5 parametri - if ( vsParams.size() != 5) - return false ; - // recupero il riferimento in cui è immerso - Frame3d frRef ; - if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) - return false ; - // centro - Point3d ptCen ; - if ( ! GetPointParam( vsParams[2], frRef, ptCen)) - return false ; - // versore ortogonale al piano della circonferenza - Vector3d vtN ; - if ( ! GetVectorParam( vsParams[3], frRef, vtN)) - return false ; - // raggio - double dRad ; - if ( ! GetLengthParam( vsParams[4], dRad)) - return false ; - // creo l'arco - PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) - return false ; - // setto l'arco - if ( ! pCrvArc->Set( ptCen, vtN, dRad)) - return false ; - // inserisco l'arco nel DB - return AddGeoObj( vsParams[0], vsParams[1], Release( pCrvArc)) ; -} - -//---------------------------------------------------------------------------- -bool -GdbExecutor::CurveArcCircleXY( const STRVECTOR& vsParams) -{ - // 4 parametri - if ( vsParams.size() != 4) - return false ; - // recupero il riferimento in cui è immerso - Frame3d frRef ; - if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) - return false ; - // centro - Point3d ptCen ; - if ( ! GetPointParam( vsParams[2], frRef, ptCen)) - return false ; - // raggio - double dRad ; - if ( ! GetLengthParam( vsParams[3], dRad)) - return false ; - // creo l'arco - PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) - return false ; - // setto l'arco - if ( ! pCrvArc->SetXY( ptCen, dRad)) - return false ; - // inserisco l'arco nel DB - return AddGeoObj( vsParams[0], vsParams[1], Release( pCrvArc)) ; -} - -//---------------------------------------------------------------------------- -bool -GdbExecutor::CurveArc3P( const STRVECTOR& vsParams, bool bCirc) +GdbExecutor::CurveArcCircle3P( const STRVECTOR& vsParams, bool bCirc) { // 5 parametri : Id, ParentId, ptP0, ptP1, ptP2 if ( vsParams.size() != 5) @@ -852,15 +1067,12 @@ GdbExecutor::CurveArc2PDi( const STRVECTOR& vsParams) double dDirI ; if ( ! GetDirParam( vsParams[4], frRef, dDirI)) return false ; - // creo l'arco - PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) - return false ; - // setto l'arco - if ( ! pCrvArc->Set2PD( ptPi, ptPf, dDirI)) + // calcolo l'arco (in casi particolari può essere una retta) + ICurve* pCurve = GetArc2PD( ptPi, ptPf, dDirI) ; + if ( pCurve == nullptr) return false ; // inserisco l'arco nel DB - return AddGeoObj( vsParams[0], vsParams[1], Release( pCrvArc)) ; + return AddGeoObj( vsParams[0], vsParams[1], pCurve) ; } //---------------------------------------------------------------------------- @@ -935,6 +1147,154 @@ GdbExecutor::CurveArcC2P( const STRVECTOR& vsParams) return AddGeoObj( vsParams[0], vsParams[1], Release( pCrvArc)) ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveCircleCenterTgArc( const STRVECTOR& vsParams) +{ + // 5 parametri : Id, ParentId, ptCen, IdArc, ptNear + if ( vsParams.size() != 5) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) + return false ; + // centro + Point3d ptCen ; + if ( ! GetPointParam( vsParams[2], frDest, ptCen)) + return false ; + // recupero l'identificativo dell'arco di tangenza + int nId ; + if ( ( nId = GetIdParam( vsParams[3])) == CMD_ID_ERROR) + return false ; + // recupero il riferimento dell'arco di tangenza + Frame3d frTgArc ; + if ( ! m_pGDB->GetGlobFrame( nId, frTgArc)) + return false ; + // recupero l'arco di tangenza + const ICurveArc* pTgArc = GetCurveArc( m_pGDB->GetGeoObj( nId)) ; + if ( pTgArc == nullptr) + return false ; + // porto il centro nel riferimento dell'arco di tangenza + Point3d ptCloc = ptCen ; + ptCloc.LocToLoc( frDest, frTgArc) ; + // recupero il punto vicino + Point3d ptNear ; + if ( ! GetPointParam( vsParams[4], frDest, ptNear)) + return false ; + Point3d ptNloc = ptNear ; + ptNloc.LocToLoc( frDest, frTgArc) ; + // calcolo la circonferenza tangente all'arco + ICurveArc* pNewArc = GetCircleCenTgArc( ptCloc, *pTgArc, ptNloc) ; + if ( pNewArc == nullptr) + return false ; + // porto il nuovo arco nel riferimento del gruppo destinazione + pNewArc->LocToLoc( frTgArc, frDest) ; + // inserisco la linea nel DB + return AddGeoObj( vsParams[0], vsParams[1], pNewArc) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveArcCenterTgArcP( const STRVECTOR& vsParams) +{ + // 6 parametri : Id, ParentId, ptCen, IdArc, ptNearTg, ptNearEnd + if ( vsParams.size() != 6) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) + return false ; + // centro + Point3d ptCen ; + if ( ! GetPointParam( vsParams[2], frDest, ptCen)) + return false ; + // recupero l'identificativo dell'arco di tangenza + int nId ; + if ( ( nId = GetIdParam( vsParams[3])) == CMD_ID_ERROR) + return false ; + // recupero il riferimento dell'arco di tangenza + Frame3d frTgArc ; + if ( ! m_pGDB->GetGlobFrame( nId, frTgArc)) + return false ; + // recupero l'arco di tangenza + const ICurveArc* pTgArc = GetCurveArc( m_pGDB->GetGeoObj( nId)) ; + if ( pTgArc == nullptr) + return false ; + // porto il centro nel riferimento dell'arco di tangenza + Point3d ptCloc = ptCen ; + ptCloc.LocToLoc( frDest, frTgArc) ; + // recupero il punto vicino alla tg + Point3d ptNear ; + if ( ! GetPointParam( vsParams[4], frDest, ptNear)) + return false ; + Point3d ptNtloc = ptNear ; + ptNtloc.LocToLoc( frDest, frTgArc) ; + // recupero il punto vicino alla fine + Point3d ptNearEnd ; + if ( ! GetPointParam( vsParams[5], frDest, ptNear)) + return false ; + Point3d ptNeloc = ptNear ; + ptNeloc.LocToLoc( frDest, frTgArc) ; + // calcolo la circonferenza tangente all'arco + ICurveArc* pNewArc = GetArcCenTgArcPnt( ptCloc, *pTgArc, ptNtloc, ptNeloc) ; + if ( pNewArc == nullptr) + return false ; + // porto il nuovo arco nel riferimento del gruppo destinazione + pNewArc->LocToLoc( frTgArc, frDest) ; + // inserisco la linea nel DB + return AddGeoObj( vsParams[0], vsParams[1], pNewArc) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveArcPDiTgArc( const STRVECTOR& vsParams) +{ + // 6 parametri : Id, ParentId, ptStart, dirStart, IdArc, ptNear + if ( vsParams.size() != 6) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) + return false ; + // punto iniziale + Point3d ptStart ; + if ( ! GetPointParam( vsParams[2], frDest, ptStart)) + return false ; + // direzione iniziale + double dDirI ; + if ( ! GetDirParam( vsParams[3], frDest, dDirI)) + return false ; + // recupero l'identificativo dell'arco di tangenza + int nId ; + if ( ( nId = GetIdParam( vsParams[4])) == CMD_ID_ERROR) + return false ; + // recupero il riferimento dell'arco di tangenza + Frame3d frTgArc ; + if ( ! m_pGDB->GetGlobFrame( nId, frTgArc)) + return false ; + // recupero l'arco di tangenza + const ICurveArc* pTgArc = GetCurveArc( m_pGDB->GetGeoObj( nId)) ; + if ( pTgArc == nullptr) + return false ; + // porto il punto di inizio nel riferimento dell'arco di tangenza + Point3d ptSloc = ptStart ; + ptSloc.LocToLoc( frDest, frTgArc) ; + // recupero il punto vicino alla tg + Point3d ptNear ; + if ( ! GetPointParam( vsParams[5], frDest, ptNear)) + return false ; + Point3d ptNtloc = ptNear ; + ptNtloc.LocToLoc( frDest, frTgArc) ; + // calcolo l'arco (in casi particolari può essere una linea) + ICurve* pCurve = GetArcPntDirTgArc( ptSloc, dDirI, *pTgArc, ptNtloc) ; + if ( pCurve == nullptr) + return false ; + // porto il nuovo arco nel riferimento del gruppo destinazione + pCurve->LocToLoc( frTgArc, frDest) ; + // inserisco la linea nel DB + return AddGeoObj( vsParams[0], vsParams[1], pCurve) ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::CurveArcInvertNormal( const STRVECTOR& vsParams) @@ -2158,7 +2518,7 @@ GdbExecutor::AddGeoObj( const string& sId, const string& sIdParent, IGeoObj* pGe // creo il gruppo int nId = GetIdParam( sId, true) ; int nIdNew = m_pGDB->AddGeoObj( nId, GetIdParam( sIdParent), pGeoObj) ; - // se IdDest da calcolare, può essere una variabili a cui cambiare il valore + // se nId da calcolare, può essere una variabile a cui cambiare il valore if ( nId == GDB_ID_NULL) m_pParser->SetVariable( sId, nIdNew) ; @@ -3972,8 +4332,11 @@ GdbExecutor::ExecuteOutTsc( const string& sCmd2, const STRVECTOR& vsParams) // 1 parametro if ( vsParams.size() != 1) return false ; + // eventuale conversione di token nel nome file + string sFile = vsParams[0] ; + m_pParser->DirReplace( sFile) ; // apro il file e scrivo intestazione - return m_OutTsc.Open( vsParams[0]) ; + return m_OutTsc.Open( sFile) ; } // chiudo il file di uscita Tsc else if ( sCmd2 == "CLOSE") { diff --git a/GdbExecutor.h b/GdbExecutor.h index 8d86f9b..31380ed 100644 --- a/GdbExecutor.h +++ b/GdbExecutor.h @@ -53,21 +53,31 @@ class GdbExecutor : public IGdbExecutor bool ExecuteGroup( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecutePoint( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteVector( const std::string& sCmd2, const STRVECTOR& vsParams) ; + bool VectorMake( const STRVECTOR& vsParams) ; + bool VectorDifference( const STRVECTOR& vsParams) ; + bool VectorCrossProduct( const STRVECTOR& vsParams) ; + bool VectorModifyBase( const STRVECTOR& vsParams) ; bool ExecuteFrame( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteCurveLine( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool CurveLineMake( const STRVECTOR& vsParams) ; bool CurveLineVersorLength( const STRVECTOR& vsParams) ; bool CurveLineDirLength( const STRVECTOR& vsParams) ; + bool CurveLinePointTgCurve( const STRVECTOR& vsParams) ; + bool CurveLineTgTwoArcs( const STRVECTOR& vsParams) ; bool CurveLineMinPointCurve( const STRVECTOR& vsParams) ; + bool ExecuteCurveCircle( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteCurveArc( const std::string& sCmd2, const STRVECTOR& vsParams) ; + bool CurveCircleMake( const STRVECTOR& vsParams) ; + bool CurveCirclePlaneXY( const STRVECTOR& vsParams) ; bool CurveArcMake( const STRVECTOR& vsParams) ; bool CurveArcPlaneXY( const STRVECTOR& vsParams) ; - bool CurveArcCircle( const STRVECTOR& vsParams) ; - bool CurveArcCircleXY( const STRVECTOR& vsParams) ; - bool CurveArc3P( const STRVECTOR& vsParams, bool bCirc) ; + bool CurveArcCircle3P( const STRVECTOR& vsParams, bool bCirc) ; bool CurveArc2PDi( const STRVECTOR& vsParams) ; bool CurveArc2PRS( const STRVECTOR& vsParams) ; bool CurveArcC2P( const STRVECTOR& vsParams) ; + bool CurveCircleCenterTgArc( const STRVECTOR& vsParams) ; + bool CurveArcCenterTgArcP( const STRVECTOR& vsParams) ; + bool CurveArcPDiTgArc( const STRVECTOR& vsParams) ; bool CurveArcInvertNormal( const STRVECTOR& vsParams) ; bool CurveArcChangeRadius( const STRVECTOR& vsParams) ; bool CurveArcChangeDeltaN( const STRVECTOR& vsParams) ; diff --git a/GeoVector3d.cpp b/GeoVector3d.cpp index 91aa012..58a8518 100644 --- a/GeoVector3d.cpp +++ b/GeoVector3d.cpp @@ -43,6 +43,21 @@ GeoVector3d::Set( const Vector3d& vtV) { // assegno i dati m_vtV = vtV ; + m_ptBase = ORIG ; + + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +GeoVector3d::Set( const Vector3d& vtV, const Point3d& ptBase) +{ + // assegno i dati + m_vtV = vtV ; + m_ptBase = ptBase ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -82,7 +97,7 @@ GeoVector3d::Copy( const GeoVector3d& clSrc) { if ( &clSrc == this) return true ; - return Set( clSrc.m_vtV) ; + return Set( clSrc.m_vtV, clSrc.m_ptBase) ; } //---------------------------------------------------------------------------- @@ -106,6 +121,7 @@ GeoVector3d::Dump( string& sOut, const char* szNewLine) const { // parametri : vettore sOut += "V(" + ToString( m_vtV) + ")" + szNewLine ; + sOut += "base(" + ToString( m_ptBase) + ")" + szNewLine ; return true ; } @@ -122,7 +138,8 @@ bool GeoVector3d::Save( NgeWriter& ngeOut) const { // parametri : vettore - ngeOut.WriteVector( m_vtV, ";", true) ; + ngeOut.WriteVector( m_vtV, ";") ; + ngeOut.WritePoint( m_ptBase, ";", true) ; return true ; } @@ -134,15 +151,19 @@ GeoVector3d::Load( NgeReader& ngeIn) // imposto ricalcolo della grafica m_OGrMgr.Reset() ; // leggo la prossima linea - return ngeIn.ReadVector( m_vtV, ";", true) ; + if ( ! ngeIn.ReadVector( m_vtV, ";")) + return false ; + if ( ! ngeIn.ReadPoint( m_ptBase, ";", true)) + return false ; + return true ; } //---------------------------------------------------------------------------- bool GeoVector3d::GetLocalBBox( BBox3d& b3Loc) const { - // reset del box (un versore non occupa posizioni nello spazio) - b3Loc.Reset() ; + // il box tiene conto della posizione della base e del tip + b3Loc.Set( m_ptBase, m_ptBase + m_vtV) ; return true ; } @@ -153,21 +174,39 @@ GeoVector3d::GetBBox( const Frame3d& frRef, BBox3d& b3Ref) const // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; - // reset del box (un versore non occupa posizioni nello spazio) - b3Ref.Reset() ; + // porto la base e il tip nel riferimento passato + Point3d ptFrBase = m_ptBase ; + ptFrBase.ToGlob( frRef) ; + Point3d ptFrTip = m_ptBase + m_vtV ; + ptFrTip.ToGlob( frRef) ; + // assegno il box nel riferimento + b3Ref.Set( ptFrBase, ptFrTip) ; return true ; } //---------------------------------------------------------------------------- bool -GeoVector3d::GetDrawWithArrowHead( double dFrazLenAH, PolyLine& PL) const +GeoVector3d::ChangeBase( const Point3d& ptBase) +{ + // assegno i dati + m_ptBase = ptBase ; + + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +GeoVector3d::GetDrawWithArrowHead( double dFrazLenAH, double dMaxDimA, PolyLine& PL) const { // vettore - PL.AddUPoint( 0, ORIG) ; - Point3d ptTip = ORIG + m_vtV ; + PL.AddUPoint( 0, m_ptBase) ; + Point3d ptTip = m_ptBase + m_vtV ; PL.AddUPoint( 1, ptTip) ; // doppia freccia - double dLenAH = dFrazLenAH * m_vtV.Len() ; + double dLenAH = min( dMaxDimA, dFrazLenAH * m_vtV.Len()) ; Frame3d frF ; frF.Set( ptTip, m_vtV) ; Point3d ptP1 = ORIG + Vector3d( 0.5, 0, -1) * dLenAH ; diff --git a/GeoVector3d.h b/GeoVector3d.h index 7934dfb..93649c8 100644 --- a/GeoVector3d.h +++ b/GeoVector3d.h @@ -1,13 +1,13 @@ //---------------------------------------------------------------------------- -// EgalTech 2013-2013 +// EgalTech 2013-2014 //---------------------------------------------------------------------------- -// File : GeoVector3d.h Data : 22.11.13 Versione : 1.3a1 +// File : GeoVector3d.h Data : 11.06.14 Versione : 1.5f4 // Contenuto : Dichiarazione della classe Vettore Geometrico 3d. // // // // Modifiche : 10.10.13 DS Creazione modulo. -// +// 11.06.14 DS Agg. punto Base. // //---------------------------------------------------------------------------- @@ -62,9 +62,13 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW public : // IGeoVector3d virtual bool Copy( const IGeoObj* pGObjSrc) ; virtual bool Set( const Vector3d& vtV) ; + virtual bool Set( const Vector3d& vtV, const Point3d& ptBase) ; virtual const Vector3d& GetVector( void) const { return m_vtV ; } - virtual bool GetDrawWithArrowHead( double dFrazLenAH, PolyLine& PL) const ; + virtual const Point3d& GetBase( void) const + { return m_ptBase ; } + virtual bool ChangeBase( const Point3d& ptBase) ; + virtual bool GetDrawWithArrowHead( double dFrazLenAH, double dMaxDimA, PolyLine& PL) const ; public : // IGeoObjRW virtual int GetNgeId( void) const ; @@ -84,4 +88,5 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto Vector3d m_vtV ; // oggetto + Point3d m_ptBase ; // punto base da cui tracciare il vettore } ; diff --git a/LinePntTgCurve.cpp b/LinePntTgCurve.cpp new file mode 100644 index 0000000..b7d4e04 --- /dev/null +++ b/LinePntTgCurve.cpp @@ -0,0 +1,160 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2014 +//---------------------------------------------------------------------------- +// File : LinePntTgCurve.cpp Data : 09.06.14 Versione : 1.5f4 +// Contenuto : Implementazione funzioni per calcolo rette tangenti a curve. +// +// +// +// Modifiche : 09.06.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "LinePntTgCurve.h" +#include "/EgtDev/Include/EgkGeoCollection.h" +#include "/EgtDev/Include/EgkLinePntTgCurve.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +ICurveLine* +GetLinePointTgCurve( const Point3d& ptP, const ICurve& cCrv, const Point3d& ptNear) +{ + switch ( cCrv.GetType()) { + case CRV_LINE : + return nullptr ; + case CRV_ARC : + { const ICurveArc& crvArc = *GetCurveArc( &cCrv) ; + return GetLinePointTgArc( ptP, crvArc, ptNear) ; } + case CRV_BEZ : + return nullptr ; + case CRV_COMPO : + return nullptr ; + default : + return nullptr ; + } +} + +//---------------------------------------------------------------------------- +ICurveLine* +GetLinePointTgArc( const Point3d& ptP, 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 ptPLoc = ptP ; + ptPLoc.ToLoc( frIntr) ; + + // calcolo le linee tangenti alla circonferenza + BIPNTVECTOR vBiPnt( 2) ; + int nSol = CalcLinePointTgCircle( ptPLoc, ORIG, crvArc.GetRadius(), vBiPnt) ; + if ( nSol == 0) + return nullptr ; + + // porto i punti nel riferimento standard dell'arco + for ( size_t i = 0 ; i < vBiPnt.size() ; ++ i) { + vBiPnt[i].first.ToGlob( frIntr) ; + vBiPnt[i].second.ToGlob( frIntr) ; + } + + // elimino le soluzioni che non stanno sull'arco + for ( int i = 1 ; i >= 0 ; -- i) { + if ( nSol > i) { + if ( ! crvArc.IsPointOn( vBiPnt[i].second)) { + -- nSol ; + for ( int j = i ; j < nSol ; ++ j) + vBiPnt[j] = vBiPnt[j+1] ; + } + } + } + + // se non sono rimaste soluzioni, esco + if ( nSol == 0) + return nullptr ; + + // scelgo la soluzione più vicina al punto di riferimento + int nIdOk = 0 ; + double dMinSqDist = INFINITO * INFINITO ; + for ( int i = 0 ; i < nSol ; ++ i) { + double dSqDist = SqDist( vBiPnt[i].second, ptNear) ; + if ( dSqDist < dMinSqDist) { + dMinSqDist = dSqDist ; + nIdOk = i ; + } + } + + // creo la linea + PtrOwner pCrvLine( CreateCurveLine()) ; + if ( ! IsValid( pCrvLine)) + return nullptr ; + + // costruisco la linea corrispondente alla soluzione scelta + if ( pCrvLine->Set( vBiPnt[nIdOk].first, vBiPnt[nIdOk].second)) + return Release( pCrvLine) ; + else + return nullptr ; +} + +//---------------------------------------------------------------------------- +int +CalcLinePointTgCircle( const Point3d& ptP, const Point3d& ptCen, double dRad, BIPNTVECTOR& vBiPnt) +{ + // --- si lavora nel piano XY --- + + // svuoto il vettore dei risultati (sono coppie di punti) + vBiPnt.clear() ; + + // se il raggio è negativo non ci sono soluzioni + if ( dRad < - EPS_SMALL) + return 0 ; + + // vettore dal punto al centro nel piano XY e relativa lunghezza/distanza + Vector3d vtPC = ptCen - ptP ; + vtPC.z = 0 ; + double dDist = vtPC.Len() ; + + // se il raggio è nullo ... + if ( dRad < EPS_SMALL) { + // se la distanza tra i punti è significativa, c'è una soluzione : la retta per i due punti + if ( dDist > EPS_SMALL) { + vBiPnt.push_back( make_pair( ptP, ptCen)) ; + return 1 ; + } + // altrimenti, nessuna soluzione + else + return 0 ; + } + + // se la distanza è inferiore o uguale al raggio non ci sono soluzioni (si esclude la retta tg nel punto P) + if ( dDist < dRad + EPS_SMALL) + return 0 ; + + // lunghezza delle tangenti + double dLen = sqrt( dDist * dDist - dRad * dRad) ; + + // punto a metà tra i punti di tangenza + Point3d ptK = ptP + vtPC * ( dLen * dLen / ( dDist * dDist)) ; + + // vettore ortogonale + Vector3d vtOrtho = vtPC * ( dRad * dLen / ( dDist * dDist)) ; + vtOrtho.Rotate( Z_AX, 0, 1) ; + + // tangente a destra + Point3d ptT = ptK + vtOrtho ; + ptT.z = ptCen.z ; + vBiPnt.push_back( make_pair( ptP, ptT)) ; + + // tangente a sinistra + ptT = ptK - vtOrtho ; + ptT.z = ptCen.z ; + vBiPnt.push_back( make_pair( ptP, ptT)) ; + + return 2 ; +} diff --git a/LinePntTgCurve.h b/LinePntTgCurve.h new file mode 100644 index 0000000..b795907 --- /dev/null +++ b/LinePntTgCurve.h @@ -0,0 +1,20 @@ +//---------------------------------------------------------------------------- +// EgalTech 2014-2014 +//---------------------------------------------------------------------------- +// File : LinePntTgCurve.h Data : 10.06.14 Versione : 1.5f3 +// Contenuto : Dichiarazione funzioni di base per calcolo rette tangenti a curve. +// +// +// +// Modifiche : 10.06.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EGkGeoCollection.h" + + +//---------------------------------------------------------------------------- +int CalcLinePointTgCircle( const Point3d& ptP, const Point3d& ptCen, double dRad, BIPNTVECTOR& vBiPnt) ; diff --git a/LineTgTwoArcs.cpp b/LineTgTwoArcs.cpp new file mode 100644 index 0000000..ad7e40e --- /dev/null +++ b/LineTgTwoArcs.cpp @@ -0,0 +1,241 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2014 +//---------------------------------------------------------------------------- +// File : LineTgArc.cpp Data : 09.06.14 Versione : 1.5f4 +// Contenuto : Implementazione funzioni per calcolo rette tangenti a circonferenze +// +// +// +// Modifiche : 09.06.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "LinePntTgCurve.h" +#include "CurveArc.h" +#include "/EgtDev/Include/EgkGeoCollection.h" +#include "/EgtDev/Include/EgkLineTgTwoArcs.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +static int CalcLineExtTg2Circles( const Point3d& ptC1, double dRad1, const Point3d& ptC2, double dRad2, BIPNTVECTOR& vBiPnt) ; +static int CalcLineIntTg2Circles( const Point3d& ptC1, double dRad1, const Point3d& ptC2, double dRad2, BIPNTVECTOR& vBiPnt) ; +static int CalcLineTg2Circles( const Point3d& ptC1, double dRad1, const Point3d& ptC2, double dRad2, BIPNTVECTOR& vBiPnt) ; + +//---------------------------------------------------------------------------- +ICurveLine* +GetLineTgTwoArcs( const ICurveArc& crvArc1, const Point3d& ptNear1, + const ICurveArc& crvArc2, const Point3d& ptNear2) +{ + // verifico che i due archi abbiano lo stesso piano intrinseco + if ( ! AreSameVectorNear( crvArc1.GetNormVersor(), crvArc2.GetNormVersor()) && + ! AreOppositeVectorNear( crvArc1.GetNormVersor(), crvArc2.GetNormVersor())) + return nullptr ; + + // calcolo il riferimento intrinseco del primo arco (Z->DirNorm e X->DirStart) + Frame3d frIntr ; + if ( ! frIntr.Set( crvArc1.GetCenter(), crvArc1.GetNormVersor(), crvArc1.GetStartVersor())) + return nullptr ; + + // porto il secondo arco nel riferimento intrinseco del primo + CurveArc crvArc2Loc = dynamic_cast( crvArc2) ; + crvArc2Loc.ToLoc( frIntr) ; + + // calcolo le linee di tangenza alle due circonferenze + BIPNTVECTOR vBiPnt( 4) ; + int nSol = CalcLineTg2Circles( ORIG, crvArc1.GetRadius(), crvArc2Loc.GetCenter(), crvArc2Loc.GetRadius(), vBiPnt) ; + if ( nSol == 0) + return nullptr ; + + // porto i punti nel riferimento standard dell'arco + for ( size_t i = 0 ; i < vBiPnt.size() ; ++ i) { + vBiPnt[i].first.ToGlob( frIntr) ; + vBiPnt[i].second.ToGlob( frIntr) ; + } + + // elimino le soluzioni che non stanno sull'arco + for ( int i = 3 ; i >= 0 ; -- i) { + if ( nSol > i) { + if ( ! crvArc1.IsPointOn( vBiPnt[i].first) || + ! crvArc2.IsPointOn( vBiPnt[i].second)) { + -- nSol ; + for ( int j = i ; j < nSol ; ++ j) + vBiPnt[j] = vBiPnt[j+1] ; + } + } + } + + // se non sono rimaste soluzioni, esco + if ( nSol == 0) + return nullptr ; + + // scelgo la soluzione più vicina ai punti di riferimento + int nIdOk = 0 ; + double dMinDist = INFINITO ; + for ( int i = 0 ; i < nSol ; ++ i) { + double dDist = Dist( vBiPnt[i].first, ptNear1) + Dist( vBiPnt[i].second, ptNear2) ; + if ( dDist < dMinDist) { + dMinDist = dDist ; + nIdOk = i ; + } + } + + // creo la linea + PtrOwner pCrvLine( CreateCurveLine()) ; + if ( ! IsValid( pCrvLine)) + return nullptr ; + + // costruisco la linea corrispondente alla soluzione scelta + if ( pCrvLine->Set( vBiPnt[nIdOk].first, vBiPnt[nIdOk].second)) + return Release( pCrvLine) ; + else + return nullptr ; +} + +//---------------------------------------------------------------------------- +int +CalcLineExtTg2Circles( const Point3d& ptC1, double dRad1, const Point3d& ptC2, double dRad2, BIPNTVECTOR& vBiPnt) +{ + // deve essere dRad2 >= dRad1 + if ( dRad2 < dRad1) + return 0 ; + + // inizializzo il numero di soluzioni + int nSol = 0 ; + + // tangenti p.to - circonf. riducendo le circonferenze della differenza dei raggi + BIPNTVECTOR vAuxBiPnt( 2) ; + int nSol1 = CalcLinePointTgCircle( ptC1, ptC2, ( dRad2 - dRad1), vAuxBiPnt) ; + + // offsetto i risultati di dRad1 + if ( nSol1 == 1) { + Vector3d vtDir ; + Point3d ptT1, ptT2 ; + // direzione della retta + vtDir = ptC2 - ptC1 ; + vtDir.Normalize() ; + vtDir.Rotate( Z_AX, 0, 1) ; + vtDir *= dRad1 ; + // offset a sinistra + ptT1 = ptC1 + vtDir ; + ptT2 = ptC2 + vtDir ; + vBiPnt.push_back( make_pair( ptT1, ptT2)) ; + ++ nSol ; + // offset a destra + ptT1 = ptC1 - vtDir ; + ptT2 = ptC2 - vtDir ; + vBiPnt.push_back( make_pair( ptT1, ptT2)) ; + ++ nSol ; + } + else if ( nSol1 == 2) { + Vector3d vtDir ; + Point3d ptT1, ptT2 ; + // direzione di offset della prima retta + vtDir = vAuxBiPnt[0].second - ptC2 ; + vtDir *= dRad1 / ( dRad2 - dRad1) ; + // punti della prima retta + ptT1 = ptC1 + vtDir ; + ptT2 = vAuxBiPnt[0].second + vtDir ; + vBiPnt.push_back( make_pair( ptT1, ptT2)) ; + ++ nSol ; + // direzione di offset della seconda retta + vtDir = vAuxBiPnt[1].second - ptC2 ; + vtDir *= dRad1 / ( dRad2 - dRad1) ; + // punti della seconda retta + ptT1 = ptC1 + vtDir ; + ptT2 = vAuxBiPnt[1].second + vtDir ; + vBiPnt.push_back( make_pair( ptT1, ptT2)) ; + ++ nSol ; + } + + return nSol ; +} + +//---------------------------------------------------------------------------- +int +CalcLineIntTg2Circles( const Point3d& ptC1, double dRad1, const Point3d& ptC2, double dRad2, BIPNTVECTOR& vBiPnt) +{ + // inizializzo il numero di soluzioni + int nSol = 0 ; + + // tangenti p.to - circonf. riducendo la prima a un punto e aumentando la prima di dRad1 + BIPNTVECTOR vAuxBiPnt( 2) ; + int nSol1 = CalcLinePointTgCircle( ptC1, ptC2, ( dRad2 + dRad1), vAuxBiPnt) ; + + // non può esserci una sola soluzione + if ( nSol1 == 1) { + nSol = 0 ; + } + // sposto le rette di dRad1 + else if ( nSol1 == 2) { + Vector3d vtDir ; + Point3d ptT1, ptT2 ; + // direzione di offset della prima retta + vtDir = ptC2 - vAuxBiPnt[0].second ; + vtDir *= dRad1 / ( dRad1 + dRad2) ; + // punti della prima retta + ptT1 = ptC1 + vtDir ; + ptT2 = vAuxBiPnt[0].second + vtDir ; + vBiPnt.push_back( make_pair( ptT1, ptT2)) ; + ++ nSol ; + // direzione di offset della seconda retta + vtDir = ptC2 - vAuxBiPnt[1].second ; + vtDir *= dRad1 / ( dRad1 + dRad2) ; + // punti della seconda retta + ptT1 = ptC1 + vtDir ; + ptT2 = vAuxBiPnt[1].second + vtDir ; + vBiPnt.push_back( make_pair( ptT1, ptT2)) ; + ++ nSol ; + } + + return nSol ; +} + +//---------------------------------------------------------------------------- +int +CalcLineTg2Circles( const Point3d& ptC1, double dRad1, const Point3d& ptC2, double dRad2, BIPNTVECTOR& vBiPnt) +{ + // --- si lavora nel piano XY --- + + // svuoto il vettore dei risultati (sono coppie di punti) + vBiPnt.clear() ; + + // se uno dei due raggi è negativo non ci sono soluzioni + if ( dRad1 < - EPS_SMALL || dRad2 < - EPS_SMALL) + return 0 ; + + // se almeno uno dei due raggi è nullo, si cade nel caso di linea per p.to tangente a circonferenza + if ( dRad1 < EPS_SMALL) + return CalcLinePointTgCircle( ptC1, ptC2, dRad2, vBiPnt) ; + else if ( dRad2 < EPS_SMALL) { + int nSol = CalcLinePointTgCircle( ptC2, ptC1, dRad1, vBiPnt) ; + if ( nSol >= 1) + swap( vBiPnt[0].first, vBiPnt[0].second) ; + if ( nSol == 2) + swap( vBiPnt[1].first, vBiPnt[1].second) ; + } + + // numero di soluzioni trovate (il numero di punti è il doppio) + int nSol = 0 ; + + // calcolo delle tangenti esterne + if ( dRad2 >= dRad1) { + nSol += CalcLineExtTg2Circles( ptC1, dRad1, ptC2, dRad2, vBiPnt) ; + } + else { + nSol += CalcLineExtTg2Circles( ptC2, dRad2, ptC1, dRad1, vBiPnt) ; + if ( nSol >= 1) + swap( vBiPnt[0].first, vBiPnt[0].second) ; + if ( nSol == 2) + swap( vBiPnt[1].first, vBiPnt[1].second) ; + } + + // calcolo delle tangenti interne + nSol += CalcLineIntTg2Circles( ptC1, dRad1, ptC2, dRad2, vBiPnt) ; + + return nSol ; +} \ No newline at end of file diff --git a/OutTsc.cpp b/OutTsc.cpp index f63b6f8..e811ac9 100644 --- a/OutTsc.cpp +++ b/OutTsc.cpp @@ -208,10 +208,10 @@ OutTsc::NewGroupRef( const Frame3d& frFrame, int nLev) // creo il gruppo del layer m_ofFile << "GR( " << ToString( m_nGroup.top()) << ", " << sParent << ", " ; - m_ofFile << "(" << ToString( frFrame.Orig()) << "), " ; + m_ofFile << "((" << ToString( frFrame.Orig()) << "), " ; m_ofFile << "(" << ToString( frFrame.VersX()) << "), " ; m_ofFile << "(" << ToString( frFrame.VersY()) << "), " ; - m_ofFile << "(" << ToString( frFrame.VersZ()) << "))" << endl ; + m_ofFile << "(" << ToString( frFrame.VersZ()) << ")))" << endl ; // emetto il materiale PutMaterial( m_nGroup.top(), true) ; @@ -285,10 +285,10 @@ OutTsc::Frame( const Frame3d& frF) // emetto riferimento m_ofFile << "FR( " << ToString( m_nId) << ", " << ToString( m_nGroup.top()) << ", " ; - m_ofFile << "(" << ToString( frF.Orig()) << "), " ; + m_ofFile << "((" << ToString( frF.Orig()) << "), " ; m_ofFile << "(" << ToString( frF.VersX()) << "), " ; m_ofFile << "(" << ToString( frF.VersY()) << "), " ; - m_ofFile << "(" << ToString( frF.VersZ()) << "))" << endl ; + m_ofFile << "(" << ToString( frF.VersZ()) << ")))" << endl ; // non usa materiale diff --git a/Vector3d.cpp b/Vector3d.cpp index d5dd83f..6869173 100644 --- a/Vector3d.cpp +++ b/Vector3d.cpp @@ -75,14 +75,11 @@ Vector3d::Len( void) const void Vector3d::ToSpherical( double* pdLen, double* pdAngVertDeg, double* pdAngOrizzDeg) const { - double dLen ; + // lunghezza + double dLen = Len() ; + // angoli double dAngVertDeg ; double dAngOrizzDeg ; - - - // lunghezza - dLen = Len() ; - // se vettore nullo if ( dLen < EPS_ZERO) { dAngVertDeg = 0 ; @@ -126,21 +123,17 @@ Vector3d::ToSpherical( double* pdLen, double* pdAngVertDeg, double* pdAngOrizzDe bool Vector3d::Normalize( double dEps) { - double dSqLen ; - double dLen ; - - // se già normalizzato, ok - dSqLen = x * x + y * y + z * z ; + double dSqLen = x * x + y * y + z * z ; if ( fabs( 1.0 - dSqLen) < ( 2 * EPS_ZERO)) return true ; // se troppo piccolo, errore - if ( fabs( dSqLen) < ( dEps * dEps)) + if ( dSqLen < ( dEps * dEps)) return false ; // eseguo la normalizzazione - dLen = sqrt( dSqLen) ; + double dLen = sqrt( dSqLen) ; *this = *this / dLen ; return true ; @@ -167,6 +160,68 @@ Vector3d::Rotate( const Vector3d& vtAx, double dCosAng, double dSinAng) if ( ! vtDirAx.Normalize()) return false ; + // se rotazione attorno all'asse Z+ + if ( vtAx.IsZplus()) { + // salvo i componenti originali + double dX = x ; + double dY = y ; + // calcolo i nuovi componenti ruotati + x = dCosAng * dX - dSinAng * dY ; + y = dSinAng * dX + dCosAng * dY ; + return true ; + } + // se rotazione attorno all'asse Z- + else if ( vtAx.IsZminus()) { + // salvo i componenti originali + double dX = x ; + double dY = y ; + // calcolo i nuovi componenti ruotati + x = dCosAng * dX + dSinAng * dY ; + y = - dSinAng * dX + dCosAng * dY ; + return true ; + } + // se rotazione attorno all'asse X+ + else if ( vtAx.IsXplus()) { + // salvo i componenti originali + double dY = y ; + double dZ = z ; + // calcolo i nuovi componenti ruotati + y = dCosAng * dY - dSinAng * dZ ; + z = dSinAng * dY + dCosAng * dZ ; + return true ; + } + // se rotazione attorno all'asse X- + else if ( vtAx.IsXminus()) { + // salvo i componenti originali + double dY = y ; + double dZ = z ; + // calcolo i nuovi componenti ruotati + y = dCosAng * dY + dSinAng * dZ ; + z = - dSinAng * dY + dCosAng * dZ ; + return true ; + } + // se rotazione attorno all'asse Y+ + else if ( vtAx.IsYplus()) { + // salvo i componenti originali + double dZ = z ; + double dX = x ; + // calcolo i nuovi componenti ruotati + z = dCosAng * dZ - dSinAng * dX ; + x = dSinAng * dZ + dCosAng * dX ; + return true ; + } + // se rotazione attorno all'asse Y- + else if ( vtAx.IsYminus()) { + // salvo i componenti originali + double dZ = z ; + double dX = x ; + // calcolo i nuovi componenti ruotati + z = dCosAng * dZ + dSinAng * dX ; + x = - dSinAng * dZ + dCosAng * dX ; + return true ; + } + + // rotazione attorno ad un asse generico // separazione del vettore nelle componenti parallela e perp. asse double dCompPar = *this * vtDirAx ; Vector3d vtCompPar = vtDirAx * dCompPar ;