Files
EgtGeomKernel/IntersLineSurfTm.cpp
T
Dario Sassi b3d868bcc9 EgtGeomKernel :
- aggiunta HashGrids3d a SurfTm con lazy evaluation
- in CAvTool aggiunta verifica utensile ben definito.
2018-12-10 07:50:42 +00:00

190 lines
6.7 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : IntersLineSurfTm.cpp Data : 09.03.15 Versione : 1.6b8
// Contenuto : Implementazione della intersezione linea/superficie trimesh.
//
//
//
// Modifiche : 09.03.15 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ProjPlane.h"
#include "IntersLineSurfStd.h"
#include "/EgtDev/Include/EGkSurfTriMesh.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
using namespace std ;
//----------------------------------------------------------------------------
void
UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen,
int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite)
{
Point3d ptInt, ptInt2 ;
int nRes = IntersLineTria( ptL, vtDir, dLen, Tria, ptInt, ptInt2, bFinite) ;
if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) {
double dU = ( ptInt - ptL) * vtDir ;
double dCosDN = vtDir * Tria.GetN() ;
vInfo.emplace_back( nRes, dU, nT, dCosDN, ptInt) ;
}
else if ( nRes == ILTT_SEGM || nRes == ILTT_SEGM_ON_EDGE) {
double dU = ( ptInt - ptL) * vtDir ;
double dU2 = ( ptInt2 - ptL) * vtDir ;
double dCosDN = vtDir * Tria.GetN() ;
vInfo.emplace_back( nRes, dU, dU2, nT, dCosDN, ptInt, ptInt2) ;
}
}
//----------------------------------------------------------------------------
void
OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
{
// se non trovati, esco
if ( vInfo.size() == 0)
return ;
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
sort( vInfo.begin(), vInfo.end(),
[]( const IntLinStmInfo& a, const IntLinStmInfo& b)
{ double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
return ( dUa < dUb) ; }) ;
}
//----------------------------------------------------------------------------
// Intersezione di una linea con una superficie TriMesh
//----------------------------------------------------------------------------
bool
IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfTriMesh& Stm,
ILSIVECTOR& vInfo, bool bFinite)
{
// verifico linea
Vector3d vtDir = vtL ;
if ( ! vtDir.Normalize( EPS_ZERO))
return false ;
// verifico superficie
if ( &Stm == nullptr)
return false ;
// verifico parametro di ritorno
if ( &vInfo == nullptr)
return false ;
vInfo.clear() ;
// limito la linea al box dei triangoli della superficie
const BBox3d b3Stm = Stm.GetAllTriaBox() ;
if ( b3Stm.IsEmpty())
return false ;
double dU1, dU2 ;
if ( ! IntersLineBox( ptL, vtL, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2))
return false ;
if ( bFinite) {
dU1 = max( dU1, 0.) ;
dU2 = min( dU2, dLen) ;
if ( dU2 - dU1 < EPS_SMALL)
return false ;
}
Point3d ptStart = ptL + dU1 * vtL ;
double dLenEff = dU2 - dU1 ;
// cerco i triangoli intersecati dalla linea
const double BOX_STEP = 10 ;
int nStep = int( ceil( dLenEff / BOX_STEP)) ;
Vector3d vtStep = dLenEff / nStep * vtL ;
INTVECTOR vPrevT ;
for ( int i = 0 ; i < nStep ; ++ i) {
BBox3d b3Box( ptL + i * vtStep, ptL + ( i + 1) * vtStep) ;
INTVECTOR vT ;
if ( Stm.GetAllTriaOverlapBox( b3Box, vT)) {
for ( auto nT : vT) {
if ( find( vPrevT.begin(), vPrevT.end(), nT) == vPrevT.end()) {
vPrevT.emplace_back( nT) ;
Triangle3d Tria ;
Stm.GetTriangle( nT, Tria) ;
// aggiorno info con intersezione
UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, nT, Tria, vInfo, bFinite) ;
}
}
}
}
// ordino il vettore delle eventuali intersezioni secondo il senso crescente del parametro di linea
OrderInfoIntersLineSurfTm( vInfo) ;
return true ;
}
//----------------------------------------------------------------------------
// Intersezione di molte linee parallele con una superficie TriMesh
//----------------------------------------------------------------------------
IntersParLinesSurfTm::IntersParLinesSurfTm( const Frame3d& frLines, const ISurfTriMesh& Stm)
: m_bOk( false), m_frLines( frLines), m_pSTm( &Stm)
{
// verifico esistenza superficie
if ( m_pSTm == nullptr || ! m_pSTm->IsValid())
return ;
// creo HashGrid 2d
const int LIM_HG_TRIA = 127 ;
m_HGrids.SetActivationGrid( m_pSTm->GetTriangleCount() > LIM_HG_TRIA) ;
// riempio HashGrid
Triangle3d Tria ;
int nT = Stm.GetFirstTriangle( Tria) ;
while ( nT != SVT_NULL) {
// calcolo il BBox del triangolo nel riferimento scelto
Tria.ToLoc( m_frLines) ;
BBox3d b3Tria ;
b3Tria.Add( Tria.GetP( 0)) ;
b3Tria.Add( Tria.GetP( 1)) ;
b3Tria.Add( Tria.GetP( 2)) ;
// inserisco nella griglia
if ( ! m_HGrids.Add( nT, b3Tria))
return ;
// passo al prossimo triangolo
nT = Stm.GetNextTriangle( nT, Tria) ;
}
// aggiorno
m_bOk = m_HGrids.Update() ;
}
//----------------------------------------------------------------------------
bool
IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vInfo, bool bFinite)
{
// verifico validità
if ( ! m_bOk)
return false ;
// verifico parametro di ritorno
if ( &vInfo == nullptr)
return false ;
vInfo.clear() ;
// calcolo box linea (nel riferimento)
BBox3d b3Line ;
b3Line.Add( ptL) ;
// calcolo punto nel riferimento trimesh
Point3d ptLL = ptL ;
ptLL.ToGlob( m_frLines) ;
// recupero indici triangoli che intersecano box in 2d
INTVECTOR vnIds ;
if ( m_HGrids.Find( b3Line, vnIds)) {
for ( int i = 0 ; i < int( vnIds.size()) ; ++ i) {
int nT = vnIds[i] ;
Triangle3d Tria ;
m_pSTm->GetTriangle( nT, Tria) ;
// aggiorno info con intersezione
UpdateInfoIntersLineSurfTm( ptLL, m_frLines.VersZ(), dLen, nT, Tria, vInfo, bFinite) ;
}
}
// ordino il vettore delle eventuali intersezioni secondo il senso crescente del parametro di linea
OrderInfoIntersLineSurfTm( vInfo) ;
return true ;
}