64c954ad4b
- fabs sostituito da abs - in Zmap razionalizzazione operazioni taglio spilloni - in SurfTriMesh UpdateFaceting senza più chiamate recursive.
148 lines
6.2 KiB
C
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 ;
|
|
}
|