diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 1d7bc11..48dc5a0 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -309,6 +309,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -316,6 +317,8 @@ copy $(TargetPath) \EgtProg\Dll64 + + @@ -628,7 +631,6 @@ copy $(TargetPath) \EgtProg\Dll64 - diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index d101d64..1f8e8f8 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -49,6 +49,9 @@ {d96752da-1884-4a73-ba1b-5b20b606e469} + + {4c6a9dc5-8fac-4ecd-bde6-3e37e056712e} + @@ -504,6 +507,9 @@ File di origine\Base + + File di origine\GeoElevation + @@ -1148,15 +1154,18 @@ File di intestazione - - File di intestazione\Include - File di intestazione File di intestazione + + File di intestazione\Include + + + File di intestazione\Include + diff --git a/Polygon3d.cpp b/Polygon3d.cpp index ee20680..2892c69 100644 --- a/Polygon3d.cpp +++ b/Polygon3d.cpp @@ -471,6 +471,18 @@ Polygon3d::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) return true ; } +//---------------------------------------------------------------------------- +bool +Polygon3d::GetLocalBBox( BBox3d& b3Loc) const +{ + // assegno il box in locale, scorrendo tutti i punti del contorno + b3Loc.Reset() ; + for ( const auto& ptP : m_vVert) + b3Loc.Add( ptP) ; + + return true ; +} + //---------------------------------------------------------------------------- void Polygon3d::Invert( void) diff --git a/PolygonElevation.cpp b/PolygonElevation.cpp new file mode 100644 index 0000000..c17abef --- /dev/null +++ b/PolygonElevation.cpp @@ -0,0 +1,224 @@ +//---------------------------------------------------------------------------- +// 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 + const double RAY_LEN = 100000 ; + dElev = 0 ; + Point3d ptP ; + bool bFound = PL.GetFirstPoint( ptP) ; + while ( bFound) { + 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) ; + } + bFound = PL.GetNextPoint( ptP, true) ; + } + // 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) ; + 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 ; +} diff --git a/SurfAux.h b/SurfAux.h index 09867fc..68b116d 100644 --- a/SurfAux.h +++ b/SurfAux.h @@ -14,20 +14,3 @@ #pragma once #include "/EgtDev/Include/EGkSurfAux.h" - -//---------------------------------------------------------------------------- -//bool IsClosed( const ICurve& crvC) ; -//bool IsValidParam( const ICurve& crvC, double dPar, ICurve::Side nSide) ; -//bool IsStartParam( const ICurve& crvC, double dPar) ; -//bool IsEndParam( const ICurve& crvC, double dPar) ; -//bool GetNearestExtremityToPoint( const Point3d& ptP, const ICurve& Curve, bool& bStart) ; -//bool MoveParamToAvoidTg( double& dU, ICurve::Side nSide, const ICurve& Curve) ; -//bool GetTang( const ICurve& crvC, double dU, ICurve::Side nS, Vector3d& vtTang) ; -//bool GetPointTang( const ICurve& crvC, double dU, ICurve::Side nS, Point3d& ptPos, Vector3d& vtTang) ; -//bool GetPointDiffGeom( const ICurve& crvC, double dU, ICurve::Side nS, CrvPointDiffGeom& oDiffG) ; -//bool ImproveCurveParamAtPoint( double& dU, const Point3d& ptP, const ICurve* pCrv) ; -//bool CurveGetAreaXY( const ICurve& crvC, double& dArea) ; -//bool CurveGetArea( const ICurve& crvC, Plane3d& plPlane, double& dArea) ; -//bool CurveDump( const ICurve& crvC, std::string& sOut, bool bMM, const char* szNewLine) ; -//bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ; -//bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ; diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index 4a11734..66422c1 100644 --- a/SurfTriMeshFaceting.cpp +++ b/SurfTriMeshFaceting.cpp @@ -939,10 +939,10 @@ SurfTriMesh::GetEdgeCount( void) const { // la superficie deve essere validata if ( m_nStatus != OK) - return 0 ; + return -1 ; // verifico stato bordi sfaccettatura if ( ! VerifyFacetEdging()) - return 0 ; + return -1 ; // restituisco il numero return int( m_vFacEdge.size()) ; } @@ -985,7 +985,7 @@ SurfTriMesh::GetEdge( int nInd, Point3d& ptP1, Point3d& ptP2, double& dAng) cons return SVT_NULL ; // recupero i dati ptP1 = m_vVert[m_vFacEdge[nInd].nIdVert[0]].ptP ; - ptP2 = m_vVert[m_vFacEdge[nInd].nIdVert[0]].ptP ; + ptP2 = m_vVert[m_vFacEdge[nInd].nIdVert[1]].ptP ; dAng = m_vFacEdge[nInd].dIntAng ; // ritorno indice edge corrente return true ;