451ef8356b
- aggiunta funzione IntersCurveSurfTm - funzioni di intersezione Line e Plane con Zmap separate dall'oggetto per l'interfaccia
224 lines
9.8 KiB
C++
224 lines
9.8 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2024-2024
|
|
//----------------------------------------------------------------------------
|
|
// File : IntersCurveSurfTm.cpp Data : 23.02.24 Versione : 2.6b4
|
|
// Contenuto : Implementazione della intersezione curva/superficie trimesh.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 23.02.24 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "GeoConst.h"
|
|
#include "/EgtDev/Include/EGkIntersLineTria.h"
|
|
#include "/EgtDev/Include/EGkIntersCurveSurfTm.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static void
|
|
UpdateInfoIntersCurveSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen, double dUs, double dUe,
|
|
int nT, const Triangle3d& Tria, ICSIVECTOR& vInfo)
|
|
{
|
|
Point3d ptInt, ptInt2 ;
|
|
int nRes = IntersLineTria( ptL, vtDir, dLen, Tria, ptInt, ptInt2, true) ;
|
|
if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) {
|
|
double dU = dUs + ( ptInt - ptL) * vtDir / dLen * ( dUe - dUs) ;
|
|
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 = dUs + ( ptInt - ptL) * vtDir / dLen * ( dUe - dUs) ;
|
|
double dU2 = dUs + ( ptInt2 - ptL) * vtDir / dLen * ( dUe - dUs) ;
|
|
double dCosDN = vtDir * Tria.GetN() ;
|
|
vInfo.emplace_back( nRes, dU, dU2, nT, dCosDN, ptInt, ptInt2) ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
static void
|
|
OrderInfoIntersCurveSurfTm( ICSIVECTOR& 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 IntCrvStmInfo& a, const IntCrvStmInfo& 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 curva con una superficie TriMesh
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
IntersCurveSurfTm( const ICurve& Curve, const ISurfTriMesh& Stm, double dLinTol, ICSIVECTOR& vInfo)
|
|
{
|
|
// verifico i parametri ricevuti
|
|
if ( & Curve == nullptr || &Stm == nullptr || &vInfo == nullptr)
|
|
return false ;
|
|
dLinTol = max( dLinTol, EPS_SMALL) ;
|
|
vInfo.clear() ;
|
|
|
|
// approssimo la curva con una spezzata
|
|
PolyLine PL ;
|
|
if ( ! Curve.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_SPECIAL, PL))
|
|
return false ;
|
|
|
|
// per ogni segmento dell'approssimante cerco l'intersezione con la superficie
|
|
double dParS, dParE ;
|
|
Point3d ptStart, ptEnd ;
|
|
bool bFound = PL.GetFirstULine( &dParS, &ptStart, &dParE, &ptEnd) ;
|
|
while ( bFound) {
|
|
Vector3d vtDir = ptEnd - ptStart ;
|
|
double dLen = vtDir.Len() ;
|
|
if ( dLen > EPS_SMALL) {
|
|
vtDir /= dLen ;
|
|
// cerco i triangoli intersecati dal segmento
|
|
const double BOX_STEP = 10 ;
|
|
int nStep = int( ceil( dLen / BOX_STEP)) ;
|
|
Vector3d vtStep = dLen / nStep * vtDir ;
|
|
INTVECTOR vPrevT ;
|
|
for ( int i = 0 ; i < nStep ; ++ i) {
|
|
BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ;
|
|
INTVECTOR vT ;
|
|
if ( Stm.GetAllTriaOverlapBox( b3Box, vT)) {
|
|
for ( auto nT : vT) {
|
|
// se triangolo non ancora intersecato
|
|
if ( find( vPrevT.begin(), vPrevT.end(), nT) == vPrevT.end()) {
|
|
vPrevT.emplace_back( nT) ;
|
|
Triangle3d Tria ;
|
|
Stm.GetTriangle( nT, Tria) ;
|
|
// aggiorno info con intersezione
|
|
UpdateInfoIntersCurveSurfTm( ptStart, vtDir, dLen, dParS, dParE, nT, Tria, vInfo) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// passo al segmento successivo
|
|
bFound = PL.GetNextULine( &dParS, &ptStart, &dParE, &ptEnd) ;
|
|
}
|
|
|
|
// ordino il vettore delle eventuali intersezioni secondo il senso crescente del parametro di linea
|
|
OrderInfoIntersCurveSurfTm( vInfo) ;
|
|
|
|
return true ;
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
IntersCurveSurfTmExt( const ICurve& Curve, const ISurfTriMesh& Stm, double dLinTol, INTDBLVECTOR& vInters)
|
|
{
|
|
ICSIVECTOR vInfo ;
|
|
vInters.clear() ;
|
|
return ( IntersCurveSurfTm( Curve, Stm, dLinTol, vInfo) && FilterCurveSurfTmInters( Curve, vInfo, vInters)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
FilterCurveSurfTmInters( const ICurve& Curve, const ICSIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
|
{
|
|
// verifico i parametri ricevuti
|
|
if ( & Curve == nullptr || &vInfo == nullptr || &vInters == nullptr)
|
|
return false ;
|
|
vInters.clear() ;
|
|
// info sulla curva
|
|
bool bClosedCrv = Curve.IsClosed() ;
|
|
double dParSCrv, dParECrv ;
|
|
Curve.GetDomain( dParSCrv, dParECrv) ;
|
|
// ciclo sulle intersezioni
|
|
for ( const auto& Info : vInfo) {
|
|
// se intersezione puntuale
|
|
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
|
|
int nFlag = CSIT_NONE ;
|
|
if ( Info.dCosDN > EPS_ZERO)
|
|
nFlag = CSIT_IN_OUT ;
|
|
else if ( Info.dCosDN < -EPS_ZERO)
|
|
nFlag = CSIT_OUT_IN ;
|
|
vInters.emplace_back( nFlag, Info.dU) ;
|
|
}
|
|
// se altrimenti intersezione con coincidenza
|
|
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
|
|
vInters.emplace_back( CSIT_IN_ON, Info.dU) ;
|
|
vInters.emplace_back( CSIT_ON_IN, Info.dU2) ;
|
|
}
|
|
}
|
|
// elimino intersezioni ripetute
|
|
int nStart = ( bClosedCrv ? 0 : 1) ;
|
|
for ( int j = nStart ; j < int( vInters.size()) ; ) {
|
|
// intersezione precedente
|
|
int i = ( j > 0 ? j - 1 : int( vInters.size()) - 1) ;
|
|
// se hanno lo stesso parametro
|
|
if ( abs( vInters[i].second - vInters[j].second) < EPS_PARAM ||
|
|
( bClosedCrv && abs( vInters[i].second - dParECrv) < EPS_PARAM && abs( vInters[j].second - dParSCrv) < EPS_PARAM)) {
|
|
// flag per eseguita cancellazione
|
|
bool bSomeErased = false ;
|
|
// se sono entrambe entranti o uscenti, elimino la seconda
|
|
if ( ( vInters[i].first == CSIT_OUT_IN && vInters[j].first == CSIT_OUT_IN) ||
|
|
( vInters[i].first == CSIT_IN_OUT && vInters[j].first == CSIT_IN_OUT)) {
|
|
vInters.erase( vInters.begin() + j) ;
|
|
bSomeErased = true ;
|
|
}
|
|
// se una entrante e l'altra uscente, cambio in touch da fuori ed elimino la seconda
|
|
else if ( vInters[i].first == CSIT_OUT_IN && vInters[j].first == CSIT_IN_OUT) {
|
|
vInters[i].first = CSIT_OUT_OUT ;
|
|
vInters.erase( vInters.begin() + j) ;
|
|
bSomeErased = true ;
|
|
}
|
|
// se una uscente e l'altra entrante, cambio in touch da dentro ed elimino la seconda
|
|
else if ( vInters[i].first == CSIT_IN_OUT && vInters[j].first == CSIT_OUT_IN) {
|
|
vInters[i].first = CSIT_IN_IN ;
|
|
vInters.erase( vInters.begin() + j) ;
|
|
bSomeErased = true ;
|
|
}
|
|
// se una touch da fuori o da dentro e l'altra entrante o uscente, elimino la prima
|
|
else if ( ( vInters[i].first == CSIT_OUT_OUT || vInters[i].first == CSIT_IN_IN) &&
|
|
( vInters[j].first == CSIT_OUT_IN || vInters[j].first == CSIT_IN_OUT)) {
|
|
vInters.erase( vInters.begin() + i) ;
|
|
bSomeErased = true ;
|
|
}
|
|
// se una entrante o uscente e l'altra touch da fuori o da dentro, elimino la seconda
|
|
else if ( ( vInters[i].first == CSIT_OUT_IN || vInters[i].first == CSIT_IN_OUT) &&
|
|
( vInters[j].first == CSIT_OUT_OUT || vInters[j].first == CSIT_IN_IN)) {
|
|
vInters.erase( vInters.begin() + j) ;
|
|
bSomeErased = true ;
|
|
}
|
|
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
|
|
else if ( ( vInters[i].first == CSIT_OUT_IN || vInters[i].first == CSIT_IN_OUT || vInters[i].first == CSIT_NONE) &&
|
|
( vInters[j].first == CSIT_IN_ON || vInters[j].first == CSIT_OUT_ON)) {
|
|
vInters[j].first = ( vInters[i].first == CSIT_IN_OUT ? CSIT_IN_ON : CSIT_OUT_ON) ;
|
|
vInters.erase( vInters.begin() + i) ;
|
|
bSomeErased = true ;
|
|
}
|
|
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
|
|
else if ( ( vInters[i].first == CSIT_ON_IN || vInters[i].first == CSIT_ON_OUT) &&
|
|
( vInters[j].first == CSIT_OUT_IN || vInters[j].first == CSIT_IN_OUT || vInters[j].first == CSIT_NONE)) {
|
|
vInters[i].first = ( vInters[j].first == CSIT_IN_OUT ? CSIT_ON_OUT : CSIT_ON_IN) ;
|
|
vInters.erase( vInters.begin() + j) ;
|
|
bSomeErased = true ;
|
|
}
|
|
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
|
|
else if ( ( vInters[i].first == CSIT_ON_IN || vInters[i].first == CSIT_ON_OUT) &&
|
|
( vInters[j].first == CSIT_IN_ON || vInters[j].first == CSIT_OUT_ON)) {
|
|
vInters.erase( vInters.begin() + j) ;
|
|
vInters.erase( vInters.begin() + ( j > 0 ? i : i - 1)) ;
|
|
bSomeErased = true ;
|
|
}
|
|
if ( bSomeErased) {
|
|
if ( j > 0)
|
|
-- j ;
|
|
continue ;
|
|
}
|
|
}
|
|
// passo alla successiva
|
|
++ j ;
|
|
}
|
|
return true ;
|
|
}
|