0dd8afedf9
- correzioni nell'intersezione di archi tangenti o quasi - pulizia uso distanze e relative costanti minime.
277 lines
11 KiB
C++
277 lines
11 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2014-2014
|
|
//----------------------------------------------------------------------------
|
|
// File : IntersLineArc.cpp Data : 07.07.14 Versione : 1.5g2
|
|
// Contenuto : Implementazione della classe intersezione linea/arco.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 07.07.14 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "IntersLineArc.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
IntersLineArc::IntersLineArc( const CurveLine& Line, const CurveArc& Arc)
|
|
{
|
|
// Le intersezioni sono calcolate nel piano XY locale.
|
|
|
|
// nessuna intersezione trovata
|
|
m_nNumInters = 0 ;
|
|
|
|
// verifico validità linea e arco
|
|
if ( ! Line.IsValid() || ! Arc.IsValid())
|
|
return ;
|
|
// l'arco deve avere il piano coincidente con XY
|
|
if ( ! Arc.GetNormVersor().IsZplus() && ! Arc.GetNormVersor().IsZminus())
|
|
return ;
|
|
// verifico che l'angolo al centro non superi il giro
|
|
if ( fabs( Arc.GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO)
|
|
return ;
|
|
// !!! Gestire l'arco proiettato come ellisse
|
|
|
|
// verifico sovrapposizione box
|
|
BBox3d boxLine ;
|
|
if ( ! Line.GetLocalBBox( boxLine))
|
|
return ;
|
|
BBox3d boxArc ;
|
|
if ( ! Arc.GetLocalBBox( boxArc))
|
|
return ;
|
|
if ( ! boxLine.OverlapsXY( boxArc))
|
|
return ;
|
|
|
|
// linea : copia e Direzione
|
|
m_Line.CopyFrom( &Line) ;
|
|
m_vtDirL = m_Line.GetEnd() - m_Line.GetStart() ;
|
|
Vector3d vtDirLXY = m_vtDirL ;
|
|
vtDirLXY.z = 0 ;
|
|
if ( m_vtDirL.IsSmallXY())
|
|
return ;
|
|
|
|
// arco : copia
|
|
m_Arc.CopyFrom( &Arc) ;
|
|
|
|
// punto proiezione del centro arco sulla linea
|
|
double dU = (( m_Arc.GetCenter() - m_Line.GetStart()) * vtDirLXY) / vtDirLXY.SqLenXY() ;
|
|
Point3d ptPrjCen = m_Line.GetStart() + m_vtDirL * dU ;
|
|
// quadrato della distanza tra centro e punto proiezione
|
|
double dSqDist = ( ptPrjCen - m_Arc.GetCenter()).SqLenXY() ;
|
|
// differenza tra quadrato del raggio e quadrato della distanza
|
|
double dSqDelta = m_Arc.GetRadius() * m_Arc.GetRadius() - dSqDist ;
|
|
|
|
// se distanza maggiore del raggio -> nessuna intersezione
|
|
if ( dSqDelta < - 2 * m_Arc.GetRadius() * EPS_SMALL)
|
|
return ;
|
|
|
|
// se distanza uguale al raggio -> una intersezione tangente, è la proiezione
|
|
// (corrisponde a una differenza max di EPS_SMALL tra i valori)
|
|
if ( dSqDelta < 2 * m_Arc.GetRadius() * EPS_SMALL) {
|
|
// determinazione geometrica dell'intersezione tra le due curve
|
|
int nPosL, nPosA ;
|
|
if ( ! CalcIntersGeomData( 0, ptPrjCen, nPosL, nPosA))
|
|
return ;
|
|
// determinazione topologica dell'intersezione tra le due curve
|
|
if ( ! CalcTgIntersTopolData( 0, nPosL, nPosA))
|
|
return ;
|
|
// aggiorno dati generali di intersezione
|
|
m_Info[0].bOverlap = false ;
|
|
m_nNumInters = 1 ;
|
|
return ;
|
|
}
|
|
|
|
// distanza minore del raggio -> due intersezioni
|
|
double dDelta = sqrt( dSqDelta) ;
|
|
Vector3d vtDelta = m_vtDirL * dDelta / m_vtDirL.LenXY() ;
|
|
int nPosL, nPosA ;
|
|
// ---> prima intersezione
|
|
// determinazione geometrica e topologica dell'intersezione tra le due curve
|
|
if ( CalcIntersGeomData( 0, ptPrjCen - vtDelta, nPosL, nPosA) &&
|
|
CalcSecIntersTopolData( 0, nPosL, nPosA)) {
|
|
// aggiorno dati generali di intersezione
|
|
m_Info[0].bOverlap = false ;
|
|
++ m_nNumInters ;
|
|
}
|
|
// ---> seconda intersezione
|
|
// determinazione geometrica e topologica dell'intersezione tra le due curve
|
|
if ( CalcIntersGeomData( m_nNumInters, ptPrjCen + vtDelta, nPosL, nPosA) &&
|
|
CalcSecIntersTopolData( m_nNumInters, nPosL, nPosA)) {
|
|
// aggiorno dati generali di intersezione
|
|
m_Info[m_nNumInters].bOverlap = false ;
|
|
++ m_nNumInters ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
IntersLineArc::CalcIntersGeomData( int nInt, const Point3d& ptInt, int& nPosL, int& nPosA)
|
|
{
|
|
// posizione parametrica dell'intersezione sulla linea
|
|
if ( ! m_Line.CalcPointParamPosiz( ptInt, true, m_Info[nInt].IciA[0].dU, nPosL))
|
|
return false ;
|
|
// posizione parametrica dell'intersezione sull'arco
|
|
if ( ! m_Arc.CalcPointParamPosiz( ptInt, m_Info[nInt].IciB[0].dU, nPosA))
|
|
return false ;
|
|
// se soluzione non accettata, esco
|
|
if ( nPosL == ICurve::PP_NULL || nPosA == ICurve::PP_NULL)
|
|
return false ;
|
|
// calcolo i punti sulle due curve (possono differire in Z)
|
|
m_Info[nInt].IciA[0].ptI = m_Line.GetStart() + m_Info[nInt].IciA[0].dU * m_vtDirL ;
|
|
m_Arc.GetPointD1D2( m_Info[nInt].IciB[0].dU, ICurve::FROM_MINUS, m_Info[nInt].IciB[0].ptI) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
IntersLineArc::CalcTgIntersTopolData( int nInt, int nPosL, int nPosA)
|
|
{
|
|
// calcolo dati ausiliari
|
|
bool bCCW = (( m_Arc.GetAngCenter() > 0 && m_Arc.GetNormVersor().IsZplus()) ||
|
|
( m_Arc.GetAngCenter() < 0 && m_Arc.GetNormVersor().IsZminus())) ;
|
|
double dCrossXY = CrossXY( m_vtDirL, ( m_Arc.GetCenter() - m_Info[nInt].IciB[0].ptI)) ;
|
|
|
|
// calcolo tipo di intersezione
|
|
m_Info[nInt].IciA[0].nPrevTy = ICCT_NULL ;
|
|
m_Info[nInt].IciA[0].nNextTy = ICCT_NULL ;
|
|
m_Info[nInt].IciB[0].nPrevTy = ICCT_NULL ;
|
|
m_Info[nInt].IciB[0].nNextTy = ICCT_NULL ;
|
|
// si incontrano alle estremità, non si può dire alcunché
|
|
if ( ( nPosL == ICurve::PP_START || nPosL == ICurve::PP_END) &&
|
|
( nPosA == ICurve::PP_START || nPosA == ICurve::PP_END)) {
|
|
; // rimangono tutti NULL
|
|
}
|
|
// l'inizio di L interseca il mezzo di A
|
|
else if ( nPosL == ICurve::PP_START) {
|
|
if ( bCCW)
|
|
m_Info[nInt].IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT
|
|
else
|
|
m_Info[nInt].IciA[0].nNextTy = ICCT_IN ; // NULL + IN
|
|
// curva B NULL + NULL
|
|
}
|
|
// la fine di L interseca il mezzo di A
|
|
else if ( nPosL == ICurve::PP_END) {
|
|
if ( bCCW)
|
|
m_Info[nInt].IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL
|
|
else
|
|
m_Info[nInt].IciA[0].nPrevTy = ICCT_IN ; // IN + NULL
|
|
// curva B NULL + NULL
|
|
}
|
|
// l'inizio di A interseca il mezzo di L
|
|
else if ( nPosA == ICurve::PP_START) {
|
|
// curva A NULL + NULL
|
|
if ( - dCrossXY > 0)
|
|
m_Info[nInt].IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT
|
|
else
|
|
m_Info[nInt].IciB[0].nNextTy = ICCT_IN ; // NULL + IN
|
|
}
|
|
// la fine di A interseca il mezzo di L
|
|
else if ( nPosA == ICurve::PP_END) {
|
|
// curva A NULL + NULL
|
|
if ( - dCrossXY > 0)
|
|
m_Info[nInt].IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL
|
|
else
|
|
m_Info[nInt].IciB[0].nPrevTy = ICCT_IN ; // IN + NULL
|
|
}
|
|
// si intersecano nel mezzo
|
|
else {
|
|
if ( bCCW) { // OUT + OUT
|
|
m_Info[nInt].IciA[0].nPrevTy = ICCT_OUT ;
|
|
m_Info[nInt].IciA[0].nNextTy = ICCT_OUT ;
|
|
}
|
|
else { // IN + IN
|
|
m_Info[nInt].IciA[0].nPrevTy = ICCT_IN ;
|
|
m_Info[nInt].IciA[0].nNextTy = ICCT_IN ;
|
|
}
|
|
if ( - dCrossXY > 0) { // OUT + OUT
|
|
m_Info[nInt].IciB[0].nPrevTy = ICCT_OUT ;
|
|
m_Info[nInt].IciB[0].nNextTy = ICCT_OUT ;
|
|
}
|
|
else { // IN + IN
|
|
m_Info[nInt].IciB[0].nPrevTy = ICCT_IN ;
|
|
m_Info[nInt].IciB[0].nNextTy = ICCT_IN ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
IntersLineArc::CalcSecIntersTopolData( int nInt, int nPosL, int nPosA)
|
|
{
|
|
// calcolo dati ausiliari
|
|
Point3d ptIntA ;
|
|
Vector3d vtDirA ;
|
|
m_Arc.GetPointD1D2( m_Info[nInt].IciB[0].dU, ICurve::FROM_MINUS, ptIntA, &vtDirA) ;
|
|
double dCrossXY = CrossXY( m_vtDirL, vtDirA) ;
|
|
// calcolo tipo di intersezione
|
|
m_Info[nInt].IciA[0].nPrevTy = ICCT_NULL ;
|
|
m_Info[nInt].IciA[0].nNextTy = ICCT_NULL ;
|
|
m_Info[nInt].IciB[0].nPrevTy = ICCT_NULL ;
|
|
m_Info[nInt].IciB[0].nNextTy = ICCT_NULL ;
|
|
// si incontrano alle estremità, non si può dire alcunché
|
|
if ( ( nPosL == ICurve::PP_START || nPosL == ICurve::PP_END) &&
|
|
( nPosA == ICurve::PP_START || nPosA == ICurve::PP_END)) {
|
|
; // rimangono tutti NULL
|
|
}
|
|
// l'inizio di 1 interseca il mezzo di 2
|
|
else if ( nPosL == ICurve::PP_START) {
|
|
if ( dCrossXY > 0)
|
|
m_Info[nInt].IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT
|
|
else
|
|
m_Info[nInt].IciA[0].nNextTy = ICCT_IN ; // NULL + IN
|
|
// curva B NULL + NULL
|
|
}
|
|
// la fine di 1 interseca il mezzo di 2
|
|
else if ( nPosL == ICurve::PP_END) {
|
|
if ( dCrossXY < 0)
|
|
m_Info[nInt].IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL
|
|
else
|
|
m_Info[nInt].IciA[0].nPrevTy = ICCT_IN ; // IN + NULL
|
|
// curva B NULL + NULL
|
|
}
|
|
// l'inizio di 2 interseca il mezzo di 1
|
|
else if ( nPosA == ICurve::PP_START) {
|
|
// curva A NULL + NULL
|
|
if ( - dCrossXY > 0)
|
|
m_Info[nInt].IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT
|
|
else
|
|
m_Info[nInt].IciB[0].nNextTy = ICCT_IN ; // NULL + IN
|
|
}
|
|
// la fine di 2 interseca il mezzo di 1
|
|
else if ( nPosA == ICurve::PP_END) {
|
|
// curva A NULL + NULL
|
|
if ( - dCrossXY < 0)
|
|
m_Info[nInt].IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL
|
|
else
|
|
m_Info[nInt].IciB[0].nPrevTy = ICCT_IN ; // IN + NULL
|
|
}
|
|
// si intersecano nel mezzo
|
|
else {
|
|
if ( CrossXY( ( m_Line.GetStart() - ( ptIntA - vtDirA)), vtDirA) > 0) {
|
|
m_Info[nInt].IciA[0].nPrevTy = ICCT_OUT ;
|
|
m_Info[nInt].IciA[0].nNextTy = ICCT_IN ;
|
|
}
|
|
else {
|
|
m_Info[nInt].IciA[0].nPrevTy = ICCT_IN ;
|
|
m_Info[nInt].IciA[0].nNextTy = ICCT_OUT ;
|
|
}
|
|
if ( CrossXY( ( ( ptIntA - vtDirA) - m_Line.GetStart()), m_vtDirL) > 0) {
|
|
m_Info[nInt].IciB[0].nPrevTy = ICCT_OUT ;
|
|
m_Info[nInt].IciB[0].nNextTy = ICCT_IN ;
|
|
}
|
|
else {
|
|
m_Info[nInt].IciB[0].nPrevTy = ICCT_IN ;
|
|
m_Info[nInt].IciB[0].nNextTy = ICCT_OUT ;
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|