Files
EgtGeomKernel/IntersSurfTmSurfTm.cpp
Dario Sassi 2ed2a34d55 EgtGeomKernel :
- modifiche per DistPointLine con interfaccia portata in Include.
2024-05-22 08:19:10 +02:00

222 lines
8.8 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2018-2018
//----------------------------------------------------------------------------
// File : IntersSurfTmSurfTm.cpp Data : 27.08.18 Versione : 1.9h3
// Contenuto : Implementazione della intersezione tra due superfici trimesh.
//
//
//
// Modifiche : 27.08.18 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "IntersLineTria.h"
#include "DllMain.h"
#include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkIntersSurfTmSurfTm.h"
#include "/EgtDev/Include/EGkIntersTriaTria.h"
#include "/EgtDev/Include/EGkPointGrid3d.h"
#include "/EgtDev/Include/EGkHashGrids3d.h"
#include "/EgtDev/Include/EGkDistPointTria.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include <array>
using namespace std ;
//----------------------------------------------------------------------------
// Intersezione di due superficie TriMesh
//----------------------------------------------------------------------------
bool
IntersSurfTmSurfTm( const ISurfTriMesh& Stm1, const ISurfTriMesh& Stm2,
PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria)
{
// verifico superfici
if ( &Stm1 == nullptr || ! Stm1.IsValid() || &Stm2 == nullptr || ! Stm2.IsValid())
return false ;
// verifico parametri di ritorno
if ( &vPnt == nullptr || &vBpt == nullptr || &vTria == nullptr)
return false ;
vPnt.clear() ;
vBpt.clear() ;
vTria.clear() ;
// per ricerca veloce di punti ripetuti
PointGrid3d PtGrid ;
PtGrid.Init( 100) ;
// per ricerca veloce di linee ripetute
HashGrids3d LnGrid ;
LnGrid.SetActivationGrid( true) ;
// per ricerca veloce di triangoli ripetuti
HashGrids3d TrGrid ;
TrGrid.SetActivationGrid( true) ;
// creo HashGrids3d per superficie con maggior numero di elementi
int nTriaNbr1 = Stm1.GetTriangleCount() ;
int nTriaNbr2 = Stm2.GetTriangleCount() ;
bool bHash1 = ( nTriaNbr1 > nTriaNbr2) ;
// cerco i triangoli che si intersecano
Triangle3d TriaA ;
int nTA = ( bHash1 ? Stm2.GetFirstTriangle( TriaA) : Stm1.GetFirstTriangle( TriaA)) ;
while ( nTA != SVT_NULL) {
BBox3d boxA ;
TriaA.GetLocalBBox( boxA) ;
INTVECTOR vnIds ;
if ( bHash1 ? Stm1.GetAllTriaOverlapBox( boxA, vnIds) : Stm2.GetAllTriaOverlapBox( boxA, vnIds)) {
for ( int h = 0 ; h < int( vnIds.size()) ; ++ h) {
int nB = vnIds[h] ;
Triangle3d TriaB ;
if ( bHash1 ? Stm1.GetTriangle( nB, TriaB) : Stm2.GetTriangle( nB, TriaB)) {
// intersezione tra i triangoli
Point3d ptInt, ptInt2 ;
TRIA3DVECTOR vIttTria ;
int nRes = IntersTriaTria( TriaA, TriaB, ptInt, ptInt2, vIttTria) ;
// se punto
if ( nRes == ITTT_VERT_VERT || nRes == ITTT_VERT_EDGE || nRes == ITTT_EDGE_VERT ||
nRes == ITTT_VERT_INT || nRes == ITTT_INT_VERT || nRes == ITTT_EDGE_EDGE_PNT) {
// verifico se punto già inserito
int nId ;
if ( ! PtGrid.Find( ptInt, 10 * EPS_SMALL, nId)) {
vPnt.emplace_back( ptInt) ;
PtGrid.InsertPoint( ptInt, int( vPnt.size()) - 1) ;
}
}
// se altrimenti segmento
else if ( nRes == ITTT_EDGE_EDGE_SEG || nRes == ITTT_EDGE_INT ||
nRes == ITTT_INT_EDGE || nRes == ITTT_INT_INT_SEG ) {
// se abbastanza lungo
if ( ! AreSamePointApprox( ptInt, ptInt2)) {
// verifico se già inserito
bool bFound = false ;
BBox3d b3Line( ptInt, ptInt2) ;
INTVECTOR vnId2s ;
if ( LnGrid.Find( b3Line, vnId2s)) {
for ( int i = 0 ; i < int( vnId2s.size()) ; ++ i) {
int nA = vnId2s[i] ;
const Point3d& ptOth = vBpt[nA].first ;
const Point3d& ptOth2 = vBpt[nA].second ;
if ( ( AreSamePointEpsilon( ptInt, ptOth, 10 * EPS_SMALL) &&
AreSamePointEpsilon( ptInt2, ptOth2, 10 * EPS_SMALL))) {
bFound = true ;
break ;
}
}
}
// se non inserito, procedo
if ( ! bFound) {
vBpt.emplace_back( ptInt, ptInt2) ;
LnGrid.Add( int( vBpt.size()) - 1, b3Line) ;
LnGrid.Update() ;
}
}
}
// se altrimenti sovrapposizione
else if ( nRes == ITTT_OVERLAPS || nRes == ITTT_COUNTER_OVERLAPS) {
for ( const auto& Tria : vIttTria) {
// verifico se triangolo già inserito
bool bFound = false ;
BBox3d b3Tria ;
Tria.GetLocalBBox( b3Tria) ;
INTVECTOR vnId2s ;
if ( TrGrid.Find( b3Tria, vnId2s)) {
for ( int i = 0 ; i < int( vnId2s.size()) ; ++ i) {
int nA = vnId2s[i] ;
const Triangle3d& trOth = vTria[nA] ;
array< bool, 3> bOth = { false, false, false} ;
for ( int j = 0 ; j < 3 ; ++ j) {
for ( int k = 0 ; k < 3 ; ++ k) {
if ( ! bOth[k])
bOth[k] = AreSamePointEpsilon( Tria.GetP( j), trOth.GetP( k), 10 * EPS_SMALL) ;
}
}
if ( bOth[0] && bOth[1] && bOth[2]) {
bFound = true ;
break ;
}
}
}
// se non inserito, procedo
if ( ! bFound) {
vTria.emplace_back( Tria) ;
TrGrid.Add( int( vTria.size()) - 1, b3Tria) ;
TrGrid.Update() ;
}
}
}
}
}
}
// passo al prossimo triangolo
nTA = ( bHash1 ? Stm2.GetNextTriangle( nTA, TriaA) : Stm1.GetNextTriangle( nTA, TriaA)) ;
}
// rimuovo i punti che stanno sui segmenti
for ( int i = int( vPnt.size()) - 1 ; i >= 0 ; -- i) {
bool bFound = false ;
BBox3d b3Pnt( vPnt[i]) ;
b3Pnt.Expand( 10 * EPS_SMALL) ;
INTVECTOR vnIds ;
if ( LnGrid.Find( b3Pnt, vnIds)) {
for ( int j = 0 ; j < int( vnIds.size()) ; ++ j) {
int nA = vnIds[j] ;
if ( DistPointLine( vPnt[i], vBpt[nA].first, vBpt[nA].second).IsEpsilon( 10 * EPS_SMALL)) {
bFound = true ;
break ;
}
}
}
if ( bFound)
vPnt.erase( vPnt.begin() + i) ;
}
// rimuovo i punti che stanno sui triangoli
for ( int i = int( vPnt.size()) - 1 ; i >= 0 ; -- i) {
bool bFound = false ;
BBox3d b3Pnt( vPnt[i]) ;
b3Pnt.Expand( 10 * EPS_SMALL) ;
INTVECTOR vnIds ;
if ( TrGrid.Find( b3Pnt, vnIds)) {
for ( int j = 0 ; j < int( vnIds.size()) ; ++ j) {
int nA = vnIds[j] ;
const Triangle3d& trOth = vTria[nA] ;
if ( DistPointTriangle( vPnt[i], trOth).IsEpsilon( 10 * EPS_SMALL)) {
bFound = true ;
break ;
}
}
}
if ( bFound)
vPnt.erase( vPnt.begin() + i) ;
}
// rimuovo i segmenti che stanno sui triangoli
for ( int i = int( vBpt.size()) - 1 ; i >= 0 ; -- i) {
bool bFound = false ;
Point3d ptStart = vBpt[i].first ;
Point3d ptEnd = vBpt[i].second ;
BBox3d b3Line( ptStart, ptEnd) ;
INTVECTOR vnIds ;
if ( TrGrid.Find( b3Line, vnIds)) {
for ( int j = 0 ; j < int( vnIds.size()) ; ++ j) {
int nA = vnIds[j] ;
const Triangle3d& trOth = vTria[nA] ;
if ( DistPointTriangle( ptStart, trOth).IsEpsilon( 10 * EPS_SMALL) &&
DistPointTriangle( ptEnd, trOth).IsEpsilon( 10 * EPS_SMALL)) {
bFound = true ;
break ;
}
}
}
if ( bFound)
vBpt.erase( vBpt.begin() + i) ;
}
return true ;
}