EgtGeomKernel 2.4a3 :

- modifiche a IntersLineBox e IntersPlaneBox
- adattamenti conseguenti.
This commit is contained in:
DarioS
2022-01-09 15:17:00 +01:00
parent 77640f3a6f
commit 4056be90d9
12 changed files with 213 additions and 284 deletions
+127 -108
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2020-2020
// EgalTech 2020-2022
//----------------------------------------------------------------------------
// File : IntersLineBox.cpp Data : 07.05.20 Versione : 2.2e1
// File : IntersLineBox.cpp Data : 08.01.22 Versione : 2.4a3
// Contenuto : Implementazione della intersezione linea/box.
//
//
@@ -13,13 +13,77 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "SurfTriMesh.h"
#include "IntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.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 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)
@@ -38,114 +102,69 @@ bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3d& b3Box, INTDBLVECTOR& vInters, bool bFinite)
{
// Recupero i dati del Box
Point3d ptMin ;
double dDimX, dDimY, dDimZ ;
if ( ! b3Box.GetMinDim( ptMin, dDimX, dDimY, dDimZ))
Point3d ptMin, ptMax ;
if ( ! b3Box.GetMinMax( ptMin, ptMax))
return false ;
// Contorno di base
PolyLine PL ;
PL.AddUPoint( 0, ptMin) ;
PL.AddUPoint( 1, ptMin + Vector3d( dDimX, 0, 0)) ;
PL.AddUPoint( 2, ptMin + Vector3d( dDimX, dDimY, 0)) ;
PL.AddUPoint( 3, ptMin + Vector3d( 0, dDimY, 0)) ;
PL.Close() ;
// Vettore altezza
Vector3d vtExtr( 0, 0, dDimZ) ;
// Creo la superficie trimesh equivalente
SurfTriMesh Stm ;
if ( ! Stm.CreateByExtrusion( PL, vtExtr))
return false ;
SurfTriMesh StmBot ;
if ( ! StmBot.CreateByFlatContour( PL))
return false ;
StmBot.Invert() ;
SurfTriMesh StmTop ;
if ( ! StmTop.CreateByFlatContour( PL))
return false ;
StmTop.Translate( vtExtr) ;
if ( ! Stm.DoSewing( StmBot) || ! Stm.DoSewing( StmTop))
return false ;
// Calcolo l'intersezione
ILSIVECTOR vInfo ;
if ( ! IntersLineSurfTm( ptL, vtL, dLen, Stm, vInfo, bFinite))
return false ;
// ciclo sulle intersezioni
double dUcurr = -INFINITO ;
for ( const auto& Info : vInfo) {
// se intersezione puntuale
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
int nFlag = ILBT_TOUCH ;
if ( Info.dCosDN > EPS_ZERO)
nFlag = ILBT_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = ILBT_IN ;
vInters.emplace_back( nFlag, Info.dU) ;
dUcurr = Info.dU ;
// 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) ;
}
// se altrimenti intersezione con coincidenza
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
if ( Info.dU > dUcurr - EPS_SMALL)
vInters.emplace_back( ILBT_TG_INI, Info.dU) ;
vInters.emplace_back( ILBT_TG_FIN, Info.dU2) ;
dUcurr = Info.dU2 ;
else {
if ( dU > - EPS_SMALL && dU < dLen + EPS_SMALL)
vInters.emplace_back( ILBT_TOUCH, Clamp( dU, 0., dLen)) ;
}
}
// elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) {
// intersezione precedente
size_t i = j - 1 ;
// se sono dello stesso tipo, elimino una delle due
if ( vInters[i].first == vInters[j].first) {
// se entranti elimino la prima
if ( vInters[i].first == ILBT_IN || vInters[i].first == ILBT_TG_INI)
vInters.erase( vInters.begin() + i) ;
// altrimenti la seconda
else
vInters.erase( vInters.begin() + j) ;
if ( i > 0)
-- j ;
continue ;
}
// se hanno lo stesso parametro
else if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
if ( ( vInters[i].first == ILBT_IN && vInters[j].first == ILBT_OUT) ||
( vInters[i].first == ILBT_OUT && vInters[j].first == ILBT_IN)) {
vInters[i].first = ILBT_TOUCH ;
vInters.erase( vInters.begin() + j) ;
if ( i > 0)
-- j ;
continue ;
}
// se prima puntuale e l'altra inizio o fine di coincidenza, elimino la prima
else if ( ( vInters[i].first == ILBT_IN || vInters[i].first == ILBT_OUT || vInters[i].first == ILBT_TOUCH) &&
( vInters[j].first == ILBT_TG_INI || vInters[j].first == ILBT_TG_FIN)) {
vInters.erase( vInters.begin() + i) ;
if ( i > 0)
-- j ;
continue ;
}
// se prima inizio o fine di coincidenza e l'altra puntuale, elimino la seconda
else if ( ( vInters[i].first == ILBT_TG_INI || vInters[i].first == ILBT_TG_FIN) &&
( vInters[j].first == ILBT_IN || vInters[j].first == ILBT_OUT || vInters[j].first == ILBT_TOUCH)) {
vInters.erase( vInters.begin() + j) ;
if ( i > 0)
-- j ;
continue ;
}
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
else if ( ( vInters[i].first == ILBT_TG_FIN && vInters[j].first == ILBT_TG_INI) ||
( vInters[i].first == ILBT_TG_INI && vInters[j].first == ILBT_TG_FIN)) {
vInters.erase( vInters.begin() + j) ;
vInters.erase( vInters.begin() + i) ;
if ( i > 0)
-- j ;
continue ;
}
}
// passo alla successiva
++ j ;
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 {
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
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 {
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
}
}
return true ;
}