Files
EgtGeomKernel/CDeCylTria.cpp
T
Dario Sassi 743c47d0e0 EgtGeomKernel 2.3a1 :
- correzioni varie a CDe e a Avoid di VolZMap
- ricompilazione per nuova versione 2.3.
2020-12-28 18:52:48 +00:00

114 lines
4.1 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2020-2020
//----------------------------------------------------------------------------
// File : CDeCylTria.cpp Data : 08.01.20 Versione : 2.2a2
// Contenuto : Implementazione della verifica di collisione tra
// Cylinder e Triangle3d.
//
//
// Modifiche :08.01.20 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "DistPointLine.h"
#include "CDeCylTria.h"
#include "CDeConvexTorusTria.h"
#include "/EgtDev/Include/EGkPolygon3d.h"
using namespace std ;
//----------------------------------------------------------------------------
bool
CDeSimpleCylTria( const Frame3d& frCyl, double dR, double dH, const Triangle3d& trTria)
{
// Costruisco il poligono equivalente
Polygon3d plyTria ;
if ( ! plyTria.FromTriangle( trTria))
return false ;
// Lo porto nel riferimento del cilindro
plyTria.ToLoc( frCyl) ;
// Lo taglio come il cilindro
Plane3d plTrimB ;
plTrimB.Set( 0., -Z_AX) ;
plyTria.Trim( plTrimB, true, false, false) ;
Plane3d plTrimT ;
plTrimT.Set( dH, Z_AX) ;
plyTria.Trim( plTrimT, true, false, false) ;
// Se non è rimasto alcunchè, allora non c'è collisione
if ( plyTria.GetSideCount() == 0)
return false ;
// Proietto il poligono sul piano XY
plyTria.Scale( GLOB_FRM, 1, 1, 0) ;
// Se la proiezione ha area nulla
if ( abs( plyTria.GetArea()) < EPS_SMALL * EPS_SMALL) {
const PNTVECTOR& vVert = plyTria.GetVertices() ;
for ( int i = 0 ; i < int( vVert.size()) ; ++ i) {
int j = ( i + 1) % vVert.size() ;
DistPointLine dstPL( ORIG, vVert[i], vVert[j]) ;
double dSqDist ;
if ( dstPL.GetSqDist( dSqDist)) {
// se distanza maggiore del raggio, allora non collide
if ( dSqDist > dR * dR)
return false ;
}
}
return true ;
}
// Verifico che sia orientato verso l'alto
if ( plyTria.GetVersN().z < - EPS_SMALL)
plyTria.Invert() ;
// Determino la distanza con segno dei lati del poligono convesso dall'origine del piano
const PNTVECTOR& vVert = plyTria.GetVertices() ;
for ( int i = 0 ; i < int( vVert.size()) ; ++ i) {
int j = ( i + 1) % vVert.size() ;
DistPointLine dstPL( ORIG, vVert[i], vVert[j]) ;
double dSqDist ;
if ( dstPL.GetSqDist( dSqDist)) {
// se distanza minore del raggio, allora collide
if ( dSqDist < dR * dR)
return true ;
Point3d ptMinDist ;
dstPL.GetMinDistPoint( ptMinDist) ;
// se sta a destra del raggio, allora non collide
if ( CrossXY( ( ORIG - ptMinDist), ( vVert[j] - vVert[i])) > 0)
return false ;
}
}
// Non sta a destra di alcun lato, deve collidere
return true ;
}
//----------------------------------------------------------------------------
bool
CDeCylTria( const Frame3d& frCyl, double dR, double dH, double dSafeDist, const Triangle3d& trTria)
{
// Se distanza di sicurezza nulla
if ( dSafeDist < EPS_SMALL)
return CDeSimpleCylTria( frCyl, dR, dH, trTria) ;
// Verifica preliminare con cilindro esteso
Frame3d frEst = frCyl ; frEst.Translate( -dSafeDist * frCyl.VersZ()) ;
if ( ! CDeSimpleCylTria( frEst, dR + dSafeDist, dH + 2 * dSafeDist, trTria))
return false ;
// Cilindro allargato
if ( CDeSimpleCylTria( frCyl, dR + dSafeDist, dH, trTria))
return true ;
// Cilindro allungato
Frame3d frTmp = frCyl ; frTmp.Translate( -dSafeDist * frCyl.VersZ()) ;
if ( CDeSimpleCylTria( frTmp, dR, dH + 2 * dSafeDist, trTria))
return true ;
// Toro inferiore
if ( CDeSimpleConvexTorusTria( frCyl, dR, dSafeDist, CT_INF, trTria))
return true ;
// Toro superiore
frTmp = frCyl ; frTmp.Translate( dH * frCyl.VersZ()) ;
if ( CDeSimpleConvexTorusTria( frTmp, dR, dSafeDist, CT_SUP, trTria))
return true ;
// Non c'è collisione
return false ;
}