1b85e111dc
- 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.
125 lines
4.9 KiB
C
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 ;
|
|
}
|