Compare commits

..

26 Commits

Author SHA1 Message Date
Riccardo Elitropi 104726c5ee EgtGeomKernel :
- migliorie varie.
2024-03-19 09:01:46 +01:00
Riccardo Elitropi e2445c0a15 EgtGeomKernel :
- modifica Swept con vettore statico.
- aggiunta Swep con FlatRegion come sezione
- migliorie varie.
2024-03-18 13:20:35 +01:00
Riccardo Elitropi 9880fa0173 EgtGeomKernel :
- migliorie varie.
2024-03-15 13:17:41 +01:00
Riccardo Elitropi d276809906 EgtGeomKernel :
- Swept con o senza caps mediante RMF
- inizio stesura codice per frame statico
- migliorie varie.
2024-03-14 13:04:09 +01:00
Riccardo Elitropi 4268da4a1f EgtGeomKernel :
- primo codice di test con Caps per funzione Swept con guida non piana.
2024-03-11 13:22:37 +01:00
Riccardo Elitropi 4f485d0e87 EgtGeomKernel :
- primo codice di prova per creazione Swept.
2024-03-07 16:53:19 +01:00
Riccardo Elitropi d48348fa1c EgtGeomKernel :
- pulizia codice.
2024-03-07 10:51:59 +01:00
Riccardo Elitropi 003dd0bdef EgtGeomKernel :
- codice di prova per RMF.
2024-03-06 16:29:36 +01:00
Riccardo Elitropi ec109908fa EgtGeomKernel :
- inizio stesura codice per Rotation Minimize Frame.
2024-03-05 16:20:28 +01:00
SaraP 3630b85632 EgtGeomKernel :
- corretto errore offset regioni con Voronoi.
2024-03-04 16:19:27 +01:00
Dario Sassi fdce6e1853 EgtGeomKernel 2.6c1 :
- piccolissima aggiunta a offset di regioni.
2024-03-02 11:52:34 +01:00
SaraP 8ffa9d7fb7 EgtGeomKernel :
- corretto errore offset con Voronoi.
2024-03-01 16:50:55 +01:00
Dario Sassi 360484c9af EgtGeomKernel :
- correzioni a RemoveAlignedPoints di Polyline (si usano indici e non il parametro U come ordine dei punti).
2024-02-29 08:47:44 +01:00
Dario Sassi 47606bffcd Merge remote-tracking branch 'origin/Douglas-Peucker' 2024-02-28 17:36:44 +01:00
Dario Sassi aea99a635f EgtGeomKernel :
- eliminati salvataggi di debug dalle booleanne delle trimesh.
2024-02-27 18:25:01 +01:00
Dario Sassi ce139c6925 EgtGeomKernel 2.6b4 :
- aggiunta funzione GetSurfTriMeshTransSwept per creare superficie swept di traslazione.
2024-02-27 18:18:13 +01:00
SaraP 5dcf5f5616 EgtGeomKernel :
- in Voronoi deallocata memoria non utilizzata.
2024-02-27 14:27:17 +01:00
Dario Sassi 451ef8356b EgtGeomKernel :
- aggiunta funzione IntersCurveSurfTm
- funzioni di intersezione Line e Plane con Zmap separate dall'oggetto per l'interfaccia
2024-02-26 15:00:15 +01:00
Riccardo Elitropi 6e810f050e Merge commit 'bd90fc2b59f3167c57dc9f13d2a99b40c63883bc' 2024-02-21 17:04:26 +01:00
Riccardo Elitropi bd90fc2b59 Merge commit 'fae6a7cd78972d7b91457994d525dba16d4e5945' into BoolStm 2024-02-21 16:54:51 +01:00
Riccardo Elitropi 5800093e53 EgtGeomKernel :
- correzione inversione delle isole ordinate per area.
- migliorie varie.
2024-02-21 16:49:28 +01:00
Riccardo Elitropi 65daddfced EgtGeomKernel :
- piccole modifiche.
2024-02-20 13:10:20 +01:00
Riccardo Elitropi 95915b16e5 EgtGeomKernel :
- migliorie per Stm booleans.
2024-02-19 13:07:50 +01:00
Riccardo Elitropi 46b91bb49d Merge commit '47e79756d17ae312d89d3617289bccabcb4bcf66' into BoolStm 2024-02-14 08:32:48 +01:00
Riccardo Elitropi 751ea085a6 Merge commit '1280037d1dfe7821c6efd45953cb7cf1e3705ecb' into BoolStm 2023-12-22 09:24:54 +01:00
Riccardo Elitropi 15ed754512 EgtGeomKernel :
- gestiti più chunk per la triangolaziome ( MakeAdvanced)
- piccole modifiche a Intersezione e creazione di Stm da curve.
2023-12-07 13:13:28 +01:00
24 changed files with 1856 additions and 385 deletions
BIN
View File
Binary file not shown.
+13
View File
@@ -309,14 +309,26 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="CurveByApprox.cpp" />
<ClCompile Include="CurveByInterp.cpp" />
<ClCompile Include="CurveCompositeOffset.cpp" />
<ClCompile Include="IntersCurveSurfTm.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="IntersLineVolZmap.cpp" />
<ClCompile Include="IntersPlaneVolZmap.cpp" />
<ClCompile Include="PolygonElevation.cpp" />
<ClCompile Include="RotationMinimizeFrame.cpp" />
<ClCompile Include="Voronoi.cpp" />
<ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" />
<ClInclude Include="..\Include\EGkCDeConeFrustumClosedSurfTm.h" />
<ClInclude Include="..\Include\EGkCDeConvexTorusClosedSurfTm.h" />
<ClInclude Include="..\Include\EGkCDeRectPrismoidClosedSurfTm.h" />
<ClInclude Include="..\Include\EGkIntersCurveSurfTm.h" />
<ClInclude Include="..\Include\EGkIntersLineBox.h" />
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h" />
<ClInclude Include="..\Include\EGkIntersPlaneBox.h" />
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h" />
<ClInclude Include="..\Include\EGkPolygonElevation.h" />
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
<ClInclude Include="CDeBoxTria.h" />
@@ -449,6 +461,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="VolZmapGraphics.cpp" />
<ClCompile Include="VolZmapVolume.cpp" />
<ClCompile Include="VolZmap.cpp" />
<ClInclude Include="RotationMinimizeFrame.h" />
<ClInclude Include="Voronoi.h" />
</ItemGroup>
<ItemGroup>
+56 -29
View File
@@ -43,15 +43,18 @@
<Filter Include="File di origine\GeoOffset">
<UniqueIdentifier>{f07670fd-9429-4b7e-ac6d-1c0022e756fb}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoCollision">
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoProject">
<UniqueIdentifier>{d96752da-1884-4a73-ba1b-5b20b606e469}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoElevation">
<UniqueIdentifier>{4c6a9dc5-8fac-4ecd-bde6-3e37e056712e}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoCollisionAvoid">
<UniqueIdentifier>{ae52e402-3063-45e3-b9f7-1710035a1f56}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\GeoCollisionDetection">
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Vector3d.cpp">
@@ -372,17 +375,8 @@
<ClCompile Include="IntersLineSurfStd.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="CAvToolTriangle.cpp">
<Filter>File di origine\GeoCollision</Filter>
</ClCompile>
<ClCompile Include="CAvToolSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
</ClCompile>
<ClCompile Include="CDeBoxTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
</ClCompile>
<ClCompile Include="CAvSimpleSurfFrMove.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="IntersSurfTmSurfTm.cpp">
<Filter>File di origine\GeoInters</Filter>
@@ -400,19 +394,19 @@
<Filter>File di origine\Geo</Filter>
</ClCompile>
<ClCompile Include="CDeCylTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeBoxClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeCylClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeSpheTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeSpheClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="SurfBezier.cpp">
<Filter>File di origine\Geo</Filter>
@@ -430,34 +424,34 @@
<Filter>File di origine\GeoDist</Filter>
</ClCompile>
<ClCompile Include="CDeTriaTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeConeTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeUtility.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeClosedSurfTmClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeConeFrustumClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeConeFrustumTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeConvexTorusClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeConvexTorusTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeRectPrismoidClosedSurfTm.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="CDeRectPrismoidTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="SurfTriMeshUtilities.cpp">
<Filter>File di origine\Geo</Filter>
@@ -469,7 +463,7 @@
<Filter>File di origine\Base</Filter>
</ClCompile>
<ClCompile Include="CDeCapsTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
<Filter>File di origine\GeoCollisionDetection</Filter>
</ClCompile>
<ClCompile Include="Circle2P.cpp">
<Filter>File di origine\GeoCreate</Filter>
@@ -510,6 +504,27 @@
<ClCompile Include="PolygonElevation.cpp">
<Filter>File di origine\GeoElevation</Filter>
</ClCompile>
<ClCompile Include="IntersCurveSurfTm.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="CAvSimpleSurfFrMove.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="CAvToolSurfTm.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="CAvToolTriangle.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="IntersLineVolZmap.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="IntersPlaneVolZmap.cpp">
<Filter>File di origine\GeoInters</Filter>
</ClCompile>
<ClCompile Include="RotationMinimizeFrame.cpp">
<Filter>File di origine\Geo</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
@@ -1169,6 +1184,18 @@
<ClInclude Include="Voronoi.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkIntersCurveSurfTm.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkIntersPlaneVolZmap.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="..\Include\EGkIntersLineVolZmap.h">
<Filter>File di intestazione\Include</Filter>
</ClInclude>
<ClInclude Include="RotationMinimizeFrame.h">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="EgtGeomKernel.rc">
+223
View File
@@ -0,0 +1,223 @@
//----------------------------------------------------------------------------
// 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 ;
}
+1 -1
View File
@@ -22,7 +22,7 @@ using namespace std ;
//----------------------------------------------------------------------------
// Linea e box allineato assi devono essere nel medesimo sistema di riferimento.
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
// In caso di intersezione viene restituito true e i parametri lunghezza in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
+1 -1
View File
@@ -17,7 +17,7 @@
//----------------------------------------------------------------------------
// Linea e box allineato agli assi sono nel medesimo riferimento.
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
// Con intersezione viene restituito true e i parametri lunghezza in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
+70 -5
View File
@@ -21,7 +21,7 @@
using namespace std ;
//----------------------------------------------------------------------------
void
static void
UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dLen,
int nT, const Triangle3d& Tria, ILSIVECTOR& vInfo, bool bFinite)
{
@@ -41,7 +41,7 @@ UpdateInfoIntersLineSurfTm( const Point3d& ptL, const Vector3d& vtDir, double dL
}
//----------------------------------------------------------------------------
void
static void
OrderInfoIntersLineSurfTm( ILSIVECTOR& vInfo)
{
// se non trovati, esco
@@ -81,7 +81,7 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
// lo ingrandisco per non avere problemi con faccia piana su piani canonici
b3Stm.Expand( 10 * EPS_SMALL) ;
double dU1, dU2 ;
if ( ! IntersLineBox( ptL, vtL, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2))
if ( ! IntersLineBox( ptL, vtDir, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2))
return true ;
if ( bFinite) {
dU1 = max( dU1, 0.) ;
@@ -89,12 +89,12 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS
if ( dU2 - dU1 < EPS_SMALL)
return true ;
}
Point3d ptStart = ptL + dU1 * vtL ;
Point3d ptStart = ptL + dU1 * vtDir ;
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 ;
Vector3d vtStep = dLenEff / nStep * vtDir ;
INTVECTOR vPrevT ;
for ( int i = 0 ; i < nStep ; ++ i) {
BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ;
@@ -189,3 +189,68 @@ IntersParLinesSurfTm::GetInters( const Point3d& ptL, double dLen, ILSIVECTOR& vI
return true ;
}
//----------------------------------------------------------------------------
bool
FilterLineSurfTmInters( const ILSIVECTOR& vInfo, INTDBLVECTOR& vInters)
{
// 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 = LST_TOUCH ;
if ( Info.dCosDN > EPS_ZERO)
nFlag = LST_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = LST_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( LST_TG_INI, Info.dU) ;
vInters.emplace_back( LST_TG_FIN, Info.dU2) ;
}
}
// elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) {
// intersezione precedente
size_t i = j - 1 ;
// se hanno lo stesso parametro
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
// se sono entrambe entranti o uscenti, elimino la seconda
if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_IN) ||
( vInters[i].first == LST_OUT && vInters[j].first == LST_OUT)) {
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
else if ( ( vInters[i].first == LST_IN && vInters[j].first == LST_OUT) ||
( vInters[i].first == LST_OUT && vInters[j].first == LST_IN)) {
vInters[i].first = LST_TOUCH ;
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
else if ( ( vInters[i].first == LST_IN || vInters[i].first == LST_OUT || vInters[i].first == LST_TOUCH) && vInters[j].first == LST_TG_INI) {
vInters.erase( vInters.begin() + i) ;
continue ;
}
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
else if ( vInters[i].first == LST_TG_FIN && ( vInters[j].first == LST_IN || vInters[j].first == LST_OUT || vInters[j].first == LST_TOUCH)) {
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
else if ( i > 0 && vInters[i].first == LST_TG_FIN && vInters[j].first == LST_TG_INI) {
vInters.erase( vInters.begin() + j) ;
vInters.erase( vInters.begin() + i) ;
-- j ;
continue ;
}
}
// passo alla successiva
++ j ;
}
return true ;
}
+106
View File
@@ -0,0 +1,106 @@
//----------------------------------------------------------------------------
// EgalTech 2024-2024
//----------------------------------------------------------------------------
// File : IntersLineVolZmap.cpp Data : 22.02.24 Versione : 2.6b4
// Contenuto : Implementazione della intersezione linea/VolZmap.
//
//
//
// Modifiche : 22.02.24 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "VolZmap.h"
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
using namespace std ;
//----------------------------------------------------------------------------
// Intersezione di una linea con la superficie di un solido VolZmap
//----------------------------------------------------------------------------
bool
IntersLineVolZmap( const Point3d& ptL, const Vector3d& vtL, const IVolZmap& Vzm, ILZIVECTOR& vInfo)
{
// verifico linea
Vector3d vtDir = vtL ;
if ( ! vtDir.Normalize( EPS_ZERO))
return false ;
// verifico volume
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
if ( pVzm == nullptr)
return false ;
// verifico parametro di ritorno
if ( &vInfo == nullptr)
return false ;
// eseguo intersezione
return pVzm->GetLineIntersection( ptL, vtL, vInfo) ;
}
//----------------------------------------------------------------------------
bool
FilterLineVolZmapInters( const ILZIVECTOR& vInfo, INTDBLVECTOR& vInters)
{
// 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 = LZT_TOUCH ;
if ( Info.dCosDN > EPS_ZERO)
nFlag = LZT_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = LZT_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( LZT_TG_INI, Info.dU) ;
vInters.emplace_back( LZT_TG_FIN, Info.dU2) ;
}
}
// elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) {
// intersezione precedente
size_t i = j - 1 ;
// se hanno lo stesso parametro
if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
// se sono entrambe entranti o uscenti, elimino la seconda
if ( ( vInters[i].first == LZT_IN && vInters[j].first == LZT_IN) ||
( vInters[i].first == LZT_OUT && vInters[j].first == LZT_OUT)) {
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
else if ( ( vInters[i].first == LZT_IN && vInters[j].first == LZT_OUT) ||
( vInters[i].first == LZT_OUT && vInters[j].first == LZT_IN)) {
vInters[i].first = LZT_TOUCH ;
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una puntuale e l'altra inizio di coincidenza, elimino la prima
else if ( ( vInters[i].first == LZT_IN || vInters[i].first == LZT_OUT || vInters[i].first == LZT_TOUCH) && vInters[j].first == LZT_TG_INI) {
vInters.erase( vInters.begin() + i) ;
continue ;
}
// se una fine di coincidenza e l'altra puntuale, elimino la seconda
else if ( vInters[i].first == LZT_TG_FIN && ( vInters[j].first == LZT_IN || vInters[j].first == LZT_OUT || vInters[j].first == LZT_TOUCH)) {
vInters.erase( vInters.begin() + j) ;
continue ;
}
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
else if ( i > 0 && vInters[i].first == LZT_TG_FIN && vInters[j].first == LZT_TG_INI) {
vInters.erase( vInters.begin() + j) ;
vInters.erase( vInters.begin() + i) ;
-- j ;
continue ;
}
}
// passo alla successiva
++ j ;
}
return true ;
}
+37
View File
@@ -0,0 +1,37 @@
//----------------------------------------------------------------------------
// EgalTech 2024-2024
//----------------------------------------------------------------------------
// File : IntersPlaneVolZmap.cpp Data : 22.02.24 Versione : 2.6b4
// Contenuto : Implementazione della intersezione piano/VolZmap.
//
//
//
// Modifiche : 22.02.24 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "VolZmap.h"
#include "/EgtDev/Include/EGkIntersPlaneVolZmap.h"
using namespace std ;
//----------------------------------------------------------------------------
// Intersezione di unpiano con la superficie di un solido VolZmap
//----------------------------------------------------------------------------
bool
IntersPlaneVolZmap( const Plane3d& plPlane, const IVolZmap& Vzm, ICURVEPOVECTOR& vpLoop)
{
// verifico volume
const VolZmap* pVzm = GetBasicVolZmap( &Vzm) ;
if ( pVzm == nullptr)
return false ;
// verifico parametro di ritorno
if ( &vpLoop == nullptr)
return false ;
// eseguo intersezione
return pVzm->GetPlaneIntersection( plPlane, vpLoop) ;
}
+3 -3
View File
@@ -119,12 +119,12 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p
Point3d ptSt1, ptEn1 ;
int nRes1 = IntersCoplanarLineTria( ptL, vtL, 100.0, trTria1, ptSt1, ptEn1, false) ;
// limito la liena di intersezione con il secondo triangolo
// limito la linea di intersezione con il secondo triangolo
Point3d ptSt2, ptEn2 ;
int nRes2 = IntersCoplanarLineTria( ptL, vtL, 100.0, trTria2, ptSt2, ptEn2, false) ;
// eseguo classificazione
double dIntStU, dIntEnU;
double dIntStU, dIntEnU ;
int nIntType = FindTriaTriaIntersType( trTria1, trTria2, ptL, vtL,
( ptSt1 - ptL) * vtL, ( ptEn1 - ptL) * vtL,
( ptSt2 - ptL) * vtL, ( ptEn2 - ptL) * vtL,
@@ -234,7 +234,7 @@ int
FindTriaTriaIntersType( const Triangle3d& trTria1, const Triangle3d& trTria2, const Point3d& ptLineSt, const Vector3d& vtLineDir,
double dStU1, double dEnU1, double dStU2, double dEnU2, int nRes1, int nRes2, double& dIntStU, double& dIntEnU)
{
// Controllo su validit input
// Controllo su validità input
if ( ! ( trTria1.IsValid() && trTria2.IsValid() && vtLineDir.IsNormalized()))
return ITTT_NO ;
// Casi
+26 -42
View File
@@ -721,22 +721,10 @@ PolyLine::AdjustForMaxSegmentLen( double dMaxLen)
return true ;
}
//----------------------------------------------------------------------------
static bool
PointsInTolerance( const PNTVECTOR& vRPT, const Point3d& ptP1, const Point3d& ptP2, double dSqTol)
{
for ( const auto& ptQ : vRPT) {
double dSqDist ;
if ( ! DistPointLine( ptQ, ptP1, ptP2).GetSqDist( dSqDist) || dSqDist > dSqTol)
return false ;
}
return true ;
}
//-----------------------------------------------------------------------------
static bool
douglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const int nIndStart,
const int nIndEnd, PNTUVECTOR& vPtU_simple)
DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const int nIndStart,
const int nIndEnd, INTVECTOR& vInd)
{
// se indici uguali, ritorno
if ( nIndStart == nIndEnd)
@@ -762,10 +750,10 @@ douglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const
// (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd)
if ( dMaxSqDist > dSqTol) {
// inserisco il punto
vPtU_simple.push_back( vPtU[nMaxInd]) ;
vInd.push_back( nMaxInd) ;
// split
if ( ! douglasPeuckerSimplification( vPtU, dSqTol, nIndStart, nMaxInd, vPtU_simple) ||
! douglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, nIndEnd, vPtU_simple))
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nIndStart, nMaxInd, vInd) ||
! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, nIndEnd, vInd))
return false ;
}
@@ -782,27 +770,24 @@ PolyLine::RemoveAlignedPoints( double dToler)
// controllo minimo valore di tolleranza
dToler = max( dToler, LIN_TOL_MIN) ;
double dSqTol = dToler * dToler ;
// vettore contenente i punti della polyline
PNTUVECTOR vPtU ; vPtU.resize( int( m_lUPoints.size())) ;
// interatore primo punto
auto ptAct = m_lUPoints.begin() ;
for ( int i = 0 ; i < int( m_lUPoints.size()) ; ++ i) {
vPtU[i] = *ptAct;
ptAct = next( ptAct) ; // incremento iteratore
}
PNTUVECTOR vPtU ; vPtU.reserve( m_lUPoints.size()) ;
for ( const auto& ptCurr : m_lUPoints)
vPtU.emplace_back( ptCurr) ;
// vettore indice dei punti semplificati
PNTUVECTOR vPtU_simple ;
// vettore indici dei punti rimanenti
INTVECTOR vInd ; vInd.reserve( vPtU.size()) ;
// POLYLINE APERTA
// se aperta
if ( ! IsClosed()) {
// considero tutti i punti della PolyLine
vPtU_simple.push_back( vPtU.front()) ;
if ( ! douglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vPtU_simple))
vInd.push_back( 0) ;
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, int( vPtU.size()) - 1, vInd))
return false ;
vPtU_simple.push_back( vPtU.back()) ;
vInd.push_back( vPtU.size() - 1) ;
}
// POLYLINE CHIUSA
// altrimenti chiusa
else {
// cerco il punto più distante dal primo
double dMaxDist = 0. ;
@@ -815,23 +800,22 @@ PolyLine::RemoveAlignedPoints( double dToler)
}
}
// recupero due PolyLine di approssimazione
vPtU_simple.push_back( vPtU.front()) ;
if ( ! douglasPeuckerSimplification( vPtU, dSqTol, 0, nMaxInd, vPtU_simple))
vInd.push_back( 0) ;
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, 0, nMaxInd, vInd))
return false ;
vPtU_simple.push_back( vPtU[ nMaxInd]) ;
if ( ! douglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vPtU_simple))
vInd.push_back( nMaxInd) ;
if ( ! DouglasPeuckerSimplification( vPtU, dSqTol, nMaxInd, int( vPtU.size()) - 1, vInd))
return false ;
vPtU_simple.push_back( vPtU.back()) ;
vInd.push_back( vPtU.size() - 1) ;
}
// ordino
sort( vPtU_simple.begin(), vPtU_simple.end(),
[]( const POINTU& a , const POINTU& b) { return ( a.second < b.second) ; }) ;
// ordino in senso crescente
sort( vInd.begin(), vInd.end()) ;
// pulisco e aggiungo i parametri ricavati
// rimetto in lista i soli punti rimasti
m_lUPoints.clear() ;
for ( int i = 0 ; i < int( vPtU_simple.size()) ; ++ i)
m_lUPoints.push_back( vPtU_simple[i]) ;
for ( auto Ind : vInd)
m_lUPoints.push_back( vPtU[Ind]) ;
return true ;
}
+265
View File
@@ -0,0 +1,265 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2024
//----------------------------------------------------------------------------
// File : RotationMinimizeFrame.cpp Data : 05.03.24 Versione : 2.6c1
// Contenuto : Classe per RotationMinimizeFrame
//
//
//
// Modifiche : 05.03.24 RE Creazione modulo.
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "RotationMinimizeFrame.h"
#include "GeoConst.h"
using namespace std ;
RotationMinimizeFrame::RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start)
{
// assegno i parametri
m_pCrv = pCrv->Clone() ;
m_Frame0 = fr_Start ;
}
//----------------------------------------------------------------------------
RotationMinimizeFrame::~RotationMinimizeFrame( void)
{
Clear() ;
}
//----------------------------------------------------------------------------
bool
RotationMinimizeFrame::Clear( void)
{
// pulizia della curva
if ( m_pCrv != nullptr)
delete m_pCrv ;
m_pCrv = nullptr ;
// reset del frame di partenza
m_Frame0.Reset() ;
return true ;
}
//----------------------------------------------------------------------------
bool
RotationMinimizeFrame::IsValid()
{
// controllo validità della curva
if ( m_pCrv == nullptr || ! m_pCrv->IsValid())
return false ;
// controllo del frame iniziale
if ( ! m_Frame0.IsValid())
return false ;
// controllo che l'origine del frame sia sulla curva e che l'asse Z sia tangente alla curva
Point3d ptS ;
Vector3d vtZ ;
if ( ! m_pCrv->GetPointD1D2( 0., ICurve::FROM_MINUS, ptS, &vtZ) ||
! vtZ.Normalize() ||
! AreSamePointApprox( ptS, m_Frame0.Orig()) ||
! AreSameVectorEpsilon( vtZ, m_Frame0.VersZ(), 5 * EPS_SMALL))
return false ;
return true ;
}
//----------------------------------------------------------------------------
bool
RotationMinimizeFrame::GetFrameAtLength( const Frame3d& frAct, const double dLenNext, Frame3d& frNext)
{
/*
Double Reflection
Computation of Rotation Minimizing Frame in Computer Graphics
Wenping Wang Bert Juttler Dayue Zheng Yang Liu
*/
// ricavo i parametri dal frame
if ( ! frAct.IsValid())
return false ;
// origine del frame e versori ( ptAct, [ vt_r, vt_s, vt_t])
Point3d ptCurr = frAct.Orig() ;
Vector3d vt_r = frAct.VersX() ;
Vector3d vt_t = frAct.VersZ() ;
// ( vt_s è implicito )
double dUNext ; // parametro sulla curva nello step successivo
Point3d ptNext ; // punto sulla curva allo step successivo
// parametro (i+1)-esimo sulla curva
if ( ! m_pCrv->GetParamAtLength( dLenNext, dUNext))
return false ;
// punto (i+1)-esimo sulla curva e suo vettore tangente
Vector3d vt_t_next ;
if ( ! m_pCrv->GetPointD1D2( dUNext, ICurve::FROM_MINUS, ptNext, &vt_t_next) ||
! vt_t_next.IsValid() || ! vt_t_next.Normalize()) // versore tangente
return false ;
// controllo per casi degeneri
if ( AreSamePointEpsilon( ptCurr, ptNext, EPS_ZERO) || // non esiste il piano R1
abs(( ptNext - ptCurr) * ( vt_t_next + vt_t)) < EPS_ZERO) // non esiste il piano R2
return false ;
// ricavo il vettore di riflessione rispetto al piano R1
Vector3d vR1_norm = ptNext - ptCurr ;
if ( ! vR1_norm.IsValid())
return false ;
// parametro di riflessione per R1
double dPar1 = vR1_norm * vR1_norm ;
// riflessione rispetto al piano R1 ( sistema sinistrorso L )
Vector3d vt_r_L = vt_r - ( 2 / dPar1) * ( vR1_norm * vt_r) * vR1_norm ;
Vector3d vt_t_L = vt_t - ( 2 / dPar1) * ( vR1_norm * vt_t) * vR1_norm ;
// ricavo il vettore di riflessione rispetto al piano R1
Vector3d vR2_norm = vt_t_next - vt_t_L ;
if ( ! vR2_norm.IsValid())
return false ;
// parametro di riflessione per R2
double dPar2 = vR2_norm * vR2_norm ;
// versore r del nuovo frame
Vector3d vt_r_next = vt_r_L - ( 2 / dPar2) * ( vR2_norm * vt_r_L) * vR2_norm ;
// versore t del nuovo frame
Vector3d vt_s_next = vt_t_next ^ vt_r_next ;
// imposto il nuovo frame
frNext.Set( ptNext, vt_r_next, vt_s_next, vt_t_next) ;
if ( ! frNext.IsValid()) { // il frame potrebbe non essere nelle tolleranze...
// ... sistemo ricavando il versore "s" mediante "t" ed "r" ...
frNext.Set( ptNext, vt_t_next, vt_r_next) ;
if ( ! frNext.IsValid())
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
RotationMinimizeFrame::GetFramesByStep( FRAME3DVECTOR& vRMFrames, double dStep, bool bUniform)
{
// controllo sullo step
dStep = max( 10 * EPS_SMALL, dStep) ;
// controllo validità
if ( ! IsValid()) {
Clear() ;
return false ;
}
// calcolo lunghezza della curva
double dLen = 0. ;
if ( ! m_pCrv->GetLength( dLen))
return false ;
// in prima posizione viene inserito il frame iniziale
vRMFrames.push_back( m_Frame0) ;
// ricavo il numero degli step
int nStep = int( ceil( dLen / dStep)) ;
if ( nStep == 0) // se non ho step allora serve sono il frame iniziale
return true ;
// lunghezza della curva identificata dal punto successivo
double dLenNext ;
// step corrente
double dMyStep = dStep ;
if ( bUniform)
dMyStep = dLen / nStep ;
// ciclo sugli step in cui la curva è suddivisa
for ( int i = 0 ; i < nStep ; ++ i) {
// ricavo la lunghezza della curva relativo allo step (i+1)-esimo
dLenNext = min( dLen - 10 * EPS_SMALL, ( i + 1) * dMyStep) ;
// ricavo il frame alla lunghezza calcolata
Frame3d frNext ;
if ( ! GetFrameAtLength( vRMFrames[i], dLenNext, frNext))
return false ;
// aggiornamento vettore dei frame
vRMFrames.push_back( frNext) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
RotationMinimizeFrame::GetFramesBySplit( FRAME3DVECTOR& vRMFrames, int nIntervals)
{
// controllo sul numero di intervalli
nIntervals = max( 1, nIntervals) ;
// ricavo lo step associato
double dLen = 0 ;
if ( ! m_pCrv->GetLength( dLen))
return false ;
// ricavo lo step associato
double dStep = dLen / nIntervals ;
return GetFramesByStep( vRMFrames, dStep) ;
}
//----------------------------------------------------------------------------
bool
RotationMinimizeFrame::GetFramesByTollerance( FRAME3DVECTOR& vRMFrames, double dTol)
{
// controllo sulla tolleranza
dTol = max( EPS_SMALL, dTol) ;
// controllo validità
if ( ! IsValid()) {
Clear() ;
return false ;
}
// ricavo la PolyLine associata alla curva mediante tale tolleranza
PolyLine PL ;
if ( ! m_pCrv->ApproxWithLines( dTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
return false ;
// ricavo la lunghezza della curva
double dCrvLen = 0 ;
if ( ! m_pCrv->GetLength( dCrvLen))
return false ;
// devo calcolare il RMF su ogni punto ricavato dall'approssimazione
Point3d ptCurr ;
bool bPoint = PL.GetFirstPoint( ptCurr) ;
bool bFirst = true ;
while ( bPoint) {
if ( bFirst) {
// in prima posizione viene inserito il frame iniziale
vRMFrames.push_back( m_Frame0) ;
bFirst = false ;
}
else {
// ricavo la lunghezza della curva al punto corrente
double dLen = 0. ;
if ( ! m_pCrv->GetLengthAtPoint( ptCurr, dLen))
return false ;
// per sicurezza controllo che sia minore della lunghezza complessiva
dLen = min( dCrvLen - 10 * EPS_SMALL , dLen) ;
// ricavo il Frame associato a tale lunghezza
Frame3d frNext ;
if ( ! GetFrameAtLength( vRMFrames.back(), dLen, frNext))
return false ;
vRMFrames.emplace_back( frNext) ;
}
// passo al punto successivo
bPoint = PL.GetNextPoint( ptCurr) ;
}
return true ;
}
+44
View File
@@ -0,0 +1,44 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2024
//----------------------------------------------------------------------------
// File : RotationMinimizeFrame.h Data : 05.03.24 Versione : 2.6c1
// Contenuto : Dichiarazione della classe RotationMinimizeFrame
//
//
//
// Modifiche : 05.03.24 RE Creazione modulo.
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/EGkCurve.h"
#include <vector>
//----------------------------------------------------------------------------
typedef std::vector<Frame3d> FRAME3DVECTOR ;
//----------------------------------------------------------------------------
class RotationMinimizeFrame
{
public :
RotationMinimizeFrame( const ICurve* pCrv, const Frame3d& fr_Start) ;
~RotationMinimizeFrame( void) ;
public :
bool GetFramesByStep( FRAME3DVECTOR& vRMFrames, double dStep, bool bUniform = false) ;
bool GetFramesBySplit( FRAME3DVECTOR& vRMFrames, int nIntervals) ;
bool GetFramesByTollerance( FRAME3DVECTOR& vRMFrames, double dTol) ;
private :
bool Clear( void) ;
bool IsValid( void) ;
bool GetFrameAtLength( const Frame3d& frAct, const double dLenNext, Frame3d& frNext) ;
private :
ICurve* m_pCrv ; // curva per il calcolo del rotation minimize frame
Frame3d m_Frame0 ; // frame iniziale della curva
} ;
+581 -95
View File
@@ -1,4 +1,4 @@
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// EgalTech 2015-2015
//----------------------------------------------------------------------------
// File : StmFromCurves.cpp Data : 01.02.15 Versione : 1.6b1
@@ -19,13 +19,16 @@
#include "CurveComposite.h"
#include "SurfTriMesh.h"
#include "Voronoi.h"
#include "RotationMinimizeFrame.h"
#include "/EgtDev/Include/EGkOffsetCurve.h"
#include "/EgtDev/Include/EGkStmFromCurves.h"
#include "/EgtDev/Include/EGkStmFromTriangleSoup.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include <algorithm>
#include <thread>
#include <future>
#include <EgtDev/Include/EGkIntersCurves.h>
using namespace std ;
@@ -109,9 +112,9 @@ GetSurfTriMeshByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr,
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByExtrusion( PL, vtExtr))
return nullptr ;
// se da fare, metto i tappi sulle estremità
// se da fare, metto i tappi sulle estremità
if ( bDoCapEnds) {
// creo la prima superficie di estremità
// creo la prima superficie di estremità
SurfTriMesh STM1 ;
if ( ! STM1.CreateByFlatContour( PL))
return nullptr ;
@@ -155,7 +158,7 @@ GetSurfTriMeshByRegionExtrusion( const CICURVEPVECTOR& vpCurve, const Vector3d&
for ( int i = 0 ; i < int( vPL.size()) ; ++ i)
vPL[i].Invert() ;
}
// creo la prima superficie di estremità
// creo la prima superficie di estremità
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM) || ! pSTM->CreateByRegion( vPL))
return nullptr ;
@@ -287,7 +290,7 @@ GetSurfTriMeshByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vecto
return nullptr ;
// se richiesti caps
if ( bCapEnds) {
// determino se la sezione è chiusa e piatta
// determino se la sezione è chiusa e piatta
Plane3d plPlane ; double dArea ;
bool bSectClosedFlat = PL.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL) ;
// determino non sia una semplice rivoluzione
@@ -331,7 +334,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
return nullptr ;
Vector3d vtNorm = plGuide.GetVersN() ;
// determino se la guida è chiusa
// determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ;
// curve di offset
OffsetCurve OffsCrvR ;
@@ -372,7 +375,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide,
pSTM->SetSmoothAngle( 20) ;
// se guida aperta e tappi piatti
if ( ! bGuideClosed && nCapType == RSCAP_FLAT) {
// verifico che le due estremità siano chiuse e piatte
// verifico che le due estremità siano chiuse e piatte
POLYLINEVECTOR vPL ;
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
return nullptr ;
@@ -451,7 +454,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
Point3d ptCen ;
pGuide->GetStartPoint( ptCen) ;
ptCen -= dDimV / 2 * vtNorm ;
// determino se la guida è chiusa
// determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ;
// curve di offset
const int NUM_OFFS = 4 ;
@@ -474,7 +477,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
}
}
else {
// se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo
// se Voronoi non è possibile calcolare gli offset di una stessa curva in parallelo
for ( int i = 0 ; i < NUM_OFFS && bOk ; ++ i)
bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ;
}
@@ -551,7 +554,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub
StmFromTriangleSoup stmCapSoup ;
if ( ! stmCapSoup.Start( nBuckets))
return nullptr ;
// verifico che le due estremità siano chiuse e piatte
// verifico che le due estremità siano chiuse e piatte
POLYLINEVECTOR vPL ;
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
return nullptr ;
@@ -650,34 +653,450 @@ GetSurfTriMeshRectSwept( double dDimH, double dDimV, double dBevelH, double dBev
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol)
GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol, Vector3d* vtStatic)
{
// verifica parametri
if ( pSect == nullptr || pGuide == nullptr)
return nullptr ;
// calcolo la polilinea che approssima la sezione
PolyLine PL ;
if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL))
return nullptr ;
// determino se la sezione è chiusa
// determino se la sezione è chiusa
bool bSectClosed = PL.IsClosed() ;
// determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ;
// definisco la superficie da restituire ( definendo la sua tolleranza )
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM))
return nullptr ;
pSTM->SetLinearTolerance( dLinTol) ;
// calcolo punto e versore tangente iniziale
Point3d ptStart ; pGuide->GetStartPoint( ptStart) ;
Vector3d vtStart ; pGuide->GetStartDir( vtStart) ;
// inizializzazione del frame iniziale ( viene definito a seconda dei casi )
Frame3d frStart ;
/* GUIDA PIANA */
// verifico che la linea guida sia piana
Plane3d plGuide ;
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL))
return nullptr ;
// determino se la guida è chiusa
bool bGuideClosed = pGuide->IsClosed() ;
// riferimento all'inizio della linea guida
Frame3d frStart ;
Point3d ptStart ;
pGuide->GetStartPoint( ptStart) ;
Vector3d vtStart ;
pGuide->GetStartDir( vtStart) ;
if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) {
/*
La guida non è piana, l'estrusione può essere definita mediante :
( 1) un versore statico
( 2) mediante l'algoritmo del Rotation Minimize Frame
*/
// recupero la sezione dalla PolyLine approssimata come Curva
PtrOwner<CurveComposite> pSecLocApprox( CreateBasicCurveComposite()) ;
if ( IsNull( pSecLocApprox) ||
! pSecLocApprox->FromPolyLine( PL) ||
! pSecLocApprox->IsValid())
return nullptr ;
// recupero il frame iniziale sulla guida ( Origine sul punto iniziale e asse Z tangente )
frStart.Set( ptStart, vtStart) ;
if ( ! frStart.IsValid())
return nullptr ;
// tengo in memoria il frame nel punto iniziale e finale della guida in caso di caps
Frame3d frCaps_start ;
Frame3d frCaps_end ;
if ( vtStatic != nullptr) { // (1) versore statico
// creo il piano di proiezione con normale definita dal vettore
Plane3d plProj ;
plProj.Set( ORIG, *vtStatic) ;
if ( ! plProj.IsValid())
return nullptr ;
// porto la sezione nel frame definito dalla guida, tenendo il versore X del frame nel piano
// definito da vtStatic
Vector3d vtX = vtStart ; // versore tangente alla curva
vtX.Rotate( *vtStatic, 90) ; // ruoto di 90 gradi rispetto a vtStatic
OrthoCompo( vtX, *vtStatic) ; // tengo la componente nel piano
vtX.Normalize() ; // normalizzo
Frame3d frInitial ; frInitial.Set( ptStart, vtStart, vtX) ; // creo il frame
if ( ! frInitial.IsValid())
return nullptr ;
// porto la sezione nel riferimento
pSecLocApprox->ToLoc( frInitial) ;
PL.ToLoc( frInitial) ; //... porto anche la PolyLine del bordo della sezione
// approssimo la guida mediante la tolleranza richiesta
PolyLine PL_G ;
if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PL_G))
return nullptr ;
// punto attuale e punto successivo sulla guida su cui definire il frame
Point3d ptCurr, ptSucc ;
if ( ! PL_G.GetFirstPoint( ptCurr))
return nullptr ;
bool bNextPoint = PL_G.GetNextPoint( ptSucc) ;
if ( ! bNextPoint)
return nullptr ;
// parametro attuale e successivo riferito ai punti sulla guida
double dParCurr = 0 ;
double dParSucc ;
// versore attuale e successivo riferito ai punti sulla guida
Vector3d vtTanCurr, vtTanSucc ;
if ( ! pGuide->GetStartDir( vtTanCurr))
return nullptr ;
// frame iniziale e successivo riferito alla curva
Frame3d frCurr, frSucc ;
bool bFirstIter = true ; // per salvare il frame iniziale nel caso di caps
while ( bNextPoint) { // finchè recupero un punto sucessivo...
// recupero il parametro successivo riferito alla guida
if ( ! pGuide->GetParamAtPoint( ptSucc, dParSucc))
return nullptr ;
// recupero il versore tangente riferito al punto successivo sulla guida
if ( ! pGuide->GetPointD1D2( dParSucc, ICurve::FROM_MINUS, ptSucc, &vtTanSucc) ||
! vtTanSucc.Normalize())
return nullptr ;
// creazione del frame nel punto corrente
Vector3d vtX_curr = vtTanCurr ;
vtX_curr.Rotate( *vtStatic, 90) ;
OrthoCompo( vtX_curr, *vtStatic) ;
vtX_curr.Normalize() ;
frCurr.Set( ptCurr, vtTanCurr, vtX_curr) ;
if ( ! frCurr.IsValid())
return nullptr ;
// memorizzo il primo frame di caso di caps
if ( bFirstIter) {
frCaps_start = frCurr ;
bFirstIter = false ;
}
// creazione del frame nel punto successivo
Vector3d vtX_succ = vtTanSucc ;
vtX_succ.Rotate( *vtStatic, 90) ;
OrthoCompo( vtX_curr, *vtStatic) ;
vtX_succ.Normalize() ;
frSucc.Set( ptSucc, vtTanSucc, vtX_succ) ;
if ( ! frSucc.IsValid())
return nullptr ;
frCaps_end = frSucc ; // aggiorno il frame finale ad ogni step
// definisco la sezione allo step corrente
PtrOwner<ICurve> pSecCurr( pSecLocApprox->Clone()) ;
if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
return nullptr ;
// considero la sezione ( in locale ) come vista dal globale
if ( ! pSecCurr->ToGlob( frCurr))
return nullptr ;
// definisco la sezione allo step successivo
PtrOwner<ICurve> pSecSucc( pSecLocApprox->Clone()) ;
if ( IsNull( pSecSucc) || ! pSecSucc->IsValid())
return nullptr ;
// considero la sezione ( in locale ) come vista dal globale
if ( ! pSecSucc->ToGlob( frSucc))
return nullptr ;
// creo la rigata tra queste due sezioni
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
if ( IsNull( pSr) || ! pSr->IsValid())
return nullptr ;
// attacco la rigata alla superficie da restituire
pSTM->DoSewing( *pSr) ;
// aggiornamento dei parametri
ptCurr = ptSucc ; // il punto corrente diventa il successivo
bNextPoint = PL_G.GetNextPoint( ptSucc) ; // il successivo lo recupero dalla PolyLine
vtTanCurr = vtTanSucc ; // il versore tangete corrente diventa il successivo
}
// la superficie definita dal RMF è invertita, il versore Z è diretto come la tangente della curva
pSTM->Invert() ;
}
else { // (2) Rotation Minimize Frame
// porto la PolyLine e la curva della sezione nel riferimento nel punto iniziale della guida
pSecLocApprox->ToLoc( frStart) ;
PL.ToLoc( frStart) ;
// calcolo il vettore di Frames campionati lungo la guida mediante la tolleranza definita
RotationMinimizeFrame RMF( pGuide, frStart) ;
FRAME3DVECTOR vRMF ;
if ( ! RMF.GetFramesByTollerance( vRMF, dLinTol) || vRMF.empty())
return nullptr ;
// per ogni RMF calcolato, la sezione va roto-traslata lungo la guida
for ( int i = 0 ; i < int( vRMF.size()) - 1 ; ++ i) {
// definisco la sezione allo step corrente
PtrOwner<ICurve> pSecCurr( pSecLocApprox->Clone()) ;
if ( IsNull( pSecCurr) || ! pSecCurr->IsValid())
return nullptr ;
// considero la sezione ( in locale ) come vista dal globale
if ( ! pSecCurr->ToGlob( vRMF[i]))
return nullptr ;
// definisco la sezione allo step successivo
PtrOwner<ICurve> pSecSucc( pSecLocApprox->Clone()) ;
if ( IsNull( pSecSucc) || ! pSecSucc->IsValid())
return nullptr ;
// considero la sezione ( in locale ) come vista dal globale
if ( ! pSecSucc->ToGlob( vRMF[i+1]))
return nullptr ;
// creo la rigata tra queste due sezioni
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pSecCurr, pSecSucc, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
if ( IsNull( pSr) || ! pSr->IsValid())
return nullptr ;
// attacco la rigata alla superficie da restituire
pSTM->DoSewing( *pSr) ;
}
// la superficie definita dal RMF è invertita, il versore Z è diretto come la tangente della curva
pSTM->Invert() ;
// assegno frame iniziale e finale per caps
frCaps_start = vRMF[0] ;
frCaps_end = vRMF.back() ;
}
// se richiesti caps e sezione chiusa e guida aperta
// (1) vtStatic, (2) Rotation Minimize Frame
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
// aggiungo il cap sull'inizio ( portandolo nel frame del punto iniziale della guida )
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
return nullptr ;
pSci->ToGlob( frCaps_start) ;
// unisco
pSTM->DoSewing( *pSci) ;
// aggiungo il cap sulla fine ( portandolo nel frame del punto finale della guida )
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
return nullptr ;
pSce->ToGlob( frCaps_end) ;
pSce->Invert() ; // il versore z è definito dalle tangenti alla curva
// unisco
pSTM->DoSewing( *pSce) ;
}
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
double dVol ;
if ( pSTM->GetVolume( dVol) && dVol < 0)
pSTM->Invert() ;
// restituisco la superficie
return Release( pSTM) ;
}
/*
GUIDA PIANA
La guida è piana, l'estrusione viene definita mediante Offset della guida sulla sezione
*/
// il frame iniziale è definito dal versore tangente e dalla normale al piano
// che contiene la guida
Vector3d vtNorm = plGuide.GetVersN() ;
frStart.Set( ptStart, -vtStart, vtStart ^ vtNorm) ;
// porto la sezione in questo riferimento e ve la appiattisco
if ( ! PL.ToLoc( frStart) || ! PL.Flatten())
return nullptr ;
// superficie swept
PtrOwner<ICurve> pPrevCrv ;
Point3d ptP ;
bool bPoint = PL.GetFirstPoint( ptP) ;
while ( bPoint) {
// nuova curva ( definita dall'Offset )
OffsetCurve OffsCrv ;
if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() == 0)
return nullptr ;
PtrOwner<ICurve> pCurrCrv( OffsCrv.GetLongerCurve()) ;
if ( IsNull( pCurrCrv))
return nullptr ;
pCurrCrv->Translate( ptP.y * frStart.VersY()) ;
// se esiste la curva precedente, costruisco la rigata ( di tipo minima distanza)
if ( ! IsNull( pPrevCrv)) {
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
if ( IsNull( pSr))
return nullptr ;
// unisco
pSTM->DoSewing( *pSr) ;
}
// salvo la curva come prossima precedente
pPrevCrv.Set( pCurrCrv) ;
// prossimo punto
bPoint = PL.GetNextPoint( ptP) ;
}
// se richiesti caps e sezione chiusa e guida aperta
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
// verifico che le due estremità siano chiuse e piatte
POLYLINEVECTOR vPL ;
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
return nullptr ;
Plane3d plEnds ; double dArea ;
if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
return nullptr ;
if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
return nullptr ;
// aggiungo il cap sull'inizio
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
return nullptr ;
pSci->ToGlob( frStart) ;
// unisco
pSTM->DoSewing( *pSci) ;
// riferimento alla fine della linea guida
Frame3d frEnd ;
Point3d ptEnd ;
pGuide->GetEndPoint( ptEnd) ;
Vector3d vtEnd ;
pGuide->GetEndDir( vtEnd) ;
frEnd.Set( ptEnd, -vtEnd, vtEnd ^ vtNorm) ;
// aggiungo il cap sulla fine
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
return nullptr ;
pSce->Invert() ;
pSce->ToGlob( frEnd) ;
// unisco
pSTM->DoSewing( *pSce) ;
}
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
double dVol ;
if ( pSTM->GetVolume( dVol) && dVol < 0)
pSTM->Invert() ;
// restituisco la superficie
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshSwept( const ISurfFlatRegion* pSfrSect, const ICurve* pGuide, bool bCapEnds,
double dLinTol, Vector3d* vtStatic)
{
// verifica dei parametri
if ( pSfrSect == nullptr || pGuide == nullptr)
return nullptr ;
// creo la Trimesh da restituire
PtrOwner<ISurfTriMesh> pStmSwept( CreateBasicSurfTriMesh()) ;
if ( IsNull( pStmSwept) || ! pStmSwept->AdjustTopology())
return nullptr ;
StmFromTriangleSoup StmSoup ;
StmSoup.Start() ;
// per ogni loop della superficie, creo una Swept
for ( int c = 0 ; c < pSfrSect->GetChunkCount() ; ++ c) {
for ( int l = 0 ; l < pSfrSect->GetLoopCount( c) ; ++ l) {
// recupero il loop
PtrOwner<ICurve> pCrvLoop( pSfrSect->GetLoop( c, l)) ;
if ( IsNull( pCrvLoop) || ! pCrvLoop->IsValid())
return nullptr ;
// creo la Trimesh Swept
PtrOwner<ISurfTriMesh> pStmLoopSwept( GetSurfTriMeshSwept( pCrvLoop, pGuide, false, dLinTol, vtStatic)) ;
if ( IsNull( pStmLoopSwept) || ! pStmLoopSwept->IsValid())
return nullptr ;
// aggiungo la Swept ricavata al risultato finale ( come triangoli )
StmSoup.AddSurfTriMesh( *pStmLoopSwept) ;
}
}
StmSoup.End() ;
if ( ! pStmSwept.Set( StmSoup.GetSurf()) || IsNull( pStmSwept) ||
! pStmSwept->IsValid() || ! pStmSwept->AdjustTopology())
return nullptr ;
// se rischista chiusura...
// NB. Controllo solo che al guida non sia chiusa, la sezione derivando da una Flatregion è chiusa per
// definizione
if ( bCapEnds && ! pGuide->IsClosed()) {
// creo il cap sull'inizio e lo attacco alla swept ( è già in posizione giusta )
PtrOwner<ISurfTriMesh> pSci( pSfrSect->GetAuxSurf()->Clone()) ;
if ( IsNull( pSci) || ! pSci->IsValid())
return nullptr ;
pStmSwept->DoSewing( *pSci) ;
// recupero i loops alla fine
POLYLINEVECTOR vPL ;
if ( ! pStmSwept->GetLoops( vPL))
return nullptr ;
// creo la superficie alla fine e la attacco
PtrOwner<ISurfTriMesh> pSce( CreateSurfTriMesh()) ;
if ( ! pSce->CreateByRegion( vPL))
return nullptr ;
// attacco la superficie finale alla swept
pSce->Invert() ;
pStmSwept->DoSewing( *pSce) ;
}
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
double dVol ;
if ( pStmSwept->GetVolume( dVol) && dVol < 0)
pStmSwept->Invert() ;
return Release( pStmSwept) ;
}
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshTransSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, double dLinTol)
{
// verifica parametri
if ( pSect == nullptr || pGuide == nullptr)
return nullptr ;
// determino se la sezione è chiusa
bool bSectClosed = pSect->IsClosed() ;
// punto iniziale della sezione e vettore a inizio guida
Point3d ptStart ;
if ( ! pSect->GetStartPoint( ptStart))
return nullptr ;
Point3d ptGuide ;
if ( ! pGuide->GetStartPoint( ptGuide))
return nullptr ;
Vector3d vtDelta = ptStart - ptGuide ;
// calcolo la polilinea che approssima la guida
PolyLine PLG ;
if ( ! pGuide->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLG))
return nullptr ;
// determino se la guida è chiusa
bool bGuideClosed = PLG.IsClosed() ;
// calcolo la superficie
PtrOwner<SurfTriMesh> pSTM( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSTM))
@@ -687,19 +1106,16 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
// superficie swept
PtrOwner<ICurve> pPrevCrv ;
Point3d ptP ;
bool bPoint = PL.GetFirstPoint( ptP) ;
bool bPoint = PLG.GetFirstPoint( ptP) ;
while ( bPoint) {
// nuova curva
OffsetCurve OffsCrv ;
if ( ! OffsCrv.Make( pGuide, ptP.x, ICurve::OFF_FILLET) || OffsCrv.GetCurveCount() == 0)
return nullptr ;
PtrOwner<ICurve> pCurrCrv( OffsCrv.GetLongerCurve()) ;
PtrOwner<ICurve> pCurrCrv( pSect->Clone()) ;
if ( IsNull( pCurrCrv))
return nullptr ;
pCurrCrv->Translate( ptP.y * frStart.VersY()) ;
pCurrCrv->Translate( ptP - ptStart + vtDelta) ;
// se esiste la curva precedente, costruisco la rigata (di tipo minima distanza)
if ( ! IsNull( pPrevCrv)) {
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_MINDIST, dLinTol)) ;
PtrOwner<ISurfTriMesh> pSr( GetSurfTriMeshRuled( pPrevCrv, pCurrCrv, ISurfTriMesh::RLT_ISOPAR, dLinTol)) ;
if ( IsNull( pSr))
return nullptr ;
pSTM->DoSewing( *pSr) ;
@@ -707,39 +1123,33 @@ GetSurfTriMeshSwept( const ICurve* pSect, const ICurve* pGuide, bool bCapEnds, d
// salvo la curva come prossima precedente
pPrevCrv.Set( pCurrCrv) ;
// prossimo punto
bPoint = PL.GetNextPoint( ptP) ;
bPoint = PLG.GetNextPoint( ptP) ;
}
// se richiesti caps e sezione chiusa e guida aperta
if ( bCapEnds && bSectClosed && ! bGuideClosed) {
// verifico che le due estremità siano chiuse e piatte
POLYLINEVECTOR vPL ;
if ( ! pSTM->GetLoops( vPL) || vPL.size() != 2)
// calcolo la polilinea che approssima la sezione
PolyLine PLS ;
if ( ! pSect->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, PLS))
return nullptr ;
Plane3d plEnds ; double dArea ;
if ( ! vPL[0].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
return nullptr ;
if ( ! vPL[1].IsClosedAndFlat( plEnds, dArea, 100 * EPS_SMALL))
return nullptr ;
// aggiungo il cap sull'inizio
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PL))
return nullptr ;
pSci->ToGlob( frStart) ;
pSTM->DoSewing( *pSci) ;
// riferimento alla fine della linea guida
Frame3d frEnd ;
Point3d ptEnd ;
pGuide->GetEndPoint( ptEnd) ;
Vector3d vtEnd ;
pGuide->GetEndDir( vtEnd) ;
frEnd.Set( ptEnd, -vtEnd, vtEnd ^ vtNorm) ;
// aggiungo il cap sulla fine
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PL))
return nullptr ;
pSce->Invert() ;
pSce->ToGlob( frEnd) ;
pSTM->DoSewing( *pSce) ;
// verifico che la sezione sia chiusa e piatta
Plane3d plSect ; double dArea ;
if ( PLS.IsClosedAndFlat( plSect, dArea, 100 * EPS_SMALL)) {
// aggiungo il cap sull'inizio
PtrOwner<SurfTriMesh> pSci( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSci) || ! pSci->CreateByFlatContour( PLS))
return nullptr ;
pSci->Invert() ;
Point3d ptGi ; PLG.GetFirstPoint( ptGi) ;
pSci->Translate( ptGi - ptStart + vtDelta) ;
pSTM->DoSewing( *pSci) ;
// aggiungo il cap sulla fine
PtrOwner<SurfTriMesh> pSce( CreateBasicSurfTriMesh()) ;
if ( IsNull( pSce) || ! pSce->CreateByFlatContour( PLS))
return nullptr ;
Point3d ptGe ; PLG.GetLastPoint( ptGe) ;
pSce->Translate( ptGe - ptStart + vtDelta) ;
pSTM->DoSewing( *pSce) ;
}
}
// se superficie risultante chiusa, verifico che la normale sia verso l'esterno
double dVol ;
@@ -800,56 +1210,132 @@ bool
CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
POLYLINEVECTOR& vPL, Vector3d& vtN)
{
// se non ho curve, non faccio nulla
if ( int( vpCurve.size()) == 0)
return true ;
// calcolo le polilinee che approssimano le curve
POLYLINEVECTOR vPLtmp ;
vPLtmp.resize( vpCurve.size()) ;
vPL.resize( vpCurve.size()) ;
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPLtmp[i]))
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
return false ;
}
// ne calcolo l'area e genero un ordine in senso decrescente
typedef pair<int,double> INDAREA ; // coppia indice, area
typedef vector<INDAREA> INDAREAVECTOR ; // vettore di coppie indice, area
INDAREAVECTOR vArea ;
vArea.reserve( vPLtmp.size()) ;
Vector3d vtN0 ;
for ( int i = 0 ; i < int( vPLtmp.size()) ; ++ i) {
// verifico chiusura, calcolo piano medio e area
// ricavo versore normale
Plane3d plPlane ; double dArea ;
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
vtN = plPlane.GetVersN() ;
typedef std::pair<int,double> INDAREA ;
std::vector<INDAREA> m_vArea ;
// calcolo piano medio e area delle curve
m_vArea.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// calcolo piano medio e area
Plane3d plPlane ;
double dArea ;
if ( ! vPLtmp[i].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
return false ;
// imposto la normale del primo contorno come riferimento
if ( i == 0)
vtN0 = plPlane.GetVersN() ;
// verifico che le normali siano molto vicine
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN0))
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
return false ;
// assegno il segno all'area secondo il verso della normale
if ( ( plPlane.GetVersN() * vtN0) > 0)
vArea.emplace_back( i, dArea) ;
if ( ( plPlane.GetVersN() * vtN) > 0)
m_vArea.emplace_back( i, dArea) ;
else
vArea.emplace_back( i, - dArea) ;
m_vArea.emplace_back( i, - dArea) ;
}
sort( vArea.begin(), vArea.end(),
// ordino in senso decrescente sull'area
sort( m_vArea.begin(), m_vArea.end(),
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
// sposto le polilinee nel vettore da restituire secondo l'ordine
vPL.clear() ;
vPL.resize( vPLtmp.size()) ;
bool bCCW = true ;
for ( int i = 0 ; i < int( vPLtmp.size()) ; ++ i) {
// scambio
swap( vPL[i], vPLtmp[vArea[i].first]) ;
// verifico senso di rotazione del contorno esterno
if ( i == 0)
bCCW = ( vArea[i].second > 0) ;
// aggiusto gli altri contorni
else {
if ( ( bCCW && vArea[i].second > 0) || ( ! bCCW && vArea[i].second < 0))
vPL[i].Invert() ;
}
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
if ( ! frRef.IsValid())
return false ;
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vCrvCompo[i].Set( CreateCurveComposite()) ;
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
vCrvCompo[i]->ToLoc( frRef) ;
}
// restituisco la normale positiva alla regione
vtN = ( bCCW ? vtN0 : - vtN0) ;
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
// successive i loop interni
INTMATRIX vnPLIndMat ;
// vettore di indici per ordinare le PolyLine
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
vPL_IndOrder[i] = m_vArea[i].first ;
// aggiungo le diverse curve
bool bFirstCrv ;
Plane3d plExtLoop ;
double dAreaExtLoop = 0. ;
do {
bFirstCrv = true ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
// recupero indice di percorso e verifico sia valido
int j = m_vArea[i].first ;
if ( j < 0)
continue ;
// lo inserisco come esterno...
if ( bFirstCrv) {
vnPLIndMat.push_back({ j}) ;
m_vArea[i].first = -1 ;
dAreaExtLoop = m_vArea[i].second ;
// inverto se necessario
if ( m_vArea[i].second < EPS_SMALL) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
dAreaExtLoop *= -1 ;
}
bFirstCrv = false ;
}
// ... altrimenti verifico se il loop è interno o no
else {
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
// esterno a tutti i loop già inseriti nella riga attuale.
// verifica rispetto loop esterno
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
bool bOk = true ;
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
}
}
if ( bOk) {
// inserisco nella matrice
vnPLIndMat.back().push_back( j) ;
m_vArea[i].first = -1 ;
// inverto se necessario
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
}
}
}
}
} while ( ! bFirstCrv) ;
// ordino le PolyLine per area
POLYLINEVECTOR vPL_tmp ;
for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i)
vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ;
swap( vPL, vPL_tmp) ;
return true ;
}
+24 -46
View File
@@ -16,6 +16,7 @@
#include "GeoConst.h"
#include "CurveComposite.h"
#include "SurfFlatRegion.h"
#include "AdjustLoops.h"
#include "Voronoi.h"
#include "/EgtDev/Include/EGkOffsetCurve.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
@@ -36,7 +37,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
if ( nChunk == 0)
return nullptr ;
// se offset nullo, la nuova regione è la copia di quella attuale
// se offset nullo, la nuova regione è la copia di quella attuale
if ( abs( dDist) < 10 * EPS_SMALL)
return this->Clone() ;
@@ -70,7 +71,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
while ( bOk && ! IsNull( pOffs)) {
if ( pOffs->GetType() == CRV_COMPO) {
CurveComposite* pOffsCompo = GetBasicCurveComposite( pOffs) ;
// assegno proprietà
// assegno proprietà
pOffsCompo->SetTempProp( j, 1) ;
for ( int k = 0 ; k < pOffsCompo->GetCurveCount() ; ++k)
pOffsCompo->SetCurveTempProp( k, j, 1) ;
@@ -80,7 +81,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
}
else
pOffs->SetTempProp( j, 1) ;
// se prima curva esterna, è il primo contorno esterno della nuova regione
// se prima curva esterna, è il primo contorno esterno della nuova regione
if ( j == 0 && bFirstCurve) {
if ( ! pSfrChk->AddExtLoop( Release( pOffs)))
return nullptr ;
@@ -137,7 +138,7 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
// -------------------- OFFSET CON VORONOI -------------------------------------
else {
// verifico se oggetto Voronoi della superficie è definito
// verifico se oggetto Voronoi della superficie è definito
if ( m_pVoronoiObj == nullptr)
CalcVoronoiObject() ;
@@ -146,51 +147,28 @@ SurfFlatRegion::CreateOffsetSurf( double dDist, int nType) const
if ( ! m_pVoronoiObj->CalcOffset( vOffs, dDist, nType))
return nullptr ;
// costruisco la superficie
if ( vOffs.size() > 0) {
BOOLVECTOR vbAddOrSub( vOffs.size(), true) ;
int nFirstId = -1 ;
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) {
// porto nel frame della flat region
PCRV_DEQUE vLoops ;
for ( int i = 0 ; i < int( vOffs.size()) ; i ++) {
vOffs[i]->ToLoc( m_frF) ;
// calcolo orientamento della curva
double dAreaXY ;
if ( ! vOffs[i]->GetAreaXY( dAreaXY))
return nullptr ;
vbAddOrSub[i] = ( dAreaXY > SQ_EPS_SMALL) ;
// verifico se è il primo loop esterno
if ( nFirstId == -1 && vbAddOrSub[i])
nFirstId = i ;
}
// inizializzo la superficie
if ( nFirstId != -1 && ! pSfr->AddExtLoop( Release( vOffs[nFirstId])))
return nullptr ;
if ( pSfr->IsValid()) {
for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) {
// verifico non sia il primo loop esterno
if ( i == nFirstId)
continue ;
// costruisco la superficie associata
PtrOwner<SurfFlatRegion> pSrfCrv( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSrfCrv) || ! pSrfCrv->AddExtLoop( Release( vOffs[i])))
return nullptr ;
if ( ! pSrfCrv->IsValid())
continue ;
// aggiungo o sottraggo
if ( vbAddOrSub[i]) {
if ( ! pSfr->Add( *pSrfCrv))
return nullptr ;
}
else {
pSrfCrv->Invert() ;
if ( ! pSfr->Subtract( *pSrfCrv))
return nullptr ;
}
// rimuovo eventuali sovrapposizioni
ICURVEPLIST CrvLst ;
AdjustLoops( Release( vOffs[i]), CrvLst, true) ;
for ( auto pCrv : CrvLst) {
pCrv->SetExtrusion( Z_AX) ;
vLoops.emplace_back( pCrv) ;
}
}
// verifico di avere ancora dei loops
if ( vLoops.size() > 0) {
pSfr.Set( MyNewSurfFromLoops( vLoops)) ;
if ( IsNull( pSfr)) {
MyTestAndDelete( vLoops) ;
return nullptr ;
}
}
}
}
@@ -207,7 +185,7 @@ SurfFlatRegion::Offset( double dDist, int nType)
if ( nChunk == 0)
return false ;
// se offset nullo, non devo fare alcunchè
// se offset nullo, non devo fare alcunchè
if ( abs( dDist) < 10 * EPS_SMALL)
return true ;
+2 -2
View File
@@ -31,7 +31,7 @@
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <new>
#include <set>
#include <set>
using namespace std ;
@@ -1960,7 +1960,7 @@ SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL)
PNTVECTOR vPnt ;
INTVECTOR vTria ;
Triangulate Tri ;
if ( ! Tri.Make( vPL, vPnt, vTria))
if ( ! Tri.MakeAdvanced( vPL, vPnt, vTria))
return false ;
// inizializzo la superficie
+192 -126
View File
@@ -52,9 +52,10 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
if ( vnDegVec[nC] > 0)
++ nExistNotDeg ;
}
// Divido il loop di partenza in sotto-loop
int nIterationCount = 0 ;
while ( cvOpenChain.size() > 0) {
while ( cvOpenChain.size() > 0) { // per ogni catena aperta...
bool bLoopSplitted = false ;
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
if ( vnDegVec[nLastOpenLoopN] == 1) {
@@ -63,13 +64,24 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
int nLastOpenLoopPoint = max( int( cvOpenChain[nLastOpenLoopN].size()) - 1, 0) ;
Point3d ptOpenLoopStP = cvOpenChain[nLastOpenLoopN][0].ptSt ;
Point3d ptOpenLoopEnP = cvOpenChain[nLastOpenLoopN][nLastOpenLoopPoint].ptEn ;
// costruisco il primo e il secondo loop che si generano
// NB. il loop esterno è chiuso, mentre la catena aperta
// è la successione dei tratti lineari dovuti ai triangoli dell'altra superficie
PNTVECTOR Loop1, Loop2 ;
// cambio il punto iniziale del loop di bordo se non coincide già con ptStart della catena aperta
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
// splitto
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
if ( ! ( bChangedStart && bSplitted) ||
( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2)))
continue ;
continue ; // la catena aperta non è interna al loop chiuso attuale
// il loop 1 segue sempre la direzione della catena, il loop 2 ha dentro la catena invertita
// Ho sempre che il loop 1 è sempre interno ( la direzione della catena è determinata
// dalla normale dei triangoli che la formano; avendo chimatao la chian senza ammettere inversioni, sono
// curve tutte concordi ) e il loop 2 che è esterno
bLoopSplitted = true ;
// ricostrusico i due loop mediante concatenazione
Chain cvCounterChain ;
for ( int nPt = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nPt >= 0 ; -- nPt) {
IntSegment CurSeg ;
@@ -181,7 +193,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
// elimino i punti superflui prima
for ( int i = 0 ; i < nCvFirst ; ++ i)
cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin()) ;
// verifico se questo punto dalla parte valida o no
// verifico se questo punto è dalla parte valida o no
bool bC12 = ( ( ptM12 - ptProva) * vtVecProva < 0) ;
vbInOut[nLoop] = bC12 ;
}
@@ -192,7 +204,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
// elimino i punti superflui intermedi
for ( int i = nCvFirst + 2 ; i < nCvSecond ; ++ i)
cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin() + nCvFirst + 2) ;
// verifico se questo punto dalla parte valida o no
// verifico se questo punto è dalla parte valida o no
bool bC21 = ( ( ptM21 - ptProva) * vtVecProva < 0) ;
vbInOut[nLoop] = bC21 ;
}
@@ -234,9 +246,13 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// La superficie deve essere valida
if ( ! Surf.IsValid())
return false ;
// Ritriangolarizzo i triangoli
// itero sulla unorderd_map
for ( auto it = LoopLines.begin() ; it != LoopLines.end() ; ++ it) {
// itero sulle catene ( secondo parametro della mappa)
for ( int nS1 = 0 ; nS1 < int( it->second.size()) - 1 ; ++ nS1) {
// tolgo i tratti degeneri ad un punto
for ( int nS2 = nS1 + 1 ; nS2 < int( it->second.size()) ; ++ nS2) {
if ( AreSamePointApprox( it->second[nS1].ptSt, it->second[nS2].ptEn) &&
AreSamePointApprox( it->second[nS1].ptEn, it->second[nS2].ptSt) &&
@@ -248,22 +264,21 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
}
// se non resta nulla, allora passo alla mappa successiva
if ( int( it->second.size()) == 0)
continue ;
// Se il triangolo è stato sottoposto a ritriangolazione, le sue componenti sono classificabili come dentro-fuori.
// Lo tolgo dall'insieme dei triangoli ambigui (intersezione edge-edge)
else {
auto itS = Ambiguos.find( it->first) ;
if ( itS != Ambiguos.end()) {
Ambiguos.erase( itS) ;
}
}
auto itS = Ambiguos.find( it->first) ;
if ( itS != Ambiguos.end())
Ambiguos.erase( itS) ;
// Creo i loop
// CREAZIONE DEI LOOP ---------------------------------------------
// Chain
ChainCurves LoopCreator ;
LoopCreator.Init( false, 2 * EPS_SMALL, int( it->second.size()), 10 * BOOLEAN_SCALE) ;
// Carico le curve per concatenarle
// Recupero le curve ( gli estremi dei tratti lineari) per concatenarle
for ( int nCv = 0 ; nCv < int( it->second.size()); ++ nCv) {
Point3d ptSt = it->second[nCv].ptSt ;
Point3d ptEn = it->second[nCv].ptEn ;
@@ -277,15 +292,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
CHAINVECTOR vChain ;
while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) {
Chain chTemp ;
for ( auto i : vIds) {
// Aggiungo la linea alla curva composta.
for ( auto i : vIds) // Aggiungo la linea alla curva composta
chTemp.emplace_back( it->second[i - 1]) ;
}
vChain.emplace_back( chTemp) ;
}
// Lavoro su loop e catene per regolarizzarle
int nChainCnt = int( vChain.size()) ;
// unisco eventuali catene estreme che sono parte di una stessa catena
// Unisco eventuali catene estreme che sono parte di una stessa catena
if ( nChainCnt > 1) {
if ( AreSamePointApprox( vChain[0].front().ptSt, vChain[nChainCnt - 1].back().ptEn)) {
vChain[0].insert( vChain[0].begin(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ;
@@ -298,7 +312,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
-- nChainCnt ;
}
}
// semplifico catene formate da punti degeneri
// Semplifico catene formate da punti degeneri
for ( int nCh = 0 ; nCh < nChainCnt ; ++ nCh) {
if ( vChain[nCh].size() == 2 && ( vChain[nCh][0].bDegenerate || vChain[nCh][1].bDegenerate)) {
vChain[nCh][0].ptEn = vChain[nCh][1].ptEn ;
@@ -377,6 +391,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
}
// Chiudo i loop costruiti a partire dalle catene
for ( int nC = 0 ; nC < nChainCnt ; ++ nC) {
int nChainLastSegPos = int( vChain[nC].size()) - 1 ;
@@ -463,7 +478,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[2] = 0 ;
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
bModif = true ;
}
int nNewCoupleId1[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 1) % 3)), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)) } ;
@@ -472,7 +487,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[2] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
bModif = true ;
}
int nNewCoupleId2[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)), Surf.AddVertex( ptIntEn) } ;
@@ -481,27 +496,32 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[2] = 0 ;
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
bModif = true ;
}
continue ;
}
}
}
// -------------------------------------------------------------------------------------------
// Creo il loop chiuso padre di tutti, il perimetro del triangolo.
// Questo viene diviso in sotto-loop chiusi mediante quelli aperti.
// I loop chiusi trovati precedentemente sono interni a uno dei sotto-loop
// chiusi di cui è formato il perimetro.
// Creo il loop chiuso padre di tutti, il perimetro del triangolo. Questo viene diviso in sotto-loop
// chiusi mediante quelli aperti. I loop chiusi trovati precedentemente sono interni a uno dei
// sotto-loop chiusi di cui è formato il perimetro.
PNTVECTOR cvFirstLoop ;
cvFirstLoop.emplace_back( trTria.GetP( 0)) ;
cvFirstLoop.emplace_back( trTria.GetP( 1)) ;
cvFirstLoop.emplace_back( trTria.GetP( 2)) ;
PNTMATRIX cvBoundClosedLoopVec;
// creo una matrice di punti ; ogni riga corrisponde ad una sequenza di punti che indentificano un loop
PNTMATRIX cvBoundClosedLoopVec ;
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
// vettore per indicare se il loop è interno/esterno all'altra superficie
BOOLVECTOR vbInOut ;
vbInOut.push_back( true) ;
// Divido il loop usando le catene
if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) {
if ( cvBoundClosedLoopVec.size() == 1 && cvOpenChain.size() == 2) {
@@ -556,7 +576,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[it->first].nTempPart = 0 ;
continue ;
}
}
}
// Rimuovo il triangolo corrente
int nOldTriaCol = Surf.m_vTria[it->first].nTFlag ;
Surf.RemoveTriangle( it->first) ;
@@ -564,14 +584,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
POLYLINEVECTOR vplPolyVec ;
vplPolyVec.resize( cvBoundClosedLoopVec.size()) ;
for ( int nLoop = 0 ; nLoop < int( vplPolyVec.size()) ; ++ nLoop) {
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine) {
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine)
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ;
}
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][0]) ;
// Assegno ai loop trovati i rispettivi interni
// Assumo che i loop interni a uno dei loop creati fino ad'ora siano tutti sullo stesso livello.
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
// loop è figlio del nodo corrispondente al loop che lo contiene.
INTVECTOR vInnerLoop ;
for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) {
@@ -692,7 +712,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
break ;
}
}
if ( vInnerLoop.size() == 0 || bDouble) {
// Eseguo triangolazione
PNTVECTOR vPt ;
@@ -710,7 +730,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( vbInOut[nLoop])
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
else
Surf.m_vTria[nNewTriaNum].nTempPart = - 1 ;
bModif = true ;
@@ -719,33 +739,32 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
else {
// se ho più loop, essi descrivono un poligono di n-lati
POLYLINEVECTOR vPolygons ;
vPolygons.emplace_back( vplPolyVec[nLoop]) ;
for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) {
// per ognuno di essi, ricavo la PolyLine dai punti
PolyLine CurLoop ;
for ( int nV = 0 ; nV < int( cvClosedChain[vInnerLoop[nL]].size()) ; ++ nV) {
for ( int nV = 0 ; nV < int( cvClosedChain[vInnerLoop[nL]].size()) ; ++ nV)
CurLoop.AddUPoint( 0., cvClosedChain[vInnerLoop[nL]][nV].ptSt) ;
}
CurLoop.AddUPoint( 0., cvClosedChain[vInnerLoop[nL]][0].ptSt) ;
vPolygons.emplace_back( CurLoop) ;
}
// poligono
Polygon3d pgPol ;
pgPol.FromPolyLine(vPolygons[1]) ;
pgPol.FromPolyLine( vPolygons[1]) ;
// controllo direzioni delle normali
bool bCodirectedNormals = trTria.GetN() * pgPol.GetVersN() > 0. ;
if ( bCodirectedNormals) {
for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) {
vPolygons[nL].Invert() ;
}
}
// Aggiungo al loop esterno i punti dei loop interni che si trovano su di esso
PNTULIST& ExternLoopList = vPolygons[0].GetUPointList() ;
// Ciclo sui segmenti del loop esterno
auto itSt = ExternLoopList.begin() ;
auto itEn = itSt ;
++ itEn ;
++ itEn ;
for ( ; itSt != ExternLoopList.end() && itEn != ExternLoopList.end() ; ++ itSt, ++ itEn) {
// Estremi del segmento corrente del loop esterno e scorrispondente vettore
Point3d ptSt = itSt->first ;
@@ -761,7 +780,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
Point3d ptInnPoint ;
bool bIsFirst = true ;
bool bContinue = vPolygons[nInnPoly].GetFirstPoint( ptInnPoint) ;
while ( bContinue) {
while ( bContinue) {
DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ;
double dDist ;
DistCalculator.GetDist( dDist) ;
@@ -788,13 +807,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// Aggiungo i punti al loop esterno
for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) ; ++ nPi) {
itSt = ExternLoopList.emplace( itEn, vPointWithOrder[nPi]) ;
}
}
}
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( vPolygons, vPt, vTr)) {
// Inserisco i nuovi triangoli
// classifico i loop e ricavo la triangolazione di essi mediante classificazione
if ( Triangulate().MakeAdvanced( vPolygons, vPt, vTr)) {
// Inserisco i nuovi triangoli
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ;
int nNewId[3] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
@@ -817,7 +837,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
// Divido i loop che si autointercettano
int nInitialLoopNum = int( vPolygons.size()) ;
for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) {
// Lista dei punti della PolyLine Loop corrente
// Lista dei punti della PolyLine Loop corrente
PNTULIST& LoopPointList = vPolygons[nL].GetUPointList() ;
// Ciclo sui segmenti
auto itSt2 = LoopPointList.begin() ;
@@ -928,26 +948,24 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
}
}
}
for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) {
vPolygons[nL].Invert() ;
if ( Triangulate().Make( vPolygons[nL], vPt, vTr)) {
// Inserisco i nuovi triangoli
for (int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ;
int nNewId[3] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
Surf.AddVertex( vPt[nNewTriaVertId[1]]),
Surf.AddVertex( vPt[nNewTriaVertId[2]])} ;
int nNewTriaNum = Surf.AddTriangle( nNewId, nOldTriaCol) ;
if ( IsValidSvt( nNewTriaNum)) {
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( bCodirectedNormals)
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
else
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
bModif = true ;
}
vPolygons.erase( vPolygons.begin()) ;
if ( Triangulate().MakeAdvanced( vPolygons, vPt, vTr)) {
// Inserisco i nuovi triangoli
for (int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ;
int nNewId[3] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
Surf.AddVertex( vPt[nNewTriaVertId[1]]),
Surf.AddVertex( vPt[nNewTriaVertId[2]])} ;
int nNewTriaNum = Surf.AddTriangle( nNewId, nOldTriaCol) ;
if ( IsValidSvt( nNewTriaNum)) {
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
if ( bCodirectedNormals)
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
else
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
bModif = true ;
}
}
}
@@ -1088,18 +1106,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
{
bool bModif = false ;
SurfTriMesh& SurfB = Other ;
// Le superfici devono essere valide
if ( m_nStatus != OK || ! SurfB.IsValid())
return false ;
// Unordered map dei segmenti di intersezione
CHAINMAP LineMapA ;
CHAINMAP LineMapB ;
// Unordered map dei triangoli ambigui (intersezione edge-edge)
TRIA3DVECTORMAP AmbiguosA ;
TRIA3DVECTORMAP AmbiguosB ;
// Ciclo sui triangoli delle mesh
int nTriaNumA = GetTriangleSize() ;
int nTriaNumB = SurfB.GetTriangleSize() ;
// Setto il triangolo come né fuori né dentro
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
m_vTria[nTA].nTempPart = 0 ;
@@ -1113,55 +1136,58 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
SurfB.m_vTria[nTB].nETempFlag[1] = 0 ;
SurfB.m_vTria[nTB].nETempFlag[2] = 0 ;
}
// Resetto e ricalcolo la HashGrid della superficie B
SurfB.ResetHashGrids3d() ;
// Scorro i triangoli della superficie A
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
// Se il triangolo A non è valido, continuo
Triangle3d trTriaA ;
if ( ! GetTriangle( nTA, trTriaA) || ! trTriaA.Validate( true))
continue ;
// Box del triangolo A
BBox3d b3dTriaA ;
trTriaA.GetLocalBBox( b3dTriaA) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ;
SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
// I scorro tutti i triangoli di B che intersecano il box di A
for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) {
// Se il triangolo B non è valido, continuo
Triangle3d trTriaB ;
if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true))
continue ;
// Interseco i triangoli
Point3d ptSegSt, ptSegEn ;
TRIA3DVECTOR vTria ;
int nIntType = IntersTriaTria( trTriaA, trTriaB, ptSegSt, ptSegEn, vTria) ;
if ( nIntType == ITTT_EDGE_EDGE_SEG ||
nIntType == ITTT_EDGE_INT ||
nIntType == ITTT_INT_EDGE ||
nIntType == ITTT_INT_INT_SEG) {
// Assegno i dati di intersezione
// se l'intersezione è identificabile con un segmento...
if ( nIntType == ITTT_EDGE_EDGE_SEG || nIntType == ITTT_EDGE_INT ||
nIntType == ITTT_INT_EDGE || nIntType == ITTT_INT_INT_SEG) {
// Assegno i dati di intersezione per la superficie A
IntSegment CurInters ;
if ( nIntType == ITTT_EDGE_EDGE_SEG || nIntType == ITTT_EDGE_INT ||
nIntType == ITTT_INT_EDGE || nIntType == ITTT_INT_INT_SEG) {
CurInters.ptSt = ptSegSt ;
CurInters.ptEn = ptSegEn ;
CurInters.bDegenerate = false ;
}
else {
CurInters.ptSt = ptSegSt ;
CurInters.ptEn = ptSegSt ;
CurInters.bDegenerate = true ;
}
CurInters.vtOuter = trTriaB.GetN() ;
CurInters.ptSt = ptSegSt ; // punto iniziale del segmento
CurInters.ptEn = ptSegEn ; // punto finale del segmento
CurInters.bDegenerate = false ; // segmento non degenere
CurInters.vtOuter = trTriaB.GetN() ; // perpendicolare alla tangente ( oritentata )
CurInters.vtOuter -= ( ( CurInters.vtOuter * trTriaA.GetN()) * trTriaA.GetN()) ;
CurInters.vtOuter.Normalize() ;
// Salvo intersezione per superficie A
bool bIntOnEndgeA = false ;
if ( nIntType != ITTT_EDGE_EDGE_SEG && nIntType != ITTT_EDGE_INT) {
// controllo se tale segmento non è già contenuto
auto itA = LineMapA.find( nTA) ;
if ( itA != LineMapA.end()) {
if ( itA != LineMapA.end())
itA->second.emplace_back( CurInters) ;
}
else {
Chain chTemp ;
chTemp.emplace_back( CurInters) ;
@@ -1171,6 +1197,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
else
bIntOnEndgeA = true ;
// Inverto i dati del segmento per intersezione con superficie B
swap( CurInters.ptSt, CurInters.ptEn) ;
CurInters.vtOuter = trTriaA.GetN() ;
CurInters.vtOuter -= ( ( CurInters.vtOuter * trTriaB.GetN()) * trTriaB.GetN()) ;
@@ -1179,10 +1206,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
// Salvo intersezione per superficie B
bool bIntOnEndgeB = false ;
if ( nIntType != ITTT_EDGE_EDGE_SEG && nIntType != ITTT_INT_EDGE) {
// controllo se tale segmento non è già contenuto
auto itB = LineMapB.find( vNearTria[nTB]) ;
if ( itB != LineMapB.end()) {
if ( itB != LineMapB.end())
itB->second.emplace_back( CurInters) ;
}
else {
Chain chTemp ;
chTemp.emplace_back( CurInters) ;
@@ -1191,8 +1218,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
else
bIntOnEndgeB = true ;
// Intersezione edge-interno
// caso di Intersezione edge-interno ( per superificie A con B)
if ( bIntOnEndgeA && ! bIntOnEndgeB) {
// calcolo la massima distanza e il tratto ad essa associato
double dMaxDist = 0. ;
int nSegMaxDist = - 1 ;
for ( int nVA = 0 ; nVA < 3 ; ++ nVA) {
@@ -1203,7 +1232,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
if ( nSegMaxDist >= 0) {
// Cerco qual'è il segmento di contatto per dichiararlo come invalicabile
// Cerco qual è il segmento di contatto per dichiararlo come invalicabile
int nVA ;
for ( nVA = 0 ; nVA < 3 ; ++ nVA) {
if ( abs( ( trTriaA.GetP( nVA) - trTriaB.GetP( 0)) * trTriaB.GetN()) < EPS_SMALL &&
@@ -1215,8 +1244,9 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
m_vTria[nTA].nETempFlag[nVA] = m_vTria[nTA].nTempPart ;
}
}
// Intersezione interno-edge
// caso di Intersezione interno-edge ( per superficie A con B)
else if ( ! bIntOnEndgeA && bIntOnEndgeB) {
// calcolo la massima distanza e il tratto ad essa associato
double dMaxDist = 0. ;
int nSegMaxDist = - 1 ;
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
@@ -1227,7 +1257,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
if ( nSegMaxDist >= 0) {
// Cerco qual'è il segmento di contatto per dichiararlo come invalicabile
// Cerco qual è il segmento di contatto per dichiararlo come invalicabile
int nVB ;
for ( nVB = 0 ; nVB < 3 ; ++ nVB) {
if ( abs( ( trTriaB.GetP( nVB) - trTriaA.GetP(0)) * trTriaA.GetN()) < EPS_SMALL &&
@@ -1266,11 +1296,11 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
}
}
// Ritriangolarizzo i triangoli delle superfici
RetriangulationForBooleanOperation( LineMapA, AmbiguosA, *this, bModif) ;
RetriangulationForBooleanOperation( LineMapB, AmbiguosB, SurfB, bModif) ;
// Se i triangoli delle superfici non si intersecano, una delle due è totalmente interna o esterna all'altra.
// non mi basta fare un controllo sulle bbox perché non so come sono orientate le superfici e che potrebbero anche non essere chiuse
bool bRetriangulated = true ;
@@ -1309,7 +1339,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = 1 ;
else if (nInOutNum == -1) {
else if ( nInOutNum == -1) {
bSame = false ;
break ;
}
@@ -1317,7 +1347,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = -1 ;
else if (nInOutNum == 1) {
else if ( nInOutNum == 1) {
bSame = false ;
break ;
}
@@ -1325,23 +1355,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
// se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino
// e ricalcolo l'informazione che mi dà la sua normale
if ( ! bSame ) {
if ( ! bSame) {
Point3d ptBar_tot ;
for (int nTriaNum : vnTriaNum) {
SurfB.GetTriangle( nTriaNum, trTriaB) ;
ptBar_tot += trTriaB.GetCentroid();
}
ptBar_tot /= (int)vnTriaNum.size() ;
for (int nTriaNum : vnTriaNum) {
ptBar_tot /= int( vnTriaNum.size()) ;
for ( int nTriaNum : vnTriaNum) {
SurfB.GetTriangle( nTriaNum, trTriaB) ;
Point3d ptInters1, ptInters2 ;
int nInters = IntersLineTria(ptFirstV, ptBar_tot, trTriaB, ptInters1, ptInters2, true) ;
if (nInters == ILTT_NO)
int nInters = IntersLineTria( ptFirstV, ptBar_tot, trTriaB, ptInters1, ptInters2, true) ;
if ( nInters == ILTT_NO)
continue ;
else if ( nInters == ILTT_IN ) {
if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL)
else if ( nInters == ILTT_IN) {
if ( ( ptFirstV - trTriaB.GetP( 0)) * trTriaB.GetN() < - EPS_SMALL)
nInOutNum = 1 ;
else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL)
else if ( ( ptFirstV - trTriaB.GetP( 0)) * trTriaB.GetN() > EPS_SMALL)
nInOutNum = -1 ;
break ;
}
@@ -1355,9 +1385,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
++ nVertNum ;
}
}
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA)
m_vTria[nTA].nTempPart = nInOutNum ;
}
nVertNum = 0 ;
nCurVert = SurfB.GetFirstVertex( ptFirstV) ;
nInOutNum = 0 ;
@@ -1374,7 +1405,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
DistCalculator.GetDist( dDist) ;
// potrei trovare più triangolo equidistanti, li salvo tutti
if ( DistPointTriangle( ptFirstV, trTriaA).GetDist( dDist)) {
if ( abs(dDist - dMinDist) < EPS_SMALL)
if ( abs( dDist - dMinDist) < EPS_SMALL)
vnTriaNum.push_back( nTA) ;
else if ( dDist < dMinDist){
vnTriaNum.clear() ;
@@ -1392,7 +1423,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() < - EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = 1 ;
else if (nInOutNum == -1) {
else if ( nInOutNum == -1) {
bSame = false ;
break ;
}
@@ -1400,7 +1431,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL) {
if ( nInOutNum == 0)
nInOutNum = -1 ;
else if (nInOutNum == 1) {
else if ( nInOutNum == 1) {
bSame = false ;
break ;
}
@@ -1408,23 +1439,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
// se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino
// e ricalcolo l'informazione che mi dà la sua normale
if ( ! bSame ) {
if ( ! bSame) {
Point3d ptBar_tot ;
for (int nTriaNum : vnTriaNum) {
for ( int nTriaNum : vnTriaNum) {
GetTriangle( nTriaNum, trTriaA) ;
ptBar_tot += trTriaA.GetCentroid();
}
ptBar_tot /= (int)vnTriaNum.size() ;
for (int nTriaNum : vnTriaNum) {
ptBar_tot /= int( vnTriaNum.size()) ;
for ( int nTriaNum : vnTriaNum) {
GetTriangle( nTriaNum, trTriaA) ;
Point3d ptInters1, ptInters2 ;
int nInters = IntersLineTria(ptFirstV, ptBar_tot, trTriaA, ptInters1, ptInters2, true) ;
if (nInters == ILTT_NO)
int nInters = IntersLineTria( ptFirstV, ptBar_tot, trTriaA, ptInters1, ptInters2, true) ;
if ( nInters == ILTT_NO)
continue ;
else if ( nInters == ILTT_IN ) {
if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() < - EPS_SMALL)
else if ( nInters == ILTT_IN) {
if ( ( ptFirstV - trTriaA.GetP( 0)) * trTriaA.GetN() < - EPS_SMALL)
nInOutNum = 1 ;
else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL)
else if ( ( ptFirstV - trTriaA.GetP( 0)) * trTriaA.GetN() > EPS_SMALL)
nInOutNum = -1 ;
break ;
}
@@ -1438,9 +1469,8 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
++ nVertNum ;
}
}
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB)
SurfB.m_vTria[nTB].nTempPart = nInOutNum ;
}
}
// Se c'è stata una ritriangolazione di almeno un triangolo, NON siamo nel caso di tutto dentro o tutto fuori.
@@ -1449,11 +1479,12 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
AmbiguosTriangleManager( AmbiguosA, *this) ;
AmbiguosTriangleManager( AmbiguosB, SurfB) ;
}
bool bContinue = true ;
// Se avvenuta modifica, aggiorno tutto
if ( bModif)
bContinue = ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ;
// Triangoli sovrapposti
if ( bContinue) {
int nTriaNum2A = GetTriangleSize() ;
@@ -1491,7 +1522,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
}
return true ;
}
return true ;
}
@@ -1620,48 +1651,83 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
return true ;
}
// Surf A è la superficie attuale ( this), SurfB è l'altra
SurfTriMesh SurfB ;
SurfB.CopyFrom( &Other) ;
// scalo la superficie
Frame3d frScalingRef ;
frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ;
Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
// ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo
IntersectTriMeshTriangle( SurfB) ;
// assegno un medesimo indice ai triangoli che non interferiscono con altri
IdentifyParts() ;
SurfB.IdentifyParts() ;
// rimozione dei triangoli di A con proprietà -1 e -2
int nTriaNumA = GetTriangleSize() ;
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
if ( m_vTria[nTA].nTempPart == - 1 || m_vTria[nTA].nTempPart == - 2)
RemoveTriangle( nTA) ;
}
// aggiunta dei triangoli di B con proprietà +1
int nPrevMaxTFlag = m_nMaxTFlag ;
int nTriaNumB = SurfB.GetTriangleSize() ;
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
if ( SurfB.m_vTria[nTB].nTempPart == 1) {
int nNewVert[3] ;
for ( int nV = 0 ; nV < 3 ; ++ nV) {
for ( int nV = 0 ; nV < 3 ; ++ nV)
nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ;
}
if ( nPrevMaxTFlag == m_nMaxTFlag)
++ m_nMaxTFlag ;
AddTriangle( nNewVert, m_nMaxTFlag) ;
}
}
// sistemazioni varie
bool bOk = ( AdjustVertices() && DoCompacting()) ;
bool bModified = false ;
bOk = bOk && RemoveDoubleTriangles( bModified) ;
if ( bModified)
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
bOk = bOk && RemoveTJunctions( bModified) ;
if ( bModified)
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
// rimuovo tutte le parti esterne all'intersezione
int nParts = GetPartCount() ;
if ( nParts > 1) {
for ( int i = 0 ; i < nParts ; ++ i) {
// recupero i triangoli della stessa Part
INTVECTOR vTriaPart ;
for ( int j = 0 ; j < int( m_vTria.size()) ; ++ j)
if ( m_vTria[j].nPart == i)
vTriaPart.push_back( j) ;
// controllo se il loro box interferisce con il box della superficie B
bool bErasePart = true ;
for ( int j = 0 ; j < int( vTriaPart.size()) && bErasePart ; ++ j) {
// Se il triangolo A non è valido, continuo
Triangle3d Tria ;
if ( ! GetTriangle( j, Tria) || ! Tria.Validate( true))
continue ;
// Box del triangolo A
BBox3d b3dTriaA ; Tria.GetLocalBBox( b3dTriaA) ;
// Recupero i triangoli di B che interferiscono col box del triangolo di A
INTVECTOR vNearTria ; SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
bErasePart = int( vNearTria.size() == 0) ;
}
if ( bErasePart)
RemovePart( i) ;
}
}
// scalo alle dimensioni originali
Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ;
if ( ! SimplifyFacets())
+1 -1
View File
@@ -531,7 +531,7 @@ SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
if ( AreSamePointApprox( OrigChain[nLastOrig], ChainToAdd[0].ptSt)) {
for ( int nPt = 1 ; nPt <= nLastToAdd ; ++ nPt) {
if ( nPt == nLastToAdd) {
if ( ! AreSamePointApprox(OrigChain[0], ChainToAdd[nPt].ptSt))
if ( ! AreSamePointApprox( OrigChain[0], ChainToAdd[nPt].ptSt))
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
}
else if ( nPt == 1) {
+138
View File
@@ -21,6 +21,8 @@
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "CurveComposite.h"
#include "IntersCrvCompoCrvCompo.h"
#include <algorithm>
using namespace std ;
@@ -218,6 +220,142 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
return true ;
}
//---------------------------------------------------------------------------
bool
Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVECTOR& vTr)
{
vPt.clear() ;
vTr.clear() ;
// se non ho PolyLine, allora non faccio nulla
if ( int( vPLORIG.size()) == 0)
return true ;
// copio il vettore di PolyLine
POLYLINEVECTOR vPL ;
for ( int i = 0 ; i < int( vPLORIG.size()) ; ++ i)
vPL.push_back( vPLORIG[i]) ;
typedef std::pair<int,double> INDAREA ;
std::vector<INDAREA> m_vArea ;
// calcolo piano medio e area delle curve
m_vArea.reserve( vPL.size()) ;
Vector3d vtN0 ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// calcolo piano medio e area
Plane3d plPlane ;
double dArea ;
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
return false ;
// imposto la normale del primo contorno come riferimento
if ( i == 0)
vtN0 = plPlane.GetVersN() ;
// verifico che le normali siano molto vicine
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN0))
return false ;
// assegno il segno all'area secondo il verso della normale
if ( ( plPlane.GetVersN() * vtN0) > 0)
m_vArea.emplace_back( i, dArea) ;
else
m_vArea.emplace_back( i, - dArea) ;
}
// ordino in senso decrescente sull'area
sort( m_vArea.begin(), m_vArea.end(),
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
Frame3d frRef ; frRef.Set( ORIG, vtN0) ;
if ( ! frRef.IsValid())
return false ;
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vCrvCompo[i].Set( CreateCurveComposite()) ;
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
vCrvCompo[i]->ToLoc( frRef) ;
}
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
// successive i loop interni
INTMATRIX vnPLIndMat ;
// aggiungo le diverse curve
bool bFirstCrv ;
Plane3d plExtLoop ;
double dAreaExtLoop = 0. ;
do {
bFirstCrv = true ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
// recupero indice di percorso e verifico sia valido
int j = m_vArea[i].first ;
if ( j < 0)
continue ;
// lo inserisco come esterno...
if ( bFirstCrv) {
vnPLIndMat.push_back({ j}) ;
m_vArea[i].first = -1 ;
dAreaExtLoop = m_vArea[i].second ;
// inverto se necessario
if ( m_vArea[i].second < EPS_SMALL) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
dAreaExtLoop *= -1 ;
}
bFirstCrv = false ;
}
// ... altrimenti verifico se il loop è interno o no
else {
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
// esterno a tutti i loop già inseriti nella riga attuale.
// verifica rispetto loop esterno
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
bool bOk = true ;
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
}
}
if ( bOk) {
// inserisco nella matrice
vnPLIndMat.back().push_back( j) ;
m_vArea[i].first = -1 ;
// inverto se necessario
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
}
}
}
}
} while ( ! bFirstCrv) ;
// chiamo la Triangolazione per ogni riga della matrice ( quindi su ogni "Chunk")
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++ i) {
PNTVECTOR vPt_tmp ; INTVECTOR vTr_tmp ;
POLYLINEVECTOR vPL_tmp ;
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++ j)
vPL_tmp.push_back( vPL[vnPLIndMat[i][j]]) ;
if ( ! Make( vPL_tmp, vPt_tmp, vTr_tmp))
return false ;
int nSize = int( vPt.size()) ;
for ( int p = 0 ; p < int( vPt_tmp.size()) ; ++ p)
vPt.push_back( vPt_tmp[p]) ;
for ( int t = 0 ; t < int( vTr_tmp.size()) ; ++ t)
vTr.push_back( nSize + vTr_tmp[t]) ;
}
return true ;
}
//----------------------------------------------------------------------------
// Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0])
// Ear Clipping algorithm from mapbox
+1
View File
@@ -22,6 +22,7 @@ class Triangulate
public :
bool Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeAdvanced( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
private :
bool MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr) ;
+6 -3
View File
@@ -17,12 +17,15 @@
#include "GeoObjRW.h"
#include "Tool.h"
#include "/EgtDev/Include/EGkVolZmap.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EGkIntersLineVolZmap.h"
#include <unordered_map>
#include <stack>
#include <mutex>
#include <atomic>
// ------------------------- FORWARD -------------------------------------------------------------
class IntersParLinesSurfTm ;
// ------------------------- STRUTTURE -----------------------------------------------------------
struct AppliedVector {
Point3d ptPApp ;
@@ -112,8 +115,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) override ;
bool GetDepth( const Point3d& ptP, const Vector3d& vtD, double& dInLength, double& dOutLength, bool bExact) const override ;
bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const override ;
bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const override ;
bool CDeBox( const Frame3d& frBox, const Vector3d& vtDiag, double dSafeDist, bool bPrecise = false) const override ;
bool CDeSphere( const Point3d& ptCenter, double dRad, double dSafeDist, bool bPrecise = false) const override ;
bool CDeCylinder( const Frame3d& frCyl, double dR, double dH, double dSafeDist, bool bPrecise = false) const override ;
@@ -149,6 +150,8 @@ class VolZmap : public IVolZmap, public IGeoObjRW
{ if ( ! CopyFrom( stSrc))
LOG_ERROR( GetEGkLogger(), "VolZmap : copy error")
return *this ; }
bool GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTOR& vIntersInfo) const ;
bool GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) const ;
private :
enum CubeType { VOX_EXTERN = 1,
+16 -8
View File
@@ -2912,8 +2912,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
nNumVox, nB, ptLineTria1, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
}
// altrimenti ci sono due intersezioni
else {
@@ -2921,8 +2922,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
}
}
}
@@ -2948,8 +2950,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
nNumVox, nB, ptLineTria1, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
}
// altrimenti ci sono due intersezioni
else {
@@ -2957,8 +2960,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
}
}
}
@@ -2974,15 +2978,17 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
continue ;
// se altrimenti c'è una sola intersezione
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
-1, nB, ptLineTria1, trTria) ;
-1, nB, trTria, dCosDN, ptLineTria1) ;
}
// altrimenti ci sono due intersezioni
else {
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
-1, nB, ptLineTria1, ptLineTria2, trTria) ;
-1, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
}
}
}
@@ -3007,8 +3013,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
else if ( nIntType == ILTT_VERT || nIntType == ILTT_EDGE || nIntType == ILTT_IN) {
int nNumVox ;
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( ptLineTria1 - ptP) * vtDir,
nNumVox, nB, ptLineTria1, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1) ;
}
// altrimenti ci sono due intersezioni
else {
@@ -3016,8 +3023,9 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
GetVoxNFromIJK( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], nNumVox) ;
double dP1 = ( ptLineTria1 - ptP) * vtDir ;
double dP2 = ( ptLineTria2 - ptP) * vtDir ;
double dCosDN = vtDir * trTria.GetN() ;
vIntersInfo.emplace_back( nIntType, ( dP1 < dP2 ? dP1 : dP2), ( dP1 < dP2 ? dP2 : dP1),
nNumVox, nB, ptLineTria1, ptLineTria2, trTria) ;
nNumVox, nB, trTria, dCosDN, ptLineTria1, ptLineTria2) ;
}
}
}
+1
View File
@@ -17,6 +17,7 @@
#include "CurveLine.h"
#include "VolZmap.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include <future>
+49 -23
View File
@@ -79,7 +79,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
if ( pCrv == nullptr)
return false ;
// verifico se è una linea
// verifico se è una linea
int nType = pCrv->GetType() ;
bool bIsLine = ( nType == CRV_LINE) ;
if ( nType == CRV_COMPO) {
@@ -92,7 +92,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
// verifico sia piana e trovo piano su cui giace
Plane3d plPlane ;
if ( bIsLine) {
// linea è sicuramente piana. Scelgo piano definito dall'estrusione ( se definita)
// linea è sicuramente piana. Scelgo piano definito dall'estrusione ( se definita)
Point3d ptS ; pCrv->GetStartPoint( ptS) ;
Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ;
if ( ! vtExtr.IsSmall())
@@ -110,7 +110,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
}
else {
// altrimenti verifico sia complanare ad eventuali curve già presenti
// altrimenti verifico sia complanare ad eventuali curve già presenti
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), plPlane.GetVersN()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
return false ;
}
@@ -122,7 +122,7 @@ Voronoi::AddCurve( const ICurve* pCrv)
pCrvLoc->ToLoc( m_Frame) ;
try {
// verifico se oggetto vroni è stato inizializzato
// verifico se oggetto vroni è stato inizializzato
if ( m_vroni == nullptr) {
m_vroni = new( nothrow) vroniObject() ;
if ( m_vroni == nullptr)
@@ -165,7 +165,7 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
m_Frame.Set( ptCen, vtN) ;
}
else {
// verifico sia complanare ad eventuali curve già presenti
// verifico sia complanare ad eventuali curve già presenti
Plane3d plPlane ;
plPlane.Set( ptCen, pSfr->GetNormVersor()) ;
if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), pSfr->GetNormVersor()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane))
@@ -173,7 +173,7 @@ Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr)
}
try {
// verifico se oggetto vroni è stato inizializzato
// verifico se oggetto vroni è stato inizializzato
if ( m_vroni == nullptr) {
m_vroni = new( nothrow) vroniObject() ;
if ( m_vroni == nullptr)
@@ -315,7 +315,7 @@ Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLo
for ( int i = 0 ; i < pCopy->GetCurveCount() ; i++) {
Point3d ptForcedEnd = P_INVALID ;
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
// se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni)
if ( i == pCopy->GetCurveCount() - 1 && bClosed)
pCompo->GetStartPoint( ptForcedEnd) ;
@@ -359,7 +359,7 @@ Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoo
ICurve*
Voronoi::GetCurve( int nId) const
{
// verifico validità indice
// verifico validità indice
if ( nId < 0 || nId > ( int)m_vpCrvs.size() - 1)
return nullptr ;
// ne faccio una copia
@@ -375,11 +375,11 @@ Voronoi::GetCurve( int nId) const
bool
Voronoi::CalcVoronoi( int nBound)
{
// se già stato calcolato con lo stesso bound non devo fare nulla
// se già stato calcolato con lo stesso bound non devo fare nulla
if ( m_bVDComputed && nBound == m_nBound)
return true ;
// se già stato calcolato reset dei dati
// se già stato calcolato reset dei dati
if ( m_bVDComputed)
m_vroni->ResetVoronoiDiagram() ;
@@ -389,8 +389,8 @@ Voronoi::CalcVoronoi( int nBound)
// calcolo
m_bVDComputed = true ;
string sTmp = "" ;
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ;
return true ;
}
@@ -501,6 +501,9 @@ Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound)
if ( ! IsNull( pCrv) && pCrv->IsValid())
vCrvs.emplace_back( Release( pCrv)) ;
}
// libero la memoria di vroni utilizzata per calcolare bisettore
m_vroni->apiFreeBisectorBuffer() ;
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
@@ -542,6 +545,9 @@ Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide)
vCrvs.emplace_back( Release( pCrv)) ;
}
}
// libero la memoria di vroni utilizzata per calcolare bisettore
m_vroni->apiFreeBisectorBuffer() ;
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
@@ -651,12 +657,12 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo
// sistemo i raccordi
if ( bClosed && bSquareMids) {
// se curva è chiusa tutti i raccordi rispondono a bSquareMids
// se curva è chiusa tutti i raccordi rispondono a bSquareMids
IdentifyFillets( pCrvOffs, dOffs) ;
AdjustCurveFillets( pCrvOffs, dOffs, ICurve::OFF_EXTEND) ;
}
else if ( ! bClosed && ( bSquareMids || bSquareEnds)) {
// se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e
// se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e
// modificare solo quelli richiesti
for ( int j = 0 ; j < pCrvOffs->GetCurveCount() ; j ++) {
int nOrigCrv ; pCrvOffs->GetCurveTempProp( j, nOrigCrv) ;
@@ -738,13 +744,13 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs, bool bRightOff
bOk = pCrvOffs->AddCurve( Release( pArc)) ;
}
// se la curva è stata aggiunta
// se la curva è stata aggiunta
if ( bOk) {
// setto come info la sottocurva da cui si è generata
// setto come info la sottocurva da cui si è generata
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
// verifico se è raccordo relativo agli estremi della curva
// verifico se è raccordo relativo agli estremi della curva
if ( nOrigCrv == -1 && ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt))
pCrvOffs->SetCurveTempParam( nCurrCrvId, 1.0, 0) ;
}
@@ -757,6 +763,9 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs, bool bRightOff
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid())
OffsList.push_back( Release( pCrvOffs)) ;
}
// libero la memoria di vroni dedicata agli offset
m_vroni->apiFreeOffsetData() ;
}
catch (...) {
LOG_ERROR( GetEGkLogger(), m_vroni->GetExceptionMessage()) ;
@@ -789,7 +798,7 @@ Voronoi::VerifyCurvesValidityForOffset()
if ( m_vpCrvs.size() == 1)
return true ;
// se ho più curve, devono essere tutte chiuse
// se ho più curve, devono essere tutte chiuse
for ( auto pCrv : m_vpCrvs) {
if ( ! pCrv->IsClosed())
return false ;
@@ -809,12 +818,29 @@ Voronoi::VerifyCurvesValidityForOffset()
// se curva con orientamento principale verifico sia esterna a tutte le altre curve con orientamento principale
if ( vArea[i] * dRefArea > EPS_SMALL) {
for ( int j = i + 1 ; j < ( int)vArea.size() ; j++) {
if ( vArea[i] * vArea[j] > EPS_SMALL) {
for ( int j = 0 ; j < ( int)vArea.size() ; j++) {
if ( j != i && vArea[i] * vArea[j] > EPS_SMALL) {
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ;
int nRes = ccInt.GetRegionCurveClassification() ;
if ( ( bRefCCW && nRes != CCREGC_OUT) || ( ! bRefCCW && nRes != CCREGC_IN1))
if ( nRes == CCREGC_NULL || nRes == CCREGC_SAME || nRes == CCREGC_INTERS)
return false ;
if ( ( bRefCCW && nRes == CCREGC_IN1) || ( ! bRefCCW && nRes == CCREGC_IN2)) {
// se è interna ad una curva con orientamento principale, verifico sia esterna ad almeno una curva con orientamento
// diverso dal principale
bool bFound = false ;
for ( int k = 0 ; k < ( int)vArea.size() ; k++) {
if ( k != i && vArea[i] * vArea[k] < EPS_SMALL) {
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[k]) ;
int nRes = ccInt.GetRegionCurveClassification() ;
if ( ( bRefCCW && nRes == CCREGC_OUT) || ( ! bRefCCW && nRes == CCREGC_IN1)) {
bFound = true ;
break ;
}
}
}
if ( ! bFound)
return false ;
}
}
}
}
@@ -884,7 +910,7 @@ Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs)
// mi posiziono dopo la junction
pCompo.ChangeStartPoint( vJunctions[0] + 1) ;
delete( pCompo.RemoveFirstOrLastCurve()) ;
// verifico validità della curva
// verifico validità della curva
int nSide = GetOffsetCurveSide( pCompo, 0) ;
if ( nSide == nSideRef) {
// scorro fino alla prima curva non valida ed elimino la curva da quel punto fino alla fine
@@ -895,7 +921,7 @@ Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs)
}
}
else {
// elimino finchè non trovo una curva valida
// elimino finchè non trovo una curva valida
while( nSide != nSideRef && pCompo.IsValid()) {
delete( pCompo.RemoveFirstOrLastCurve( false)) ;
if ( pCompo.IsValid())