c8e2d88bb7
- Migliorata la gestione intersezioni Linea con Box.
183 lines
6.4 KiB
C++
183 lines
6.4 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2020-2022
|
|
//----------------------------------------------------------------------------
|
|
// File : IntersLineBox.cpp Data : 08.01.22 Versione : 2.4a3
|
|
// Contenuto : Implementazione della intersezione linea/box.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 07.05.20 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "IntersLineBox.h"
|
|
#include "/EgtDev/Include/EGkIntersLineBox.h"
|
|
#include "/EgtDev/Include/EgtNumUtils.h"
|
|
#include <algorithm>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Linea e box allineato assi devono essere nel medesimo sistema di riferimento.
|
|
// In caso di intersezione viene restituito true e i parametri lunghezza in dU1 e dU2.
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
|
|
const Point3d& ptMin, const Point3d& ptMax,
|
|
double& dU1, double& dU2)
|
|
{
|
|
// Verifico il versore
|
|
if ( vtL.IsSmall())
|
|
return false ;
|
|
|
|
// Verifico gli estremi del box
|
|
if ( ptMin.x > ptMax.x + EPS_SMALL ||
|
|
ptMin.y > ptMax.y + EPS_SMALL ||
|
|
ptMin.z > ptMax.z + EPS_SMALL)
|
|
return false ;
|
|
|
|
// Casi di intersezione impossibile
|
|
if ( abs( vtL.x) < EPS_ZERO && ( ptL.x < ptMin.x - EPS_SMALL || ptL.x > ptMax.x + EPS_SMALL))
|
|
return false ;
|
|
if ( abs( vtL.y) < EPS_ZERO && ( ptL.y < ptMin.y - EPS_SMALL || ptL.y > ptMax.y + EPS_SMALL))
|
|
return false ;
|
|
if ( abs( vtL.z) < EPS_ZERO && ( ptL.z < ptMin.z - EPS_SMALL || ptL.z > ptMax.z + EPS_SMALL))
|
|
return false ;
|
|
|
|
// Parametri degli estremi della retta
|
|
dU1 = -INFINITO ;
|
|
dU2 = INFINITO ;
|
|
|
|
// Confronto con piani YZ (perpendicolari ad asse X)
|
|
if ( vtL.x > EPS_ZERO) {
|
|
dU1 = max( dU1, ( ptMin.x - ptL.x) / vtL.x) ;
|
|
dU2 = min( dU2, ( ptMax.x - ptL.x) / vtL.x) ;
|
|
}
|
|
else if ( vtL.x < -EPS_ZERO) {
|
|
dU1 = max( dU1, ( ptMax.x - ptL.x) / vtL.x) ;
|
|
dU2 = min( dU2, ( ptMin.x - ptL.x) / vtL.x) ;
|
|
}
|
|
|
|
// Confronto con piani ZX (perpendicolari ad asse Y)
|
|
if ( vtL.y > EPS_ZERO) {
|
|
dU1 = max( dU1, ( ptMin.y - ptL.y) / vtL.y) ;
|
|
dU2 = min( dU2, ( ptMax.y - ptL.y) / vtL.y) ;
|
|
}
|
|
else if ( vtL.y < -EPS_ZERO) {
|
|
dU1 = max( dU1, ( ptMax.y - ptL.y) / vtL.y) ;
|
|
dU2 = min( dU2, ( ptMin.y - ptL.y) / vtL.y) ;
|
|
}
|
|
|
|
// Confronto con piani XY (perpendicolari ad asse Z)
|
|
if ( vtL.z > EPS_ZERO) {
|
|
dU1 = max( dU1, ( ptMin.z - ptL.z) / vtL.z) ;
|
|
dU2 = min( dU2, ( ptMax.z - ptL.z) / vtL.z) ;
|
|
}
|
|
else if ( vtL.z < -EPS_ZERO){
|
|
dU1 = max( dU1, ( ptMax.z - ptL.z) / vtL.z) ;
|
|
dU2 = min( dU2, ( ptMin.z - ptL.z) / vtL.z) ;
|
|
}
|
|
|
|
return ( dU2 >= dU1) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
IntersLineBox( const Point3d& ptL1, const Point3d& ptL2, const BBox3d& b3Box, INTDBLVECTOR& vInters, bool bFinite)
|
|
{
|
|
Vector3d vtL = ptL2 - ptL1 ;
|
|
double dLen = vtL.Len() ;
|
|
if ( dLen > EPS_SMALL)
|
|
vtL /= dLen ;
|
|
else
|
|
vtL = V_NULL ;
|
|
return IntersLineBox( ptL1, vtL, dLen, b3Box, vInters, bFinite) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3d& b3Box, INTDBLVECTOR& vInters, bool bFinite)
|
|
{
|
|
// Recupero i dati del Box
|
|
Point3d ptMin, ptMax ;
|
|
if ( ! b3Box.GetMinMax( ptMin, ptMax))
|
|
return false ;
|
|
|
|
// Pulisco vettore intersezioni
|
|
vInters.clear() ;
|
|
|
|
// Eseguo intersezione della linea completa
|
|
double dU1, dU2 ;
|
|
bool bInters = IntersLineBox( ptL, vtL, b3Box.GetMin(), b3Box.GetMax(), dU1, dU2) ;
|
|
|
|
// Se non c'è intersezione
|
|
if ( ! bInters || ( bFinite && ( dU1 > dLen + EPS_SMALL || dU2 < -EPS_SMALL)))
|
|
return true ;
|
|
|
|
// Se le due intersezioni coincidono
|
|
if ( ( dU2 - dU1) < EPS_SMALL) {
|
|
double dU = ( dU1 + dU2) / 2 ;
|
|
if ( ! bFinite) {
|
|
vInters.emplace_back( ILBT_TOUCH, dU) ;
|
|
}
|
|
else {
|
|
if ( dU > - EPS_SMALL && dU < dLen + EPS_SMALL)
|
|
vInters.emplace_back( ILBT_TOUCH, Clamp( dU, 0., dLen)) ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
// Se sono due intersezioni con la linea giacente su una faccia del box
|
|
if ( ( abs( vtL.x) < EPS_ZERO && ( abs( ptL.x - ptMin.x) < EPS_SMALL || abs( ptL.x - ptMax.x) < EPS_SMALL)) ||
|
|
( abs( vtL.y) < EPS_ZERO && ( abs( ptL.y - ptMin.y) < EPS_SMALL || abs( ptL.y - ptMax.y) < EPS_SMALL)) ||
|
|
( abs( vtL.z) < EPS_ZERO && ( abs( ptL.z - ptMin.z) < EPS_SMALL || abs( ptL.z - ptMax.z) < EPS_SMALL))) {
|
|
if ( ! bFinite) {
|
|
vInters.emplace_back( ILBT_TG_INI, dU1) ;
|
|
vInters.emplace_back( ILBT_TG_FIN, dU2) ;
|
|
}
|
|
else {
|
|
if ( dU1 > dLen - EPS_SMALL)
|
|
vInters.emplace_back( ILBT_IN, dLen) ;
|
|
else if ( dU2 < EPS_SMALL)
|
|
vInters.emplace_back( ILBT_OUT, 0) ;
|
|
else {
|
|
if ( dU1 < - EPS_SMALL)
|
|
vInters.emplace_back( ILBT_TG_INSIDE, 0.) ;
|
|
else
|
|
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
|
|
if ( dU2 > dLen + EPS_SMALL)
|
|
vInters.emplace_back( ILBT_TG_INSIDE, dLen) ;
|
|
else
|
|
vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
// Altrimenti sono due intersezioni con attraversamento
|
|
if ( ! bFinite) {
|
|
vInters.emplace_back( ILBT_IN, dU1) ;
|
|
vInters.emplace_back( ILBT_OUT, dU2) ;
|
|
}
|
|
else {
|
|
if ( dU1 > dLen - EPS_SMALL)
|
|
vInters.emplace_back( ILBT_IN, dLen) ;
|
|
else if ( dU2 < EPS_SMALL)
|
|
vInters.emplace_back( ILBT_OUT, 0) ;
|
|
else {
|
|
if ( dU1 < - EPS_SMALL)
|
|
vInters.emplace_back( ILBT_INSIDE, 0.) ;
|
|
else
|
|
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
|
|
if ( dU2 > dLen + EPS_SMALL)
|
|
vInters.emplace_back( ILBT_INSIDE, dLen) ;
|
|
else
|
|
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
|
|
}
|
|
}
|
|
return true ;
|
|
}
|