//---------------------------------------------------------------------------- // 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 ; //---------------------------------------------------------------------------- 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_SMALL) return ; // cerchi interni -> nessuna intersezione if ( dDist < abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) - EPS_SMALL) return ; // cerchi coincidenti -> sovrapposizioni e/o intersezioni agli estremi if ( dDist < EPS_SMALL && abs( m_Arc1.GetRadius() - m_Arc2.GetRadius()) < EPS_SMALL) { // 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_SMALL) { // 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_SMALL) { // 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 ; }