Files
EgtGeomKernel/IntersLineLine.cpp
T
Dario Sassi f119a5a1be EgtGeomKernel 1.5f6 :
- agg. intersezione linee-linee
- agg. alle curve metodi per passare da lunghezza a parametro e viceversa
- agg. metodi per creare curve composite come poligoni regolari
- corr. errore in triangulate con contorni CW
- agg. opportune funzioni a TSC.
2014-06-24 07:05:43 +00:00

221 lines
9.4 KiB
C++

//----------------------------------------------------------------------------
// 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 ;
}
}