Files
EgtGeomKernel/ProjPlane.h
T
Dario Sassi 1b85e111dc EgtGeomKernel 1.6b7 :
- aggiunto calcolo baricentro di Curve
- migliorata gestione richiesta nuovo Id
- aggiunta intersezione linea-piano e linea-triangolo
- corretto errore in PointGrid3d con 1 solo punto (non faceva alcunchè)
- aggiunte funzioni di accesso a dati di SurfTM.
2015-02-24 22:47:10 +00:00

125 lines
4.9 KiB
C

//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : ProjPlane.h Data : 20.02.15 Versione : 1.6b7
// Contenuto : Gestione calcoli su proiezione in piano canonico.
//
//
//
// Modifiche : 20.02.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EGkTriangle3d.h"
//-----------------------------------------------------------------------------
enum PlaneType { PL_NULL = 0,
PL_XY = 1,
PL_YZ = 2,
PL_ZX = 3} ;
enum PntTriaPos { PTT_OUT = 0, // punto esterno al triangolo
PTT_VERT = 1, // punto su un vertice
PTT_EDGE = 2, // punto interno ad un lato
PTT_IN = 3} ; // punto interno
//----------------------------------------------------------------------------
// Piano canonico di miglior proiezione (perpendicolare alla componente maggiore della normale)
inline bool
CalcProjPlane( const Vector3d& vtN, int& nPlane, bool& bCCW)
{
// verifico che la normale non sia nulla
if ( vtN.IsZero())
return false ;
// proiezione sul piano XY (Nz con valore maggiore)
if ( fabs( vtN.z) > fabs( vtN.x) &&
fabs( vtN.z) > fabs( vtN.y)) {
nPlane = PL_XY ;
bCCW = ( vtN.z > 0) ;
}
// proiezione sul piano YZ (Nx con valore maggiore)
else if ( fabs( vtN.x) > fabs( vtN.y)) {
nPlane = PL_YZ ;
bCCW = ( vtN.x > 0) ;
}
// proiezione sul piano ZX (Ny con valore maggiore)
else {
nPlane = PL_ZX ;
bCCW = ( vtN.y > 0) ;
}
return true ;
}
//----------------------------------------------------------------------------
// Lunghezza del segmento nel piano di proiezione
inline double
LenSegment( int nPlane, const Point3d& ptA, const Point3d& ptB)
{
switch ( nPlane) {
default : // PL_XY
return sqrt( ( ptB.x - ptA.x) * ( ptB.x - ptA.x) + ( ptB.y - ptA.y) * ( ptB.y - ptA.y)) ;
case PL_YZ :
return sqrt( ( ptB.y - ptA.y) * ( ptB.y - ptA.y) + ( ptB.z - ptA.z) * ( ptB.z - ptA.z)) ;
case PL_ZX :
return sqrt( ( ptB.z - ptA.z) * ( ptB.z - ptA.z) + ( ptB.x - ptA.x) * ( ptB.x - ptA.x)) ;
}
}
//----------------------------------------------------------------------------
// Prodotto vettoriale nel piano di proiezione ( positivo se i 3 punti in ordine CCW)
inline double
TwoArea( int nPlane, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC)
{
switch ( nPlane) {
default : // PL_XY
return ( ptB.x - ptA.x) * ( ptC.y - ptB.y) - ( ptB.y - ptA.y) * ( ptC.x - ptB.x) ;
case PL_YZ :
return ( ptB.y - ptA.y) * ( ptC.z - ptB.z) - ( ptB.z - ptA.z) * ( ptC.y - ptB.y) ;
case PL_ZX :
return ( ptB.z - ptA.z) * ( ptC.x - ptB.x) - ( ptB.x - ptA.x) * ( ptC.z - ptB.z) ;
}
}
//----------------------------------------------------------------------------
inline int
PointInTria( const Point3d& ptP,
const Point3d& ptA, const Point3d& ptB, const Point3d& ptC, const Vector3d& vtN)
{
// calcolo il piano ottimale di proiezione
int nPlane ;
bool bCCW ;
if ( ! CalcProjPlane( vtN, nPlane, bCCW))
return PTT_OUT ;
// calcolo la lunghezza dei lati
double dLenAB = LenSegment( nPlane, ptA, ptB) ;
double dLenBC = LenSegment( nPlane, ptB, ptC) ;
double dLenCA = LenSegment( nPlane, ptC, ptA) ;
if ( dLenAB < EPS_SMALL || dLenBC < EPS_SMALL || dLenCA < EPS_SMALL)
return PTT_OUT ;
// determino la posizione del punto rispetto ai lati del triangolo
double dPosAB = TwoArea( nPlane, ptP, ptA, ptB) / dLenAB ;
double dPosBC = TwoArea( nPlane, ptP, ptB, ptC) / dLenBC ;
double dPosCA = TwoArea( nPlane, ptP, ptC, ptA) / dLenCA ;
// se tre valori nulli, triangolo non definito correttamente
if ( fabs( dPosAB) < EPS_SMALL && fabs( dPosBC) < EPS_SMALL && fabs( dPosCA) < EPS_SMALL)
return PTT_OUT ;
// se due valori nulli, sta su un vertice
if ( ( fabs( dPosAB) < EPS_SMALL && fabs( dPosBC) < EPS_SMALL) ||
( fabs( dPosBC) < EPS_SMALL && fabs( dPosCA) < EPS_SMALL) ||
( fabs( dPosCA) < EPS_SMALL && fabs( dPosAB) < EPS_SMALL))
return PTT_VERT ;
// se un valore nullo e gli altri due con lo stesso segno, sta su un lato
if ( ( fabs( dPosAB) < EPS_SMALL && ( dPosBC * dPosCA > 0)) ||
( fabs( dPosBC) < EPS_SMALL && ( dPosCA * dPosAB > 0)) ||
( fabs( dPosCA) < EPS_SMALL && ( dPosAB * dPosBC > 0)))
return PTT_EDGE ;
// se tre valori con lo stesso segno, sta dentro
if ( ( dPosAB > EPS_SMALL && dPosBC > EPS_SMALL && dPosCA > EPS_SMALL) ||
( dPosAB < - EPS_SMALL && dPosBC < - EPS_SMALL && dPosCA < - EPS_SMALL))
return PTT_IN ;
// deve essere esterno
return PTT_OUT ;
}