diff --git a/ArcXxTgArc.cpp b/ArcXxTgArc.cpp index 22510c1..f63fbbe 100644 --- a/ArcXxTgArc.cpp +++ b/ArcXxTgArc.cpp @@ -216,7 +216,6 @@ GetArcPntDirTgArc( const Point3d& ptP, double dDirStartDeg, const ICurveArc& crv 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)) ; diff --git a/CreateCurveAux.cpp b/CreateCurveAux.cpp new file mode 100644 index 0000000..e296061 --- /dev/null +++ b/CreateCurveAux.cpp @@ -0,0 +1,101 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2013 +//---------------------------------------------------------------------------- +// File : CreateCurveAux.cpp Data : 27.11.14 Versione : 1.5k5 +// Contenuto : Implementazione funzioni di utilità per creazione curve. +// +// +// +// Modifiche : 27.11.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "CreateCurveAux.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +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 ; +} + +//---------------------------------------------------------------------------- +bool +FindPointOnArc( const CurveArc& crvArc, const Vector3d& vtDirP, const Point3d& ptNear, Point3d& ptP) +{ + // calcolo i due punti e verifico se stanno sull'arco + Point3d ptPa = crvArc.GetCenter() + vtDirP * crvArc.GetRadius() ; + bool bPaOn = crvArc.IsPointOn( ptPa) ; + Point3d ptPb = crvArc.GetCenter() - vtDirP * crvArc.GetRadius() ; + bool bPbOn = crvArc.IsPointOn( ptPb) ; + // se nessuno valido + if ( ! bPaOn && ! bPbOn) + return false ; + // altrimenti scelgo + if ( ! bPaOn) + ptP = ptPb ; + else if ( ! bPbOn) + ptP = ptPa ; + else { + if ( SqDist( ptPa, ptNear) <= SqDist( ptPb, ptNear)) + ptP = ptPa ; + else + ptP = ptPb ; + } + return true ; +} diff --git a/LinePntTgCurve.h b/CreateCurveAux.h similarity index 58% rename from LinePntTgCurve.h rename to CreateCurveAux.h index b795907..0c9e153 100644 --- a/LinePntTgCurve.h +++ b/CreateCurveAux.h @@ -1,20 +1,24 @@ //---------------------------------------------------------------------------- // EgalTech 2014-2014 //---------------------------------------------------------------------------- -// File : LinePntTgCurve.h Data : 10.06.14 Versione : 1.5f3 -// Contenuto : Dichiarazione funzioni di base per calcolo rette tangenti a curve. +// File : CreateCurveAux.h Data : 27.11.14 Versione : 1.5k5 +// Contenuto : Dichiarazione funzioni di utilità per creazione curve. // // // -// Modifiche : 10.06.14 DS Creazione modulo. +// Modifiche : 27.11.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- #pragma once +#include "CurveLine.h" +#include "CurveArc.h" #include "/EgtDev/Include/EGkGeoCollection.h" - //---------------------------------------------------------------------------- int CalcLinePointTgCircle( const Point3d& ptP, const Point3d& ptCen, double dRad, BIPNTVECTOR& vBiPnt) ; +bool FindPointOnArc( const CurveArc& crvArc, const Vector3d& vtDirP, const Point3d& ptNear, Point3d& ptP) ; + + diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 12201d0..debfe97 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index cd8a579..45c704f 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -243,6 +243,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -277,8 +278,12 @@ copy $(TargetPath) \EgtProg\Dll64 + + + - + + @@ -335,8 +340,12 @@ copy $(TargetPath) \EgtProg\Dll64 + + + - + + @@ -359,6 +368,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -393,7 +403,6 @@ copy $(TargetPath) \EgtProg\Dll64 - diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 4941eb2..4d31519 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -183,9 +183,6 @@ File di origine\Gdb - - File di origine\GeoCreate - File di origine\GeoCreate @@ -228,6 +225,24 @@ File di origine\Base + + File di origine\GeoCreate + + + File di origine\GeoCreate + + + File di origine\GeoCreate + + + File di origine\GeoCreate + + + File di origine\GeoCreate + + + File di origine\GeoCreate + @@ -365,9 +380,6 @@ File di intestazione - - File di intestazione - File di intestazione @@ -485,9 +497,6 @@ File di intestazione\Include - - File di intestazione\Include - File di intestazione\Include @@ -548,6 +557,24 @@ File di intestazione + + File di intestazione\Include + + + File di intestazione\Include + + + File di intestazione\Include + + + File di intestazione\Include + + + File di intestazione + + + File di intestazione\Include + diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index 223e1f5..b6e1bbf 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -26,7 +26,7 @@ #include "/EgtDev/Include/EgkCurveLine.h" #include "/EgtDev/Include/EgkCurveAux.h" #include "/EgtDev/Include/EgkLinePntTgCurve.h" -#include "/EgtDev/Include/EgkLineTgTwoArcs.h" +#include "/EgtDev/Include/EgkLineTgTwoCurves.h" #include "/EgtDev/Include/EgkCurveArc.h" #include "/EgtDev/Include/EgkArcXxTgArc.h" #include "/EgtDev/Include/EgkCurveBezier.h" @@ -761,61 +761,60 @@ GdbExecutor::CurveLinePointTgCurve( const STRVECTOR& vsParams) bool GdbExecutor::CurveLineTgTwoArcs( const STRVECTOR& vsParams) { - // 6 parametri : Id, IdParent, IdArc1, ptNear1, IdArc2, ptNear2 + // 6 parametri : Id, IdParent, IdCrv1, ptNear1, IdCrv2, 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 + // recupero l'identificativo della prima curva 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)) + // recupero il riferimento della prima curva + Frame3d frCrv1 ; + if ( ! m_pGDB->GetGlobFrame( nId1, frCrv1)) return false ; - // recupero il primo arco - const ICurveArc* pArc1 = GetCurveArc( m_pGDB->GetGeoObj( nId1)) ; - if ( pArc1 == nullptr) + // recupero la prima curva + const ICurve* pCrv1 = GetCurve( m_pGDB->GetGeoObj( nId1)) ; + if ( pCrv1 == nullptr) return false ; - // recupero il primo punto vicino e lo porto nel riferimento del primo arco + // recupero il primo punto vicino e lo porto nel riferimento della prima curva Point3d ptNear1 ; if ( ! GetPointParam( vsParams[3], frDest, ptNear1)) return false ; Point3d ptN1loc = ptNear1 ; - ptN1loc.LocToLoc( frDest, frArc1) ; - // recupero l'identificativo del secondo arco + ptN1loc.LocToLoc( frDest, frCrv1) ; + // recupero l'identificativo della seconda curva 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)) + // recupero il riferimento della seconda curva + Frame3d frCrv2 ; + if ( ! m_pGDB->GetGlobFrame( nId2, frCrv2)) return false ; - // recupero il secondo arco - const ICurveArc* pArc2 = GetCurveArc( m_pGDB->GetGeoObj( nId2)) ; - if ( pArc2 == nullptr) + // recupero la seconda curva + const ICurve* pCrv2 = GetCurve( m_pGDB->GetGeoObj( nId2)) ; + if ( pCrv2 == nullptr) return false ; - // porto il secondo arco nel riferimento del primo - PtrOwner pArc2Loc( CreateCurveArc()) ; - if ( IsNull( pArc2Loc)) + // porto la seconda curva nel riferimento della prima + PtrOwner pCrv2Loc( pCrv2->Clone()) ; + if ( IsNull( pCrv2Loc)) return false ; - pArc2Loc->CopyFrom( pArc2) ; - pArc2Loc->LocToLoc( frArc2, frArc1) ; - // recupero il secondo punto vicino e lo porto nel riferimento del primo arco + pCrv2Loc->LocToLoc( frCrv2, frCrv1) ; + // recupero il secondo punto vicino e lo porto nel riferimento della prima curva 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) ; + ptN2loc.LocToLoc( frDest, frCrv1) ; + // calcolo la retta tangente alle due curve + ICurveLine* pCrvLine = GetLineTgTwoCurves( *pCrv1, ptN1loc, *pCrv2, ptN2loc) ; if ( pCrvLine == nullptr) return false ; // porto la linea nel riferimento del gruppo destinazione - pCrvLine->LocToLoc( frArc1, frDest) ; + pCrvLine->LocToLoc( frCrv1, frDest) ; // inserisco la linea nel DB return AddGeoObj( vsParams[0], vsParams[1], pCrvLine) ; } diff --git a/LinePerpTwoCurves.cpp b/LinePerpTwoCurves.cpp new file mode 100644 index 0000000..98a365d --- /dev/null +++ b/LinePerpTwoCurves.cpp @@ -0,0 +1,234 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2014 +//---------------------------------------------------------------------------- +// File : LinePerpTwoCurves.cpp Data : 25.11.14 Versione : 1.5k5 +// Contenuto : Implementazione funzioni per calcolo rette perpendicolari a curve. +// +// +// +// Modifiche : 25.11.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "CurveLine.h" +#include "CurveArc.h" +#include "CreateCurveAux.h" +#include "/EgtDev/Include/EgkLinePerpTwoCurves.h" +#include "/EgtDev/Include/EgkLinePntPerpCurve.h" +#include "/EgtDev/Include/EgkDistPointCurve.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +static CurveLine* GetLinePerpTwoLines( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveLine& crvLine2, const Point3d& ptNear2) ; +static CurveLine* GetLinePerpLineArc( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) ; +static CurveLine* GetLinePerpTwoArcs( const CurveArc& crvArc1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) ; +static CurveLine* GetLinePerpTwoConcentricArcs( const CurveArc& crvArc1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) ; + +//---------------------------------------------------------------------------- +ICurveLine* +GetLinePerpTwoCurves( const ICurve& cCrv1, const Point3d& ptNear1, + const ICurve& cCrv2, const Point3d& ptNear2) +{ + switch ( cCrv1.GetType()) { + case CRV_LINE : + { const CurveLine& crvLine1 = *GetBasicCurveLine( &cCrv1) ; + switch ( cCrv2.GetType()) { + case CRV_LINE : + { const CurveLine& crvLine2 = *GetBasicCurveLine( &cCrv2) ; + return GetLinePerpTwoLines( crvLine1, ptNear1, crvLine2, ptNear2) ; } + case CRV_ARC : + { const CurveArc& crvArc2 = *GetBasicCurveArc( &cCrv2) ; + return GetLinePerpLineArc( crvLine1, ptNear1, crvArc2, ptNear2) ; } + case CRV_BEZ : + return nullptr ; + case CRV_COMPO : + return nullptr ; + default : + return nullptr ; + } + } break ; + case CRV_ARC : + { const CurveArc& crvArc1 = *GetBasicCurveArc( &cCrv1) ; + switch ( cCrv2.GetType()) { + case CRV_LINE : + { const CurveLine& crvLine2 = *GetBasicCurveLine( &cCrv2) ; + CurveLine* pCrvLine = GetLinePerpLineArc( crvLine2, ptNear2, crvArc1, ptNear1) ; + if ( pCrvLine != nullptr) + pCrvLine->Invert() ; + return pCrvLine ; } + case CRV_ARC : + { const CurveArc& crvArc2 = *GetBasicCurveArc( &cCrv2) ; + return GetLinePerpTwoArcs( crvArc1, ptNear1, crvArc2, ptNear2) ; } + case CRV_BEZ : + return nullptr ; + case CRV_COMPO : + return nullptr ; + default : + return nullptr ; + } + } break ; + case CRV_BEZ : + return nullptr ; + case CRV_COMPO : + return nullptr ; + default : + return nullptr ; + } +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLinePerpTwoLines( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveLine& crvLine2, const Point3d& ptNear2) +{ + // le due linee devono essere parallele + Vector3d vtDir1 ; + if ( ! crvLine1.GetStartDir( vtDir1)) + return nullptr ; + Vector3d vtDir2 ; + if ( ! crvLine2.GetStartDir( vtDir2)) + return nullptr ; + if ( ! AreSameOrOppositeVectorApprox( vtDir1, vtDir2)) + return nullptr ; + // determino la sovrapposizione longitudinale del secondo segmento sul primo + double dLen1 ; + crvLine1.GetLength( dLen1) ; + double dStartLen = ( crvLine2.GetStart() - crvLine1.GetStart()) * vtDir1 ; + double dEndLen = ( crvLine2.GetEnd() - crvLine1.GetStart()) * vtDir1 ; + if ( dStartLen > dEndLen) + swap( dStartLen, dEndLen) ; + if ( dStartLen < 0) + dStartLen = 0 ; + if ( dEndLen > dLen1) + dEndLen = dLen1 ; + // determino la posizione dei punti vicini sull'intervallo ammesso + double dNear1Len = ( ptNear1 - crvLine1.GetStart()) * vtDir1 ; + if ( dNear1Len < dStartLen) + dNear1Len = dStartLen ; + if ( dNear1Len > dEndLen) + dNear1Len = dEndLen ; + double dNear2Len = ( ptNear2 - crvLine1.GetStart()) * vtDir1 ; + if ( dNear2Len < dStartLen) + dNear2Len = dStartLen ; + if ( dNear2Len > dEndLen) + dNear2Len = dEndLen ; + // prendo la posizione intermedia + double dPosLen = 0.5 * ( dNear1Len + dNear2Len) ; + Point3d ptP1 = crvLine1.GetStart() + vtDir1 * dPosLen ; + Point3d ptP2 = crvLine2.GetStart() + ( ptP1 - crvLine2.GetStart()) * vtDir2 * vtDir2 ; + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // setto la linea + if ( ! pCrvLine->Set( ptP1, ptP2)) + return nullptr ; + // la restituisco + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLinePerpLineArc( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) +{ + // l'arco deve essere piatto (no elica) + if ( ! crvArc2.IsFlat()) + return nullptr ; + // versore della linea + Vector3d vtDir1 ; + if ( ! crvLine1.GetStartDir( vtDir1)) + return nullptr ; + // la linea deve giacere nel piano dell'arco o parallelo + if ( ! AreOrthoApprox( vtDir1, crvArc2.GetNormVersor())) + return nullptr ; + // lunghezza della linea + double dLen1 ; + crvLine1.GetLength( dLen1) ; + // determino la proiezione del centro dell'arco sulla linea e verifico stia sul segmento + double dCenLen = ( crvArc2.GetCenter() - crvLine1.GetStart()) * vtDir1 ; + if ( dCenLen < - EPS_ZERO || dCenLen > dLen1 + EPS_ZERO) + return nullptr ; + // punto di proiezione + Point3d ptP1 = crvLine1.GetStart() + vtDir1 * dCenLen ; + // punto sulla circonferenza (linea e circonferenza possono essere su piani paralleli) + Vector3d vtDirP = crvArc2.GetCenter() - ptP1 ; + vtDirP -= vtDirP * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; + if ( ! vtDirP.Normalize()) { + // il centro è sul segmento, prendo la normale alla retta nel piano dell'arco + vtDirP = vtDir1 ^ crvArc2.GetNormVersor() ; + if ( ! vtDirP.Normalize()) + return nullptr ; + } + Point3d ptP2 ; + if ( ! FindPointOnArc( crvArc2, vtDirP, ptNear2, ptP2)) + return nullptr ; + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // setto la linea + if ( ! pCrvLine->Set( ptP1, ptP2)) + return nullptr ; + // la restituisco + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLinePerpTwoArcs( const CurveArc& crvArc1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) +{ + // i due archi devono giacere nello stesso piano o in piani paralleli ed essere piatti + if ( ! AreSameOrOppositeVectorApprox( crvArc1.GetNormVersor(), crvArc2.GetNormVersor()) || + ! crvArc1.IsFlat() || ! crvArc2.IsFlat()) + return nullptr ; + // la linea cercata deve passare per i due centri + Vector3d vtDirP = crvArc2.GetCenter() - crvArc1.GetCenter() ; + vtDirP -= vtDirP * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; + if ( ! vtDirP.Normalize()) + return GetLinePerpTwoConcentricArcs( crvArc1, ptNear1, crvArc2, ptNear2) ; + Point3d ptP1 ; + if ( ! FindPointOnArc( crvArc1, vtDirP, ptNear1, ptP1)) + return nullptr ; + Point3d ptP2 ; + if ( ! FindPointOnArc( crvArc2, vtDirP, ptNear2, ptP2)) + return nullptr ; + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // setto la linea + if ( ! pCrvLine->Set( ptP1, ptP2)) + return nullptr ; + // la restituisco + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLinePerpTwoConcentricArcs( const CurveArc& crvArc1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) +{ + // trovo il punto più vicino a Near2 sul secondo arco + DistPointCurve dstPtCurve( ptNear2, crvArc2) ; + Point3d ptP ; + int nFlag ; + if ( ! dstPtCurve.GetMinDistPoint( 0, ptP, nFlag)) + return nullptr ; + // calcolo la linea perpendicolare al primo arco dal punto trovato e la inverto + CurveLine* pCrvLine = GetBasicCurveLine( GetLinePointPerpCurve( ptP, crvArc1, ptNear1)) ; + if ( pCrvLine != nullptr) + pCrvLine->Invert() ; + // restituisco la linea + return pCrvLine ; +} diff --git a/LinePntMinDistCurve.cpp b/LinePntMinDistCurve.cpp new file mode 100644 index 0000000..8d3f2e6 --- /dev/null +++ b/LinePntMinDistCurve.cpp @@ -0,0 +1,80 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2014 +//---------------------------------------------------------------------------- +// File : LinePntMinDistCurve.cpp Data : 27.11.14 Versione : 1.5k5 +// Contenuto : Implementazione funzioni per calcolo rette di minima distanza da curve. +// +// +// +// Modifiche : 25.11.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "CurveLine.h" +#include "/EgtDev/Include/EgkLinePntMinDistCurve.h" +#include "/EgtDev/Include/EgkDistPointCurve.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +ICurveLine* +GetLinePointMinDistCurve( const Point3d& ptP, const ICurve& cCrv, const Point3d& ptNear) +{ + // calcolo i punti a minima distanza + DistPointCurve dstPtCurve( ptP, cCrv) ; + // ciclo su questi punti per trovare il più vicino al desiderato + bool bFound = false ; + double dMinSqDist = INFINITO * INFINITO ; + Point3d ptFoot ; + MinDistPCInfo mdInfo ; + for ( int i = 0 ; dstPtCurve.GetMinDistInfo( i, mdInfo) ; ++ i) { + // verifico punto + double dSqDist = SqDist( mdInfo.ptQ, ptNear) ; + if ( dSqDist < dMinSqDist) { + bFound = true ; + dMinSqDist = dSqDist ; + ptFoot = mdInfo.ptQ ; + } + } + // verifico eventuali tratti continui + for ( int i = 0 ; dstPtCurve.GetMinDistInfo( i, mdInfo) ; ++ i) { + if ( mdInfo.nFlag == MDPCI_START_CONT) { + MinDistPCInfo mdInfo2 ; + if ( dstPtCurve.GetMinDistInfo( i+1, mdInfo2) && mdInfo2.nFlag == MDPCI_END_CONT) { + // copio la curva e la limito al tratto continuo + PtrOwner pCrvLim( cCrv.Clone()) ; + if ( IsNull( pCrvLim) || + ! pCrvLim->TrimStartEndAtParam( mdInfo.dPar, mdInfo2.dPar)) + break ; + // trovo il punto del tratto continuo a minima distanza dal punto near + Point3d ptTest ; + int nFlag ; + DistPointCurve dstPtCurve2( ptNear, *pCrvLim) ; + if ( dstPtCurve2.GetMinDistPoint( 0, ptTest, nFlag)) { + double dSqDist = SqDist( ptTest, ptNear) ; + if ( dSqDist < dMinSqDist) { + bFound = true ; + dMinSqDist = dSqDist ; + ptFoot = ptTest ; + } + } + } + } + } + + if ( ! bFound) + return nullptr ; + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // setto la linea + if ( ! pCrvLine->Set( ptP, ptFoot)) + return nullptr ; + // la restituisco + return Release( pCrvLine) ; +} diff --git a/LinePntPerpCurve.cpp b/LinePntPerpCurve.cpp new file mode 100644 index 0000000..0cca4d2 --- /dev/null +++ b/LinePntPerpCurve.cpp @@ -0,0 +1,170 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2014 +//---------------------------------------------------------------------------- +// File : LinePntPerpCurve.cpp Data : 25.11.14 Versione : 1.5k5 +// Contenuto : Implementazione funzioni per calcolo rette perpendicolari a curve. +// +// +// +// Modifiche : 25.11.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "CurveLine.h" +#include "CurveArc.h" +#include "CurveBezier.h" +#include "CurveComposite.h" +#include "CreateCurveAux.h" +#include "GeoConst.h" +#include "/EgtDev/Include/EgkLinePntPerpCurve.h" +#include "/EgtDev/Include/EgkDistPointCurve.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +static CurveLine* GetLinePointPerpLine( const Point3d& ptP, const CurveLine& crvLine, const Point3d& ptNear) ; +static CurveLine* GetLinePointPerpArc( const Point3d& ptP, const CurveArc& crvArc, const Point3d& ptNear) ; +static CurveLine* GetLinePointPerpBezier( const Point3d& ptP, const CurveBezier& crvBezier, const Point3d& ptNear) ; +static CurveLine* GetLinePointPerpCompo( const Point3d& ptP, const CurveComposite& crvCompo, const Point3d& ptNear) ; + +//---------------------------------------------------------------------------- +ICurveLine* +GetLinePointPerpCurve( const Point3d& ptP, const ICurve& cCrv, const Point3d& ptNear) +{ + switch ( cCrv.GetType()) { + case CRV_LINE : + { const CurveLine& crvLine = *GetBasicCurveLine( &cCrv) ; + return GetLinePointPerpLine( ptP, crvLine, ptNear) ; } + case CRV_ARC : + { const CurveArc& crvArc = *GetBasicCurveArc( &cCrv) ; + return GetLinePointPerpArc( ptP, crvArc, ptNear) ; } + case CRV_BEZ : + { const CurveBezier& crvBezier = *GetBasicCurveBezier( &cCrv) ; + return GetLinePointPerpBezier( ptP, crvBezier, ptNear) ; } + case CRV_COMPO : + { const CurveComposite& crvCompo = *GetBasicCurveComposite( &cCrv) ; + return GetLinePointPerpCompo( ptP, crvCompo, ptNear) ; } + default : + return nullptr ; + } +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLinePointPerpLine( const Point3d& ptP, const CurveLine& crvLine, const Point3d& ptNear) +{ + // direzione della linea + Vector3d vtDir ; + if ( ! crvLine.GetStartDir( vtDir)) + return nullptr ; + // lunghezza della linea + double dLen ; + if ( ! crvLine.GetLength( dLen)) + return nullptr ; + // piede della perpendicolare dal punto alla linea + double dPerpLen = ( ptP - crvLine.GetStart()) * vtDir ; + if ( dPerpLen < - EPS_ZERO || dPerpLen > dLen + EPS_ZERO) + return nullptr ; + if ( dPerpLen < 0) + dPerpLen = 0 ; + else if ( dPerpLen > dLen) + dPerpLen = dLen ; + Point3d ptFoot = crvLine.GetStart() + dPerpLen * vtDir ; + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // costruisco la linea + if ( ! pCrvLine->Set( ptP, ptFoot)) + return nullptr ; + // restituisco la linea + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLinePointPerpArc( const Point3d& ptP, const CurveArc& crvArc, const Point3d& ptNear) +{ + // l'arco deve essere piatto (no elica) + if ( ! crvArc.IsFlat()) + return nullptr ; + // punti sull'arco su direzione della linea dal punto al centro dell'arco + Point3d ptP2 ; + Vector3d vtDirP = crvArc.GetCenter() - ptP ; + vtDirP -= vtDirP * crvArc.GetNormVersor() * crvArc.GetNormVersor() ; + if ( ! vtDirP.Normalize()) { + // il punto è nel centro dell'arco, l'estremo sull'arco dipende solo da Near + DistPointCurve dstPtCurve( ptNear, crvArc) ; + int nFlag ; + if ( ! dstPtCurve.GetMinDistPoint( 0, ptP2, nFlag)) + return nullptr ; + } + else { + if ( ! FindPointOnArc( crvArc, vtDirP, ptNear, ptP2)) + return nullptr ; + } + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // costruisco la linea + if ( ! pCrvLine->Set( ptP, ptP2)) + return nullptr ; + // restituisco la linea + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLinePointPerpBezier( const Point3d& ptP, const CurveBezier& crvBezier, const Point3d& ptNear) +{ + // 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 linea perpendicolare a questa approssimazione + PtrOwner pCrvLine( GetBasicCurveLine( GetLinePointPerpCurve( ptP, *pCrvCompo, ptNear))) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // porto il punto finale della linea esattamente sulla curva di Bezier + DistPointCurve dstPtCurve( pCrvLine->GetEnd(), crvBezier) ; + Point3d ptP2 ; + int nFlag ; + if ( ! dstPtCurve.GetMinDistPoint( 0, ptP2, nFlag) || ! pCrvLine->ModifyEnd( ptP2)) + return nullptr ; + // restituisco la linea + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLinePointPerpCompo( const Point3d& ptP, const CurveComposite& crvCompo, const Point3d& ptNear) +{ + // ciclo sulla curva composita + double dMinSqDist = INFINITO * INFINITO ; + PtrOwner pCrvLine ; + for ( const ICurve* pCrv = crvCompo.GetFirstCurve() ; + pCrv != nullptr ; + pCrv = crvCompo.GetNextCurve()) { + // recupero la linea perpendicolare alla curva elementare + PtrOwner pCrvLtmp( GetBasicCurveLine( GetLinePointPerpCurve( ptP, *pCrv, ptNear))) ; + if ( IsNull( pCrvLtmp)) + continue ; + // verifico se è la più vicina al punto desiderato + double dSqDist = SqDist( ptNear, pCrvLtmp->GetEnd()) ; + if ( dSqDist < dMinSqDist) { + dMinSqDist = dSqDist ; + pCrvLine.Set( Release( pCrvLtmp)) ; + } + } + + return Release( pCrvLine) ; +} diff --git a/LinePntTgCurve.cpp b/LinePntTgCurve.cpp index 118ff48..7279c5c 100644 --- a/LinePntTgCurve.cpp +++ b/LinePntTgCurve.cpp @@ -13,35 +13,76 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" -#include "LinePntTgCurve.h" -#include "/EgtDev/Include/EgkGeoCollection.h" +#include "CurveLine.h" +#include "CurveArc.h" +#include "CurveBezier.h" +#include "CurveComposite.h" +#include "CreateCurveAux.h" +#include "GeoConst.h" #include "/EgtDev/Include/EgkLinePntTgCurve.h" +#include "/EgtDev/Include/EgkDistPointCurve.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; +//---------------------------------------------------------------------------- +static CurveLine* GetLinePointTgLine( const Point3d& ptP, const CurveLine& crvLine, const Point3d& ptNear) ; +static CurveLine* GetLinePointTgArc( const Point3d& ptP, const CurveArc& crvArc, const Point3d& ptNear) ; +static CurveLine* GetLinePointTgBezier( const Point3d& ptP, const CurveBezier& crvBezier, const Point3d& ptNear) ; +static CurveLine* GetLinePointTgCompo( const Point3d& ptP, const CurveComposite& crvCompo, const Point3d& ptNear) ; + + //---------------------------------------------------------------------------- ICurveLine* GetLinePointTgCurve( const Point3d& ptP, const ICurve& cCrv, const Point3d& ptNear) { switch ( cCrv.GetType()) { case CRV_LINE : - return nullptr ; + { const CurveLine& crvLine = *GetBasicCurveLine( &cCrv) ; + return GetLinePointTgLine( ptP, crvLine, ptNear) ; } case CRV_ARC : - { const ICurveArc& crvArc = *GetCurveArc( &cCrv) ; + { const CurveArc& crvArc = *GetBasicCurveArc( &cCrv) ; return GetLinePointTgArc( ptP, crvArc, ptNear) ; } case CRV_BEZ : - return nullptr ; + { const CurveBezier& crvBezier = *GetBasicCurveBezier( &cCrv) ; + return GetLinePointTgBezier( ptP, crvBezier, ptNear) ; } case CRV_COMPO : - return nullptr ; + { const CurveComposite& crvCompo = *GetBasicCurveComposite( &cCrv) ; + return GetLinePointTgCompo( ptP, crvCompo, ptNear) ; } default : return nullptr ; } } //---------------------------------------------------------------------------- -ICurveLine* -GetLinePointTgArc( const Point3d& ptP, const ICurveArc& crvArc, const Point3d& ptNear) +CurveLine* +GetLinePointTgLine( const Point3d& ptP, const CurveLine& crvLine, const Point3d& ptNear) +{ + // verifico che il punto giaccia sulla linea estesa + DistPointCurve dstPtCurve( ptP, crvLine, false) ; + double dSqDist ; + if ( ! dstPtCurve.GetSqDist( dSqDist) || dSqDist > EPS_SMALL * EPS_SMALL) + return nullptr ; + // recupero il punto sulla linea più vicino al punto near + Point3d ptP2 ; + int nFlag ; + DistPointCurve dstNearCurve( ptNear, crvLine) ; + if ( ! dstNearCurve.GetMinDistPoint( 0, ptP2, nFlag)) + return nullptr ; + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // setto la linea + if ( ! pCrvLine->Set( ptP, ptP2)) + return nullptr ; + // la restituisco + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLinePointTgArc( const Point3d& ptP, const CurveArc& crvArc, const Point3d& ptNear) { // calcolo il riferimento intrinseco dell'arco (DirNorm->Z e DirStart->X) Frame3d frIntr ; @@ -91,70 +132,63 @@ GetLinePointTgArc( const Point3d& ptP, const ICurveArc& crvArc, const Point3d& p } // creo la linea - PtrOwner pCrvLine( CreateCurveLine()) ; + PtrOwner pCrvLine( CreateBasicCurveLine()) ; if ( IsNull( pCrvLine)) return nullptr ; - // costruisco la linea corrispondente alla soluzione scelta - if ( pCrvLine->Set( vBiPnt[nIdOk].first, vBiPnt[nIdOk].second)) - return Release( pCrvLine) ; - else + if ( ! pCrvLine->Set( vBiPnt[nIdOk].first, vBiPnt[nIdOk].second)) return nullptr ; + // restituisco la linea + return Release( pCrvLine) ; } //---------------------------------------------------------------------------- -int -CalcLinePointTgCircle( const Point3d& ptP, const Point3d& ptCen, double dRad, BIPNTVECTOR& vBiPnt) +CurveLine* +GetLinePointTgBezier( const Point3d& ptP, const CurveBezier& crvBezier, const Point3d& ptNear) { - // --- si lavora nel piano XY --- + // 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 linea tangente a questa approssimazione + PtrOwner pCrvLine( GetBasicCurveLine( GetLinePointTgCurve( ptP, *pCrvCompo, ptNear))) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // porto il punto finale della linea esattamente sulla curva di Bezier + DistPointCurve dstPtCurve( pCrvLine->GetEnd(), crvBezier) ; + Point3d ptP2 ; + int nFlag ; + if ( ! dstPtCurve.GetMinDistPoint( 0, ptP2, nFlag) || ! pCrvLine->ModifyEnd( ptP2)) + return nullptr ; + // restituisco la linea + return Release( pCrvLine) ; +} - // 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 ; +//---------------------------------------------------------------------------- +CurveLine* +GetLinePointTgCompo( const Point3d& ptP, const CurveComposite& crvCompo, const Point3d& ptNear) +{ + // ciclo sulla curva composita + double dMinSqDist = INFINITO * INFINITO ; + PtrOwner pCrvLine ; + for ( const ICurve* pCrv = crvCompo.GetFirstCurve() ; + pCrv != nullptr ; + pCrv = crvCompo.GetNextCurve()) { + // recupero la linea tangente alla curva elementare + PtrOwner pCrvLtmp( GetBasicCurveLine( GetLinePointTgCurve( ptP, *pCrv, ptNear))) ; + if ( IsNull( pCrvLtmp)) + continue ; + // verifico se è la più vicina al punto desiderato + double dSqDist = SqDist( ptNear, pCrvLtmp->GetEnd()) ; + if ( dSqDist < dMinSqDist) { + dMinSqDist = dSqDist ; + pCrvLine.Set( Release( pCrvLtmp)) ; } - // 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 ; -} + return Release( pCrvLine) ; +} \ No newline at end of file diff --git a/LineTgCurvePerpCurve.cpp b/LineTgCurvePerpCurve.cpp new file mode 100644 index 0000000..7a03ba9 --- /dev/null +++ b/LineTgCurvePerpCurve.cpp @@ -0,0 +1,266 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2014 +//---------------------------------------------------------------------------- +// File : LineTgCurvePerpCurve.cpp Data : 27.11.14 Versione : 1.5k5 +// Contenuto : Implementazione funzioni per calcolo rette tg e perp. a curve. +// +// +// +// Modifiche : 27.11.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "CreateCurveAux.h" +#include "DistPointLine.h" +#include "/EgtDev/Include/EgkLineTgCurvePerpCurve.h" +#include "/EgtDev/Include/EgkLinePntTgCurve.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +static CurveLine* GetLineTgLinePerpLine( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveLine& crvLine2, const Point3d& ptNear2) ; +static CurveLine* GetLineTgLinePerpArc( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) ; +static CurveLine* GetLineTgArcPerpArc( const CurveArc& crvArc1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) ; +static CurveLine* GetLineTgArcPerpLine( const CurveArc& crvArc1, const Point3d& ptNear1, + const CurveLine& crvLine2, const Point3d& ptNear2) ; + +//---------------------------------------------------------------------------- +ICurveLine* +GetLineTgCurvePerpCurve( const ICurve& cCrv1, const Point3d& ptNear1, + const ICurve& cCrv2, const Point3d& ptNear2) +{ + switch ( cCrv1.GetType()) { + case CRV_LINE : + { const CurveLine& crvLine1 = *GetBasicCurveLine( &cCrv1) ; + switch ( cCrv2.GetType()) { + case CRV_LINE : + { const CurveLine& crvLine2 = *GetBasicCurveLine( &cCrv2) ; + return GetLineTgLinePerpLine( crvLine1, ptNear1, crvLine2, ptNear2) ; } + case CRV_ARC : + { const CurveArc& crvArc2 = *GetBasicCurveArc( &cCrv2) ; + return GetLineTgLinePerpArc( crvLine1, ptNear1, crvArc2, ptNear2) ; } + return nullptr ; + case CRV_BEZ : + return nullptr ; + case CRV_COMPO : + return nullptr ; + default : + return nullptr ; + } + } + return nullptr ; + case CRV_ARC : + { const CurveArc& crvArc1 = *GetBasicCurveArc( &cCrv1) ; + switch ( cCrv2.GetType()) { + case CRV_LINE : + { const CurveLine& crvLine2 = *GetBasicCurveLine( &cCrv2) ; + return GetLineTgArcPerpLine( crvArc1, ptNear1, crvLine2, ptNear2) ; } + case CRV_ARC : + { const CurveArc& crvArc2 = *GetBasicCurveArc( &cCrv2) ; + return GetLineTgArcPerpArc( crvArc1, ptNear1, crvArc2, ptNear2) ; } + case CRV_BEZ : + return nullptr ; + case CRV_COMPO : + return nullptr ; + default : + return nullptr ; + } + } + case CRV_BEZ : + return nullptr ; + case CRV_COMPO : + return nullptr ; + default : + return nullptr ; + } +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLineTgLinePerpLine( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveLine& crvLine2, const Point3d& ptNear2) +{ + // versore della prima linea + Vector3d vtDir1 ; + if ( ! crvLine1.GetStartDir( vtDir1)) + return nullptr ; + // versore della seconda linea + Vector3d vtDir2 ; + if ( ! crvLine2.GetStartDir( vtDir2)) + return nullptr ; + // le due linee devono essere tra loro ortogonali + if ( ! AreOrthoApprox( vtDir1, vtDir2)) + return nullptr ; + // determino il piede delle perpendicolare da un estremo della prima linea alla seconda linea + // e verifico stia sul secondo segmento + Point3d ptP2 ; + if ( ! DistPointLine( crvLine1.GetStart(), crvLine2, false).GetMinDistPoint( ptP2) || + ! crvLine2.IsPointOn( ptP2) ) + return nullptr ; + // calcolo il punto sulla prima linea più vicino a Near1 + Point3d ptP1 ; + if ( ! DistPointLine( ptNear1, crvLine1).GetMinDistPoint( ptP1)) + return nullptr ; + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // setto la linea + if ( ! pCrvLine->Set( ptP1, ptP2)) + return nullptr ; + // la restituisco + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLineTgLinePerpArc( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) +{ + // l'arco deve essere piatto (no elica) + if ( ! crvArc2.IsFlat()) + return nullptr ; + // versore della linea + Vector3d vtDir1 ; + if ( ! crvLine1.GetStartDir( vtDir1)) + return nullptr ; + // la linea deve giacere nel piano dell'arco o parallelo + if ( ! AreOrthoApprox( vtDir1, crvArc2.GetNormVersor())) + return nullptr ; + // il centro dell'arco deve essere sulla linea ( o la sua proiezione sul piano // arco contenente linea) + Point3d ptCen = crvArc2.GetCenter() ; + ptCen -= ( ptCen - crvLine1.GetStart()) * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; + if ( ! DistPointLine( ptCen, crvLine1, false).IsSmall()) + return nullptr ; + // calcolo i due punti possibili sulla circonferenza e scelgo il più vicino a Near2 + Vector3d vtDirP = crvArc2.GetCenter() - crvLine1.GetStart() ; + vtDirP -= vtDirP * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; + if ( ! vtDirP.Normalize()) + return nullptr ; + Point3d ptP2 ; + if ( ! FindPointOnArc( crvArc2, vtDirP, ptNear2, ptP2)) + return nullptr ; + // calcolo il punto sulla linea più vicino a Near1 + Point3d ptP1 ; + if ( ! DistPointLine( ptNear1, crvLine1).GetMinDistPoint( ptP1)) + return nullptr ; + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // setto la linea + if ( ! pCrvLine->Set( ptP1, ptP2)) + return nullptr ; + // la restituisco + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLineTgArcPerpArc( const CurveArc& crvArc1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) +{ + // i due archi devono giacere nello stesso piano o in piani paralleli ed essere piatti + if ( ! AreSameOrOppositeVectorApprox( crvArc1.GetNormVersor(), crvArc2.GetNormVersor()) || + ! crvArc1.IsFlat() || ! crvArc2.IsFlat()) + return nullptr ; + // calcolo la retta dal centro del secondo arco tangente al primo arco e la inverto + PtrOwner pCrvPtA( GetBasicCurveLine( GetLinePointTgCurve( crvArc2.GetCenter(), crvArc1, ptNear1))) ; + if ( ! IsNull( pCrvPtA)) + pCrvPtA->Invert() ; + else { + // se il centro del secondo arco sta sul primo arco, la retta si riduce ad un punto... + // (inoltre possono essere su piani paralleli e diversi) + Point3d ptCen = crvArc2.GetCenter() ; + ptCen -= ( ptCen - crvArc1.GetCenter()) * crvArc1.GetNormVersor() * crvArc1.GetNormVersor() ; + if ( crvArc1.IsPointOn( ptCen)) { + // vettore tangente al primo arco nel punto considerato + Vector3d vtTang = ( ptCen - crvArc1.GetCenter()) ^ crvArc1.GetNormVersor() ; + if ( ! vtTang.Normalize()) + return nullptr ; + // costruisco la linea tangente + pCrvPtA.Set( CreateBasicCurveLine()) ; + if ( IsNull( pCrvPtA)) + return nullptr ; + pCrvPtA->Set( ptCen, ptCen + vtTang) ; + } + else + return nullptr ; + } + // determino le intersezioni della retta con il secondo arco + Vector3d vtDirP = pCrvPtA->GetEnd() - pCrvPtA->GetStart() ; + vtDirP -= vtDirP * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; + if ( ! vtDirP.Normalize()) + return nullptr ; + Point3d ptP2 ; + if ( ! FindPointOnArc( crvArc2, vtDirP, ptNear2, ptP2)) + return nullptr ; + // modifico il punto finale della retta + if ( ! pCrvPtA->ModifyEnd( ptP2)) + return nullptr ; + // restituisco la retta + return Release( pCrvPtA) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLineTgArcPerpLine( const CurveArc& crvArc1, const Point3d& ptNear1, + const CurveLine& crvLine2, const Point3d& ptNear2) +{ + // l'arco deve essere piatto (no elica) + if ( ! crvArc1.IsFlat()) + return nullptr ; + // versore della linea + Vector3d vtDir2 ; + if ( ! crvLine2.GetStartDir( vtDir2)) + return nullptr ; + // la linea deve giacere nel piano dell'arco o parallelo + if ( ! AreOrthoApprox( vtDir2, crvArc1.GetNormVersor())) + return nullptr ; + // determino la proiezione del centro dell'arco sulla linea + Point3d ptCenPro = crvLine2.GetStart() + ( crvArc1.GetCenter() - crvLine2.GetStart()) * vtDir2 * vtDir2 ; + // versore perpendicolare alla direzione tra centro arco e sua proiezione sulla linea + Vector3d vtDirP = ( ptCenPro - crvArc1.GetCenter()) ^ crvArc1.GetNormVersor() ; + if ( ! vtDirP.Normalize()) + return nullptr ; + // punti estremi della linea cercata tra arco e linea data + Point3d ptP1a = crvArc1.GetCenter() + vtDirP * crvArc1.GetRadius() ; + Point3d ptP2a = ptCenPro + vtDirP * crvArc1.GetRadius() ; + bool bLaOk = crvArc1.IsPointOn( ptP1a) && crvLine2.IsPointOn( ptP2a) ; + Point3d ptP1b = crvArc1.GetCenter() - vtDirP * crvArc1.GetRadius() ; + Point3d ptP2b = ptCenPro - vtDirP * crvArc1.GetRadius() ; + bool bLbOk = crvArc1.IsPointOn( ptP1b) && crvLine2.IsPointOn( ptP2b) ; + // se nessuna valida + if ( ! bLaOk && ! bLbOk) + return nullptr ; + // altrimenti scelgo + if ( ! bLaOk) { + swap( ptP1a, ptP1b) ; + swap( ptP2a, ptP2b) ; + } + else if ( ! bLbOk) + ; + else { + if ( SqDist( ptP1a, ptNear1) + SqDist( ptP2a, ptNear2) > + SqDist( ptP1b, ptNear1) + SqDist( ptP2b, ptNear2)) { + swap( ptP1a, ptP1b) ; + swap( ptP2a, ptP2b) ; + } + } + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // setto la linea + if ( ! pCrvLine->Set( ptP1a, ptP2a)) + return nullptr ; + // la restituisco + return Release( pCrvLine) ; +} diff --git a/LineTgTwoArcs.cpp b/LineTgTwoCurves.cpp similarity index 56% rename from LineTgTwoArcs.cpp rename to LineTgTwoCurves.cpp index 723c50c..788c6de 100644 --- a/LineTgTwoArcs.cpp +++ b/LineTgTwoCurves.cpp @@ -1,8 +1,8 @@ //---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- -// File : LineTgArc.cpp Data : 09.06.14 Versione : 1.5f4 -// Contenuto : Implementazione funzioni per calcolo rette tangenti a circonferenze +// File : LineTgTwoCurves.cpp Data : 25.11.14 Versione : 1.5k5 +// Contenuto : Implementazione funzioni per calcolo rette tangenti a curve. // // // @@ -13,26 +13,156 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" -#include "LinePntTgCurve.h" -#include "CurveArc.h" -#include "/EgtDev/Include/EgkGeoCollection.h" -#include "/EgtDev/Include/EgkLineTgTwoArcs.h" +#include "CreateCurveAux.h" +#include "DistPointLine.h" +#include "/EgtDev/Include/EgkLineTgTwoCurves.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- +static CurveLine* GetLineTgTwoLines( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveLine& crvLine2, const Point3d& ptNear2) ; +static CurveLine* GetLineTgLineArc( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) ; +static CurveLine* GetLineTgTwoArcs( const CurveArc& crvArc1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) ; 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) +GetLineTgTwoCurves( const ICurve& cCrv1, const Point3d& ptNear1, + const ICurve& cCrv2, const Point3d& ptNear2) { - // verifico che i due archi abbiano lo stesso piano intrinseco - if ( ! AreSameOrOppositeVectorApprox( crvArc1.GetNormVersor(), crvArc2.GetNormVersor())) + switch ( cCrv1.GetType()) { + case CRV_LINE : + { const CurveLine& crvLine1 = *GetBasicCurveLine( &cCrv1) ; + switch ( cCrv2.GetType()) { + case CRV_LINE : + { const CurveLine& crvLine2 = *GetBasicCurveLine( &cCrv2) ; + return GetLineTgTwoLines( crvLine1, ptNear1, crvLine2, ptNear2) ; } + case CRV_ARC : + { const CurveArc& crvArc2 = *GetBasicCurveArc( &cCrv2) ; + return GetLineTgLineArc( crvLine1, ptNear1, crvArc2, ptNear2) ; } + case CRV_BEZ : + return nullptr ; + case CRV_COMPO : + return nullptr ; + default : + return nullptr ; + } + } break ; + case CRV_ARC : + { const CurveArc& crvArc1 = *GetBasicCurveArc( &cCrv1) ; + switch ( cCrv2.GetType()) { + case CRV_LINE : + { const CurveLine& crvLine2 = *GetBasicCurveLine( &cCrv2) ; + CurveLine* pCrvLine = GetLineTgLineArc( crvLine2, ptNear2, crvArc1, ptNear1) ; + if ( pCrvLine != nullptr) + pCrvLine->Invert() ; + return pCrvLine ; } + case CRV_ARC : + { const CurveArc& crvArc2 = *GetBasicCurveArc( &cCrv2) ; + return GetLineTgTwoArcs( crvArc1, ptNear1, crvArc2, ptNear2) ; } + case CRV_BEZ : + return nullptr ; + case CRV_COMPO : + return nullptr ; + default : + return nullptr ; + } + } + case CRV_BEZ : + return nullptr ; + case CRV_COMPO : + return nullptr ; + default : + return nullptr ; + } +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLineTgTwoLines( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveLine& crvLine2, const Point3d& ptNear2) +{ + // le due linee devono essere allineate ( i punti dell'una devo appartenere all'altra) + if ( ! DistPointLine( crvLine2.GetStart(), crvLine1, false).IsSmall() || + ! DistPointLine( crvLine2.GetEnd(), crvLine1, false).IsSmall()) + return nullptr ; + // ricavo i due punti sulle linee più vicini ai rispettivi near + Point3d ptP1 ; + if ( ! DistPointLine( ptNear1, crvLine1).GetMinDistPoint( ptP1)) + return nullptr ; + Point3d ptP2 ; + if ( ! DistPointLine( ptNear2, crvLine2).GetMinDistPoint( ptP2)) + return nullptr ; + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // costruisco la linea + if ( ! pCrvLine->Set( ptP1, ptP2)) + return nullptr ; + // restituisco la linea + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLineTgLineArc( const CurveLine& crvLine1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) +{ + // l'arco deve essere piatto (no elica) + if ( ! crvArc2.IsFlat()) + return nullptr ; + // versore della linea + Vector3d vtDir1 ; + if ( ! crvLine1.GetStartDir( vtDir1)) + return nullptr ; + // la linea deve giacere nel piano dell'arco o parallelo + if ( ! AreOrthoApprox( vtDir1, crvArc2.GetNormVersor())) + return nullptr ; + // vettore spostamento dal piano linea parallelo al piano arco a questo + Vector3d vtMove = ( crvArc2.GetCenter() - crvLine1.GetStart()) * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; + // sposto il centro sul piano della linea parallelo a quello dell'arco + Point3d ptCen = crvArc2.GetCenter() - vtMove ; + // il centro deve distare dalla linea quanto il raggio + DistPointLine dstPL( ptCen, crvLine1, false) ; + double dDist ; + if ( ! dstPL.GetDist( dDist) || fabs( dDist - crvArc2.GetRadius()) > EPS_SMALL) + return nullptr ; + // sposto il punto sulla circonferenza e verifico appartenga all'arco + Point3d ptP2 ; + dstPL.GetMinDistPoint( ptP2) ; + ptP2 += vtMove ; + if ( ! crvArc2.IsPointOn( ptP2)) + return nullptr ; + // punto sulla linea vicino al desiderato + Point3d ptP1 ; + if ( ! DistPointLine( ptNear1, crvLine1).GetMinDistPoint( ptP1)) + return nullptr ; + // creo la linea + PtrOwner pCrvLine( CreateBasicCurveLine()) ; + if ( IsNull( pCrvLine)) + return nullptr ; + // costruisco la linea + if ( ! pCrvLine->Set( ptP1, ptP2)) + return nullptr ; + // restituisco la linea + return Release( pCrvLine) ; +} + +//---------------------------------------------------------------------------- +CurveLine* +GetLineTgTwoArcs( const CurveArc& crvArc1, const Point3d& ptNear1, + const CurveArc& crvArc2, const Point3d& ptNear2) +{ + // verifico che i due archi abbiano lo stesso piano intrinseco e siano piatti + if ( ! AreSameOrOppositeVectorApprox( crvArc1.GetNormVersor(), crvArc2.GetNormVersor()) || + ! crvArc1.IsFlat() || ! crvArc2.IsFlat()) return nullptr ; // calcolo il riferimento intrinseco del primo arco (Z->DirNorm e X->DirStart) @@ -84,7 +214,7 @@ GetLineTgTwoArcs( const ICurveArc& crvArc1, const Point3d& ptNear1, } // creo la linea - PtrOwner pCrvLine( CreateCurveLine()) ; + PtrOwner pCrvLine( CreateBasicCurveLine()) ; if ( IsNull( pCrvLine)) return nullptr ; @@ -237,4 +367,4 @@ CalcLineTg2Circles( const Point3d& ptC1, double dRad1, const Point3d& ptC2, doub nSol += CalcLineIntTg2Circles( ptC1, dRad1, ptC2, dRad2, vBiPnt) ; return nSol ; -} \ No newline at end of file +}