66cec4a872
- ridotte tolleranze su tangenza in intersezione archi.
610 lines
28 KiB
C++
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 ;
|
|
}
|