Files
EgtGeomKernel/IntersArcArc.cpp
T
Dario Sassi 66cec4a872 EgtGeomKernel :
- ridotte tolleranze su tangenza in intersezione archi.
2024-07-17 09:00:33 +02:00

610 lines
28 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : IntersArcArc.cpp Data : 10.07.14 Versione : 1.5g2
// Contenuto : Implementazione della classe intersezione arco/arco.
//
//
//
// Modifiche : 10.07.14 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "IntersArcArc.h"
using namespace std ;
//----------------------------------------------------------------------------
static const double EPS_INTER_ARC = 0.1 * EPS_SMALL ;
//----------------------------------------------------------------------------
IntersArcArc::IntersArcArc( const CurveArc& Arc1, const CurveArc& Arc2)
{
// Le intersezioni sono calcolate nel piano XY locale.
// nessuna intersezione trovata
m_bOverlaps = false ;
m_nNumInters = 0 ;
// verifico validità archi
if ( ! Arc1.IsValid() || ! Arc2.IsValid())
return ;
// verifico che l'angolo al centro non superi il giro
if ( abs( Arc1.GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO ||
abs( Arc2.GetAngCenter()) > ANG_FULL + EPS_ANG_ZERO)
return ;
// gli archi devono avere il piano coincidente con XY
if ( ! Arc1.GetNormVersor().IsZplus() && ! Arc1.GetNormVersor().IsZminus())
return ;
if ( ! Arc2.GetNormVersor().IsZplus() && ! Arc2.GetNormVersor().IsZminus())
return ;
// verifico sovrapposizione box
BBox3d boxArc1 ;
if ( ! Arc1.GetLocalBBox( boxArc1))
return ;
BBox3d boxArc2 ;
if ( ! Arc2.GetLocalBBox( boxArc2))
return ;
if ( ! boxArc1.OverlapsXY( boxArc2))
return ;
// ne faccio una copia
m_Arc1.CopyFrom( &Arc1) ;
m_Arc2.CopyFrom( &Arc2) ;
// versore e distanza tra i centri
Vector3d vtDir = ( m_Arc2.GetCenter() - m_Arc1.GetCenter()) ;
vtDir.z = 0 ;
double dDist = vtDir.LenXY() ;
vtDir /= dDist ;
// cerchi esterni -> nessuna intersezione
if ( dDist > m_Arc1.GetRadius() + m_Arc2.GetRadius() + EPS_INTER_ARC)
return ;
// cerchi interni -> nessuna intersezione
if ( dDist < abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) - EPS_INTER_ARC)
return ;
// cerchi coincidenti -> sovrapposizioni e/o intersezioni agli estremi
if ( dDist < EPS_SMALL && abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) < EPS_INTER_ARC) {
// coefficiente da parametro dell'arco 1 a lunghezza
double dU2L = abs( m_Arc1.GetAngCenter()) * DEGTORAD * m_Arc1.GetRadius() ;
// determino se sono equiversi o controversi
bool bEqVers = (( m_Arc1.GetAngCenter() * m_Arc1.GetNormVersor().z *
m_Arc2.GetAngCenter() * m_Arc2.GetNormVersor().z) > 0) ;
// calcolo degli estremi degli archi
Point3d ptS1, ptE1 ;
if ( ! m_Arc1.GetStartPoint( ptS1) || ! m_Arc1.GetEndPoint( ptE1))
return ;
Point3d ptS2, ptE2 ;
if ( ! m_Arc2.GetStartPoint( ptS2) || ! m_Arc2.GetEndPoint( ptE2))
return ;
// determino se sono chiusi ( cerchi)
bool bClosed1 = AreSamePointApprox( ptS1, ptE1) ;
bool bClosed2 = AreSamePointApprox( ptS2, ptE2) ;
// calcolo del parametro di inizio dell'arco 2 nel riferimento dell'arco 1
double dUS2 ;
int nPosS2 ;
if ( ! m_Arc1.CalcPointParamPosiz( ptS2, dUS2, nPosS2))
return ;
// calcolo dell'ampiezza parametrica dell'arco 2 nel riferimento dell'arco 1
double dDeltaU2 = abs( m_Arc2.GetAngCenter() / m_Arc1.GetAngCenter()) * ( bEqVers ? 1 : -1) ;
// calcolo dell'ampiezza parametrica di un giro nel riferimento dell'arco 1
double dTurnU = abs( ANG_FULL / m_Arc1.GetAngCenter()) ;
// determinazione del minimo e massimo parametro dell'arco 2 nel riferimento dell'arco 1
double dU2min = dUS2 ;
double dU2max = dUS2 + dDeltaU2 ;
if ( dU2min > dU2max)
swap( dU2min, dU2max) ;
// se il minimo è negativo, aggiungo un giro
if ( dU2min * dU2L < - EPS_SMALL) {
dU2min += dTurnU ;
dU2max += dTurnU ;
}
// se il minimo di 2 coincide con il massimo di 1 nel primo giro -> un punto estremo
if ( abs( 1 - dU2min) * dU2L < EPS_SMALL) {
m_Info[0].IciA[0].dU = 1 ;
m_Info[0].IciB[0].dU = ( bEqVers ? 0 : 1) ;
m_Info[0].IciA[0].ptI = ptE1 ;
m_Info[0].IciB[0].ptI = ( bEqVers ? ptS2 : ptE2) ;
m_Info[0].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciA[0].nNextTy = ICCT_NULL ;
m_Info[0].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciB[0].nNextTy = ICCT_NULL ;
m_Info[0].bOverlap = false ;
m_nNumInters = 1 ;
}
// se invece è minore -> una sovrapposizione
else if ( dU2min < 1) {
// inizio dell'intervallo
m_Info[0].IciA[0].dU = dU2min ;
m_Info[0].IciB[0].dU = ( bEqVers ? 0 : 1) ;
m_Arc1.GetPointD1D2( m_Info[0].IciA[0].dU, ICurve::FROM_MINUS, m_Info[0].IciA[0].ptI) ;
m_Info[0].IciB[0].ptI = ( bEqVers ? ptS2 : ptE2) ;
m_Info[0].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciA[0].nNextTy = ICCT_ON ;
if ( bEqVers) {
m_Info[0].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciB[0].nNextTy = ICCT_ON ;
}
else {
m_Info[0].IciB[0].nPrevTy = ICCT_ON ;
m_Info[0].IciB[0].nNextTy = ICCT_NULL ;
}
// fine dell'intervallo
if ( dU2max < 1) {
m_Info[0].IciA[1].dU = dU2max ;
m_Info[0].IciB[1].dU = ( bEqVers ? 1 : 0) ;
}
else {
m_Info[0].IciA[1].dU = 1 ;
int nPos ;
m_Arc2.CalcPointParamPosiz( ptE1, m_Info[0].IciB[1].dU, nPos) ;
}
m_Arc1.GetPointD1D2( m_Info[0].IciA[1].dU, ICurve::FROM_MINUS, m_Info[0].IciA[1].ptI) ;
m_Arc2.GetPointD1D2( m_Info[0].IciB[1].dU, ICurve::FROM_MINUS, m_Info[0].IciB[1].ptI) ;
m_Info[0].IciA[1].nPrevTy = ICCT_ON ;
m_Info[0].IciA[1].nNextTy = ICCT_NULL ;
if ( bEqVers) {
m_Info[0].IciB[1].nPrevTy = ICCT_ON ;
m_Info[0].IciB[1].nNextTy = ICCT_NULL ;
}
else {
m_Info[0].IciB[1].nPrevTy = ICCT_NULL ;
m_Info[0].IciB[1].nNextTy = ICCT_ON ;
}
// dati generali
m_Info[0].bOverlap = true ;
m_Info[0].bCBOverEq = bEqVers ;
m_bOverlaps = true ;
m_nNumInters = 1 ;
}
// se il massimo di 2 coincide con il minimo di 1 nel secondo giro e 1 e 2 non completi -> un punto estremo
if ( abs( dTurnU - dU2max) * dU2L < EPS_SMALL && ! bClosed1 && ! bClosed2) {
m_Info[m_nNumInters].IciA[0].dU = 0 ;
m_Info[m_nNumInters].IciB[0].dU = ( bEqVers ? 1 : 0) ;
m_Info[m_nNumInters].IciA[0].ptI = ptS1 ;
m_Info[m_nNumInters].IciB[0].ptI = ( bEqVers ? ptE2 : ptS2) ;
m_Info[m_nNumInters].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[m_nNumInters].IciA[0].nNextTy = ICCT_NULL ;
m_Info[m_nNumInters].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[m_nNumInters].IciB[0].nNextTy = ICCT_NULL ;
m_Info[m_nNumInters].bOverlap = false ;
++ m_nNumInters ;
}
// se invece è maggiore -> una sovrapposizione
else if ( dU2max > dTurnU) {
// inizio dell'intervallo
m_Info[m_nNumInters].IciA[0].dU = 0 ;
int nPos ;
m_Arc2.CalcPointParamPosiz( ptS1, m_Info[m_nNumInters].IciB[0].dU, nPos) ;
m_Info[m_nNumInters].IciA[0].ptI = ptS1 ;
m_Arc2.GetPointD1D2( m_Info[m_nNumInters].IciB[0].dU, ICurve::FROM_MINUS, m_Info[m_nNumInters].IciB[0].ptI) ;
m_Info[m_nNumInters].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[m_nNumInters].IciA[0].nNextTy = ICCT_ON ;
if ( bEqVers) {
m_Info[m_nNumInters].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[m_nNumInters].IciB[0].nNextTy = ICCT_ON ;
}
else {
m_Info[m_nNumInters].IciB[0].nPrevTy = ICCT_ON ;
m_Info[m_nNumInters].IciB[0].nNextTy = ICCT_NULL ;
}
// fine dell'intervallo
if ( dU2max - dTurnU < 1) {
m_Info[m_nNumInters].IciA[1].dU = dU2max - dTurnU ;
m_Info[m_nNumInters].IciB[1].dU = ( bEqVers ? 1 : 0) ;
}
else {
m_Info[m_nNumInters].IciA[1].dU = 1 ;
int nPos ;
m_Arc2.CalcPointParamPosiz( ptE1, m_Info[m_nNumInters].IciB[1].dU, nPos) ;
}
m_Arc1.GetPointD1D2( m_Info[m_nNumInters].IciA[1].dU, ICurve::FROM_MINUS, m_Info[m_nNumInters].IciA[1].ptI) ;
m_Arc2.GetPointD1D2( m_Info[m_nNumInters].IciB[1].dU, ICurve::FROM_MINUS, m_Info[m_nNumInters].IciB[1].ptI) ;
m_Info[m_nNumInters].IciA[1].nPrevTy = ICCT_ON ;
m_Info[m_nNumInters].IciA[1].nNextTy = ICCT_NULL ;
if ( bEqVers) {
m_Info[m_nNumInters].IciB[1].nPrevTy = ICCT_ON ;
m_Info[m_nNumInters].IciB[1].nNextTy = ICCT_NULL ;
}
else {
m_Info[m_nNumInters].IciB[1].nPrevTy = ICCT_NULL ;
m_Info[m_nNumInters].IciB[1].nNextTy = ICCT_ON ;
}
// dati generali
m_Info[m_nNumInters].bOverlap = true ;
m_Info[m_nNumInters].bCBOverEq = bEqVers ;
m_bOverlaps = true ;
++ m_nNumInters ;
}
// se due intersezioni, le ordino in senso crescente del parametro U della prima curva
if ( m_nNumInters == 2) {
if ( m_Info[0].IciA[0].dU > m_Info[1].IciA[0].dU)
swap( m_Info[0], m_Info[1]) ;
}
return ;
}
// parametri per calcolo intersezioni
// distanza da centro 1 della proiezione delle intersezioni sulla retta congiungente i centri
double dA = ( m_Arc1.GetRadius() * m_Arc1.GetRadius() - m_Arc2.GetRadius() * m_Arc2.GetRadius() +
dDist * dDist) / ( 2 * dDist) ;
// semi-distanza tra i punti di intersezione (al quadrato)
double dSqH = m_Arc1.GetRadius() * m_Arc1.GetRadius() - dA * dA ;
// cerchi tangenti esterni -> una intersezione
if ( abs( dDist - ( m_Arc1.GetRadius() + m_Arc2.GetRadius())) < EPS_INTER_ARC) {
// tolleranza tangenziale sull'intersezione
double dTgTol = ( dSqH > SQ_EPS_SMALL ? sqrt( dSqH) : EPS_SMALL) ;
// calcolo il punto di intersezione
Point3d ptInt = m_Arc1.GetCenter() + vtDir * m_Arc1.GetRadius() ;
// posizione parametrica dell'intersezione sul primo arco
int nPos1 ;
if ( ! m_Arc1.MyCalcPointParamPosiz( ptInt, m_Info[0].IciA[0].dU, nPos1, dTgTol))
return ;
// posizione parametrica dell'intersezione sul secondo arco
int nPos2 ;
if ( ! m_Arc2.MyCalcPointParamPosiz( ptInt, m_Info[0].IciB[0].dU, nPos2, dTgTol))
return ;
// se soluzione non accettata, esco
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
return ;
// calcolo i punti sui due archi (possono differire in Z)
m_Arc1.GetPointD1D2( m_Info[0].IciA[0].dU, ICurve::FROM_MINUS, m_Info[0].IciA[0].ptI) ;
m_Arc2.GetPointD1D2( m_Info[0].IciB[0].dU, ICurve::FROM_MINUS, m_Info[0].IciB[0].ptI) ;
// verifico che non distino in XY più della tolleranza generale
if ( ! AreSamePointXYApprox( m_Info[0].IciA[0].ptI, m_Info[0].IciB[0].ptI)) {
// se entrambi interni, c'è un errore imprevisto (dovrebbero essere entro la tolleranza)
if ( nPos1 == ICurve::PP_MID && nPos2 == ICurve::PP_MID)
return ;
// se entrambi già agli estremi, non posso spostarli
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END))
return ;
// se primo all'estremo dell'entità, provo a spostare il secondo
if ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) {
// ridetermino posizione parametrica del secondo
if ( ! m_Arc2.MyCalcPointParamPosiz( m_Info[0].IciA[0].ptI, m_Info[0].IciB[0].dU, nPos2, dTgTol) || nPos2 == ICurve::PP_NULL)
return ;
// ricalcolo il punto sull'arco e riverifico in XY
m_Arc2.GetPointD1D2( m_Info[0].IciB[0].dU, ICurve::FROM_MINUS, m_Info[0].IciB[0].ptI) ;
if ( ! AreSamePointXYApprox( m_Info[0].IciA[0].ptI, m_Info[0].IciB[0].ptI))
return ;
}
// altrimenti secondo all'estremo dell'entità, provo a spostare il primo
else {
// ridetermino posizione parametrica del primo
if ( ! m_Arc1.MyCalcPointParamPosiz( m_Info[0].IciB[0].ptI, m_Info[0].IciA[0].dU, nPos1, dTgTol) || nPos1 == ICurve::PP_NULL)
return ;
// ricalcolo il punto sull'arco e riverifico in XY
m_Arc1.GetPointD1D2( m_Info[0].IciA[0].dU, ICurve::FROM_MINUS, m_Info[0].IciA[0].ptI) ;
if ( ! AreSamePointXYApprox( m_Info[0].IciA[0].ptI, m_Info[0].IciB[0].ptI))
return ;
}
}
// calcolo dati ausiliari
bool bCCW1 = (( m_Arc1.GetAngCenter() > 0 && m_Arc1.GetNormVersor().IsZplus()) ||
( m_Arc1.GetAngCenter() < 0 && m_Arc1.GetNormVersor().IsZminus())) ;
bool bCCW2 = (( m_Arc2.GetAngCenter() > 0 && m_Arc2.GetNormVersor().IsZplus()) ||
( m_Arc2.GetAngCenter() < 0 && m_Arc2.GetNormVersor().IsZminus())) ;
// calcolo tipo di intersezione
m_Info[0].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciA[0].nNextTy = ICCT_NULL ;
m_Info[0].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciB[0].nNextTy = ICCT_NULL ;
// si incontrano alle estremità, non si può dire alcunché
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
; // rimangono tutti NULL
}
// l'inizio di 1 interseca il mezzo di 2
else if ( nPos1 == ICurve::PP_START) {
if ( bCCW2)
m_Info[0].IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[0].IciA[0].nNextTy = ICCT_IN ; // NULL + IN
// curva 2 NULL + NULL
}
// la fine di 1 interseca il mezzo di 2
else if ( nPos1 == ICurve::PP_END) {
if ( bCCW2)
m_Info[0].IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[0].IciA[0].nPrevTy = ICCT_IN ; // IN + NULL
// curva 2 NULL + NULL
}
// l'inizio di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_START) {
// curva 1 NULL + NULL
if ( bCCW1)
m_Info[0].IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[0].IciB[0].nNextTy = ICCT_IN ; // NULL + IN
}
// la fine di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_END) {
// curva 1 NULL + NULL
if ( bCCW1)
m_Info[0].IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[0].IciB[0].nPrevTy = ICCT_IN ; // IN + NULL
}
// si intersecano nel mezzo
else {
if ( bCCW2) {
m_Info[0].IciA[0].nPrevTy = ICCT_OUT ; // OUT + OUT
m_Info[0].IciA[0].nNextTy = ICCT_OUT ;
}
else {
m_Info[0].IciA[0].nPrevTy = ICCT_IN ; // IN + IN
m_Info[0].IciA[0].nNextTy = ICCT_IN ;
}
if ( bCCW1) {
m_Info[0].IciB[0].nPrevTy = ICCT_OUT ; // OUT + OUT
m_Info[0].IciB[0].nNextTy = ICCT_OUT ;
}
else {
m_Info[0].IciB[0].nPrevTy = ICCT_IN ; // IN + IN
m_Info[0].IciB[0].nNextTy = ICCT_IN ;
}
}
// aggiorno dati generali di intersezione
m_Info[0].bOverlap = false ;
m_nNumInters = 1 ;
return ;
}
// cerchi tangenti interni -> una intersezione
if ( abs( dDist - abs( m_Arc1.GetRadius() - m_Arc2.GetRadius())) < EPS_INTER_ARC) {
// tolleranza tangenziale sull'intersezione
double dTgTol = ( dSqH > SQ_EPS_SMALL ? sqrt( dSqH) : EPS_SMALL) ;
// determino quale dei due contiene l'altro
bool bBiggest1 = ( m_Arc1.GetRadius() > m_Arc2.GetRadius()) ;
// calcolo il punto di intersezione
Point3d ptInt = m_Arc1.GetCenter() + ( bBiggest1 ? vtDir : - vtDir) * m_Arc1.GetRadius() ;
// posizione parametrica dell'intersezione sul primo arco
int nPos1 ;
if ( ! m_Arc1.MyCalcPointParamPosiz( ptInt, m_Info[0].IciA[0].dU, nPos1, dTgTol))
return ;
// posizione parametrica dell'intersezione sul secondo arco
int nPos2 ;
if ( ! m_Arc2.MyCalcPointParamPosiz( ptInt, m_Info[0].IciB[0].dU, nPos2, dTgTol))
return ;
// se soluzione non accettata, esco
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
return ;
// calcolo i punti sui due archi (possono differire in Z)
m_Arc1.GetPointD1D2( m_Info[0].IciA[0].dU, ICurve::FROM_MINUS, m_Info[0].IciA[0].ptI) ;
m_Arc2.GetPointD1D2( m_Info[0].IciB[0].dU, ICurve::FROM_MINUS, m_Info[0].IciB[0].ptI) ;
// verifico che non distino in XY più della tolleranza generale
if ( ! AreSamePointXYApprox( m_Info[0].IciA[0].ptI, m_Info[0].IciB[0].ptI)) {
// se entrambi interni, c'è un errore imprevisto (dovrebbero essere entro la tolleranza)
if ( nPos1 == ICurve::PP_MID && nPos2 == ICurve::PP_MID)
return ;
// se entrambi già agli estremi, non posso spostarli
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END))
return ;
// se primo all'estremo dell'entità, provo a spostare il secondo
if ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) {
// ridetermino posizione parametrica del secondo
if ( ! m_Arc2.MyCalcPointParamPosiz( m_Info[0].IciA[0].ptI, m_Info[0].IciB[0].dU, nPos2, dTgTol) || nPos2 == ICurve::PP_NULL)
return ;
// ricalcolo il punto sull'arco e riverifico in XY
m_Arc2.GetPointD1D2( m_Info[0].IciB[0].dU, ICurve::FROM_MINUS, m_Info[0].IciB[0].ptI) ;
if ( ! AreSamePointXYApprox( m_Info[0].IciA[0].ptI, m_Info[0].IciB[0].ptI))
return ;
}
// altrimenti secondo all'estremo dell'entità, provo a spostare il primo
else {
// ridetermino posizione parametrica del primo
if ( ! m_Arc1.MyCalcPointParamPosiz( m_Info[0].IciB[0].ptI, m_Info[0].IciA[0].dU, nPos1, dTgTol) || nPos1 == ICurve::PP_NULL)
return ;
// ricalcolo il punto sull'arco e riverifico in XY
m_Arc1.GetPointD1D2( m_Info[0].IciA[0].dU, ICurve::FROM_MINUS, m_Info[0].IciA[0].ptI) ;
if ( ! AreSamePointXYApprox( m_Info[0].IciA[0].ptI, m_Info[0].IciB[0].ptI))
return ;
}
}
// calcolo dati ausiliari
bool bCCW1 = (( m_Arc1.GetAngCenter() > 0 && m_Arc1.GetNormVersor().IsZplus()) ||
( m_Arc1.GetAngCenter() < 0 && m_Arc1.GetNormVersor().IsZminus())) ;
bool bCCW2 = (( m_Arc2.GetAngCenter() > 0 && m_Arc2.GetNormVersor().IsZplus()) ||
( m_Arc2.GetAngCenter() < 0 && m_Arc2.GetNormVersor().IsZminus())) ;
// calcolo tipo di intersezione
m_Info[0].IciA[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciA[0].nNextTy = ICCT_NULL ;
m_Info[0].IciB[0].nPrevTy = ICCT_NULL ;
m_Info[0].IciB[0].nNextTy = ICCT_NULL ;
// si incontrano alle estremità, non si può dire alcunché
if ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
; // rimangono tutti NULL
}
// l'inizio di 1 interseca il mezzo di 2
else if ( nPos1 == ICurve::PP_START) {
if ( ( bBiggest1 && bCCW2) || ( ! bBiggest1 && ! bCCW2))
m_Info[0].IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[0].IciA[0].nNextTy = ICCT_IN ; // NULL + IN
// curva 2 NULL + NULL
}
// la fine di 1 interseca il mezzo di 2
else if ( nPos1 == ICurve::PP_END) {
if ( ( bBiggest1 && bCCW2) || ( ! bBiggest1 && ! bCCW2))
m_Info[0].IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[0].IciA[0].nPrevTy = ICCT_IN ; // IN + NULL
// curva 2 NULL + NULL
}
// l'inizio di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_START) {
// curva 1 NULL + NULL
if ( ( bBiggest1 && ! bCCW1) || ( ! bBiggest1 && bCCW1))
m_Info[0].IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT
else
m_Info[0].IciB[0].nNextTy = ICCT_IN ; // NULL + IN
}
// la fine di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_END) {
// curva 1 NULL + NULL
if ( ( bBiggest1 && ! bCCW1) || ( ! bBiggest1 && bCCW1))
m_Info[0].IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL
else
m_Info[0].IciB[0].nPrevTy = ICCT_IN ; // IN + NULL
}
// si intersecano nel mezzo
else {
if ( ( bBiggest1 && bCCW2) || ( ! bBiggest1 && ! bCCW2)) {
m_Info[0].IciA[0].nPrevTy = ICCT_OUT ; // OUT + OUT
m_Info[0].IciA[0].nNextTy = ICCT_OUT ;
}
else {
m_Info[0].IciA[0].nPrevTy = ICCT_IN ; // IN + IN
m_Info[0].IciA[0].nNextTy = ICCT_IN ;
}
if ( ( bBiggest1 && ! bCCW1) || ( ! bBiggest1 && bCCW1)) {
m_Info[0].IciB[0].nPrevTy = ICCT_OUT ; // OUT + OUT
m_Info[0].IciB[0].nNextTy = ICCT_OUT ;
}
else {
m_Info[0].IciB[0].nPrevTy = ICCT_IN ; // IN + IN
m_Info[0].IciB[0].nNextTy = ICCT_IN ;
}
}
// aggiorno dati generali di intersezione
m_Info[0].bOverlap = false ;
m_nNumInters = 1 ;
return ;
}
// due intersezioni
double dH = sqrt( dSqH) ;
Point3d ptRef = m_Arc1.GetCenter() + dA * vtDir ;
Vector3d vtDelta = dH * vtDir ;
vtDelta.Rotate( Z_AX, 0, 1) ;
int nPos1, nPos2 ;
// ---> prima intersezione
// determinazione geometrica e topologica dell'intersezione tra le due curve
if ( CalcSecIntersGeomData( 0, ptRef + vtDelta, nPos1, nPos2) &&
CalcSecIntersTopolData( 0, nPos1, nPos2)) {
// 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 ( CalcSecIntersGeomData( m_nNumInters, ptRef - vtDelta, nPos1, nPos2) &&
CalcSecIntersTopolData( m_nNumInters, nPos1, nPos2)) {
// aggiorno dati generali di intersezione
m_Info[m_nNumInters].bOverlap = false ;
++ m_nNumInters ;
}
// se due intersezioni, le ordino in senso crescente del parametro U della prima curva
if ( m_nNumInters == 2) {
if ( m_Info[0].IciA[0].dU > m_Info[1].IciA[0].dU)
swap( m_Info[0], m_Info[1]) ;
}
}
//----------------------------------------------------------------------------
bool
IntersArcArc::CalcSecIntersGeomData( int nInt, const Point3d& ptInt, int& nPos1, int& nPos2)
{
// posizione parametrica dell'intersezione sul primo arco
if ( ! m_Arc1.CalcPointParamPosiz( ptInt, m_Info[nInt].IciA[0].dU, nPos1))
return false ;
// posizione parametrica dell'intersezione sul secondo arco
if ( ! m_Arc2.CalcPointParamPosiz( ptInt, m_Info[nInt].IciB[0].dU, nPos2))
return false ;
// se soluzione non accettata, esco
if ( nPos1 == ICurve::PP_NULL || nPos2 == ICurve::PP_NULL)
return false ;
// calcolo i punti sulle due curve (possono differire in Z)
m_Arc1.GetPointD1D2( m_Info[nInt].IciA[0].dU, ICurve::FROM_MINUS, m_Info[nInt].IciA[0].ptI) ;
m_Arc2.GetPointD1D2( m_Info[nInt].IciB[0].dU, ICurve::FROM_MINUS, m_Info[nInt].IciB[0].ptI) ;
return true ;
}
//----------------------------------------------------------------------------
bool
IntersArcArc::CalcSecIntersTopolData( int nInt, int nPos1, int nPos2)
{
// calcolo dati ausiliari
Point3d ptInt1, ptInt2 ;
Vector3d vtDir1, vtDir2 ;
m_Arc1.GetPointD1D2( m_Info[nInt].IciA[0].dU, ICurve::FROM_MINUS, ptInt1, &vtDir1) ;
m_Arc2.GetPointD1D2( m_Info[nInt].IciB[0].dU, ICurve::FROM_MINUS, ptInt2, &vtDir2) ;
double dCrossXY = CrossXY( vtDir1, vtDir2) ;
// 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 ( ( nPos1 == ICurve::PP_START || nPos1 == ICurve::PP_END) &&
( nPos2 == ICurve::PP_START || nPos2 == ICurve::PP_END)) {
; // rimangono tutti NULL
}
// l'inizio di 1 interseca il mezzo di 2
else if ( nPos1 == 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 2 NULL + NULL
}
// la fine di 1 interseca il mezzo di 2
else if ( nPos1 == 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 2 NULL + NULL
}
// l'inizio di 2 interseca il mezzo di 1
else if ( nPos2 == ICurve::PP_START) {
// curva 1 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 ( nPos2 == ICurve::PP_END) {
// curva 1 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( ( ( ptInt1 - vtDir1) - ( ptInt2 - vtDir2)), vtDir2) > 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( ( ( ptInt2 - vtDir2) - ( ptInt1 - vtDir1)), vtDir1) > 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 ;
}