Files
Dario Sassi 64c954ad4b EgtGeomKernel 1.9l4 :
- fabs sostituito da abs
- in Zmap razionalizzazione operazioni taglio spilloni
- in SurfTriMesh UpdateFaceting senza più chiamate recursive.
2018-12-27 11:19:40 +00:00

148 lines
6.2 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 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
//----------------------------------------------------------------------------
#define UpdateMin( dMin, dVal) if ( dVal < dMin) dMin = dVal ;
#define UpdateMax( dMax, dVal) if ( dVal > dMax) dMax = dVal ;
//----------------------------------------------------------------------------
// Verifica se un punto è compreso nel box del triangolo.
inline bool
PointInTriaBox( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC)
{
double Xmin = ptA.x ; UpdateMin( Xmin, ptB.x) UpdateMin( Xmin, ptC.x)
if ( ptP.x < Xmin - EPS_SMALL)
return false ;
double Ymin = ptA.y ; UpdateMin( Ymin, ptB.y) UpdateMin( Ymin, ptC.y)
if ( ptP.y < Ymin - EPS_SMALL)
return false ;
double Zmin = ptA.z ; UpdateMin( Zmin, ptB.z) UpdateMin( Zmin, ptC.z)
if ( ptP.z < Zmin - EPS_SMALL)
return false ;
double Xmax = ptA.x ; UpdateMax( Xmax, ptB.x) UpdateMax( Xmax, ptC.x)
if ( ptP.x > Xmax + EPS_SMALL)
return false ;
double Ymax = ptA.y ; UpdateMax( Ymax, ptB.y) UpdateMax( Ymax, ptC.y)
if ( ptP.y > Ymax + EPS_SMALL)
return false ;
double Zmax = ptA.z ; UpdateMax( Zmax, ptB.z) UpdateMax( Zmax, ptC.z)
if ( ptP.z > Zmax + EPS_SMALL)
return false ;
return true ;
}
//----------------------------------------------------------------------------
// Coincidenza approssimata di punti nel piano di proiezione
inline bool
AreSamePointApproxInPlane( int nPlane, const Point3d& ptP1, const Point3d& ptP2)
{
double dX, dY, dZ ;
switch ( nPlane) {
default : // PL_XY
dX = ptP1.x - ptP2.x ;
dY = ptP1.y - ptP2.y ;
return ( ( dX * dX + dY * dY) < SQ_EPS_SMALL) ;
case PL_YZ :
dY = ptP1.y - ptP2.y ;
dZ = ptP1.z - ptP2.z ;
return ( ( dY * dY + dZ * dZ) < SQ_EPS_SMALL) ;
case PL_ZX :
dZ = ptP1.z - ptP2.z ;
dX = ptP1.x - ptP2.x ;
return ( ( dZ * dZ + dX * dX) < SQ_EPS_SMALL) ;
}
}
//----------------------------------------------------------------------------
// Lunghezza del segmento nel piano di proiezione
inline double
LenSegmentInPlane( 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)) ;
}
}
//----------------------------------------------------------------------------
// Verifica se un punto giacente nel piano del triangolo è compreso nello stesso.
inline int
PointInTria( const Point3d& ptP, const Triangle3d& Tria)
{
// verifico che il punto stia nel box del triangolo
if ( ! PointInTriaBox( ptP, Tria.GetP( 0), Tria.GetP( 1), Tria.GetP( 2)))
return PTT_OUT ;
// calcolo il piano ottimale di proiezione
int nPlane ;
bool bCCW ;
if ( ! CalcProjPlane( Tria.GetN(), nPlane, bCCW))
return PTT_OUT ;
// verifico se il punto sta su un vertice
if ( AreSamePointApproxInPlane( nPlane, ptP, Tria.GetP( 0)) ||
AreSamePointApproxInPlane( nPlane, ptP, Tria.GetP( 1)) ||
AreSamePointApproxInPlane( nPlane, ptP, Tria.GetP( 2)))
return PTT_VERT ;
// calcolo la lunghezza dei lati
double dLenAB = LenSegmentInPlane( nPlane, Tria.GetP( 0), Tria.GetP( 1)) ;
double dLenBC = LenSegmentInPlane( nPlane, Tria.GetP( 1), Tria.GetP( 2)) ;
double dLenCA = LenSegmentInPlane( nPlane, Tria.GetP( 2), Tria.GetP( 0)) ;
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 = TwoAreaInPlane( nPlane, ptP, Tria.GetP( 0), Tria.GetP( 1)) / dLenAB ;
double dPosBC = TwoAreaInPlane( nPlane, ptP, Tria.GetP( 1), Tria.GetP( 2)) / dLenBC ;
double dPosCA = TwoAreaInPlane( nPlane, ptP, Tria.GetP( 2), Tria.GetP( 0)) / dLenCA ;
// se tre valori nulli, triangolo non definito correttamente
if ( abs( dPosAB) < EPS_SMALL && abs( dPosBC) < EPS_SMALL && abs( dPosCA) < EPS_SMALL)
return PTT_OUT ;
// se un valore nullo e gli altri due con lo stesso segno
if ( abs( dPosAB) < EPS_SMALL && ( dPosBC * dPosCA) > 0) {
// se la proiezione del punto sta sul lato AB
double dPro = ProScaInPlane( nPlane, ptP, Tria.GetP( 0), Tria.GetP( 1)) / dLenAB ;
if ( dPro > 0 && dPro < dLenAB)
return PTT_EDGE ;
}
if ( abs( dPosBC) < EPS_SMALL && ( dPosCA * dPosAB) > 0) {
// se la proiezione del punto sta sul lato BC
double dPro = ProScaInPlane( nPlane, ptP, Tria.GetP( 1), Tria.GetP( 2)) / dLenBC ;
if ( dPro > 0 && dPro < dLenBC)
return PTT_EDGE ;
}
if ( abs( dPosCA) < EPS_SMALL && ( dPosAB * dPosBC) > 0) {
// se la proiezione del punto sta sul lato CA
double dPro = ProScaInPlane( nPlane, ptP, Tria.GetP( 2), Tria.GetP( 0)) / dLenCA ;
if ( dPro > 0 && dPro < dLenCA)
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 ;
}