Files
EgtGeomKernel/LineTgCurvePerpCurve.cpp
Dario Sassi 2ed2a34d55 EgtGeomKernel :
- modifiche per DistPointLine con interfaccia portata in Include.
2024-05-22 08:19:10 +02:00

267 lines
11 KiB
C++

//----------------------------------------------------------------------------
// 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 "/EgtDev/Include/EGkDistPointLine.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_BEZIER :
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_BEZIER :
return nullptr ;
case CRV_COMPO :
return nullptr ;
default :
return nullptr ;
}
}
case CRV_BEZIER :
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<CurveLine> 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.IsPlane())
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<CurveLine> 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.IsPlane() || ! crvArc2.IsPlane())
return nullptr ;
// calcolo la retta dal centro del secondo arco tangente al primo arco e la inverto
PtrOwner<CurveLine> 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.IsPlane())
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<CurveLine> pCrvLine( CreateBasicCurveLine()) ;
if ( IsNull( pCrvLine))
return nullptr ;
// setto la linea
if ( ! pCrvLine->Set( ptP1a, ptP2a))
return nullptr ;
// la restituisco
return Release( pCrvLine) ;
}