b8bf9b2f21
- ApproxWithLines di curve con nuove opzioni - semplificata CurveComposite - completate IntersLineTria e IntersLineSurfTm - aggiunta MakeConvex a PolyLine.
188 lines
6.6 KiB
C++
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 ;
|
|
} |