Files
EgtGeomKernel/LinePerpTwoCurves.cpp
T
Dario Sassi 9347e52d18 EgtGeomKernel 1.5k5 :
- sviluppo linee tangenti e perpendicolari a curve.
2014-12-01 14:48:44 +00:00

235 lines
9.2 KiB
C++

//----------------------------------------------------------------------------
// 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<CurveLine> 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<CurveLine> 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<CurveLine> 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 ;
}