Files
Include/EGkTriangle3d.h
Dario Sassi c47feff394 Include :
- aggiunta seconda versione di CalcNormal per normale in un punto di un triangolo come media baricentrica di quelle ai vertici.
2025-01-14 08:44:31 +01:00

586 lines
24 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2014-2019
//----------------------------------------------------------------------------
// File : EGkTria3d.h Data : 17.12.19 Versione : 2.1l5
// Contenuto : Dichiarazione classe triangolo Triangle3d.
//
//
//
// Modifiche : 30.03.14 DS Creazione modulo.
// 07.02.15 DS Agg. GetArea e GetAspectRatio.
// 15.01.18 LM Agg. flag.
// 06.06.19 LM Agg. IsPointInsideTriangle.
// 17.12.19 DS Agg. controllo lunghezza di tutti e tre i lati.
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EGkBBox3d.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include <vector>
#include <list>
#include <algorithm>
//-----------------------------------------------------------------------------
class Triangle3d
{
public :
Triangle3d( void) : m_nGrade( 0)
{ m_nAttr[0] = 0 ; m_nAttr[1] = 0 ; m_nAttr[2] = 0 ; }
void Set( const Point3d& ptP0, const Point3d& ptP1, const Point3d& ptP2)
{ m_ptP[0] = ptP0 ; m_ptP[1] = ptP1 ; m_ptP[2] = ptP2 ; m_vtN = V_NULL ; }
void Set( const Point3d& ptP0, const Point3d& ptP1, const Point3d& ptP2, const Vector3d& vtV)
{ m_ptP[0] = ptP0 ; m_ptP[1] = ptP1 ; m_ptP[2] = ptP2 ; m_vtN = vtV ; }
bool SetP( int nInd, const Point3d& ptP)
{ if ( nInd < 0 || nInd >= 3)
return false ;
m_ptP[nInd] = ptP ;
m_vtN = V_NULL ;
return true ;
}
bool SetGrade( int nFlag)
{ m_nGrade = nFlag ;
return true ;
}
bool SetAttrib( int nInd, int nVal)
{ if ( nInd < 0 || nInd >= 3)
return false ;
m_nAttr[nInd] = nVal ;
return true ;
}
bool Validate( bool bOverwrite = false)
{ if ( AreSamePointApprox( m_ptP[0], m_ptP[1]) ||
AreSamePointApprox( m_ptP[1], m_ptP[2]) ||
AreSamePointApprox( m_ptP[2], m_ptP[0]))
return false ;
Vector3d vtV1 = m_ptP[1] - m_ptP[0] ;
Vector3d vtV2 = m_ptP[2] - m_ptP[1] ;
Vector3d vtN = vtV1 ^ vtV2 ;
double dSqN = vtN.SqLen() ;
if ( dSqN < SQ_EPS_ZERO)
return false ;
if ( dSqN < SQ_EPS_TRIA_H * std::max( { vtV1.SqLen(), vtV2.SqLen(), ( vtV1 + vtV2).SqLen()}))
return false ;
vtN /= sqrt( dSqN) ;
if ( m_vtN.IsSmall() || bOverwrite) {
m_vtN = vtN ;
return true ;
}
return AreSameVectorApprox( vtN, m_vtN) ;
}
bool IsValid( void) const
{ if ( AreSamePointApprox( m_ptP[0], m_ptP[1]) ||
AreSamePointApprox( m_ptP[1], m_ptP[2]) ||
AreSamePointApprox( m_ptP[2], m_ptP[0]))
return false ;
if ( m_vtN.IsSmall())
return false ;
Vector3d vtV1 = m_ptP[1] - m_ptP[0] ;
Vector3d vtV2 = m_ptP[2] - m_ptP[1] ;
Vector3d vtN = vtV1 ^ vtV2 ;
double dSqN = vtN.SqLen() ;
if ( dSqN < SQ_EPS_ZERO)
return false ;
if ( dSqN < SQ_EPS_TRIA_H * std::max( { vtV1.SqLen(), vtV2.SqLen(), ( vtV1 + vtV2).SqLen()}))
return false ;
vtN /= sqrt( dSqN) ;
return AreSameVectorApprox( vtN, m_vtN) ;
}
void Translate( const Vector3d& vtMove)
{ m_ptP[0].Translate( vtMove) ;
m_ptP[1].Translate( vtMove) ;
m_ptP[2].Translate( vtMove) ;
}
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
{ double dAngRad = dAngDeg * DEGTORAD ;
return Rotate( ptAx, vtAx, cos( dAngRad), sin( dAngRad)) ;
}
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{ return ( m_ptP[0].Rotate( ptAx, vtAx, dCosAng, dSinAng) &&
m_ptP[1].Rotate( ptAx, vtAx, dCosAng, dSinAng) &&
m_ptP[2].Rotate( ptAx, vtAx, dCosAng, dSinAng) &&
m_vtN.Rotate( vtAx, dCosAng, dSinAng)) ;
}
bool Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
{ m_ptP[0].Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
m_ptP[1].Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
m_ptP[2].Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
return Validate( true) ;
}
bool Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
{ m_ptP[0].Mirror( ptOn, vtNorm) ;
m_ptP[1].Mirror( ptOn, vtNorm) ;
m_ptP[2].Mirror( ptOn, vtNorm) ;
return Validate( true) ;
}
bool Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff)
{ m_ptP[0].Shear( ptOn, vtNorm, vtDir, dCoeff) ;
m_ptP[1].Shear( ptOn, vtNorm, vtDir, dCoeff) ;
m_ptP[2].Shear( ptOn, vtNorm, vtDir, dCoeff) ;
return Validate( true) ;
}
bool ToGlob( const Frame3d& frRef)
{ return ( m_ptP[0].ToGlob( frRef) && m_ptP[1].ToGlob( frRef) && m_ptP[2].ToGlob( frRef) && m_vtN.ToGlob( frRef)) ; }
bool ToLoc( const Frame3d& frRef)
{ return ( m_ptP[0].ToLoc( frRef) && m_ptP[1].ToLoc( frRef) && m_ptP[2].ToLoc( frRef) && m_vtN.ToLoc( frRef)) ; }
bool LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{ return ( m_ptP[0].LocToLoc( frOri, frDest) &&
m_ptP[1].LocToLoc( frOri, frDest) &&
m_ptP[2].LocToLoc( frOri, frDest) &&
m_vtN.LocToLoc( frOri, frDest)) ;
}
bool GetLocalBBox( BBox3d& b3Loc) const
{ b3Loc.Reset() ;
for ( const auto& ptP : m_ptP)
b3Loc.Add( ptP) ;
return true ;
}
const Point3d& GetP( int nInd) const
{ if ( nInd >= 0 && nInd < 3)
return m_ptP[nInd] ;
else if ( nInd < 0)
return m_ptP[0] ;
else
return m_ptP[2] ;
}
int GetGrade( void) const
{ return m_nGrade ; }
int GetAttrib( int nInd) const
{ if ( nInd >= 0 && nInd < 3)
return m_nAttr[nInd] ;
else if ( nInd < 0)
return m_nAttr[0] ;
else
return m_nAttr[2] ;
}
const Vector3d& GetN( void) const
{ return m_vtN ; }
Point3d GetCentroid( void) const
{ return ( m_ptP[0] + m_ptP[1] + m_ptP[2]) / 3 ; }
Plane3d GetPlane( void) const
{ Plane3d plT ; plT.Set( GetCentroid(), m_vtN) ; return plT ; }
double GetArea( void) const
{ return (( m_ptP[1] - m_ptP[0]) ^ ( m_ptP[2] - m_ptP[0])).Len() / 2 ; }
double GetAspectRatio( void) const
{ double dSqDistA = SqDist( m_ptP[0], m_ptP[1]) ;
double dSqDistB = SqDist( m_ptP[1], m_ptP[2]) ;
double dSqDistC = SqDist( m_ptP[2], m_ptP[0]) ;
double dTwoArea = (( m_ptP[1] - m_ptP[0]) ^ ( m_ptP[2] - m_ptP[0])).Len() ;
if ( dTwoArea < SQ_EPS_SMALL)
return INFINITO ;
else
return ( std::max( dSqDistA, std::max( dSqDistB, dSqDistC)) / dTwoArea) ;
}
double GetSqMinHeight( void) const
{ Vector3d vtV1 = m_ptP[1] - m_ptP[0] ;
Vector3d vtV2 = m_ptP[2] - m_ptP[1] ;
Vector3d vtN = vtV1 ^ vtV2 ;
double dSqN = vtN.SqLen() ;
if ( dSqN < SQ_EPS_ZERO)
return 0 ;
return ( dSqN / std::max( { vtV1.SqLen(), vtV2.SqLen(), ( vtV1 + vtV2).SqLen()})) ;
}
protected :
Point3d m_ptP[3] ;
Vector3d m_vtN ;
int m_nGrade ;
int m_nAttr[3] ;
} ;
//----------------------------------------------------------------------------
// Raccolte di Triangle3d
typedef std::vector<Triangle3d> TRIA3DVECTOR ; // vettore di Triangle3d
typedef std::list<Triangle3d> TRIA3DLIST ; // lista di Triangle3d
typedef std::vector<TRIA3DLIST> TRIA3DLISTVECTOR ; // vettore di liste di Triangle3d
//-----------------------------------------------------------------------------
// Flags indicanti se i lati sono parte del contorno di un poligono di più triangoli
class TriFlags3d
{
public :
TriFlags3d( void)
{ bFlag[0] = true ; bFlag[1] = true ; bFlag[2] = true ; }
TriFlags3d( bool bF)
{ bFlag[0] = bF ; bFlag[1] = bF ; bFlag[2] = bF ; }
TriFlags3d( bool bF0, bool bF1, bool bF2)
{ bFlag[0] = bF0 ; bFlag[1] = bF1 ; bFlag[2] = bF2 ; }
public :
bool bFlag[3] ;
} ;
//-----------------------------------------------------------------------------
// Normali sui vertici, ottenute mediando opportunamente coi triangoli vicini
class TriNormals3d
{
public :
TriNormals3d( void)
{}
TriNormals3d( const Vector3d& vtNrm)
{ vtN[0] = vtNrm ; vtN[1] = vtNrm ; vtN[2] = vtNrm ; }
TriNormals3d( const Vector3d& vtN0, const Vector3d& vtN1, const Vector3d& vtN2)
{ vtN[0] = vtN0 ; vtN[1] = vtN1 ; vtN[2] = vtN2 ; }
public :
Vector3d vtN[3] ;
} ;
//-----------------------------------------------------------------------------
// Classe derivata da Triangle3d che include anche i flag dei lati e le normali dei vertici
class Triangle3dEx : public Triangle3d
{
public :
Triangle3dEx( void)
{}
Triangle3dEx( const Triangle3d& trTria)
{ *(static_cast<Triangle3d*>(this)) = trTria ;
for ( int i = 0 ; i < 3 ; ++ i)
m_triN.vtN[i] = m_vtN ;
}
bool SetEdgeFlag( int nInd, bool bVal)
{ if ( nInd < 0 || nInd >= 3)
return false ;
m_triF.bFlag[nInd] = bVal ;
return true ;
}
bool GetEdgeFlag( int nInd) const
{ if ( nInd >= 0 && nInd < 3)
return m_triF.bFlag[nInd] ;
else if ( nInd < 0)
return m_triF.bFlag[0] ;
else
return m_triF.bFlag[2] ;
}
const TriFlags3d& GetTriFlags( void) const
{ return m_triF ; }
void ResetEdgeFlags( void)
{ m_triF.bFlag[0] = m_triF.bFlag[1] = m_triF.bFlag[2] = true ; }
bool SetVertexNorm( int nInd, const Vector3d& vtN)
{ if ( nInd < 0 || nInd >= 3)
return false ;
m_triN.vtN[nInd] = vtN ;
return true ;
}
const Vector3d& GetVertexNorm( int nInd) const
{ if ( nInd >= 0 && nInd < 3)
return m_triN.vtN[nInd] ;
else if ( nInd < 0)
return m_triN.vtN[0] ;
else
return m_triN.vtN[2] ;
}
const TriNormals3d& GetTriNormals( void) const
{ return m_triN ; }
bool Validate( bool bOverwrite = false)
{ if ( ! Triangle3d::Validate( bOverwrite))
return false ;
for ( int i = 0 ; i < 3 ; ++ i) {
if ( m_triN.vtN[i].IsZero())
m_triN.vtN[i] = m_vtN ;
}
return true ;
}
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dAngDeg)
{ double dAngRad = dAngDeg * DEGTORAD ;
return Rotate( ptAx, vtAx, cos( dAngRad), sin( dAngRad)) ; }
bool Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
{ return ( m_ptP[0].Rotate( ptAx, vtAx, dCosAng, dSinAng) &&
m_ptP[1].Rotate( ptAx, vtAx, dCosAng, dSinAng) &&
m_ptP[2].Rotate( ptAx, vtAx, dCosAng, dSinAng) &&
m_vtN.Rotate( vtAx, dCosAng, dSinAng) &&
m_triN.vtN[0].Rotate( vtAx, dCosAng, dSinAng) &&
m_triN.vtN[1].Rotate( vtAx, dCosAng, dSinAng) &&
m_triN.vtN[2].Rotate( vtAx, dCosAng, dSinAng)) ;
}
bool Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
{ m_ptP[0].Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
m_ptP[1].Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
m_ptP[2].Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
for ( int i = 0 ; i < 3 ; ++ i)
m_triN.vtN[i] = V_NULL ;
return Validate( true) ;
}
bool Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
{ m_ptP[0].Mirror( ptOn, vtNorm) ;
m_ptP[1].Mirror( ptOn, vtNorm) ;
m_ptP[2].Mirror( ptOn, vtNorm) ;
for ( int i = 0 ; i < 3 ; ++ i)
m_triN.vtN[i].Mirror( vtNorm) ;
return Validate( true) ;
}
bool Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff)
{ m_ptP[0].Shear( ptOn, vtNorm, vtDir, dCoeff) ;
m_ptP[1].Shear( ptOn, vtNorm, vtDir, dCoeff) ;
m_ptP[2].Shear( ptOn, vtNorm, vtDir, dCoeff) ;
for ( int i = 0 ; i < 3 ; ++ i)
m_triN.vtN[i] = V_NULL ;
return Validate( true) ;
}
bool ToGlob( const Frame3d& frRef)
{ return ( m_ptP[0].ToGlob( frRef) && m_ptP[1].ToGlob( frRef) && m_ptP[2].ToGlob( frRef) && m_vtN.ToGlob( frRef) &&
m_triN.vtN[0].ToGlob( frRef) && m_triN.vtN[1].ToGlob( frRef) && m_triN.vtN[2].ToGlob( frRef)) ; }
bool ToLoc( const Frame3d& frRef)
{ return ( m_ptP[0].ToLoc( frRef) && m_ptP[1].ToLoc( frRef) && m_ptP[2].ToLoc( frRef) && m_vtN.ToLoc( frRef) &&
m_triN.vtN[0].ToLoc( frRef) && m_triN.vtN[1].ToLoc( frRef) && m_triN.vtN[2].ToLoc( frRef)) ; }
bool LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{ return ( m_ptP[0].LocToLoc( frOri, frDest) &&
m_ptP[1].LocToLoc( frOri, frDest) &&
m_ptP[2].LocToLoc( frOri, frDest) &&
m_vtN.LocToLoc( frOri, frDest) &&
m_triN.vtN[0].LocToLoc( frOri, frDest) &&
m_triN.vtN[1].LocToLoc( frOri, frDest) &&
m_triN.vtN[2].LocToLoc( frOri, frDest)) ; }
private :
TriFlags3d m_triF ;
TriNormals3d m_triN ;
} ;
//----------------------------------------------------------------------------
// Raccolte di Triangle3dEx
typedef std::vector<Triangle3dEx> TRIA3DEXVECTOR ; // vettore di Triangle3dEx
typedef std::list<Triangle3dEx> TRIA3DEXLIST ; // lista di Triangle3dEx
typedef std::vector<TRIA3DEXLIST> TRIA3DEXLISTVECTOR ; // vettore di liste di Triangle3dEx
//-----------------------------------------------------------------------------
enum PlaneType { PL_NULL = 0,
PL_XY = 1,
PL_YZ = 2,
PL_ZX = 3} ;
//----------------------------------------------------------------------------
// 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 ( abs( vtN.z) > abs( vtN.x) &&
abs( vtN.z) > abs( vtN.y)) {
nPlane = PL_XY ;
bCCW = ( vtN.z > 0) ;
}
// proiezione sul piano YZ (Nx con valore maggiore)
else if ( abs( vtN.x) > abs( 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 ;
}
//----------------------------------------------------------------------------
// Prodotto vettoriale nel piano di proiezione ( positivo se i 3 punti in ordine CCW)
inline double
TwoAreaInPlane( 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) ;
}
}
//----------------------------------------------------------------------------
// Prodotto scalare nel piano di proiezione
inline double
ProScaInPlane( int nPlane, const Point3d& ptP, const Point3d& ptA, const Point3d& ptB)
{
switch ( nPlane) {
default : // PL_XY
return ( ptP.x - ptA.x) * ( ptB.x - ptA.x) + ( ptP.y - ptA.y) * ( ptB.y - ptA.y) ;
case PL_YZ :
return ( ptP.y - ptA.y) * ( ptB.y - ptA.y) + ( ptP.z - ptA.z) * ( ptB.z - ptA.z) ;
case PL_ZX :
return ( ptP.z - ptA.z) * ( ptB.z - ptA.z) + ( ptP.x - ptA.x) * ( ptB.x - ptA.x) ;
}
}
//----------------------------------------------------------------------------
// Coordinate baricentriche di un punto giacente nel piano del triangolo
inline bool
BarycentricCoord( const Point3d& ptP, const Triangle3d& Tria,
double& dU, double& dV, double& dW)
{
// calcolo del piano ottimale di proiezione
int nPlane ;
bool bCCW ;
if ( ! CalcProjPlane( Tria.GetN(), nPlane, bCCW))
return false ;
// verifico che l'area (doppia) non sia nulla
double d2Area = TwoAreaInPlane( nPlane, Tria.GetP( 0), Tria.GetP( 1), Tria.GetP( 2)) ;
if ( abs( d2Area) < SQ_EPS_SMALL)
return false ;
// calcolo delle coordinate baricentriche
double dInv2Area = 1 / d2Area ;
dU = TwoAreaInPlane( nPlane, ptP, Tria.GetP( 1), Tria.GetP( 2)) * dInv2Area ;
dV = TwoAreaInPlane( nPlane, Tria.GetP( 0), ptP, Tria.GetP( 2)) * dInv2Area ;
dW = TwoAreaInPlane( nPlane, Tria.GetP( 0), Tria.GetP( 1), ptP) * dInv2Area ;
// devono dare somma unitaria
double dSumm = dU + dV + dW ;
if ( abs( dSumm) < EPS_ZERO)
return false ;
if ( abs( dSumm - 1) > EPS_ZERO) {
double dInvSumm = 1 / dSumm ;
dU *= dInvSumm ;
dV *= dInvSumm ;
dW *= dInvSumm ;
}
return true ;
}
//----------------------------------------------------------------------------
// Normale in un punto del triangolo, come media baricentrica delle normali nei vertici
inline bool
CalcNormal( const Point3d& ptP, const Triangle3d& Tria, const TriNormals3d& Tnorms, Vector3d& vtNorm)
{
// calcolo le coordinate baricentriche del punto
double dU, dV, dW ;
if ( ! BarycentricCoord( ptP, Tria, dU, dV, dW))
return false ;
// calcolo la media
vtNorm = dU * Tnorms.vtN[0] + dV * Tnorms.vtN[1] + dW * Tnorms.vtN[2] ;
// la normalizzo
return vtNorm.Normalize( EPS_ZERO) ;
}
//----------------------------------------------------------------------------
inline bool
CalcNormal( const Point3d& ptP, const Triangle3dEx& Tria, Vector3d& vtNorm)
{
return CalcNormal( ptP, Tria, Tria.GetTriNormals(), vtNorm) ;
}
//----------------------------------------------------------------------------
enum TriangleType { OPEN = -1, EXACT = 0, CLOSED = 1 };
//----------------------------------------------------------------------------
// Stabilisce se un punto appartiene al triangolo aperto, esatto o chiuso.
inline bool
IsPointInsideTriangle( const Point3d& ptP, const Triangle3d& trTria, int nTriType)
{
// Se il punto non è nel box del triangolo, è sicuramente esterno
BBox3d b3Tria( trTria.GetP( 0)) ;
b3Tria.Add( trTria.GetP( 1)) ;
b3Tria.Add( trTria.GetP( 2)) ;
if ( ! b3Tria.Encloses( ptP))
return false ;
// Se il punto non sta sul piano del triangolo, è sicuramente esterno
if ( abs( ( ptP - trTria.GetP(0)) * trTria.GetN()) > EPS_SMALL)
return false ;
// Tolleranza di appartenenza dipendente dal tipo di triangolo
double dEps ;
switch ( nTriType) {
case OPEN :
dEps = EPS_SMALL ;
break ;
case EXACT :
dEps = 0 ;
break ;
case CLOSED :
dEps = -EPS_SMALL ;
break ;
default :
return false ;
}
// Verifico se il punto è a destra del primo lato
Vector3d vtV0 = trTria.GetP( 1) - trTria.GetP( 0) ;
vtV0.Normalize() ;
double dProd0 = ( vtV0 ^ (ptP - trTria.GetP( 0))) * trTria.GetN() ;
if ( dProd0 < dEps)
return false ;
// Verifico se il punto è a destra del secondo lato
Vector3d vtV1 = trTria.GetP( 2) - trTria.GetP( 1) ;
vtV1.Normalize() ;
double dProd1 = ( vtV1 ^ (ptP - trTria.GetP( 1))) * trTria.GetN() ;
if ( dProd1 < dEps)
return false ;
// Verifico se il punto è a destra del terzo lato
Vector3d vtV2 = trTria.GetP( 0) - trTria.GetP( 2) ;
vtV2.Normalize() ;
double dProd2 = ( vtV2 ^ (ptP - trTria.GetP(2))) * trTria.GetN() ;
if ( dProd2 < dEps)
return false ;
// Punto a sinistra di tutti i lati, quindi interno
return true ;
}
//----------------------------------------------------------------------------
// Stabilisce se un punto appartiene a un vertice del triangolo
inline bool
IsPointOnTriangleVertex( const Point3d& ptP, const Triangle3d& trTria)
{
return ( AreSamePointApprox( trTria.GetP( 0), ptP) ||
AreSamePointApprox( trTria.GetP( 1), ptP) ||
AreSamePointApprox( trTria.GetP( 2), ptP)) ;
}
//----------------------------------------------------------------------------
inline bool
GetTriaVertexNearestToLine( const Triangle3d& trTria, const Point3d& ptL, const Vector3d& vtL,
int& nVert, double& dSqDist)
{
// Imposto valori di default
nVert = - 1 ;
dSqDist = SQ_INFINITO ;
// Verifico validità triangolo
if ( ! trTria.IsValid())
return false ;
// Verifico validità linea
Vector3d vtDir = vtL ;
if ( ! vtDir.Normalize())
return false ;
// Cerco il vertice più vicino
for ( int i = 0 ; i < 3 ; ++ i) {
Point3d ptP = trTria.GetP( i) ;
double dCurrSqDist = (( ptP - ptL) - vtL * ( vtL * ( ptP - ptL))).SqLen() ;
if ( dCurrSqDist < dSqDist) {
dSqDist = dCurrSqDist ;
nVert = i ;
}
}
return ( nVert != -1) ;
}
//----------------------------------------------------------------------------
inline bool
GetTriaMidEdgeNearestToLine( const Triangle3d& trTria, const Point3d& ptL, const Vector3d& vtL,
Point3d& ptMid, double& dSqDist)
{
// Imposto valori di default
dSqDist = SQ_INFINITO ;
// Verifico validità triangolo
if ( ! trTria.IsValid())
return false ;
// Verifico validità linea
Vector3d vtDir = vtL ;
if ( ! vtDir.Normalize())
return false ;
// Cerco il punto medio dei lati del triangolo più vicino
bool bFound = false ;
for ( int i = 0 ; i < 3 ; ++ i) {
Point3d ptP = Media( trTria.GetP( i), trTria.GetP( (i + 1) % 3)) ;
double dCurrSqDist = (( ptP - ptL) - vtL * ( vtL * ( ptP - ptL))).SqLen() ;
if ( dCurrSqDist < dSqDist) {
dSqDist = dCurrSqDist ;
ptMid = ptP ;
bFound = true ;
}
}
return bFound ;
}