07b1f21ecd
- aggiunta IntersSurfTmSurfTm - correzioni a HashGrids.
319 lines
10 KiB
C++
319 lines
10 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2015-2017
|
|
//----------------------------------------------------------------------------
|
|
// File : IntersLineTria.cpp Data : 16.10.17 Versione : 1.8j4
|
|
// 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 "IntersLineTria.h"
|
|
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
|
#include "/EgtDev/Include/EGkFrame3d.h"
|
|
#include <array>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
IntersLineTria( const Point3d& ptL1, const Point3d& ptL2, const Triangle3d& trTria,
|
|
Point3d& ptInt, Point3d& ptInt2, bool bFinite)
|
|
{
|
|
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, bFinite) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
IntersLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria,
|
|
Point3d& ptInt, Point3d& ptInt2, bool bFinite)
|
|
{
|
|
// determino il piano del triangolo
|
|
Plane3d plPlane ;
|
|
plPlane.Set( trTria.GetP( 0), trTria.GetN()) ;
|
|
// calcolo l'intersezione tra il segmento di linea e il piano del triangolo
|
|
int nRes = IntersLinePlane( ptL, vtL, dLen, plPlane, ptInt, bFinite) ;
|
|
// 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, bFinite) ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
IntersCoplanarLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria,
|
|
Point3d& ptInt, Point3d& ptInt2, bool bFinite)
|
|
{
|
|
// Normale alla linea giacente nel piano
|
|
Vector3d vtN = vtL ^ trTria.GetN() ;
|
|
vtN.Normalize() ;
|
|
// calcolo le distanze dei vertici del triangolo dalla retta
|
|
array< double, 3> vDist ;
|
|
for ( int i = 0 ; i < 3 ; ++i)
|
|
vDist[i] = ( trTria.GetP( i) - ptL) * vtN ;
|
|
// verifico posizione del triangolo rispetto alla retta
|
|
array<int, 3> vPos = { 0, 0, 0} ;
|
|
int nVertPos = 0 ; int nVertNeg = 0 ;
|
|
for ( int i = 0 ; i < 3 ; ++i) {
|
|
if ( vDist[i] > EPS_SMALL) {
|
|
vPos[i] = 1 ;
|
|
++ nVertPos ;
|
|
}
|
|
else if ( vDist[i] < -EPS_SMALL) {
|
|
vPos[i] = -1 ;
|
|
++ nVertNeg ;
|
|
}
|
|
}
|
|
// Se il triangolo giace tutto da una parte della retta, nessuna intersezione
|
|
if ( nVertPos == 3 || nVertNeg == 3) {
|
|
return ILTT_NO ;
|
|
}
|
|
// Se altrimenti il triangolo giace sulla retta (triangolo schiacciato), sovrapposizione
|
|
else if ( nVertPos == 0 && nVertNeg == 0) {
|
|
// Determino i vertici estremi sulla retta
|
|
double dUmin = ( trTria.GetP( 0) - ptL) * vtL ;
|
|
double dUmax = ( trTria.GetP( 1) - ptL) * vtL ;
|
|
ptInt = trTria.GetP( 0) ;
|
|
ptInt2 = trTria.GetP( 1) ;
|
|
if ( dUmin > dUmax) {
|
|
swap( dUmin, dUmax) ;
|
|
swap( ptInt, ptInt2) ;
|
|
}
|
|
double dU2 = ( trTria.GetP( 2) - ptL) * vtL ;
|
|
if ( dU2 < dUmin)
|
|
ptInt = trTria.GetP( 2) ;
|
|
else if ( dU2 > dUmax)
|
|
ptInt2 = trTria.GetP( 2) ;
|
|
// Se linea infinita
|
|
if ( ! bFinite) {
|
|
return ILTT_SEGM_ON_EDGE ;
|
|
}
|
|
// Altrimenti linea finita
|
|
else {
|
|
// se massimo coincide con inizio segmento di retta
|
|
if ( abs( dUmax) < EPS_SMALL) {
|
|
ptInt = ptInt2 ;
|
|
return ILTT_VERT ;
|
|
}
|
|
// se minimo coincide con fine segmento di retta
|
|
else if ( abs ( dUmin - dLen) < EPS_SMALL) {
|
|
return ILTT_VERT ;
|
|
}
|
|
// se segmento non si sovrappone
|
|
else if ( dUmax < 0 || dUmin > dLen) {
|
|
return ILTT_NO ;
|
|
}
|
|
// altrimenti sovrapposizione parziale
|
|
else {
|
|
if ( dUmin < 0)
|
|
ptInt = ptL ;
|
|
if ( dUmax > dLen)
|
|
ptInt2 = ptL + vtL * dLen ;
|
|
return ILTT_SEGM_ON_EDGE ;
|
|
}
|
|
}
|
|
}
|
|
// se altrimenti due vertici del triangolo giacciono sulla linea
|
|
else if ( nVertPos + nVertNeg == 1) {
|
|
// Determino i vertici sulla linea
|
|
int nCount = 0 ;
|
|
for ( int i = 0 ; i < 3 ; ++i) {
|
|
if ( vPos[i] == 0) {
|
|
if ( nCount == 0)
|
|
ptInt = trTria.GetP( i) ;
|
|
else
|
|
ptInt2 = trTria.GetP( i) ;
|
|
nCount ++ ;
|
|
}
|
|
}
|
|
// Ordino i vertici sulla linea
|
|
double dUmin = ( ptInt - ptL) * vtL ;
|
|
double dUmax = ( ptInt2 - ptL) * vtL ;
|
|
if ( dUmin > dUmax) {
|
|
swap( dUmin, dUmax) ;
|
|
swap( ptInt, ptInt2) ;
|
|
}
|
|
// Se linea infinita
|
|
if ( ! bFinite) {
|
|
return ILTT_SEGM_ON_EDGE ;
|
|
}
|
|
// Altrimenti linea finita
|
|
else {
|
|
// se massimo coincide con inizio segmento di retta
|
|
if ( abs( dUmax) < EPS_SMALL) {
|
|
ptInt = ptInt2 ;
|
|
return ILTT_VERT ;
|
|
}
|
|
// se minimo coincide con fine segmento di retta
|
|
else if ( abs ( dUmin - dLen) < EPS_SMALL) {
|
|
return ILTT_VERT ;
|
|
}
|
|
// se segmento non si sovrappone
|
|
else if ( dUmax < 0 || dUmin > dLen) {
|
|
return ILTT_NO ;
|
|
}
|
|
// altrimenti sovrapposizione parziale
|
|
else {
|
|
if ( dUmin < 0)
|
|
ptInt = ptL ;
|
|
if ( dUmax > dLen)
|
|
ptInt2 = ptL + vtL * dLen ;
|
|
return ILTT_SEGM_ON_EDGE ;
|
|
}
|
|
}
|
|
}
|
|
// se altrimenti un vertice del triangolo giace sulla retta e gli altri due sono dalla stessa parte
|
|
else if ( ( nVertPos == 2 && nVertNeg == 0) || ( nVertPos == 0 && nVertNeg == 2)) {
|
|
// Determino quale è il vertice sulla linea
|
|
for ( int i = 0 ; i < 3 ; ++i) {
|
|
if ( vPos[i] == 0) {
|
|
ptInt = trTria.GetP( i) ;
|
|
break ;
|
|
}
|
|
}
|
|
// Se linea infinita
|
|
if ( ! bFinite) {
|
|
return ILTT_VERT ;
|
|
}
|
|
// Altrimenti linea finita
|
|
else {
|
|
// devo verificare che il vertice stia sul segmento
|
|
double dU = ( ptInt - ptL) * vtL ;
|
|
if ( dU < -EPS_SMALL || dU > dLen + EPS_SMALL)
|
|
return ILTT_NO ;
|
|
else
|
|
return ILTT_VERT ;
|
|
}
|
|
}
|
|
// se altrimenti un vertice del triangolo giace sulla retta e gli altri due sono da parti opposte
|
|
else if ( nVertPos == 1 && nVertNeg == 1) {
|
|
// Determino il vertice sulla linea e gli altri due da interpolare
|
|
int nP, nM ;
|
|
for ( int i = 0 ; i < 3 ; ++i) {
|
|
if ( vPos[i] == 0)
|
|
ptInt = trTria.GetP( i) ;
|
|
else if ( vPos[i] > 0)
|
|
nP = i ;
|
|
else
|
|
nM = i ;
|
|
}
|
|
// Calcolo l'intersezione con la linea
|
|
double dCoeff = abs( vDist[nP]) / ( abs( vDist[nP]) + abs( vDist[nM])) ;
|
|
ptInt2 = Media( trTria.GetP( nP), trTria.GetP( nM), dCoeff) ;
|
|
// Ordino i vertici sulla linea
|
|
double dUmin = ( ptInt - ptL) * vtL ;
|
|
double dUmax = ( ptInt2 - ptL) * vtL ;
|
|
if ( dUmin > dUmax) {
|
|
swap( dUmin, dUmax) ;
|
|
swap( ptInt, ptInt2) ;
|
|
}
|
|
// Se linea infinita
|
|
if ( ! bFinite) {
|
|
return ILTT_SEGM ;
|
|
}
|
|
// Altrimenti linea finita
|
|
else {
|
|
// se massimo coincide con inizio segmento di retta
|
|
if ( abs( dUmax) < EPS_SMALL) {
|
|
ptInt = ptInt2 ;
|
|
return ILTT_EDGE ;
|
|
}
|
|
// se minimo coincide con fine segmento di retta
|
|
else if ( abs ( dUmin - dLen) < EPS_SMALL) {
|
|
return ILTT_EDGE ;
|
|
}
|
|
// se segmento non si sovrappone
|
|
else if ( dUmax < 0 || dUmin > dLen) {
|
|
return ILTT_NO ;
|
|
}
|
|
// altrimenti sovrapposizione parziale
|
|
else {
|
|
if ( dUmin < 0)
|
|
ptInt = ptL ;
|
|
if ( dUmax > dLen)
|
|
ptInt2 = ptL + vtL * dLen ;
|
|
return ILTT_SEGM ;
|
|
}
|
|
}
|
|
}
|
|
// altrimenti due vertici giacciono da una parte e uno da quella opposta
|
|
else {
|
|
// Determino le intersezioni
|
|
int nCount = 0 ;
|
|
for ( int i = 0 ; i < 3 ; ++ i) {
|
|
int j = ( i + 1) % 3 ;
|
|
if ( vPos[i] != vPos[j]) {
|
|
double dCoeff = abs( vDist[i]) / ( abs( vDist[i]) + abs( vDist[j])) ;
|
|
( nCount == 0 ? ptInt : ptInt2) = Media( trTria.GetP( i), trTria.GetP( j), dCoeff) ;
|
|
++ nCount ;
|
|
}
|
|
}
|
|
// Ordino i vertici sulla linea
|
|
double dUmin = ( ptInt - ptL) * vtL ;
|
|
double dUmax = ( ptInt2 - ptL) * vtL ;
|
|
if ( dUmin > dUmax) {
|
|
swap( dUmin, dUmax) ;
|
|
swap( ptInt, ptInt2) ;
|
|
}
|
|
// Se linea infinita
|
|
if ( ! bFinite) {
|
|
return ILTT_SEGM ;
|
|
}
|
|
// Altrimenti linea finita
|
|
else {
|
|
// se massimo coincide con inizio segmento di retta
|
|
if ( abs( dUmax) < EPS_SMALL) {
|
|
ptInt = ptInt2 ;
|
|
return ILTT_EDGE ;
|
|
}
|
|
// se minimo coincide con fine segmento di retta
|
|
else if ( abs ( dUmin - dLen) < EPS_SMALL) {
|
|
return ILTT_EDGE ;
|
|
}
|
|
// se segmento non si sovrappone
|
|
else if ( dUmax < 0 || dUmin > dLen) {
|
|
return ILTT_NO ;
|
|
}
|
|
// altrimenti sovrapposizione parziale
|
|
else {
|
|
if ( dUmin < 0)
|
|
ptInt = ptL ;
|
|
if ( dUmax > dLen)
|
|
ptInt2 = ptL + vtL * dLen ;
|
|
return ILTT_SEGM ;
|
|
}
|
|
}
|
|
}
|
|
}
|