Files
EgtGeomKernel/IntersLineTria.cpp
T
Dario Sassi b8bf9b2f21 EgtGeomKernel 1.6f4 :
- ApproxWithLines di curve con nuove opzioni
- semplificata CurveComposite
- completate IntersLineTria e IntersLineSurfTm
- aggiunta MakeConvex a PolyLine.
2015-06-30 14:04:02 +00:00

188 lines
6.6 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : IntersLinePlane.cpp Data : 18.02.15 Versione : 1.6b7
// Contenuto : Implementazione della intersezione linea/triangolo.
//
//
//
// Modifiche : 18.02.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ProjPlane.h"
#include "CurveLine.h"
#include "IntersLineLine.h"
#include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
//----------------------------------------------------------------------------
static int IntersCoplanarLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria,
Point3d& ptInt, Point3d& ptInt2) ;
//----------------------------------------------------------------------------
int
IntersLineTria( const Point3d& ptL1, const Point3d& ptL2, const Triangle3d& trTria,
Point3d& ptInt, Point3d& ptInt2)
{
Vector3d vtL = ptL2 - ptL1 ;
double dLen = vtL.Len() ;
if ( dLen > EPS_SMALL)
vtL /= dLen ;
else
vtL = V_NULL ;
return IntersLineTria( ptL1, vtL, dLen, trTria, ptInt, ptInt2) ;
}
//----------------------------------------------------------------------------
int
IntersLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria,
Point3d& ptInt, Point3d& ptInt2)
{
// determino il piano del triangolo
Plane3d plPlane ;
plPlane.vtN = trTria.GetN() ;
plPlane.dDist = ( trTria.GetP(0) - ORIG) * plPlane.vtN ;
// calcolo l'intersezione tra il segmento di linea e il piano del triangolo
int nRes = IntersLinePlane( ptL, vtL, dLen, plPlane, ptInt) ;
// se non c'è intersezione
if ( nRes == ILPT_NO)
return ILTT_NO ;
// se c'è una intersezione
else if ( nRes == ILPT_START || nRes == ILPT_END || nRes == ILPT_YES) {
int nPTT = PointInTria( ptInt, trTria) ;
switch ( nPTT) {
case PTT_OUT :
return ILTT_NO ;
case PTT_VERT :
return ILTT_VERT ;
case PTT_EDGE :
return ILTT_EDGE ;
default :
return ILTT_IN ;
}
}
// se la linea giace nel piano del triangolo
else {
return IntersCoplanarLineTria( ptL, vtL, dLen, trTria, ptInt, ptInt2) ;
}
}
//----------------------------------------------------------------------------
int
IntersCoplanarLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria,
Point3d& ptInt, Point3d& ptInt2)
{
// verifico se il segmento è completamente contenuto nel triangolo
ptInt = ptL ;
ptInt2 = ptL + vtL * dLen ;
int nPTT = PointInTria( ptInt, trTria) ;
int nPTT2 = PointInTria( ptInt2, trTria) ;
if ( nPTT != PTT_OUT && nPTT2 != PTT_OUT)
return ILTT_SEGM ;
// se segmento nullo, basta verificare la posizione del punto iniziale
if ( dLen < EPS_SMALL || vtL.IsSmall()) {
switch ( nPTT) {
case PTT_OUT :
return ILTT_NO ;
case PTT_VERT :
return ILTT_VERT ;
case PTT_EDGE :
return ILTT_EDGE ;
default :
return ILTT_IN ;
}
}
// definisco un riferimento coincidente con il piano del triangolo
Frame3d frRef ;
if ( ! frRef.Set( trTria.GetP( 0), trTria.GetN(), ( trTria.GetP( 1) - trTria.GetP( 0))))
return ILTT_NO ;
// esprimo il triangolo e il segmento in questo riferimento
Triangle3d trTriaL = trTria ;
trTriaL.ToLoc( frRef) ;
Point3d ptLL = ptL ;
ptLL.ToLoc( frRef) ;
Vector3d vtLL = vtL ;
vtLL.ToLoc( frRef) ;
// calcolo le intersezioni tra i lati del triangolo e il segmento
CurveLine LineLL ;
LineLL.Set( ptLL, ptLL + vtLL * dLen) ;
int nNumInt = 0 ;
IntCrvCrvInfo IntCCI[3] ;
for ( int i = 0 ; i < 3 ; ++ i) {
CurveLine LineTL ;
LineTL.Set( trTriaL.GetP( i), trTriaL.GetP( ( i + 1) % 3)) ;
IntersLineLine IntLL( LineLL, LineTL) ;
if ( IntLL.GetIntCrvCrvInfo( IntCCI[nNumInt]))
++ nNumInt ;
}
// se nessuna intersezione
if ( nNumInt == 0)
return ILTT_NO ;
// se una sola intersezione
else if ( nNumInt == 1) {
// punto di intersezione
Point3d ptIntL = IntCCI[0].IciA[0].ptI ;
ptInt = ptIntL ;
ptInt.ToGlob( frRef) ;
// se è l'inizio del segmento ( e il resto del segmento deve essere per forza esterno)
if ( AreSamePointApprox( ptIntL, LineLL.GetStart()))
return ( ( nPTT == PTT_VERT) ? ILTT_VERT : ILTT_EDGE) ;
// se è la fine del segmento ( e il resto del segmento deve essere per forza esterno)
else if ( AreSamePointApprox( ptIntL, LineLL.GetEnd()))
return ( ( nPTT2 == PTT_VERT) ? ILTT_VERT : ILTT_EDGE) ;
// altrimenti è un punto intermedio
else {
// se l'inizio è nel triangolo
if ( nPTT == PTT_IN) {
ptInt2 = ptInt ;
ptInt = ptL ;
}
// altrimenti è la fine nel triangolo
else
ptInt2 = ptL + vtL * dLen ;
return ILTT_SEGM ;
}
}
// se 2 intersezioni
else if ( nNumInt == 2) {
// punti di intersezione
Point3d ptIntL = IntCCI[0].IciA[0].ptI ;
ptInt = ptIntL ;
ptInt.ToGlob( frRef) ;
Point3d ptInt2L = IntCCI[1].IciA[0].ptI ;
ptInt2 = ptInt2L ;
ptInt2.ToGlob( frRef) ;
// se coincidono, deve essere un vertice
if ( AreSamePointApprox( ptIntL, ptInt2L))
return ILTT_VERT ;
// altrimenti è un tratto
else {
// le ordino secondo il verso positivo della linea
if ( ( ptInt - ptL) * vtL > ( ptInt2 - ptL) * vtL)
std::swap( ptInt, ptInt2) ;
return ILTT_SEGM ;
}
}
// altrimenti 3 intersezioni, una deve coincidere con un lato le altre due sono i suoi vertici
else {
for ( int i = 0 ; i < 3 ; ++ i) {
if ( IntCCI[i].bOverlap) {
// punti di intersezione
Point3d ptIntL = IntCCI[i].IciA[0].ptI ;
ptInt = ptIntL ;
ptInt.ToGlob( frRef) ;
Point3d ptInt2L = IntCCI[i].IciA[1].ptI ;
ptInt2 = ptInt2L ;
ptInt2.ToGlob( frRef) ;
return ILTT_SEGM_ON_EDGE ;
}
}
}
return ILTT_NO ;
}