2ed2a34d55
- modifiche per DistPointLine con interfaccia portata in Include.
267 lines
11 KiB
C++
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) ;
|
|
}
|