Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 104726c5ee | |||
| e2445c0a15 | |||
| 9880fa0173 | |||
| d276809906 | |||
| 4268da4a1f | |||
| 4f485d0e87 | |||
| d48348fa1c | |||
| 003dd0bdef | |||
| ec109908fa | |||
| 3630b85632 | |||
| fdce6e1853 | |||
| 8ffa9d7fb7 | |||
| 360484c9af | |||
| 47606bffcd | |||
| aea99a635f | |||
| ce139c6925 | |||
| 5dcf5f5616 | |||
| 451ef8356b | |||
| 6e810f050e | |||
| bd90fc2b59 | |||
| 5800093e53 | |||
| 65daddfced | |||
| 95915b16e5 | |||
| 46b91bb49d | |||
| 751ea085a6 | |||
| 15ed754512 |
Binary file not shown.
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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())
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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) ;
|
||||
|
||||
@@ -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
@@ -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) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user