//---------------------------------------------------------------------------- // EgalTech 2014-2014 //---------------------------------------------------------------------------- // File : IntersLineLine.cpp Data : 15.06.14 Versione : 1.5f6 // Contenuto : Implementazione della classe intersezione linea/linea. // // // // Modifiche : 15.06.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "IntersLineLine.h" using namespace std ; //---------------------------------------------------------------------------- IntersLineLine::IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2, bool bFinites) { // Le intersezioni sono calcolate nel piano XY locale. // nessuna intersezione trovata m_bOverlaps = false ; m_nNumInters = 0 ; // verifico validità linee if ( ! Line1.IsValid() || ! Line2.IsValid()) return ; // linea 1 : pto Start e direzione Point3d ptS1 = Line1.GetStart() ; Vector3d vtDir1 = Line1.GetEnd() - ptS1 ; // linea 2 : pto Start e direzione Point3d ptS2 = Line2.GetStart() ; Vector3d vtDir2 = Line2.GetEnd() - ptS2 ; // prodotto vettoriale nel piano XY tra le direzioni delle linee double dCrossXY = CrossXY( vtDir1, vtDir2) ; // se le linee non sono parallele if ( dCrossXY * dCrossXY > EPS_ZERO * EPS_ZERO) { // posizioni parametriche dell'intersezione sulle linee m_Info[0].Ici[0].dU = CrossXY( ( ptS2 - ptS1), vtDir2) / dCrossXY ; m_Info[0].Ici[1].dU = CrossXY( ( ptS2 - ptS1), vtDir1) / dCrossXY ; // tipo di posizione enum IntPos { IP_NULL = 0, IP_START = 1, IP_MID = 2, IP_END = 3} ; int nPos1 = IP_MID ; int nPos2 = IP_MID ; // se segmenti, ne verifico la posizione if ( bFinites) { // prima linea if ( ( m_Info[0].Ici[0].dU * vtDir1).IsSmall()) nPos1 = IP_START ; // vicino a inizio else if ( (( 1 - m_Info[0].Ici[0].dU) * vtDir1).IsSmall()) nPos1 = IP_END ; // vicino a fine else if ( m_Info[0].Ici[0].dU > 0 && m_Info[0].Ici[0].dU < 1) nPos1 = IP_MID ; // nell'interno else nPos1 = IP_NULL ; // fuori // seconda linea if ( ( m_Info[0].Ici[1].dU * vtDir2).IsSmall()) nPos2 = IP_START ; // vicino a inizio else if ( (( 1 - m_Info[0].Ici[1].dU) * vtDir2).IsSmall()) nPos2 = IP_END ; // vicino a fine else if ( m_Info[0].Ici[1].dU > 0 && m_Info[0].Ici[1].dU < 1) nPos2 = IP_MID ; // nell'interno else nPos2 = IP_NULL ; // fuori } // se soluzione non accettata, esco if ( nPos1 == IP_NULL || nPos2 == IP_NULL) return ; // calcolo i punti sulle due linee (possono differire in Z) m_Info[0].Ici[0].ptI = ptS1 + m_Info[0].Ici[0].dU * vtDir1 ; m_Info[0].Ici[1].ptI = ptS2 + m_Info[0].Ici[1].dU * vtDir2 ; // calcolo tipo di intersezione m_Info[0].Ici[0].nTy = ICCT_RESET ; m_Info[0].Ici[1].nTy = ICCT_RESET ; // si incontrano alle estremità, non si può dire alcunché if ( ( nPos1 == IP_START || nPos1 == IP_END) && ( nPos2 == IP_START || nPos2 == IP_END)) { m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL } // l'inizio di 1 interseca il mezzo di 2 else if ( nPos1 == IP_START) { if ( dCrossXY > 0) m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NOUT ; // NULL + OUT else m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NIN ; // NULL + IN m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL } // la fine di 1 interseca il mezzo di 2 else if ( nPos1 == IP_END) { if ( dCrossXY < 0) m_Info[0].Ici[0].nTy = ICCT_POUT + ICCT_NNULL ; // OUT + NULL else m_Info[0].Ici[0].nTy = ICCT_PIN + ICCT_NNULL ; // IN + NULL m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL } // l'inizio di 2 interseca il mezzo di 1 else if ( nPos2 == IP_START) { m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL if ( - dCrossXY > 0) m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NOUT ; // NULL + OUT else m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NIN ; // NULL + IN } // la fine di 2 interseca il mezzo di 1 else if ( nPos2 == IP_END) { m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL if ( - dCrossXY < 0) m_Info[0].Ici[1].nTy = ICCT_POUT + ICCT_NNULL ; // OUT + NULL else m_Info[0].Ici[1].nTy = ICCT_PIN + ICCT_NNULL ; // IN + NULL } // si intersecano nel mezzo else { if ( CrossXY( ( ptS1 - ptS2), vtDir2) > 0) m_Info[0].Ici[0].nTy = ICCT_POUT + ICCT_NIN ; // OUT + IN else m_Info[0].Ici[0].nTy = ICCT_PIN + ICCT_NOUT ; // IN + OUT if ( CrossXY( ( ptS2 - ptS1), vtDir1) > 0) m_Info[0].Ici[1].nTy = ICCT_POUT + ICCT_NIN ; // OUT + IN else m_Info[0].Ici[1].nTy = ICCT_PIN + ICCT_NOUT ; // IN + OUT } m_bOverlaps = false ; m_nNumInters = 1 ; // una intersezione return ; } // se le linee sono parallele e non coincidenti if ( fabs( CrossXY( ( ptS2 - ptS1), vtDir1)) > EPS_SMALL * vtDir1.LenXY()) return ; // non ci sono intersezioni // le linee sono parallele e coincidenti e sono infinite if ( ! bFinites) { m_bOverlaps = true ; m_nNumInters = 0 ; // non esistono estremi del tratto sovrapposto return ; } // le linee sono parallele e coincidenti e sono segmenti, si cercano eventuali sovrapposizioni // determino se sono equiverse o controverse bool bEqVers = ( ScalarXY( vtDir1, vtDir2) > 0) ; // calcolo dei valori parametrici degli estremi del secondo segmento sul primo double dUmin = ScalarXY( ( ptS2 - ptS1), vtDir1) / vtDir1.SqLenXY() ; double dUmax = ScalarXY( ( ptS2 + vtDir2 - ptS1), vtDir1) / vtDir1.SqLenXY() ; if ( ! bEqVers) swap( dUmin, dUmax) ; // estremo inferiore del primo coincide con superiore del secondo -> un punto estremo if ( ( dUmax * vtDir1).IsSmall()) { m_Info[0].Ici[0].dU = 0 ; m_Info[0].Ici[1].dU = ( bEqVers ? 1 : 0) ; m_Info[0].Ici[0].ptI = ptS1 + m_Info[0].Ici[0].dU * vtDir1 ; m_Info[0].Ici[1].ptI = ptS2 + m_Info[0].Ici[1].dU * vtDir2 ; m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL m_bOverlaps = false ; m_nNumInters = 1 ; // una intersezione return ; } // estremo superiore del primo coincide con inferiore del secondo -> un punto estremo else if ( ( ( 1 - dUmin) * vtDir1).IsSmall()) { m_Info[0].Ici[0].dU = 1 ; m_Info[0].Ici[1].dU = ( bEqVers ? 0 : 1) ; m_Info[0].Ici[0].ptI = ptS1 + m_Info[0].Ici[0].dU * vtDir1 ; m_Info[0].Ici[1].ptI = ptS2 + m_Info[0].Ici[1].dU * vtDir2 ; m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL m_bOverlaps = false ; m_nNumInters = 1 ; // una intersezione return ; } // esterni -> nessuna intersezione else if ( dUmax < 0 || 1 < dUmin) { return ; } // altrimenti si sovrappongono -> tratto comune else { // devo prendere il massimo dei minimi if ( dUmin > 0) { m_Info[0].Ici[0].dU = dUmin ; m_Info[0].Ici[1].dU = ( bEqVers ? 0 : 1) ; } else { m_Info[0].Ici[0].dU = 0 ; m_Info[0].Ici[1].dU = ScalarXY( ( ptS1 - ptS2), vtDir2) / vtDir2.SqLenXY() ; } m_Info[0].Ici[0].ptI = ptS1 + m_Info[0].Ici[0].dU * vtDir1 ; m_Info[0].Ici[1].ptI = ptS2 + m_Info[0].Ici[1].dU * vtDir2 ; m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NON ; // NULL + ON if ( bEqVers) m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NON ; // NULL + ON else m_Info[0].Ici[1].nTy = ICCT_PON + ICCT_NNULL ; // ON + NULL // e il minimo dei massimi if ( dUmax < 1) { m_Info[1].Ici[0].dU = dUmax ; m_Info[1].Ici[1].dU = ( bEqVers ? 1 : 0) ; } else { m_Info[1].Ici[0].dU = 1 ; m_Info[1].Ici[1].dU = ScalarXY( ( ptS1 + vtDir1 - ptS2), vtDir2) / vtDir2.SqLenXY() ; } m_Info[1].Ici[0].ptI = ptS1 + m_Info[1].Ici[0].dU * vtDir1 ; m_Info[1].Ici[1].ptI = ptS2 + m_Info[1].Ici[1].dU * vtDir2 ; m_Info[1].Ici[0].nTy = ICCT_PON + ICCT_NNULL ; // ON + NULL if ( bEqVers) m_Info[1].Ici[1].nTy = ICCT_PON + ICCT_NNULL ; // ON + NULL else m_Info[1].Ici[1].nTy = ICCT_PNULL + ICCT_NON ; // NULL + ON m_bOverlaps = true ; m_nNumInters = 2 ; // estremi del tratto di sovrapposizione return ; } }