d343f474e4
- Aggiunti controlli in PolygonElevation.
238 lines
10 KiB
C++
238 lines
10 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2023-2023
|
|
//----------------------------------------------------------------------------
|
|
// File : PolygonElevation.cpp Data : 17.12.23 Versione : 2.5l3
|
|
// Contenuto : Implementazione di funzioni per calcolo elevazione di
|
|
// un poligono (faccia piana) in solidi di diverso tipo.
|
|
//
|
|
//
|
|
// Modifiche : 17.12.23 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "CurveLine.h"
|
|
#include "CurveComposite.h"
|
|
#include "/EgtDev/Include/EGkIntersLineBox.h"
|
|
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
|
#include "/EgtDev/Include/EGkIntersCurves.h"
|
|
#include "/EgtDev/Include/EGkPolygonElevation.h"
|
|
|
|
using namespace std ;
|
|
|
|
//-------------------------------------------------------------------------------
|
|
bool
|
|
PolygonElevationInBBox( const Polygon3d& pgFacet, const BBox3d& b3Box, bool bAcceptOutFacet, double& dElev)
|
|
{
|
|
// verifico validità del poligono e del box
|
|
if ( ! pgFacet.IsValid() || b3Box.IsEmpty())
|
|
return false ;
|
|
|
|
// se richiesto, verifico che la faccia sia contenuta nel box
|
|
if ( ! bAcceptOutFacet) {
|
|
BBox3d b3Fac ;
|
|
if ( ! pgFacet.GetLocalBBox( b3Fac))
|
|
return false ;
|
|
BBox3d b3ExpBox = b3Box ; b3ExpBox.Expand( 100 * EPS_SMALL) ;
|
|
if ( ! b3ExpBox.Encloses( b3Fac)) {
|
|
dElev = -1 ;
|
|
return true ;
|
|
}
|
|
}
|
|
|
|
// recupero centro, normale e contorno delle faccia poligonale
|
|
Point3d ptCen = pgFacet.GetCentroid() ;
|
|
Vector3d vtN = pgFacet.GetVersN() ;
|
|
PolyLine PL = pgFacet.GetPolyLine() ;
|
|
|
|
// calcolo elevazione massima del contorno della faccia
|
|
const double RAY_LEN = 100000 ;
|
|
dElev = 0 ;
|
|
Point3d ptP ;
|
|
bool bFound = PL.GetFirstPoint( ptP) ;
|
|
while ( bFound) {
|
|
INTDBLVECTOR vInters ;
|
|
IntersLineBox( ptP, vtN, RAY_LEN, b3Box, vInters, true) ;
|
|
for ( int i = 0 ; i < int( vInters.size()) ; ++ i) {
|
|
if ( i == 0 && ( vInters[i].first == ILBT_IN || vInters[i].first == ILBT_TG_INI)) {
|
|
if ( ! bAcceptOutFacet && vInters[i].second > 100 * EPS_SMALL) {
|
|
dElev = -1 ;
|
|
return true ;
|
|
}
|
|
}
|
|
else if ( vInters[i].first == ILBT_OUT || vInters[i].first == ILBT_TG_FIN)
|
|
dElev = max( dElev, vInters[i].second) ;
|
|
}
|
|
bFound = PL.GetNextPoint( ptP, true) ;
|
|
}
|
|
|
|
// calcolo elevazione massima degli eventuali spigoli (e vertici) del box dalla parte positiva della faccia e che cadono in essa
|
|
BIPNTVECTOR vEdges( 12) ;
|
|
vEdges[0].first = b3Box.GetMin() ; vEdges[0].second = vEdges[0].first + b3Box.GetDimX() * X_AX ;
|
|
vEdges[1].first = vEdges[0].second ; vEdges[1].second = vEdges[1].first + b3Box.GetDimY() * Y_AX ;
|
|
vEdges[2].first = vEdges[1].second ; vEdges[2].second = vEdges[0].first + b3Box.GetDimY() * Y_AX ;
|
|
vEdges[3].first = vEdges[2].second ; vEdges[3].second = vEdges[0].first ;
|
|
vEdges[4].first = vEdges[0].first + b3Box.GetDimZ() * Z_AX ; vEdges[4].second = vEdges[0].second + b3Box.GetDimZ() * Z_AX ;
|
|
vEdges[5].first = vEdges[1].first + b3Box.GetDimZ() * Z_AX ; vEdges[5].second = vEdges[1].second + b3Box.GetDimZ() * Z_AX ;
|
|
vEdges[6].first = vEdges[2].first + b3Box.GetDimZ() * Z_AX ; vEdges[6].second = vEdges[2].second + b3Box.GetDimZ() * Z_AX ;
|
|
vEdges[7].first = vEdges[3].first + b3Box.GetDimZ() * Z_AX ; vEdges[7].second = vEdges[3].second + b3Box.GetDimZ() * Z_AX ;
|
|
vEdges[8].first = vEdges[0].first ; vEdges[8].second = vEdges[4].first ;
|
|
vEdges[9].first = vEdges[1].first ; vEdges[9].second = vEdges[5].first ;
|
|
vEdges[10].first = vEdges[2].first ; vEdges[10].second = vEdges[6].first ;
|
|
vEdges[11].first = vEdges[3].first ; vEdges[11].second = vEdges[7].first ;
|
|
// porto tutto nel riferimento intrinseco della faccia (già calcolato in quello del box)
|
|
Frame3d frOcs ; frOcs.Set( ptCen, vtN) ;
|
|
PL.ToLoc( frOcs) ;
|
|
for ( int i = 0 ; i < int( vEdges.size()) ; ++ i) {
|
|
vEdges[i].first.ToLoc( frOcs) ;
|
|
vEdges[i].second.ToLoc( frOcs) ;
|
|
}
|
|
// calcolo la curva di loop
|
|
CurveComposite ccLoop ;
|
|
if ( ! ccLoop.FromPolyLine( PL))
|
|
return false ;
|
|
// eseguo i calcoli di elevazione
|
|
for ( int i = 0 ; i < int( vEdges.size()) ; ++ i) {
|
|
// se sta sul piano o sotto, lo salto
|
|
if ( vEdges[i].first.z < EPS_SMALL && vEdges[i].second.z < EPS_SMALL)
|
|
continue ;
|
|
// calcolo il segmento di linea
|
|
CurveLine clLine ;
|
|
if ( ! clLine.Set( vEdges[i].first, vEdges[i].second))
|
|
return false ;
|
|
// l'elevazione va aggiornata con la massima Z delle eventuali intersezioni dell'edge con il loop
|
|
IntersCurveCurve intLL( clLine, ccLoop) ;
|
|
IntCrvCrvInfo aInfo ;
|
|
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
|
|
dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
|
|
if ( aInfo.bOverlap)
|
|
dElev = max( dElev, aInfo.IciA[1].ptI.z) ;
|
|
// se prima intersezione va da interno ad esterno allora devo considerare il punto iniziale del segmento (vertice)
|
|
if ( j == 0 && aInfo.IciA[0].nPrevTy == ICCT_IN)
|
|
dElev = max( dElev, vEdges[i].first.z) ;
|
|
// c'è anche il caso di ultima intersezione da esterno a interno, ma vertice già considerato nel caso precedente
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------
|
|
bool
|
|
PolygonElevationInClosedSurfTm( const Polygon3d& pgFacet, const ISurfTriMesh& CldStm, bool bAcceptOutFacet, double& dElev)
|
|
{
|
|
// verifico validità del poligono e della superficie
|
|
if ( ! pgFacet.IsValid() || ! CldStm.IsValid() || ! CldStm.IsClosed())
|
|
return false ;
|
|
|
|
// se superficie vuota
|
|
if ( CldStm.IsEmpty()) {
|
|
dElev = ( bAcceptOutFacet ? 0 : -1) ;
|
|
return true ;
|
|
}
|
|
|
|
// se richiesto, verifico sia contenuta nel box della superficie chiusa
|
|
if ( ! bAcceptOutFacet) {
|
|
BBox3d b3Fac ;
|
|
if ( ! pgFacet.GetLocalBBox( b3Fac))
|
|
return false ;
|
|
BBox3d b3ExpCldStm ; CldStm.GetLocalBBox( b3ExpCldStm) ; b3ExpCldStm.Expand( 100 * EPS_SMALL) ;
|
|
if ( ! b3ExpCldStm.Encloses( b3Fac)) {
|
|
dElev = -1 ;
|
|
return true ;
|
|
}
|
|
}
|
|
|
|
// recupero centro, normale e contorno delle faccia poligonale
|
|
Point3d ptCen = pgFacet.GetCentroid() ;
|
|
Vector3d vtN = pgFacet.GetVersN() ;
|
|
PolyLine PL = pgFacet.GetPolyLine() ;
|
|
|
|
// calcolo elevazione massima del contorno della faccia e nel suo centro
|
|
const double RAY_LEN = 100000 ;
|
|
dElev = 0 ;
|
|
PNTVECTOR vptP ; vptP.reserve( PL.GetPointNbr()) ;
|
|
Point3d ptP ;
|
|
bool bFound = PL.GetFirstPoint( ptP) ;
|
|
while ( bFound) {
|
|
vptP.push_back( ptP) ;
|
|
bFound = PL.GetNextPoint( ptP, true) ;
|
|
}
|
|
vptP.push_back( ptCen) ;
|
|
for ( const Point3d& ptP : vptP) {
|
|
ILSIVECTOR vInters ;
|
|
IntersLineSurfTm( ptP, vtN, RAY_LEN, CldStm, vInters, true) ;
|
|
for ( int i = 0 ; i < int( vInters.size()) ; ++ i) {
|
|
const auto& Inters = vInters[i] ;
|
|
if ( i == 0 && Inters.nILTT != ILTT_NO && Inters.dCosDN < -EPS_ZERO) {
|
|
if ( ! bAcceptOutFacet && Inters.dU > 100 * EPS_SMALL) {
|
|
dElev = -1 ;
|
|
return true ;
|
|
}
|
|
}
|
|
else if ( ( Inters.nILTT == ILTT_VERT || Inters.nILTT == ILTT_EDGE || Inters.nILTT == ILTT_IN) && Inters.dCosDN > EPS_ZERO)
|
|
dElev = max( dElev, Inters.dU) ;
|
|
else if ( Inters.nILTT == ILTT_SEGM || Inters.nILTT == ILTT_SEGM_ON_EDGE)
|
|
dElev = max( dElev, Inters.dU2) ;
|
|
}
|
|
}
|
|
// calcolo elevazione massima degli eventuali spigoli (e vertici) della superficie chiusa dalla parte positiva della faccia e che cadono in essa
|
|
int nEdgeCnt = CldStm.GetEdgeCount() ;
|
|
if ( nEdgeCnt < 0)
|
|
return false ;
|
|
BIPNTVECTOR vEdges ;
|
|
vEdges.reserve( nEdgeCnt) ;
|
|
for ( int i = 0 ; i < nEdgeCnt ; ++ i) {
|
|
Point3d ptP1, ptP2 ; double dAng ;
|
|
CldStm.GetEdge( i, ptP1, ptP2, dAng) ;
|
|
vEdges.emplace_back( ptP1, ptP2) ;
|
|
}
|
|
// porto tutto nel riferimento intrinseco della faccia (già calcolato in quello della superficie chiusa)
|
|
Frame3d frOcs ; frOcs.Set( ptCen, vtN) ;
|
|
PL.ToLoc( frOcs) ;
|
|
for ( int i = 0 ; i < int( vEdges.size()) ; ++ i) {
|
|
vEdges[i].first.ToLoc( frOcs) ;
|
|
vEdges[i].second.ToLoc( frOcs) ;
|
|
}
|
|
// calcolo la curva di loop
|
|
CurveComposite ccLoop ;
|
|
if ( ! ccLoop.FromPolyLine( PL))
|
|
return false ;
|
|
// eseguo i calcoli di elevazione
|
|
for ( int i = 0 ; i < int( vEdges.size()) ; ++ i) {
|
|
// se sta sul piano o sotto, lo salto
|
|
if ( vEdges[i].first.z < EPS_SMALL && vEdges[i].second.z < EPS_SMALL)
|
|
continue ;
|
|
// calcolo il segmento di linea
|
|
CurveLine clLine ;
|
|
if ( ! clLine.Set( vEdges[i].first, vEdges[i].second))
|
|
return false ;
|
|
// l'elevazione va aggiornata con la massima Z delle eventuali intersezioni dell'edge con il loop
|
|
IntersCurveCurve intLL( clLine, ccLoop) ;
|
|
if ( intLL.GetIntersCount() == 0) {
|
|
Point3d ptM = Media( vEdges[i].first, vEdges[i].second) ;
|
|
ptM.z = 0 ;
|
|
if ( IsPointInsidePolyLine( ptM, PL, -EPS_SMALL))
|
|
dElev = max( dElev, max( vEdges[i].first.z, vEdges[i].second.z)) ;
|
|
}
|
|
else {
|
|
IntCrvCrvInfo aInfo ;
|
|
for ( int j = 0 ; intLL.GetIntCrvCrvInfo( j, aInfo) ; ++ j) {
|
|
dElev = max( dElev, aInfo.IciA[0].ptI.z) ;
|
|
if ( aInfo.bOverlap)
|
|
dElev = max( dElev, aInfo.IciA[1].ptI.z) ;
|
|
// se prima intersezione va da interno ad esterno allora devo considerare il punto iniziale del segmento (vertice)
|
|
if ( j == 0 && aInfo.IciA[0].nPrevTy == ICCT_IN)
|
|
dElev = max( dElev, vEdges[i].first.z) ;
|
|
// se ultima intersezione va da esterno a interno allora devo considerare il punto finale del segmento (vertice)
|
|
else if ( j == intLL.GetIntersCount() - 1 && aInfo.IciA[ aInfo.bOverlap ? 1 : 0].nNextTy == ICCT_IN)
|
|
dElev = max( dElev, vEdges[i].second.z) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true ;
|
|
}
|