Compare commits

..

3 Commits

Author SHA1 Message Date
SaraP 3a4ee5cc19 EgtGeomKernel :
- correzione errori compliazione con Clang-cl/LLVM.
2021-07-20 16:10:16 +02:00
SaraP 32883dab86 Merge remote-tracking branch 'origin/master' into SaraP 2021-07-20 15:16:02 +02:00
SaraP 8ac3fdab47 EgtGeomKernel :
- aggiunta triangolazione constrained Delaunay con libreria GeometricToolsEngine
- correzione errori triangolazione con TrianglePP.
2021-07-09 16:05:59 +02:00
68 changed files with 23001 additions and 8513 deletions
+2 -2
View File
@@ -13,8 +13,8 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "/EgtDev/Include/EGkBBox3d.h"
#include "/EgtDev/Include/EGkFrame3d.h"
#include "\EgtDev\Include\EGkBBox3d.h"
#include "\EgtDev\Include\EGkFrame3d.h"
#include <algorithm>
using namespace std ;
+2 -5
View File
@@ -59,10 +59,8 @@ class ArcApproxer
//----------------------------------------------------------------------------
CurveArc::CurveArc( void)
: m_nStatus( TO_VERIFY), m_PtCen(), m_VtN(), m_VtS(), m_dRad(),
m_dAngCenDeg(), m_dDeltaN(), m_VtExtr(), m_dThick()
m_dAngCenDeg(), m_dDeltaN(), m_VtExtr(), m_dThick(), m_nTempProp()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -580,8 +578,7 @@ CurveArc::CopyFrom( const CurveArc& caSrc)
return true ;
m_VtExtr = caSrc.m_VtExtr ;
m_dThick = caSrc.m_dThick ;
m_nTempProp[0] = caSrc.m_nTempProp[0] ;
m_nTempProp[1] = caSrc.m_nTempProp[1] ;
m_nTempProp = caSrc.m_nTempProp ;
return Set( caSrc.m_PtCen, caSrc.m_VtN, caSrc.m_dRad,
caSrc.m_VtS, caSrc.m_dAngCenDeg, caSrc.m_dDeltaN) ;
}
+5 -6
View File
@@ -49,11 +49,10 @@ class CurveArc : public ICurveArc, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // ICurve
bool IsSimple( void) const override
@@ -212,7 +211,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW
double m_dDeltaN ; // variazione di quota lungo VtN della fine rispetto all'inizio
Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN)
double m_dThick ; // spessore
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
} ;
//-----------------------------------------------------------------------------
+2 -5
View File
@@ -45,10 +45,8 @@ GEOOBJ_REGISTER( CRV_BEZIER, NGE_C_BEZ, CurveBezier) ;
//----------------------------------------------------------------------------
CurveBezier::CurveBezier( void)
: m_nStatus( TO_VERIFY), m_nDeg(), m_bRat( false), m_dParSing( -2),
m_VtExtr(), m_dThick()
m_VtExtr(), m_dThick(), m_nTempProp()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -285,8 +283,7 @@ CurveBezier::CopyFrom( const CurveBezier& cbSrc)
m_vWeCtrl = cbSrc.m_vWeCtrl ;
m_VtExtr = cbSrc.m_VtExtr ;
m_dThick = cbSrc.m_dThick ;
m_nTempProp[0] = cbSrc.m_nTempProp[0] ;
m_nTempProp[1] = cbSrc.m_nTempProp[1] ;
m_nTempProp = cbSrc.m_nTempProp ;
return true ;
}
+5 -6
View File
@@ -51,11 +51,10 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // ICurve
bool IsSimple( void) const override { return true ; }
@@ -190,7 +189,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN)
double m_dThick ; // spessore
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
} ;
//-----------------------------------------------------------------------------
+11 -17
View File
@@ -30,7 +30,6 @@
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include <algorithm>
@@ -41,10 +40,8 @@ GEOOBJ_REGISTER( CRV_COMPO, NGE_C_CMP, CurveComposite) ;
//----------------------------------------------------------------------------
CurveComposite::CurveComposite( void)
: m_nStatus( TO_VERIFY), m_VtExtr(), m_dThick(), m_ptStart(), m_Iter( m_CrvSmplS.end())
: m_nStatus( TO_VERIFY), m_VtExtr(), m_dThick(), m_ptStart(), m_nTempProp(), m_Iter( m_CrvSmplS.end())
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -66,8 +63,7 @@ CurveComposite::Clear( void)
m_VtExtr = V_NULL ;
m_dThick = 0 ;
m_ptStart = ORIG ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
m_nTempProp = 0 ;
m_Iter = m_CrvSmplS.end() ;
// imposto ricalcolo della grafica
@@ -545,8 +541,7 @@ CurveComposite::CopyFrom( const CurveComposite& ccSrc)
Clear() ;
m_VtExtr = ccSrc.m_VtExtr ;
m_dThick = ccSrc.m_dThick ;
m_nTempProp[0] = ccSrc.m_nTempProp[0] ;
m_nTempProp[1] = ccSrc.m_nTempProp[1] ;
m_nTempProp = ccSrc.m_nTempProp ;
for ( auto& pCrv : ccSrc.m_CrvSmplS) {
if ( ! AddCurve( *pCrv))
return false ;
@@ -563,8 +558,7 @@ CurveComposite::RelocateFrom( CurveComposite& ccSrc)
Clear() ;
m_VtExtr = ccSrc.m_VtExtr ;
m_dThick = ccSrc.m_dThick ;
m_nTempProp[0] = ccSrc.m_nTempProp[0] ;
m_nTempProp[1] = ccSrc.m_nTempProp[1] ;
m_nTempProp = ccSrc.m_nTempProp ;
for ( ICurve* pCrv = ccSrc.RemoveFirstOrLastCurve( false) ;
pCrv != nullptr ;
pCrv = ccSrc.RemoveFirstOrLastCurve( false)) {
@@ -1322,8 +1316,8 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P
// se lineare con lato obbligato...
if ( nType == APL_LEFT || nType == APL_LEFT_CONVEX ||
nType == APL_RIGHT || nType == APL_RIGHT_CONVEX) {
// prima approssimazione lineare alla tolleranza minima del programma
if ( ! ApproxWithLines( EPS_SMALL, dAngTolDeg, APL_SPECIAL, PL))
// prima approssimazione lineare a 10 * Epsilon
if ( ! ApproxWithLines( 10 * EPS_SMALL, dAngTolDeg, APL_SPECIAL, PL))
return false ;
// eliminazione dei punti in tolleranza andando solo dalla parte ammessa
Vector3d vtExtr = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ;
@@ -3135,7 +3129,7 @@ CurveComposite::RemoveUndercutOnY( double dLinTol, double dAngTolDeg)
pSfrCut->Translate( b3Box.GetMin() - Point3d( 10 * EPS_SMALL, dLen, 0)) ;
// calcolo la classificazione della curva rispetto alla regione
CRVCVECTOR ccClass ;
if ( ! pSfrCut->GetCurveClassification( *pOutLoop, EPS_SMALL, ccClass))
if ( ! pSfrCut->GetCurveClassification( *pOutLoop, ccClass))
return false ;
// determino gli intervalli di curva da conservare
Intervals inOk ;
@@ -3249,7 +3243,7 @@ CurveComposite::IsACircle( double dLinTol, Point3d& ptCen, Vector3d& vtN, double
//----------------------------------------------------------------------------
bool
CurveComposite::SetCurveTempProp( int nCrv, int nProp, int nPropNum)
CurveComposite::SetCurveTempProp( int nCrv, int nProp)
{
// la curva deve essere validata
if ( m_nStatus != OK)
@@ -3258,13 +3252,13 @@ CurveComposite::SetCurveTempProp( int nCrv, int nProp, int nPropNum)
if ( nCrv < 0 || nCrv >= int( m_CrvSmplS.size()))
return false ;
// eseguo assegnazione
m_CrvSmplS[nCrv]->SetTempProp( nProp, nPropNum) ;
m_CrvSmplS[nCrv]->SetTempProp( nProp) ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveComposite::GetCurveTempProp( int nCrv, int& nProp, int nPropNum) const
CurveComposite::GetCurveTempProp( int nCrv, int& nProp) const
{
// la curva deve essere validata
if ( m_nStatus != OK)
@@ -3273,6 +3267,6 @@ CurveComposite::GetCurveTempProp( int nCrv, int& nProp, int nPropNum) const
if ( nCrv < 0 || nCrv >= int( m_CrvSmplS.size()))
return false ;
// eseguo recupero
nProp = m_CrvSmplS[nCrv]->GetTempProp( nPropNum) ;
nProp = m_CrvSmplS[nCrv]->GetTempProp() ;
return true ;
}
+7 -8
View File
@@ -50,11 +50,10 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // ICurve
bool IsSimple( void) const override
@@ -159,8 +158,8 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
bool IsAPoint( void) const override ;
bool IsALine( double dLinTol, Point3d& ptStart, Point3d& ptEnd) const override ;
bool IsACircle( double dLinTol, Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const override ;
bool SetCurveTempProp( int nCrv, int nProp, int nPropNum = 0) override ;
bool GetCurveTempProp( int nCrv, int& nProp, int nPropNum = 0) const override ;
bool SetCurveTempProp( int nCrv, int nProp) override ;
bool GetCurveTempProp( int nCrv, int& nProp) const override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
@@ -203,7 +202,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN)
double m_dThick ; // spessore
Point3d m_ptStart ; // punto iniziale per composita vuota per Add di linee o archi
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
mutable PCSD_CONST_ITER m_Iter ; // iteratore
} ;
+2 -5
View File
@@ -29,10 +29,8 @@ GEOOBJ_REGISTER( CRV_LINE, NGE_C_LIN, CurveLine) ;
//----------------------------------------------------------------------------
CurveLine::CurveLine( void)
: m_nStatus( TO_VERIFY), m_PtStart(), m_PtEnd(), m_VtExtr(), m_dThick()
: m_nStatus( TO_VERIFY), m_PtStart(), m_PtEnd(), m_VtExtr(), m_dThick(), m_nTempProp()
{
m_nTempProp[0] = 0 ;
m_nTempProp[0] = 0 ;
}
//----------------------------------------------------------------------------
@@ -125,8 +123,7 @@ CurveLine::CopyFrom( const CurveLine& clSrc)
return true ;
m_VtExtr = clSrc.m_VtExtr ;
m_dThick = clSrc.m_dThick ;
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
m_nTempProp = clSrc.m_nTempProp ;
return Set( clSrc.m_PtStart, clSrc.m_PtEnd) ;
}
+5 -6
View File
@@ -49,11 +49,10 @@ class CurveLine : public ICurveLine, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // ICurve
bool IsSimple( void) const override
@@ -165,7 +164,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW
Point3d m_PtEnd ; // punto finale
Vector3d m_VtExtr ; // vettore estrusione
double m_dThick ; // spessore
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
} ;
//-----------------------------------------------------------------------------
+11 -10
View File
@@ -23,30 +23,33 @@
bool
CalcMinDistPointPolyLine( const Point3d& ptP, PolyLine& PL, double dLinTol, MDCVECTOR& vApproxMin)
{
double dSqDist ;
double dPar ;
double dUIni ;
double dUFin ;
Point3d ptIni ;
Point3d ptFin ;
double dMinDist ;
double dSqMinDist ;
MinDistCalc approxMin ;
vApproxMin.reserve( 4) ;
vApproxMin.clear() ;
bool bFound = false ;
bool bOnEnd = false ;
double dUIni, dUFin ;
Point3d ptIni, ptFin ;
double dMinDist, dSqMinDist ;
vApproxMin.reserve( 4) ;
vApproxMin.clear() ;
for ( bool bLine = PL.GetFirstULine( &dUIni, &ptIni, &dUFin, &ptFin) ;
bLine ;
bLine = PL.GetNextULine( &dUIni, &ptIni, &dUFin, &ptFin)) {
// calcolo la distanza del punto dal segmento
DistPointLine dstPtLn( ptP, ptIni, ptFin) ;
double dSqDist ;
if ( ! dstPtLn.GetSqDist( dSqDist))
continue ;
// altro punto con la stessa minima distanza già trovata
if ( bFound && abs( dSqDist - dSqMinDist) < 2 * dMinDist * dLinTol) {
// salvo i dati nella struttura
MinDistCalc approxMin ;
approxMin.dDist = dMinDist ;
dstPtLn.GetMinDistPoint( approxMin.ptQ) ;
double dPar ;
dstPtLn.GetParamAtMinDistPoint( dPar) ;
approxMin.dPar = ( 1 - dPar) * dUIni + dPar * dUFin ;
approxMin.dParMin = dUIni ;
@@ -63,10 +66,8 @@ CalcMinDistPointPolyLine( const Point3d& ptP, PolyLine& PL, double dLinTol, MDCV
dSqMinDist = dSqDist ;
dMinDist = sqrt( dSqMinDist) ;
// salvo i dati nella struttura
MinDistCalc approxMin ;
approxMin.dDist = dMinDist ;
dstPtLn.GetMinDistPoint( approxMin.ptQ) ;
double dPar ;
dstPtLn.GetParamAtMinDistPoint( dPar) ;
approxMin.dPar = ( 1 - dPar) * dUIni + dPar * dUFin ;
approxMin.dParMin = dUIni ;
BIN
View File
Binary file not shown.
+19 -13
View File
@@ -51,7 +51,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>false</WholeProgramOptimization>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>ClangCL</PlatformToolset>
@@ -86,7 +86,6 @@
<OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
<IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
<IncludePath>C:\;$(IncludePath)</IncludePath>
<EnableClangTidyCodeAnalysis>false</EnableClangTidyCodeAnalysis>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<TargetName>$(ProjectName)R$(PlatformArchitecture)</TargetName>
@@ -102,7 +101,6 @@
<OutDir>$(SolutionDir)$(Configuration)$(PlatformArchitecture)\</OutDir>
<IntDir>$(Configuration)$(PlatformArchitecture)\</IntDir>
<IncludePath>C:\;$(IncludePath)</IncludePath>
<EnableClangTidyCodeAnalysis>false</EnableClangTidyCodeAnalysis>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@@ -116,6 +114,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<EnablePREfast>false</EnablePREfast>
<AdditionalIncludeDirectories>\EgtDev\Extern\GeometricToolsEngine</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -150,8 +149,7 @@ copy $(TargetPath) \EgtProg\DllD32</Command>
<MinimalRebuild>false</MinimalRebuild>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
<AdditionalIncludeDirectories>\EgtDev\Extern\GeometricToolsEngine</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -198,6 +196,7 @@ copy $(TargetPath) \EgtProg\DllD64</Command>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<WholeProgramOptimization>false</WholeProgramOptimization>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>\EgtDev\Extern\GeometricToolsEngine</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -240,11 +239,10 @@ copy $(TargetPath) \EgtProg\Dll32</Command>
<OmitFramePointers>true</OmitFramePointers>
<FloatingPointModel>Precise</FloatingPointModel>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<EnableFiberSafeOptimizations>false</EnableFiberSafeOptimizations>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<WholeProgramOptimization>false</WholeProgramOptimization>
<DebugInformationFormat>None</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
<AdditionalIncludeDirectories>\EgtDev\Extern\GeometricToolsEngine</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -368,7 +366,12 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="IntersCurveCurve.cpp" />
<ClCompile Include="IntersLineArc.cpp" />
<ClCompile Include="IntersLineLine.cpp" />
<ClCompile Include="IntersLinePlane.cpp" />
<ClCompile Include="IntersLinePlane.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="IntersLineSurfTm.cpp" />
<ClCompile Include="IntersLineTria.cpp" />
<ClCompile Include="Intervals.cpp" />
@@ -394,10 +397,10 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="SurfFlatRegionBooleans.cpp" />
<ClCompile Include="SurfFlatRegionOffset.cpp" />
<ClCompile Include="SurfTriMeshBooleans.cpp" />
<ClCompile Include="SurfTriMeshCuts.cpp" />
<ClCompile Include="SurfTriMeshUtilities.cpp" />
<ClCompile Include="TextureData.cpp" />
<ClCompile Include="Tool.cpp" />
<ClCompile Include="tpp_assert.cpp" />
<ClCompile Include="tpp_impl.cpp" />
<ClCompile Include="UserObjDefault.cpp" />
<ClCompile Include="UserObjFactory.cpp" />
<ClCompile Include="OutTsc.cpp" />
@@ -561,7 +564,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="DistPointCrvComposite.h" />
<ClInclude Include="DistPointLine.h" />
<ClInclude Include="DllMain.h" />
<ClInclude Include="earcut.hpp" />
<ClInclude Include="dpoint.hpp" />
<ClInclude Include="ExtDimension.h" />
<ClInclude Include="ExtText.h" />
<ClInclude Include="FontAux.h" />
@@ -590,7 +593,6 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="IntersArcArc.h" />
<ClInclude Include="IntersCrvCompoCrvCompo.h" />
<ClInclude Include="IntersLineArc.h" />
<ClInclude Include="IntersLineBox.h" />
<ClInclude Include="IntersLineLine.h" />
<ClInclude Include="IntersLineSurfStd.h" />
<ClInclude Include="IntersLineTria.h" />
@@ -610,6 +612,10 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="TextureData.h" />
<ClInclude Include="Tool.h" />
<ClInclude Include="CAvToolTriangle.h" />
<ClInclude Include="tpp_assert.hpp" />
<ClInclude Include="tpp_interface.hpp" />
<ClInclude Include="triangle.h" />
<ClInclude Include="triangle_impl.hpp" />
<ClInclude Include="UserObjDefault.h" />
<ClInclude Include="OutTsc.h" />
<ClInclude Include="PointsPCA.h" />
+23 -8
View File
@@ -46,6 +46,12 @@
<Filter Include="File di origine\GeoCollision">
<UniqueIdentifier>{865b76ee-b10d-41fc-861c-b48ce52fa277}</UniqueIdentifier>
</Filter>
<Filter Include="File di intestazione\tpp">
<UniqueIdentifier>{9596e38a-8880-4ab5-bd65-e1db39c92ac5}</UniqueIdentifier>
</Filter>
<Filter Include="File di origine\tpp">
<UniqueIdentifier>{636e60fa-4b24-4a7b-b2e9-74e1c1e8fb31}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Vector3d.cpp">
@@ -453,11 +459,11 @@
<ClCompile Include="CDeRectPrismoidTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
</ClCompile>
<ClCompile Include="SurfTriMeshUtilities.cpp">
<Filter>File di origine\Geo</Filter>
<ClCompile Include="tpp_assert.cpp">
<Filter>File di origine\tpp</Filter>
</ClCompile>
<ClCompile Include="SurfTriMeshCuts.cpp">
<Filter>File di origine\Geo</Filter>
<ClCompile Include="tpp_impl.cpp">
<Filter>File di origine\tpp</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@@ -1082,11 +1088,20 @@
<ClInclude Include="CDeRectPrismoidTria.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="earcut.hpp">
<Filter>File di intestazione</Filter>
<ClInclude Include="dpoint.hpp">
<Filter>File di intestazione\tpp</Filter>
</ClInclude>
<ClInclude Include="IntersLineBox.h">
<Filter>File di intestazione</Filter>
<ClInclude Include="tpp_assert.hpp">
<Filter>File di intestazione\tpp</Filter>
</ClInclude>
<ClInclude Include="tpp_interface.hpp">
<Filter>File di intestazione\tpp</Filter>
</ClInclude>
<ClInclude Include="triangle.h">
<Filter>File di intestazione\tpp</Filter>
</ClInclude>
<ClInclude Include="triangle_impl.hpp">
<Filter>File di intestazione\tpp</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
+1 -4
View File
@@ -49,8 +49,6 @@ ExtDimension::ExtDimension( void)
: m_dExtLineLen( STD_EXTLINELEN), m_dArrowLen( STD_ARROWLEN), m_dTextDist( STD_TEXTDIST),
m_bLenIsMM( true), m_nDecDigit( STD_DECDIGIT), m_sFont( STD_FONT), m_dTextHeight( STD_TEXTHEIGHT)
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -188,8 +186,7 @@ ExtDimension::CopyFrom( const ExtDimension& clSrc)
m_nDecDigit = clSrc.m_nDecDigit ;
m_sFont = clSrc.m_sFont ;
m_dTextHeight = clSrc.m_dTextHeight ;
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
m_nTempProp = clSrc.m_nTempProp ;
return true ;
}
+5 -6
View File
@@ -50,11 +50,10 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // IExtDimension
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -149,5 +148,5 @@ class ExtDimension : public IExtDimension, public IGeoObjRW
int m_nDecDigit ; // numero di cifre decimali
std::string m_sFont ; // font del testo
double m_dTextHeight ; // altezza del testo
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
} ;
+2 -5
View File
@@ -35,10 +35,8 @@ GEOOBJ_REGISTER( EXT_TEXT, NGE_E_TXT, ExtText) ;
//----------------------------------------------------------------------------
ExtText::ExtText( void)
: m_pSTM( nullptr), m_bNoSTM( false), m_ptP(), m_vtN( 0, 0, 1), m_vtD( 1, 0, 0), m_sFont(),
m_nWeight( 400), m_bItalic( false), m_dHeight( 10), m_dRatio( 1), m_dAddAdvance( 0)
m_nWeight( 400), m_bItalic( false), m_dHeight( 10), m_dRatio( 1), m_dAddAdvance( 0), m_nTempProp()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -186,8 +184,7 @@ ExtText::CopyFrom( const ExtText& clSrc)
m_dRatio = clSrc.m_dRatio ;
m_dAddAdvance = clSrc.m_dAddAdvance ;
m_nInsPos = clSrc.m_nInsPos ;
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
m_nTempProp = clSrc.m_nTempProp ;
return true ;
}
+5 -6
View File
@@ -50,11 +50,10 @@ class ExtText : public IExtText, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // IExtText
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -144,5 +143,5 @@ class ExtText : public IExtText, public IGeoObjRW
double m_dRatio ; // rapporto tra larghezza e altezza
double m_dAddAdvance ; // avanzamento addizionale tra caratteri
int m_nInsPos ; // posizione del punto di inserimento rispetto al testo
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
} ;
+118 -118
View File
@@ -57,7 +57,7 @@
using namespace std ;
//----------------------------------------------------------------------------
// Per Id di entità
// Per Id di entità
static const int ID_NO = -99 ;
// Per tipo di costruzione di poligono
static const int POLYG_INSCR = 1 ;
@@ -189,7 +189,7 @@ GdbExecutor::Execute( const string& sCmd1, const string& sCmd2, const STRVECTOR&
LOG_ERROR( GetEGkLogger(), "Error : null GeomDb in GdbExecutor.")
return ER_ERR ;
}
// verifico validità CmdParser
// verifico validità CmdParser
if ( m_pParser == nullptr) {
LOG_ERROR( GetEGkLogger(), "Error : null CmdParser in GdbExecutor.")
return ER_ERR ;
@@ -218,7 +218,7 @@ GdbExecutor::ExecuteGroup( const string& sCmd2, const STRVECTOR& vsParams)
// 2 o 3 parametri : Id, Id del padre[, Frame]
if ( vsParams.size() != 2 && vsParams.size() != 3)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -236,7 +236,7 @@ GdbExecutor::ExecuteGroup( const string& sCmd2, const STRVECTOR& vsParams)
// 3 parametri : Id, Id del padre, Orig
if ( vsParams.size() != 3)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -253,7 +253,7 @@ GdbExecutor::ExecuteGroup( const string& sCmd2, const STRVECTOR& vsParams)
// creo il gruppo
int nIdDest = GetIdParam( vsParams[0], true) ;
int nIdNew = m_pGDB->AddGroup( nIdDest, GetIdParam( vsParams[1]), frFrame) ;
// se IdDest da calcolare, può essere una variabili a cui cambiare il valore
// se IdDest da calcolare, può essere una variabili a cui cambiare il valore
if ( nIdDest == GDB_ID_NULL)
m_pParser->SetVariable( vsParams[0], nIdNew) ;
@@ -270,7 +270,7 @@ GdbExecutor::ExecutePoint( const string& sCmd2, const STRVECTOR& vsParams)
// 3 parametri : Id, IdParent e punto
if ( vsParams.size() != 3)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frPnt ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frPnt))
return false ;
@@ -289,7 +289,7 @@ GdbExecutor::ExecutePoint( const string& sCmd2, const STRVECTOR& vsParams)
// 4 : Id, IdParent, ptP, vtV
if ( vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frPnt ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frPnt))
return false ;
@@ -351,7 +351,7 @@ GdbExecutor::VectorMake( const STRVECTOR& vsParams)
// 3 o 4 parametri : Id, IdParent, Vettore [, ScaleFactor]
if ( vsParams.size() != 3 && vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect))
return false ;
@@ -378,7 +378,7 @@ GdbExecutor::VectorFromSpherical( const STRVECTOR& vsParams)
// 5 parametri : Id, IdParent, dLen, dAngVertDeg, dAngOrizzDeg
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect))
return false ;
@@ -386,7 +386,7 @@ GdbExecutor::VectorFromSpherical( const STRVECTOR& vsParams)
double dLen ;
if ( ! GetLengthParam( vsParams[2], dLen))
return false ;
// recupero l'angolo in verticale (non c'è metodo generale)
// recupero l'angolo in verticale (non c'è metodo generale)
double dAngVertDeg ;
if ( ! FromString( vsParams[3], dAngVertDeg))
return false ;
@@ -410,7 +410,7 @@ GdbExecutor::VectorCrossProduct( const STRVECTOR& vsParams)
// 4 o 5 parametri : Id, IdParent, vtV1, vtV2 [, bNorm]
if ( vsParams.size() != 4 && vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect))
return false ;
@@ -444,7 +444,7 @@ GdbExecutor::VectorDifference( const STRVECTOR& vsParams)
// 4 o 5 parametri : Id, IdParent, ptP1, ptP2 [, bNorm]
if ( vsParams.size() != 4 && vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect))
return false ;
@@ -478,7 +478,7 @@ GdbExecutor::VectorBaseVector( const STRVECTOR& vsParams)
// 4 o 5 parametri : Id, IdParent, PtBase, Vettore [, ScaleFactor]
if ( vsParams.size() != 4 && vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frVect))
return false ;
@@ -512,7 +512,7 @@ GdbExecutor::VectorModifyBase( const STRVECTOR& vsParams)
return false ;
// indice dell'oggetto
int nId = GetIdParam( vsParams[0]) ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frVect ;
if ( ! m_pGDB->GetGlobFrame( nId, frVect))
return false ;
@@ -537,7 +537,7 @@ GdbExecutor::ExecuteFrame( const string& sCmd2, const STRVECTOR& vsParams)
// 3 parametri : Id, ParentId, Frame
if ( vsParams.size() != 3)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -557,7 +557,7 @@ GdbExecutor::ExecuteFrame( const string& sCmd2, const STRVECTOR& vsParams)
// 5 parametri : Id, ParentId, ptOrig, ptOnX, ptNearY
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -579,7 +579,7 @@ GdbExecutor::ExecuteFrame( const string& sCmd2, const STRVECTOR& vsParams)
// 4 parametri
if ( vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -634,7 +634,7 @@ GdbExecutor::CurveLineMake( const STRVECTOR& vsParams)
// 4 parametri : Id, IdParent, ptStart, ptEnd
if ( vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -664,7 +664,7 @@ GdbExecutor::CurveLineVersorLength( const STRVECTOR& vsParams)
// 5 parametri : Id, IdParent, ptStart, vtDir, dLen
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -698,7 +698,7 @@ GdbExecutor::CurveLineDirLength( const STRVECTOR& vsParams)
// 5 parametri : Id, IdParent, ptStart, dAngDeg, dLen
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -863,7 +863,7 @@ GdbExecutor::CurveLineMinPointCurve( const STRVECTOR& vsParams)
// porto il punto nel riferimento della curva
Point3d ptSloc = ptStart ;
ptSloc.LocToLoc( frPoint, frCurve) ;
// recupero eventuale parametro per discriminare tra più soluzioni
// recupero eventuale parametro per discriminare tra più soluzioni
double dNearParam ;
if ( vsParams.size() < 5 || ! FromString( vsParams[4], dNearParam))
dNearParam = 0 ;
@@ -962,7 +962,7 @@ GdbExecutor::CurveCircleMake( const STRVECTOR& vsParams)
// 5 parametri
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -996,7 +996,7 @@ GdbExecutor::CurveCirclePlaneXY( const STRVECTOR& vsParams)
// 4 parametri
if ( vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1026,7 +1026,7 @@ GdbExecutor::CurveArcMake( const STRVECTOR& vsParams)
// 8 parametri
if ( vsParams.size() != 8)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1072,7 +1072,7 @@ GdbExecutor::CurveArcPlaneXY( const STRVECTOR& vsParams)
// 7 parametri
if ( vsParams.size() != 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1114,7 +1114,7 @@ GdbExecutor::CurveArcCircle3P( const STRVECTOR& vsParams, bool bCirc)
// 5 parametri : Id, ParentId, ptP0, ptP1, ptP2
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1148,7 +1148,7 @@ GdbExecutor::CurveArc2PDi( const STRVECTOR& vsParams)
// 5 parametri : Id, ParentId, ptPi, ptPf, dDiri
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1164,7 +1164,7 @@ GdbExecutor::CurveArc2PDi( const STRVECTOR& vsParams)
double dDirI ;
if ( ! GetDirParam( vsParams[4], frRef, dDirI))
return false ;
// calcolo l'arco (in casi particolari può essere una retta)
// calcolo l'arco (in casi particolari può essere una retta)
ICurve* pCurve = GetArc2PD( ptPi, ptPf, dDirI) ;
if ( pCurve == nullptr)
return false ;
@@ -1179,7 +1179,7 @@ GdbExecutor::CurveArc2PRS( const STRVECTOR& vsParams)
// 5 o 6 parametri : Id, ParentId, ptPi, ptPf, dRad[, CCW/CW]
if ( vsParams.size() != 5 && vsParams.size() != 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1217,7 +1217,7 @@ GdbExecutor::CurveArcC2P( const STRVECTOR& vsParams)
// 5 parametri : Id, ParentId, ptCen, ptPi, ptNearPf
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1251,7 +1251,7 @@ GdbExecutor::CurveCircleCenterTgArc( const STRVECTOR& vsParams)
// 5 parametri : Id, ParentId, ptCen, IdArc, ptNear
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frDest ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest))
return false ;
@@ -1297,7 +1297,7 @@ GdbExecutor::CurveArcCenterTgArcP( const STRVECTOR& vsParams)
// 6 parametri : Id, ParentId, ptCen, IdArc, ptNearTg, ptNearEnd
if ( vsParams.size() != 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frDest ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest))
return false ;
@@ -1349,7 +1349,7 @@ GdbExecutor::CurveArcPDiTgArc( const STRVECTOR& vsParams)
// 6 parametri : Id, ParentId, ptStart, dirStart, IdArc, ptNear
if ( vsParams.size() != 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frDest ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest))
return false ;
@@ -1382,7 +1382,7 @@ GdbExecutor::CurveArcPDiTgArc( const STRVECTOR& vsParams)
return false ;
Point3d ptNtloc = ptNear ;
ptNtloc.LocToLoc( frDest, frTgArc) ;
// calcolo l'arco (in casi particolari può essere una linea)
// calcolo l'arco (in casi particolari può essere una linea)
ICurve* pCurve = GetArcPntDirTgCurve( ptSloc, FromPolar( 1, dDirI), *pTgArc, ptNtloc, Z_AX) ;
if ( pCurve == nullptr)
return false ;
@@ -1521,7 +1521,7 @@ GdbExecutor::ExecuteCurveBez( const string& sCmd2, const STRVECTOR& vsParams)
// inizializzo la curva di Bezier
if ( ! pCrvBez->Init( nDeg, false))
return false ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1547,7 +1547,7 @@ GdbExecutor::ExecuteCurveBez( const string& sCmd2, const STRVECTOR& vsParams)
// inizializzo la curva di Bezier
if ( ! pCrvBez->Init( nDeg, true))
return false ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1949,7 +1949,7 @@ GdbExecutor::CurveCompoFromPolygon( const STRVECTOR& vsParams, int nType)
int nNumLati ;
if ( ! FromString( vsParams[2], nNumLati))
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -1994,7 +1994,7 @@ GdbExecutor::CurveCompoFromBiarc( const STRVECTOR& vsParams)
// 6 o 7 parametri : Id, IdParent, ptP1, Dir1, ptP2, Dir2 [, Par]
if ( vsParams.size() != 6 && vsParams.size() != 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -2074,7 +2074,7 @@ GdbExecutor::CurveCompoExtractCurve( const STRVECTOR& vsParams, bool bEndOrStart
Frame3d frSou ;
if ( ! m_pGDB->GetGlobFrame( nIdCCompo, frSou))
return false ;
// estraggo la opportuna entità
// estraggo la opportuna entità
PtrOwner<ICurve> pCrv( pCrvCompo->RemoveFirstOrLastCurve( bEndOrStart)) ;
// se 1 solo parametro -> cancellazione
if ( vsParams.size() == 1)
@@ -2161,7 +2161,7 @@ GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams)
else if ( sCmd2 == "COMP" || sCmd2 == "DOCOMPACTING") {
return SurfTriMeshDoCompacting( vsParams) ;
}
// se unione di due o più superfici per cucitura
// se unione di due o più superfici per cucitura
else if ( sCmd2 == "SEW" || sCmd2 == "DOSEWING") {
return SurfTriMeshDoSewing( vsParams) ;
}
@@ -2395,7 +2395,7 @@ GdbExecutor::SurfTriMeshByExtrusion( const STRVECTOR& vsParams)
CurveLocal CrvLoc( m_pGDB, nCrvId, frDest) ;
if ( CrvLoc.Get() == nullptr)
return false ;
// recupero il vettore di estrusione (già in locale)
// recupero il vettore di estrusione (già in locale)
Vector3d vtExtr ;
if ( ! GetVectorParam( vsParams[3], frDest, vtExtr))
return false ;
@@ -2471,7 +2471,7 @@ GdbExecutor::SurfTriMeshByScrewing( bool bMove, const STRVECTOR& vsParams)
// recupero la tolleranza lineare
if ( vsParams.size() == 7)
FromString( vsParams[6], dLinTol) ;
// non c'é movimento lungo l'asse
// non c'é movimento lungo l'asse
}
// recupero il riferimento del gruppo destinazione
Frame3d frDest ;
@@ -2642,7 +2642,7 @@ GdbExecutor::SurfTrimeshClonePart( const STRVECTOR& vsParams)
// Parametri : IdNew, IdOld, IdParent, nPart
if ( vsParams.size() != 4)
return false ;
// Recupero il riferimento in cui è immerso
// Recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[2]), frRef))
return false ;
@@ -2785,7 +2785,7 @@ GdbExecutor::VolZmapCreate( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptO, dLengthX, dLengthY, dLengthZ, dPrec [, bTriDexel]
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -2829,7 +2829,7 @@ GdbExecutor::VolZmapCreateFromFlatRegion( const STRVECTOR& vsParams)
// parametri : Id, IdParent, idCurv, dPrec, dLengthZ [, bTriDexel]
if ( vsParams.size() < 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -2867,7 +2867,7 @@ GdbExecutor::VolZmapCreateFromTriMesh( const STRVECTOR& vsParams)
// parametri : Id, IdParent, idSurf, dPrec, bFlag
if ( vsParams.size() != 5)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -2900,7 +2900,7 @@ GdbExecutor::VolZmapMilling( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptPs, ptPe, vtVs, vtVe, dLinTol, dAngTolDeg (dLinTol e dAngTol sono per lavo con gen tool), bType
if ( vsParams.size() != 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3019,7 +3019,7 @@ bool GdbExecutor::VolZmapDeepnessMeasure( const STRVECTOR& vsParams) {
VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ;
if ( pZmap == nullptr)
return false ;
// recupero il riferimento in cui è immerso lo Zmap
// recupero il riferimento in cui è immerso lo Zmap
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3051,7 +3051,7 @@ GdbExecutor::VolZmapBBoxZmapIntersection( const STRVECTOR& vsParams)
VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ;
if ( pZmap == nullptr)
return false ;
// recupero il riferimento in cui è immerso lo Zmap
// recupero il riferimento in cui è immerso lo Zmap
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3096,7 +3096,7 @@ GdbExecutor::VolZmapBBoxZmapIntersection( const STRVECTOR& vsParams)
// VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ;
// if ( pZmap == nullptr)
// return false ;
// // recupero il riferimento in cui è immerso lo Zmap
// // recupero il riferimento in cui è immerso lo Zmap
// Frame3d frRef ;
// if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
// return false ;
@@ -3143,7 +3143,7 @@ GdbExecutor::VolZmapBBoxZmapIntersection( const STRVECTOR& vsParams)
// VolZmap* pZmap = GetBasicVolZmap( m_pGDB->GetGeoObj( nZmapId)) ;
// if ( pZmap == nullptr)
// return false;
// // recupero il riferimento in cui è immerso lo Zmap
// // recupero il riferimento in cui è immerso lo Zmap
// Frame3d frRef ;
// if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
// return false ;
@@ -3213,7 +3213,7 @@ GdbExecutor::LineDiscInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptDisc, ptLine, vtDisc, vtLine, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3281,7 +3281,7 @@ GdbExecutor::RayDiscInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptDisc, ptLine, vtDisc, vtLine, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3349,7 +3349,7 @@ GdbExecutor::SegmentDiscInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptDisc, ptLine, vtDisc, vtLine, dRad, dLen
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3421,7 +3421,7 @@ GdbExecutor::LineSphereInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptC, ptP, vtV, dRad
if ( vsParams.size() < 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3472,7 +3472,7 @@ GdbExecutor::RaySphereInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptC, ptP, vtV, dRad
if ( vsParams.size() < 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3530,7 +3530,7 @@ GdbExecutor::SegmentSphereInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptC, ptP, vtV, dRad, dLen
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3594,7 +3594,7 @@ GdbExecutor::LineSemiSphereInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3651,7 +3651,7 @@ GdbExecutor::RaySemiSphereInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3714,7 +3714,7 @@ GdbExecutor::SegmentSemiSphereInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad, dLen
if ( vsParams.size() < 8)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3783,7 +3783,7 @@ GdbExecutor::LinCompSemiSphereInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad, dLen, nLinType
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3854,7 +3854,7 @@ GdbExecutor::LineInfiniteCylinderInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3923,7 +3923,7 @@ GdbExecutor::RayInfiniteCylinderInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad
if ( vsParams.size() < 7)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -3992,7 +3992,7 @@ GdbExecutor::SegmentInfiniteCylinderInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad, dLen
if ( vsParams.size() < 8)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4064,7 +4064,7 @@ GdbExecutor::SegmentCylinderInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad, dCylHeigth, dLen
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4140,7 +4140,7 @@ GdbExecutor::SegmentConeInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptVCone, ptLine, vtCone, vtLine, dRad, dCylHeigth, dLen
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4221,7 +4221,7 @@ GdbExecutor::LineTruncateConeInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4303,7 +4303,7 @@ GdbExecutor::RayTruncateConeInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4384,7 +4384,7 @@ GdbExecutor::SegmentTruncateConeInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth
if ( vsParams.size() < 10)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4469,7 +4469,7 @@ GdbExecutor::LineTorusInters( const STRVECTOR& vsParams)
{ // parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad,
if ( vsParams.size() < 8)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4584,7 +4584,7 @@ GdbExecutor::RayTorusInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad,
if ( vsParams.size() < 8)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4734,7 +4734,7 @@ GdbExecutor::SegmentTorusInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, dSgLen
if ( vsParams.size() < 9)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -4903,7 +4903,7 @@ GdbExecutor::LinCompTorusPartInters( const STRVECTOR& vsParams)
// parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, dSgLen, nLinType
if ( vsParams.size() < 10)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -5124,7 +5124,7 @@ GdbExecutor::ExecuteDistPointTrimesh( const std::string& sCmd2, const STRVECTOR&
// parametri : Id, IdMovedTria, IdParent, ptP, idSurf
if ( vsParams.size() != 4)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -5228,7 +5228,7 @@ GdbExecutor::TextSimple( const STRVECTOR& vsParams)
// parametri : Id, ParentId, Text, Point, AngDeg, H
if ( vsParams.size() != 6)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -5266,7 +5266,7 @@ GdbExecutor::TextComplete( const STRVECTOR& vsParams)
// parametri : Id, ParentId, Text, Point, AngDeg, Font, W, Italic, H, Rat, AddAdv, PosIns
if ( vsParams.size() != 12)
return false ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frRef ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef))
return false ;
@@ -5486,7 +5486,7 @@ GdbExecutor::AddGeoObj( const string& sId, const string& sIdParent, IGeoObj* pGe
// creo il gruppo
int nId = GetIdParam( sId, true) ;
int nIdNew = m_pGDB->AddGeoObj( nId, GetIdParam( sIdParent), pGeoObj) ;
// se nId da calcolare, può essere una variabile a cui cambiare il valore
// se nId da calcolare, può essere una variabile a cui cambiare il valore
if ( nId == GDB_ID_NULL)
m_pParser->SetVariable( sId, nIdNew) ;
@@ -5600,9 +5600,9 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
// ci deve essere almeno un parametro
if ( vsParams.size() < 1)
return false ;
// recupero l'indice dell'entità indicata dal primo parametro
// recupero l'indice dell'entità indicata dal primo parametro
int nIdEnt = GetIdParam( vsParams[0]) ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frEnt ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt, frEnt))
return false ;
@@ -5623,7 +5623,7 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
return false ;
}
}
// se entità geometrica
// se entità geometrica
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGDB->GetGeoObj( nIdEnt)) != nullptr) {
// se curva
@@ -5659,7 +5659,7 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
return false ;
return vtV.LocToLoc( frEnt, frVect) ;
}
case 'N' : // versore direzione nel punto più vicino a punto dato
case 'N' : // versore direzione nel punto più vicino a punto dato
{
// secondo parametro : punto di riferimento
Point3d ptRef ;
@@ -5669,7 +5669,7 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
ICurve::Side nSide = ICurve::FROM_MINUS ;
if ( vsParams.size() >= 3 && vsParams[2] == "+")
nSide = ICurve::FROM_PLUS ;
// calcolo il parametro del punto della curva più vicino al punto di riferimento
// calcolo il parametro del punto della curva più vicino al punto di riferimento
DistPointCurve dstPC( ptRef, *pCrv) ;
int nFlag ;
double dU ;
@@ -5723,7 +5723,7 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
}
return false ;
}
// altrimenti nome di vettore già nel DB
// altrimenti nome di vettore già nel DB
else {
int nIdEnt = GetIdParam( sParam) ;
const IGeoVector3d* pV ;
@@ -5742,7 +5742,7 @@ GdbExecutor::GetVectorParam( const string& sParam, const Frame3d& frVect, Vector
bool
GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d& ptP)
{
// se insieme di 2 o 3 coordinate (considerate già nel riferimento frPnt)
// se insieme di 2 o 3 coordinate (considerate già nel riferimento frPnt)
if ( sParam[0] == '(') {
// divido in parti
STRVECTOR vsParams ;
@@ -5766,7 +5766,7 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
else
return false ;
}
// se altrimenti punto predefinito ORIG (considerato già nel riferimento frPnt)
// se altrimenti punto predefinito ORIG (considerato già nel riferimento frPnt)
else if ( sParam == "ORIG") {
ptP = ORIG ;
return true ;
@@ -5784,9 +5784,9 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
// ci deve essere almeno un parametro
if ( vsParams.size() < 1)
return false ;
// recupero l'indice dell'entità indicata dal primo parametro
// recupero l'indice dell'entità indicata dal primo parametro
int nIdEnt = GetIdParam( vsParams[0]) ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frEnt ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt, frEnt))
return false ;
@@ -5801,7 +5801,7 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
return false ;
}
}
// se entità geometrica
// se entità geometrica
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGDB->GetGeoObj( nIdEnt)) != nullptr) {
// se curva
@@ -5835,13 +5835,13 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
return false ;
return ptP.LocToLoc( frEnt, frPnt) ;
}
case 'N' : // punto più vicino a punto dato
case 'N' : // punto più vicino a punto dato
{
// secondo parametro : punto di riferimento
Point3d ptRef ;
if ( vsParams.size() < 2 || ! GetPointParam( vsParams[1], frEnt, ptRef))
return false ;
// calcolo il punto della curva più vicino al punto di riferimento
// calcolo il punto della curva più vicino al punto di riferimento
DistPointCurve dstPC( ptRef, *pCrv) ;
int nFlag ;
if ( ! dstPC.GetMinDistPoint( 0, ptP, nFlag))
@@ -5859,11 +5859,11 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
const ICurve* pCrv2 = GetCurve( pGObj2) ;
if ( pCrv2 == nullptr)
return false ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frEnt2 ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt2, frEnt2))
return false ;
// se il riferimento è diverso da quello della prima entità, devo trasformarla
// se il riferimento è diverso da quello della prima entità, devo trasformarla
PtrOwner<ICurve> pcrvTrans( nullptr) ;
if ( ! AreSameFrame( frEnt, frEnt2)) {
pcrvTrans.Set( pCrv2->Clone()) ;
@@ -5876,7 +5876,7 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
Point3d ptRef ;
if ( vsParams.size() >= 3 && ! GetPointParam( vsParams[2], frEnt, ptRef))
return false ;
// calcolo il punto di intersezione sulla prima curva più vicino al punto di riferimento
// calcolo il punto di intersezione sulla prima curva più vicino al punto di riferimento
IntersCurveCurve intCC( *pCrv, *pCrv2, true) ;
if ( ! intCC.GetIntersPointNearTo( 0, ptRef, ptP))
return false ;
@@ -5938,7 +5938,7 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d&
}
return false ;
}
// altrimenti nome di punto già nel DB
// altrimenti nome di punto già nel DB
else {
int nIdEnt = GetIdParam( sParam) ;
const IGeoPoint3d* pPt ;
@@ -6015,7 +6015,7 @@ GdbExecutor::GetPointWParam( const string& sParam, const Frame3d& frPnt, Point3d
FromString( vsParams[1], ptP.y) &&
FromString( vsParams[2], dW)) ;
}
// se 2 parti, nome di punto predefinito, punto notevole o già nel DB e un peso
// se 2 parti, nome di punto predefinito, punto notevole o già nel DB e un peso
else if ( vsParams.size() == 2) {
// recupero il punto
if ( ! GetPointParam( vsParams[0], frPnt, ptP))
@@ -6065,7 +6065,7 @@ GdbExecutor::GetLengthParam( const string& sParam, double& dLen)
// ci deve essere almeno un parametro
if ( vsParams.size() < 1)
return false ;
// recupero l'entità indicata dal primo parametro
// recupero l'entità indicata dal primo parametro
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGDB->GetGeoObj( GetIdParam( vsParams[0]))) == nullptr)
return false ;
@@ -6088,7 +6088,7 @@ GdbExecutor::GetLengthParam( const string& sParam, double& dLen)
// ci deve essere almeno un parametro
if ( vsParams.size() < 1)
return false ;
// recupero l'entità indicata dal primo parametro
// recupero l'entità indicata dal primo parametro
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGDB->GetGeoObj( GetIdParam( vsParams[0]))) == nullptr)
return false ;
@@ -6124,12 +6124,12 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
// ci deve essere almeno un parametro
if ( vsParams.size() < 1)
return false ;
// recupero l'entità indicata dal primo parametro
// recupero l'entità indicata dal primo parametro
int nIdEnt = GetIdParam( vsParams[0]) ;
const IGeoObj* pGObj ;
if ( ( pGObj = m_pGDB->GetGeoObj( nIdEnt)) == nullptr)
return false ;
// recupero il riferimento in cui è immersa
// recupero il riferimento in cui è immersa
Frame3d frEnt ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt, frEnt))
return false ;
@@ -6143,7 +6143,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
if ( ! pCrv->GetStartDir( vtDir) || ! vtDir.LocToLoc( frEnt, frDir))
return false ;
vtDir.ToSpherical( nullptr, nullptr, &dDir) ;
// se esiste un secondo parametro è un offset di rotazione
// se esiste un secondo parametro è un offset di rotazione
if ( vsParams.size() >= 2) {
double dOffsetDeg = 0 ;
FromString( vsParams[1], dOffsetDeg) ;
@@ -6154,7 +6154,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
if ( ! pCrv->GetEndDir( vtDir) || ! vtDir.LocToLoc( frEnt, frDir))
return false ;
vtDir.ToSpherical( nullptr, nullptr, &dDir) ;
// se esiste un secondo parametro è un offset di rotazione
// se esiste un secondo parametro è un offset di rotazione
if ( vsParams.size() >= 2) {
double dOffsetDeg = 0 ;
FromString( vsParams[1], dOffsetDeg) ;
@@ -6165,7 +6165,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
if ( ! pCrv->GetMidDir( vtDir) || ! vtDir.LocToLoc( frEnt, frDir))
return false ;
vtDir.ToSpherical( nullptr, nullptr, &dDir) ;
// se esiste un secondo parametro è un offset di rotazione
// se esiste un secondo parametro è un offset di rotazione
if ( vsParams.size() >= 2) {
double dOffsetDeg = 0 ;
FromString( vsParams[1], dOffsetDeg) ;
@@ -6196,7 +6196,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
}
return true ;
}
case 'N' : // versore direzione nel punto più vicino a punto dato
case 'N' : // versore direzione nel punto più vicino a punto dato
{
// secondo parametro : punto di riferimento
Point3d ptRef ;
@@ -6206,7 +6206,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
ICurve::Side nSide = ICurve::FROM_MINUS ;
if ( vsParams.size() >= 3 && vsParams[2] == "+")
nSide = ICurve::FROM_PLUS ;
// calcolo il parametro del punto della curva più vicino al punto di riferimento
// calcolo il parametro del punto della curva più vicino al punto di riferimento
DistPointCurve dstPC( ptRef, *pCrv) ;
int nFlag ;
double dU ;
@@ -6236,7 +6236,7 @@ GdbExecutor::GetDirParam( const string& sParam, const Frame3d& frDir, double& dD
Vector3d vtDir = pGVect->GetVector() ;
vtDir.LocToLoc( frEnt, frDir) ;
vtDir.ToSpherical( nullptr, nullptr, &dDir) ;
// se esiste un secondo parametro è un offset di rotazione
// se esiste un secondo parametro è un offset di rotazione
if ( vsParams.size() >= 2) {
double dOffsetDeg = 0 ;
FromString( vsParams[1], dOffsetDeg) ;
@@ -6294,7 +6294,7 @@ GdbExecutor::GetFrameParam( const string& sParam, const Frame3d& frRef, Frame3d&
STRVECTOR::iterator Iter ;
for ( Iter = vsParams.begin() ; Iter != vsParams.end() ; ++Iter)
Trim( (*Iter), " \t\r\n") ;
// se c'è un parametro è l'origine
// se c'è un parametro è l'origine
Point3d ptOrig ;
if ( vsParams.size() >= 1) {
if ( ! GetPointParam( vsParams[0], frRef, ptOrig))
@@ -6325,11 +6325,11 @@ GdbExecutor::GetFrameParam( const string& sParam, const Frame3d& frRef, Frame3d&
}
return true ;
}
// altrimenti nome di gruppo o di frame già nel DB
// altrimenti nome di gruppo o di frame già nel DB
else {
// identificativo
int nIdEnt = GetIdParam( sParam) ;
// recupero il riferimento in cui è immerso
// recupero il riferimento in cui è immerso
Frame3d frEnt ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt, frEnt))
return false ;
@@ -6337,7 +6337,7 @@ GdbExecutor::GetFrameParam( const string& sParam, const Frame3d& frRef, Frame3d&
if ( m_pGDB->GetGroupFrame( nIdEnt, frF)) {
return frF.LocToLoc( frEnt, frRef) ;
}
// altrimenti entità geometrica
// altrimenti entità geometrica
else {
// verifico se riferimento
const IGeoFrame3d* pFr ;
@@ -6393,7 +6393,7 @@ GdbExecutor::GetColorParam( const string& sParam, bool& bByParent, Color& cCol)
// ci deve essere un parametro
if ( vsParams.size() != 1)
return false ;
// recupero il colore dell'entità indicata dal parametro
// recupero il colore dell'entità indicata dal parametro
bByParent = false ;
return m_pGDB->GetCalcMaterial( GetIdParam( vsParams[0]), cCol) ;
}
@@ -6427,7 +6427,7 @@ GdbExecutor::GetMaterialParam( const string& sParam, bool& bByParent, int& nMat)
// ci deve essere un parametro
if ( vsParams.size() != 1)
return false ;
// recupero il materiale dell'entità indicata dal parametro
// recupero il materiale dell'entità indicata dal parametro
bByParent = false ;
return ( m_pGDB->GetCalcMaterial( GetIdParam( vsParams[0]), nMat) && nMat != GDB_MT_COLOR) ;
}
@@ -6975,7 +6975,7 @@ GdbExecutor::ExecuteCopy( const string& sCmd2, const STRVECTOR& vsParams)
nIdNew = m_pGDB->CopyGlob( GetIdParam( vsParams[0]), nIdDest, GetIdParam( vsParams[2]), nSonBeforeAfter) ;
else
nIdNew = m_pGDB->Copy( GetIdParam( vsParams[0]), nIdDest, GetIdParam( vsParams[2]), nSonBeforeAfter) ;
// se IdDest da calcolare, può essere una variabile a cui cambiare il valore
// se IdDest da calcolare, può essere una variabile a cui cambiare il valore
if ( nIdDest == GDB_ID_NULL)
m_pParser->SetVariable( vsParams[1], nIdNew) ;
@@ -7647,7 +7647,7 @@ GdbExecutor::CurveCopyBySplitClass( const STRVECTOR& vsParams)
IntersCurveCurve intCC( *pCrv, *pCloCrv, true) ;
// recupero la classificazione della prima curva
CRVCVECTOR ccClass ;
if ( ! intCC.GetCurveClassification( 0, EPS_SMALL, ccClass))
if ( ! intCC.GetCurveClassification( 0, ccClass))
return false ;
// recupero gli indici dei gruppi destinazione e i loro riferimenti
const int N_GRP = 4 ;
@@ -7877,7 +7877,7 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams)
// devono essere 6 parametri : IdText, IdGroup, IdEnt1, IdEnt2, ptText, hText
if ( vsParams.size() != 6)
return false ;
// recupero l'indice delle entità
// recupero l'indice delle entità
int nIdEnt1 = GetIdParam( vsParams[2]) ;
int nIdEnt2 = GetIdParam( vsParams[3]) ;
// verifico siano due curve
@@ -7894,7 +7894,7 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams)
Frame3d frEnt2 ;
if ( ! m_pGDB->GetGlobFrame( nIdEnt2, frEnt2))
return false ;
// se i riferimenti sono diversi, porto la seconda entità nel riferimento della prima
// se i riferimenti sono diversi, porto la seconda entità nel riferimento della prima
PtrOwner<ICurve> pcrvTrans ;
if ( ! AreSameFrame( frEnt1, frEnt2)) {
pcrvTrans.Set( pCrv2->Clone()) ;
@@ -7953,7 +7953,7 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams)
}
}
}
// recupero il riferimento in cui è immerso il testo
// recupero il riferimento in cui è immerso il testo
Frame3d frText ;
if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frText))
return false ;
@@ -8090,7 +8090,7 @@ bool
GdbExecutor::OutGroupTsc( int nId, int nFlag, int nLev)
{
m_OutTsc.Remark( "Start Group ---") ;
// emetto dati gruppo ( se non è radice)
// emetto dati gruppo ( se non è radice)
if ( nId > GDB_ID_ROOT) {
Frame3d frFrame ;
if ( ( nLev == 0 && m_pGDB->GetGroupGlobFrame( nId, frFrame)) ||
@@ -8113,7 +8113,7 @@ GdbExecutor::OutGroupTsc( int nId, int nFlag, int nLev)
}
}
}
// emetto entità gruppo
// emetto entità gruppo
m_OutTsc.Remark( "Entities :") ;
GdbIterator Iter( m_pGDB) ;
bool bNext = Iter.GoToFirstInGroup( nId) ;
+2 -3
View File
@@ -32,9 +32,8 @@ using namespace std ;
//----------------------------------------------------------------------------
GdbObj::GdbObj( void)
: m_nId( GDB_ID_NULL), m_pAttribs( nullptr), m_pTxrData( nullptr), m_pUserObj( nullptr),
m_pGDB( nullptr), m_pNext( nullptr), m_pPrev( nullptr), m_pParent( nullptr),
m_pSelNext( nullptr), m_pSelPrev( nullptr)
m_pSelPrev( nullptr), m_pSelNext( nullptr),
m_pGDB( nullptr), m_pNext( nullptr), m_pPrev( nullptr), m_pParent( nullptr)
{
}
+2 -5
View File
@@ -29,10 +29,8 @@ GEOOBJ_REGISTER( GEO_FRAME3D, NGE_G_FRM, GeoFrame3d) ;
//----------------------------------------------------------------------------
GeoFrame3d::GeoFrame3d( void)
: m_frF()
: m_frF(), m_nTempProp()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -116,8 +114,7 @@ GeoFrame3d::CopyFrom( const GeoFrame3d& gfSrc)
{
if ( &gfSrc == this)
return true ;
m_nTempProp[0] = gfSrc.m_nTempProp[0] ;
m_nTempProp[1] = gfSrc.m_nTempProp[1] ;
m_nTempProp = gfSrc.m_nTempProp ;
return Set( gfSrc.m_frF) ;
}
+5 -6
View File
@@ -57,11 +57,10 @@ class GeoFrame3d : public IGeoFrame3d, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // IGeoFrame3d
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -96,5 +95,5 @@ class GeoFrame3d : public IGeoFrame3d, public IGeoObjRW
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
Frame3d m_frF ; // oggetto
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
} ;
+2 -5
View File
@@ -28,10 +28,8 @@ GEOOBJ_REGISTER( GEO_PNT3D, NGE_G_PNT, GeoPoint3d) ;
//----------------------------------------------------------------------------
GeoPoint3d::GeoPoint3d( void)
: m_ptP()
: m_ptP(), m_nTempProp()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -84,8 +82,7 @@ GeoPoint3d::CopyFrom( const GeoPoint3d& clSrc)
{
if ( &clSrc == this)
return true ;
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
m_nTempProp = clSrc.m_nTempProp ;
return Set( clSrc.m_ptP) ;
}
+5 -6
View File
@@ -57,11 +57,10 @@ class GeoPoint3d : public IGeoPoint3d, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // IGeoPoint3d
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -90,5 +89,5 @@ class GeoPoint3d : public IGeoPoint3d, public IGeoObjRW
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
Point3d m_ptP ; // oggetto
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
} ;
+2 -5
View File
@@ -29,10 +29,8 @@ GEOOBJ_REGISTER( GEO_VECT3D, NGE_G_VEC, GeoVector3d) ;
//----------------------------------------------------------------------------
GeoVector3d::GeoVector3d( void)
: m_vtV()
: m_vtV(), m_nTempProp()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -100,8 +98,7 @@ GeoVector3d::CopyFrom( const GeoVector3d& clSrc)
{
if ( &clSrc == this)
return true ;
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
m_nTempProp = clSrc.m_nTempProp ;
return Set( clSrc.m_vtV, clSrc.m_ptBase) ;
}
+5 -6
View File
@@ -65,11 +65,10 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // IGeoVector3d
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -105,5 +104,5 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
Vector3d m_vtV ; // oggetto
Point3d m_ptBase ; // punto base da cui tracciare il vettore
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
} ;
+1
View File
@@ -684,6 +684,7 @@ HashGrids3d::Update( void)
double dSize = 0 ;
Obj.box.GetDiameter( dSize) ;
double dCellSpan = pGrid->GetCellSpan() ;
if ( dSize >= dCellSpan || dSize < ( dCellSpan / hierarchyFactor)) {
pGrid->Remove( Obj) ;
addGrid( Obj) ;
+8 -10
View File
@@ -391,7 +391,7 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
//----------------------------------------------------------------------------
bool
IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR& ccClass)
IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
{
// pulisco vettore classificazioni
ccClass.clear() ;
@@ -407,7 +407,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
return false ;
// se esiste almeno una intersezione
if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[0], m_Info, dLenMin, ccClass) ;
return CalcCurveClassification( m_pCurve[0], m_Info, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna
else
return CalcCurveInOrOut( m_pCurve[0], m_pCurve[1], ccClass) ;
@@ -424,7 +424,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR&
SwapInfoAB( InfoTmp, 1) ;
// se esiste almeno una intersezione
if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[1], InfoTmp, dLenMin, ccClass) ;
return CalcCurveClassification( m_pCurve[1], InfoTmp, ccClass) ;
// altrimenti la curva è completamente interna oppure completamente esterna
else
return CalcCurveInOrOut( m_pCurve[1], m_pCurve[0], ccClass) ;
@@ -461,7 +461,7 @@ IntersCurveCurve::SwapInfoAB( ICCIVECTOR& Info, int IndCrvOrd)
//----------------------------------------------------------------------------
bool
IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTOR& Info, double dLenMin, CRVCVECTOR& ccClass)
IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTOR& Info, CRVCVECTOR& ccClass)
{
// numero intersezioni
int nNumInters = int( Info.size()) ;
@@ -471,8 +471,6 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
double dStartPar, dEndPar ;
if ( pCurve == nullptr || ! pCurve->GetDomain( dStartPar, dEndPar))
return false ;
// limito lunghezza minima
dLenMin = max( dLenMin, EPS_ZERO) ;
// elimino intersezioni senza attraversamento che giacciono in intervalli di sovrapposizione
ICCIVECTOR InfoCorr ;
InfoCorr.reserve( Info.size()) ;
@@ -529,7 +527,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
for ( int i = 0 ; i < nNumInters ; ++ i) {
// se è definito un tratto precedente
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].IciA[0].dU, dLenU) ;
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > EPS_SMALL) {
// verifico che la definizione sul tratto sia omogenea e valida
int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ;
if ( ( nLastTy != ICCT_NULL && nPrevTy != nLastTy) ||
@@ -564,7 +562,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
}
}
// eventuale tratto finale rimasto
if ( dCurrPar < dEndPar - EPS_PARAM && dEndLen - dCurrLen > dLenMin) {
if ( dCurrPar < dEndPar - EPS_PARAM && dEndLen - dCurrLen > EPS_SMALL) {
// verifico che la definizione sul tratto sia valida
if ( nLastTy == ICCT_NULL || nLastTy == ICCT_ON)
return false ;
@@ -675,7 +673,7 @@ IntersCurveCurve::GetRegionCurveClassification( void)
{
// classifico la prima curva rispetto alla seconda
CRVCVECTOR ccClass ;
if ( ! GetCurveClassification( 0, EPS_SMALL, ccClass))
if ( ! GetCurveClassification( 0, ccClass))
return CCREGC_NULL ;
// derivo la classificazione delle curve come regioni
bool bIn = false ;
@@ -712,7 +710,7 @@ IntersCurveCurve::GetRegionCurveClassification( void)
if ( bOnP)
return CCREGC_IN2 ;
CRVCVECTOR ccClass2 ;
if ( ! GetCurveClassification( 1, EPS_SMALL, ccClass2) || ccClass2.empty())
if ( ! GetCurveClassification( 1, ccClass2) || ccClass2.empty())
return CCREGC_NULL ;
if ( ccClass2[0].nClass == CRVC_OUT)
return CCREGC_OUT ;
+104 -123
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2020-2022
// EgalTech 2020-2020
//----------------------------------------------------------------------------
// File : IntersLineBox.cpp Data : 08.01.22 Versione : 2.4a3
// File : IntersLineBox.cpp Data : 07.05.20 Versione : 2.2e1
// Contenuto : Implementazione della intersezione linea/box.
//
//
@@ -13,77 +13,13 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "IntersLineBox.h"
#include "SurfTriMesh.h"
#include "/EgtDev/Include/EGkIntersLineBox.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include <algorithm>
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.
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
const Point3d& ptMin, const Point3d& ptMax,
double& dU1, double& dU2)
{
// Verifico il versore
if ( vtL.IsSmall())
return false ;
// Verifico gli estremi del box
if ( ptMin.x > ptMax.x + EPS_SMALL ||
ptMin.y > ptMax.y + EPS_SMALL ||
ptMin.z > ptMax.z + EPS_SMALL)
return false ;
// Casi di intersezione impossibile
if ( abs( vtL.x) < EPS_ZERO && ( ptL.x < ptMin.x - EPS_SMALL || ptL.x > ptMax.x + EPS_SMALL))
return false ;
if ( abs( vtL.y) < EPS_ZERO && ( ptL.y < ptMin.y - EPS_SMALL || ptL.y > ptMax.y + EPS_SMALL))
return false ;
if ( abs( vtL.z) < EPS_ZERO && ( ptL.z < ptMin.z - EPS_SMALL || ptL.z > ptMax.z + EPS_SMALL))
return false ;
// Parametri degli estremi della retta
dU1 = -INFINITO ;
dU2 = INFINITO ;
// Confronto con piani YZ (perpendicolari ad asse X)
if ( vtL.x > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.x - ptL.x) / vtL.x) ;
dU2 = min( dU2, ( ptMax.x - ptL.x) / vtL.x) ;
}
else if ( vtL.x < -EPS_ZERO) {
dU1 = max( dU1, ( ptMax.x - ptL.x) / vtL.x) ;
dU2 = min( dU2, ( ptMin.x - ptL.x) / vtL.x) ;
}
// Confronto con piani ZX (perpendicolari ad asse Y)
if ( vtL.y > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.y - ptL.y) / vtL.y) ;
dU2 = min( dU2, ( ptMax.y - ptL.y) / vtL.y) ;
}
else if ( vtL.y < -EPS_ZERO) {
dU1 = max( dU1, ( ptMax.y - ptL.y) / vtL.y) ;
dU2 = min( dU2, ( ptMin.y - ptL.y) / vtL.y) ;
}
// Confronto con piani XY (perpendicolari ad asse Z)
if ( vtL.z > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.z - ptL.z) / vtL.z) ;
dU2 = min( dU2, ( ptMax.z - ptL.z) / vtL.z) ;
}
else if ( vtL.z < -EPS_ZERO){
dU1 = max( dU1, ( ptMax.z - ptL.z) / vtL.z) ;
dU2 = min( dU2, ( ptMin.z - ptL.z) / vtL.z) ;
}
return ( dU2 >= dU1) ;
}
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptL1, const Point3d& ptL2, const BBox3d& b3Box, INTDBLVECTOR& vInters, bool bFinite)
@@ -102,69 +38,114 @@ bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3d& b3Box, INTDBLVECTOR& vInters, bool bFinite)
{
// Recupero i dati del Box
Point3d ptMin, ptMax ;
if ( ! b3Box.GetMinMax( ptMin, ptMax))
Point3d ptMin ;
double dDimX, dDimY, dDimZ ;
if ( ! b3Box.GetMinDim( ptMin, dDimX, dDimY, dDimZ))
return false ;
// Pulisco vettore intersezioni
vInters.clear() ;
// Eseguo intersezione della linea completa
double dU1, dU2 ;
bool bInters = IntersLineBox( ptL, vtL, b3Box.GetMin(), b3Box.GetMax(), dU1, dU2) ;
// Se non c'è intersezione
if ( ! bInters || ( bFinite && ( dU1 > dLen + EPS_SMALL || dU2 < -EPS_SMALL)))
return true ;
// Se le due intersezioni coincidono
if ( ( dU2 - dU1) < EPS_SMALL) {
double dU = ( dU1 + dU2) / 2 ;
if ( ! bFinite) {
vInters.emplace_back( ILBT_TOUCH, dU) ;
// Contorno di base
PolyLine PL ;
PL.AddUPoint( 0, ptMin) ;
PL.AddUPoint( 1, ptMin + Vector3d( dDimX, 0, 0)) ;
PL.AddUPoint( 2, ptMin + Vector3d( dDimX, dDimY, 0)) ;
PL.AddUPoint( 3, ptMin + Vector3d( 0, dDimY, 0)) ;
PL.Close() ;
// Vettore altezza
Vector3d vtExtr( 0, 0, dDimZ) ;
// Creo la superficie trimesh equivalente
SurfTriMesh Stm ;
if ( ! Stm.CreateByExtrusion( PL, vtExtr))
return false ;
SurfTriMesh StmBot ;
if ( ! StmBot.CreateByFlatContour( PL))
return false ;
StmBot.Invert() ;
SurfTriMesh StmTop ;
if ( ! StmTop.CreateByFlatContour( PL))
return false ;
StmTop.Translate( vtExtr) ;
if ( ! Stm.DoSewing( StmBot) || ! Stm.DoSewing( StmTop))
return false ;
// Calcolo l'intersezione
ILSIVECTOR vInfo ;
if ( ! IntersLineSurfTm( ptL, vtL, dLen, Stm, vInfo, bFinite))
return false ;
// ciclo sulle intersezioni
double dUcurr = -INFINITO ;
for ( const auto& Info : vInfo) {
// se intersezione puntuale
if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) {
int nFlag = ILBT_TOUCH ;
if ( Info.dCosDN > EPS_ZERO)
nFlag = ILBT_OUT ;
else if ( Info.dCosDN < -EPS_ZERO)
nFlag = ILBT_IN ;
vInters.emplace_back( nFlag, Info.dU) ;
dUcurr = Info.dU ;
}
else {
if ( dU > - EPS_SMALL && dU < dLen + EPS_SMALL)
vInters.emplace_back( ILBT_TOUCH, Clamp( dU, 0., dLen)) ;
// se altrimenti intersezione con coincidenza
else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) {
if ( Info.dU > dUcurr - EPS_SMALL)
vInters.emplace_back( ILBT_TG_INI, Info.dU) ;
vInters.emplace_back( ILBT_TG_FIN, Info.dU2) ;
dUcurr = Info.dU2 ;
}
return true ;
}
// Se sono due intersezioni con la linea giacente su una faccia del box
if ( ( abs( vtL.x) < EPS_ZERO && ( abs( ptL.x - ptMin.x) < EPS_SMALL || abs( ptL.x - ptMax.x) < EPS_SMALL)) ||
( abs( vtL.y) < EPS_ZERO && ( abs( ptL.y - ptMin.y) < EPS_SMALL || abs( ptL.y - ptMax.y) < EPS_SMALL)) ||
( abs( vtL.z) < EPS_ZERO && ( abs( ptL.z - ptMin.z) < EPS_SMALL || abs( ptL.z - ptMax.z) < EPS_SMALL))) {
if ( ! bFinite) {
vInters.emplace_back( ILBT_TG_INI, dU1) ;
vInters.emplace_back( ILBT_TG_FIN, dU2) ;
// elimino intersezioni ripetute
for ( size_t j = 1 ; j < vInters.size() ; ) {
// intersezione precedente
size_t i = j - 1 ;
// se sono dello stesso tipo, elimino una delle due
if ( vInters[i].first == vInters[j].first) {
// se entranti elimino la prima
if ( vInters[i].first == ILBT_IN || vInters[i].first == ILBT_TG_INI)
vInters.erase( vInters.begin() + i) ;
// altrimenti la seconda
else
vInters.erase( vInters.begin() + j) ;
if ( i > 0)
-- j ;
continue ;
}
else {
if ( dU1 > dLen - EPS_SMALL)
vInters.emplace_back( ILBT_IN, dLen) ;
else if ( dU2 < EPS_SMALL)
vInters.emplace_back( ILBT_OUT, 0) ;
else {
vInters.emplace_back( ILBT_TG_INI, Clamp( dU1, 0., dLen)) ;
vInters.emplace_back( ILBT_TG_FIN, Clamp( dU2, 0., dLen)) ;
// se hanno lo stesso parametro
else if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) {
// se una entrante e l'altra uscente, cambio in touch ed elimino la seconda
if ( ( vInters[i].first == ILBT_IN && vInters[j].first == ILBT_OUT) ||
( vInters[i].first == ILBT_OUT && vInters[j].first == ILBT_IN)) {
vInters[i].first = ILBT_TOUCH ;
vInters.erase( vInters.begin() + j) ;
if ( i > 0)
-- j ;
continue ;
}
// se prima puntuale e l'altra inizio o fine di coincidenza, elimino la prima
else if ( ( vInters[i].first == ILBT_IN || vInters[i].first == ILBT_OUT || vInters[i].first == ILBT_TOUCH) &&
( vInters[j].first == ILBT_TG_INI || vInters[j].first == ILBT_TG_FIN)) {
vInters.erase( vInters.begin() + i) ;
if ( i > 0)
-- j ;
continue ;
}
// se prima inizio o fine di coincidenza e l'altra puntuale, elimino la seconda
else if ( ( vInters[i].first == ILBT_TG_INI || vInters[i].first == ILBT_TG_FIN) &&
( vInters[j].first == ILBT_IN || vInters[j].first == ILBT_OUT || vInters[j].first == ILBT_TOUCH)) {
vInters.erase( vInters.begin() + j) ;
if ( i > 0)
-- j ;
continue ;
}
// se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe
else if ( ( vInters[i].first == ILBT_TG_FIN && vInters[j].first == ILBT_TG_INI) ||
( vInters[i].first == ILBT_TG_INI && vInters[j].first == ILBT_TG_FIN)) {
vInters.erase( vInters.begin() + j) ;
vInters.erase( vInters.begin() + i) ;
if ( i > 0)
-- j ;
continue ;
}
}
return true ;
// passo alla successiva
++ j ;
}
// Altrimenti sono due intersezioni con attraversamento
if ( ! bFinite) {
vInters.emplace_back( ILBT_IN, dU1) ;
vInters.emplace_back( ILBT_OUT, dU2) ;
}
else {
if ( dU1 > dLen - EPS_SMALL)
vInters.emplace_back( ILBT_IN, dLen) ;
else if ( dU2 < EPS_SMALL)
vInters.emplace_back( ILBT_OUT, 0) ;
else {
vInters.emplace_back( ILBT_IN, Clamp( dU1, 0., dLen)) ;
vInters.emplace_back( ILBT_OUT, Clamp( dU2, 0., dLen)) ;
}
}
return true ;
}
-34
View File
@@ -1,34 +0,0 @@
//----------------------------------------------------------------------------
// EgalTech 2022-2022
//----------------------------------------------------------------------------
// File : IntersLineBox.h Data : 08.01.22 Versione : 2.4a3
// Contenuto : Dichiarazione delle funzioni base per intersezione linea/box.
//
//
//
// Modifiche : 08.01.22 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#pragma once
#include "/EgtDev/Include/EGkPoint3d.h"
//----------------------------------------------------------------------------
// Linea e box allineato agli assi sono nel medesimo riferimento.
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL,
const Point3d& ptMin, const Point3d& ptMax,
double& dU1, double& dU2) ;
//----------------------------------------------------------------------------
inline bool
TestIntersLineBox( const Point3d& ptL, const Vector3d& vtL,
const Point3d& ptMin, const Point3d& ptMax)
{
double dU1, dU2 ;
return IntersLineBox( ptL, vtL, ptMin, ptMax, dU1, dU2) ;
}
+56 -3
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2017-2022
// EgalTech 2017-2018
//----------------------------------------------------------------------------
// File : IntersLineSurfStd.cpp Data : 08.01.22 Versione : 2.4a3
// File : IntersLineSurfStd.cpp Data : 03.12.18 Versione : 1.9l1
// Contenuto : Implementazione delle funzioni di intersezione
// componente lineare e superficie standard.
//
@@ -13,7 +13,6 @@
#include "stdafx.h"
#include "IntersLineSurfStd.h"
#include "IntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h"
@@ -22,6 +21,60 @@
using namespace std ;
//----------------------------------------------------------------------------
// Punti e vettore devono essere espressi nel medesimo sistema di riferimento.
// Il box è allineato con gli assi di questo sistema di riferimento.
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
//----------------------------------------------------------------------------
bool
IntersLineBox( const Point3d& ptP, const Vector3d& vtV,
const Point3d& ptMin, const Point3d& ptMax, double& dU1, double& dU2)
{
// Casi di intersezione impossibile
if ( abs( vtV.x) < EPS_ZERO && ( ptP.x < ptMin.x - EPS_SMALL || ptP.x > ptMax.x + EPS_SMALL))
return false ;
if ( abs( vtV.y) < EPS_ZERO && ( ptP.y < ptMin.y - EPS_SMALL || ptP.y > ptMax.y + EPS_SMALL))
return false ;
if ( abs( vtV.z) < EPS_ZERO && ( ptP.z < ptMin.z - EPS_SMALL || ptP.z > ptMax.z + EPS_SMALL))
return false ;
// Inizializzo parametri intersezioni
dU1 = -INFINITO ;
dU2 = INFINITO ;
// Confronto con piani YZ (perpendicolari ad asse X)
if ( vtV.x > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.x - ptP.x) / vtV.x) ;
dU2 = min( dU2, ( ptMax.x - ptP.x) / vtV.x) ;
}
else if ( vtV.x < -EPS_ZERO) {
dU1 = max( dU1, ( ptMax.x - ptP.x) / vtV.x) ;
dU2 = min( dU2, ( ptMin.x - ptP.x) / vtV.x) ;
}
// Confronto con piani ZX (perpendicolari ad asse Y)
if ( vtV.y > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.y - ptP.y) / vtV.y) ;
dU2 = min( dU2, ( ptMax.y - ptP.y) / vtV.y) ;
}
else if ( vtV.y < -EPS_ZERO) {
dU1 = max( dU1, ( ptMax.y - ptP.y) / vtV.y) ;
dU2 = min( dU2, ( ptMin.y - ptP.y) / vtV.y) ;
}
// Confronto con piani XY (perpendicolari ad asse Z)
if ( vtV.z > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.z - ptP.z) / vtV.z) ;
dU2 = min( dU2, ( ptMax.z - ptP.z) / vtV.z) ;
}
else if ( vtV.z < -EPS_ZERO) {
dU1 = max( dU1, ( ptMax.z - ptP.z) / vtV.z) ;
dU2 = min( dU2, ( ptMin.z - ptP.z) / vtV.z) ;
}
return ( dU2 >= dU1) ;
}
//----------------------------------------------------------------------------
int
LineDisc( const Point3d& ptPLine, const Vector3d& vtVLine,
+5
View File
@@ -34,6 +34,11 @@
// Costanti tipologia di componente lineare
enum LinType { Line = 0, Ray = 1, Segment = 2} ;
//----------------------------------------------------------------------------
bool IntersLineBox( const Point3d& ptP, const Vector3d& vtV,
const Point3d& ptMin, const Point3d& ptMax, double& dU1, double& dU2) ;
// Costanti tipologia di intersezioni fra un componente lineare e un disco
enum LinCompDiscIntersType { D_ERROR_INT = -1, D_NO_INTERS = 0, D_BOUNDARY_INT_LINE_NOT_IN_PLANE = 1,
D_INNER_INT_LINE_NOT_IN_PLANE = 2, D_ONE_INT_LINE_ON_PLANE = 3,
+4 -3
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2022
// EgalTech 2015-2019
//----------------------------------------------------------------------------
// File : IntersLineSurfTm.cpp Data : 08.01.22 Versione : 2.4a3
// File : IntersLineSurfTm.cpp Data : 09.03.15 Versione : 2.1b6
// Contenuto : Implementazione della intersezione linea/superficie trimesh.
//
//
@@ -14,7 +14,8 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ProjPlane.h"
#include "IntersLineBox.h"
#include "IntersLineSurfStd.h"
#include "/EgtDev/Include/EGkSurfTriMesh.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
+6 -34
View File
@@ -1,8 +1,8 @@
//----------------------------------------------------------------------------
// EgalTech 2020-2020
//----------------------------------------------------------------------------
// File : IntersPlaneBox.cpp Data : 07.05.20 Versione : 2.2e1
// Contenuto : Implementazione della intersezione piano/box.
// File : IntersLineBox.cpp Data : 07.05.20 Versione : 2.2e1
// Contenuto : Implementazione della intersezione linea/box.
//
//
//
@@ -20,47 +20,19 @@
using namespace std ;
//----------------------------------------------------------------------------
// Box e piano devono essere nello stesso riferimento. Il box deve essere axis aligned.
bool
TestIntersPlaneBox( const Plane3d& plPlane, const BBox3d& b3Box)
{
// Verifica del piano
if ( ! plPlane.IsValid())
return false ;
// Centro e estensione del box
Point3d ptCen ;
Vector3d vtExt ;
if ( ! b3Box.GetCenterExtent( ptCen, vtExt))
return false ;
// Distanza del centro dal piano
double dDist = DistPointPlane( ptCen, plPlane) ;
// Proiezione dell'estensione sulla normale al piano
Vector3d vtN = plPlane.GetVersN() ;
double dProjExt = vtExt.x * abs( vtN.x) + vtExt.y * abs( vtN.y) + vtExt.z * abs( vtN.z) ;
// Confronto distanza del centro con estensione proiettata
return ( abs( dDist) < dProjExt + EPS_SMALL) ;
}
//----------------------------------------------------------------------------
bool
IntersPlaneBox( const Plane3d& plPlane, const BBox3d& b3Box,
IntersPlaneBox( const Point3d& ptOn, const Vector3d& vtN, const BBox3d& b3Box,
PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria)
{
// Verifico il piano
if ( ! plPlane.IsValid())
// Creo il piano
Plane3d plPlane ;
if ( ! plPlane.Set( ptOn, vtN))
return false ;
// Recupero i dati del Box
Point3d ptMin ;
double dDimX, dDimY, dDimZ ;
if ( ! b3Box.GetMinDim( ptMin, dDimX, dDimY, dDimZ))
return false ;
// Pulisco vettori intersezioni
vPnt.clear() ;
vBpt.clear() ;
vTria.clear() ;
// Verifico se può esistere intersezione
if ( ! TestIntersPlaneBox( plPlane, b3Box))
return true ;
// Contorno di base
PolyLine PL ;
PL.AddUPoint( 0, ptMin) ;
+1 -1
View File
@@ -116,7 +116,7 @@ IntersSurfTmSurfTm( const ISurfTriMesh& Stm1, const ISurfTriMesh& Stm2,
}
}
// se altrimenti sovrapposizione
else if ( nRes == ITTT_OVERLAPS || nRes == ITTT_COUNTER_OVERLAPS) {
else if ( nRes == ITTT_OVERLAPS) {
for ( const auto& Tria : vIttTria) {
// verifico se triangolo già inserito
bool bFound = false ;
+5 -34
View File
@@ -83,37 +83,8 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p
// se i triangoli sono complanari
if ( nResPP == IPPT_OVERLAPS ||
((( nVertPos1 == 0 && nVertNeg1 == 0) || ( nVertPos2 == 0 && nVertNeg2 == 0)) &&
( trTria1.GetN() ^ trTria2.GetN()).SqLen() < 25 * SIN_EPS_ANG_SMALL * SIN_EPS_ANG_SMALL)) {
// verifica per triangoli con normali controverse
bool bCounter = false ;
Triangle3d trMyTria2 = trTria2 ;
if ( trTria1.GetN() * trTria2.GetN() < 0) {
Point3d ptV0 = trMyTria2.GetP( 0) ;
trMyTria2.SetP( 0, trMyTria2.GetP( 1)) ;
trMyTria2.SetP( 1, ptV0) ;
trMyTria2.Validate() ;
bCounter = true ;
}
// verifica per triangoli coincidenti
bool bAreSameTria = ( ( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 0)) &&
AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 1)) &&
AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 2))) ||
( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 1)) &&
AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 2)) &&
AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 0))) ||
( AreSamePointExact( trTria1.GetP( 0), trMyTria2.GetP( 2)) &&
AreSamePointExact( trTria1.GetP( 1), trMyTria2.GetP( 0)) &&
AreSamePointExact( trTria1.GetP( 2), trMyTria2.GetP( 1)))) &&
( AreSameVectorExact( trTria1.GetN(), trMyTria2.GetN())) ;
if ( bAreSameTria) {
vTria.emplace_back( trTria1) ;
return ( bCounter ? ITTT_COUNTER_OVERLAPS : ITTT_OVERLAPS) ;
}
if ( ITTT_OVERLAPS == IntersCoplanarTriaTria( trTria1, trMyTria2, vTria)) {
return ( bCounter ? ITTT_COUNTER_OVERLAPS : ITTT_OVERLAPS) ;
}
return ITTT_NO ;
}
( trTria1.GetN() ^ trTria2.GetN()).SqLen() < 25 * SIN_EPS_ANG_SMALL * SIN_EPS_ANG_SMALL))
return IntersCoplanarTriaTria( trTria1, trTria2, vTria) ;
// limito la linea di intersezione con il primo triangolo
Point3d ptSt1, ptEn1 ;
@@ -141,7 +112,7 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p
int
IntersCoplanarTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, TRIA3DVECTOR& vTria)
{
// Se i tre vertici del secondo triangolo stanno tutti a destra di almeno un lato del primo, non c' intersezione
// Se i tre vertici del secondo triangolo stanno tutti a destra di almeno un lato del primo, non c'è intersezione
for ( int i = 0 ; i < 3 ; ++ i) {
Vector3d vtSide = trTria1.GetP( ( i + 1) % 3) - trTria1.GetP( i) ;
Vector3d vtSN = vtSide ^ trTria1.GetN() ;
@@ -151,7 +122,7 @@ IntersCoplanarTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, TR
( trTria2.GetP( 2) - trTria1.GetP( i)) * vtSN > - EPS_TRIA_H)
return ITTT_NO ;
}
// Se i tre vertici del primo triangolo stanno tutti a destra di almeno un lato del secondo, non c' intersezione
// Se i tre vertici del primo triangolo stanno tutti a destra di almeno un lato del secondo, non c'è intersezione
for ( int i = 0 ; i < 3 ; ++ i) {
Vector3d vtSide = trTria2.GetP( ( i + 1) % 3) - trTria2.GetP( i) ;
Vector3d vtSN = vtSide ^ trTria2.GetN() ;
@@ -234,7 +205,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
+15 -52
View File
@@ -68,36 +68,18 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
{
// pulisco tutto
Reset() ;
// verifico se la curva è un segmento di retta
bool bIsLine = false ;
const CurveLine* pLine = GetBasicCurveLine( pCrv) ;
if ( pLine != nullptr)
bIsLine = true ;
else {
const CurveComposite* pCompo = GetBasicCurveComposite( pCrv) ;
Point3d ptStart, ptEnd ;
if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd))
bIsLine = true ;
}
// verifico che la curva esista e sia piana
Plane3d plPlane ;
if ( pCrv == nullptr || ! pCrv->IsFlat( plPlane, bIsLine, 10 * EPS_SMALL))
if ( pCrv == nullptr || ! pCrv->IsFlat( plPlane))
return false ;
// recupero o assegno estrusione
// se esiste estrusione, verifico sia perpendicolare al piano della curva
Vector3d vtExtr ;
if ( ! pCrv->GetExtrusion( vtExtr) || vtExtr.IsSmall()) {
vtExtr = plPlane.GetVersN() ;
if ( vtExtr.IsZminus())
vtExtr.Invert() ;
if ( pCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall()) {
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtExtr))
return false ;
}
// recupero normale al piano della curva
Vector3d vtNorm = plPlane.GetVersN() ;
if ( vtNorm * vtExtr < 0)
vtNorm.Invert() ;
// verifico che estrusione non sia troppo vicina al piano della curva (almeno 30 gradi di angolazione)
double dExtrOnN = vtExtr * vtNorm ;
if ( dExtrOnN < 0.5)
return false ;
else
vtExtr = plPlane.GetVersN() ;
// recupero spessore
double dThick ;
pCrv->GetThickness( dThick) ;
@@ -120,9 +102,6 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
// determino se necessario cambiare riferimento ( dal vettore estrusione)
bool bNeedRef = ( ! vtExtr.IsZplus()) ;
// determino se necessario effettuare scalatura
bool bNeedScale = ( abs( dExtrOnN) < cos( 0.1 * DEGTORAD)) ;
// creo una copia della curva
CurveComposite ccCopy ;
if ( ! ccCopy.CopyFrom( pCrv))
@@ -130,23 +109,13 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
ccCopy.SetExtrusion( vtExtr) ;
// se necessario cambio il riferimento
Frame3d frCopy ;
if ( bNeedScale) {
// calcolo il riferimento con vtNorm come asse Z e componente di vtExtr perpendicolare a vtNorm come asse X
if ( ! frCopy.Set( ORIG, vtNorm, vtExtr - dExtrOnN * vtNorm))
return false ;
ccCopy.SetExtrusion( vtNorm) ;
// esprimo la curva in questo riferimento
ccCopy.ToLoc( frCopy) ;
// scalo lungo l'asse X locale
ccCopy.Scale( GLOB_FRM, dExtrOnN, 1, 1) ;
}
else if ( bNeedRef) {
Frame3d frExtr ;
if ( bNeedRef) {
// calcolo il riferimento OCS con VtExtr come asse Z
if ( ! frCopy.Set( ORIG, vtExtr))
if ( ! frExtr.Set( ORIG, vtExtr))
return false ;
// esprimo la curva in questo riferimento
ccCopy.ToLoc( frCopy) ;
ccCopy.ToLoc( frExtr) ;
}
// verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+)
@@ -460,7 +429,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
inOk.Set( dStart, dEnd) ;
IntersCurveCurve ccInt( *pCrv, *pCircS) ;
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccPart))
if ( ! ccInt.GetCurveClassification( 0, ccPart))
return false ;
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
@@ -509,7 +478,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
inOk.Set( dStart, dEnd) ;
IntersCurveCurve ccInt( *pCrv, *pCircE) ;
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccPart))
if ( ! ccInt.GetCurveClassification( 0, ccPart))
return false ;
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
@@ -632,15 +601,9 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
}
// riporto il risultato nel riferimento originale
if ( bNeedScale) {
for ( auto pCrv : m_CrvLst) {
pCrv->Scale( GLOB_FRM, 1 / dExtrOnN, 1, 1) ;
pCrv->ToGlob( frCopy) ;
}
}
else if ( bNeedRef) {
if ( bNeedRef) {
for ( auto pCrv : m_CrvLst)
pCrv->ToGlob( frCopy) ;
pCrv->ToGlob( frExtr) ;
}
// assegno estrusione e spessore come curva originale
+297 -190
View File
@@ -23,6 +23,7 @@
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "/EgtDev/Include/EGkPolygon3d.h"
using namespace std ;
@@ -830,11 +831,12 @@ PolyLine::MyChangeStart( int nPos)
// solo per polilinee chiuse
if ( ! IsClosed())
return false ;
// cancello l'ultimo punto ( coincide con il primo)
// cancello ultimo punto ( coincide con primo)
m_lUPoints.pop_back() ;
// sposto la parte iniziale dei punti alla fine
m_lUPoints.splice( m_lUPoints.end(), m_lUPoints, m_lUPoints.begin(), next( m_lUPoints.begin(), nPos)) ;
// aggiungo il punto finale come copia dell'iniziale
// sposto la metà iniziale dei punti alla fine
for ( int i = 0 ; i < nPos ; ++ i)
m_lUPoints.splice( m_lUPoints.end(), m_lUPoints, m_lUPoints.begin()) ;
// aggiungo punto finale come copia dell'iniziale
m_lUPoints.push_back( m_lUPoints.front()) ;
return true ;
@@ -1297,220 +1299,325 @@ PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
return true ;
}
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
bool
DistPointPolyLine( const Point3d& ptP, const PolyLine& plPoly, double& dDist)
/*static*/ bool
ChangePolyLineStart( const Point3d& ptNewStart, PolyLine& Loop, double dTol)
{
// La polilinea deve contenere almeno due punti
if ( plPoly.GetPointNbr() < 2)
return false ;
// Ciclo sui punti della polilinea
dDist = INFINITO ;
Point3d ptStart, ptEnd ;
plPoly.GetFirstPoint( ptStart) ;
while ( plPoly.GetNextPoint( ptEnd)) {
// distanza del punto dal segmento della polilinea
DistPointLine PointLineDistCalc( ptP, ptStart, ptEnd) ;
double dPlDist ;
PointLineDistCalc.GetDist( dPlDist) ;
if ( dPlDist < dDist)
dDist = dPlDist ;
// assegno nuovo inizio
ptStart = ptEnd ;
// Rinomino la lista di punti della PolyLine.
PNTULIST& LoopList = Loop.GetUPointList() ;
// Ciclo sui segmenti del loop per cercare il tratto del loop chiuso più vicino al punto.
double dMinSqDist = DBL_MAX ;
auto itMinDist = LoopList.end() ;
auto itSt = LoopList.begin() ;
auto itEn = itSt ;
++ itEn ;
for ( ; itSt != LoopList.end() && itEn != LoopList.end() ; ++ itSt, ++ itEn) {
// Estremi del segmento corrente del loop
Point3d ptSegSt = itSt->first ;
Point3d ptSegEn = itEn->first ;
// Distanza del punto dal segmento del loop
DistPointLine dDistCalc( ptNewStart, ptSegSt, ptSegEn) ;
double dSqDist ;
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
itMinDist = itSt ;
}
}
// Se il punto non sta sul loop, errore
if ( dMinSqDist > dTol * dTol)
return false ;
// Se il punto non sta su un vertice del segmento, lo aggiungo. Altrimenti non devo fare nulla.
auto itNewPointSt = LoopList.begin() ;
auto itNext = itMinDist ;
++ itNext ;
bool bOnStart = AreSamePointApprox( ptNewStart, itMinDist->first) ;
bool bOnEnd = AreSamePointApprox( ptNewStart, itNext->first) ;
itNewPointSt = LoopList.emplace( itNext, ptNewStart, 0) ;
// Sposto i punti precedenti in coda.
bool bStartRemoved = false ;
auto it = LoopList.begin() ;
while ( it != itNewPointSt) {
if ( bStartRemoved) {
LoopList.emplace_back( it->first, it->second) ;
}
bStartRemoved = true ;
it = LoopList.erase( it) ;
}
// Se il punto inserito non coincide con l'inizio del segmento chiudo il loop.
if ( ! bOnStart) {
LoopList.emplace_back( ptNewStart, 0) ;
// Se coincide con la fine tolgo il punto di fine che diviene inutile.
if ( bOnEnd) {
//LoopList.erase( itNext) ;
auto itNewStart = LoopList.begin() ;
++ itNewStart ;
LoopList.erase( itNewStart) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler)
// nSegNum 0-based
/*static*/ bool
PointPositionOnPolyLine( const Point3d& ptPoint, /*const*/ PolyLine& Loop, int& nSegNum, double& dParOnSeg, double dTol)
{
// La polilinea deve essere chiusa e piatta, altrimenti non ha senso parlare di interno
Plane3d plPlane ;
double dArea ;
if ( ! plPoly.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL))
return false ;
// Impongo l'orientamento CCW
if ( dArea < 0)
plPlane.Invert() ;
// Il punto deve giacere nel piano della polilinea
if ( ! PointInPlaneEpsilon( ptP, plPlane, 10 * EPS_SMALL))
return false ;
// Riferimento alla lista dei punti
PNTULIST& List = const_cast<PolyLine&>( plPoly).GetUPointList() ;
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
double dMinSqDist = SQ_INFINITO ;
Point3d ptMinDist ;
auto itMinDistEnd = List.end() ;
auto itStart = List.begin() ;
auto itEnd = next( itStart) ;
for ( ; itEnd != List.end() ; ++ itStart, ++ itEnd) {
// Distanza del punto dal segmento corrente
DistPointLine dDistCalc( ptP, itStart->first, itEnd->first) ;
// Rinomino la lista di punti della PolyLine.
/*const*/ PNTULIST& LoopList = Loop.GetUPointList() ;
// Ciclo sui segmenti del loop per cercare il tratto del loop chiuso più vicino al punto.
nSegNum = - 1 ;
double dMinSqDist = DBL_MAX ;
int nS = 0 ;
auto itMinDistSt = LoopList.end() ;
auto itMinDistEn = itMinDistSt ;
auto itSt = LoopList.begin() ;
auto itEn = itSt ;
++ itEn ;
for ( ; itSt != LoopList.end() && itEn != LoopList.end() ; ++ itSt, ++ itEn, ++ nS) {
// Estremi del segmento corrente del loop
Point3d ptSegSt = itSt->first ;
Point3d ptSegEn = itEn->first ;
// Distanza del punto dal segmento del loop
DistPointLine dDistCalc( ptPoint, ptSegSt, ptSegEn) ;
double dSqDist ;
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDist) {
nSegNum = nS ;
dMinSqDist = dSqDist ;
dDistCalc.GetMinDistPoint( ptMinDist) ;
itMinDistEnd = itEnd ;
itMinDistSt = itSt ;
itMinDistEn = itEn ;
}
}
// Determino tangente di riferimento
Vector3d vtTang ;
// se minima distanza nell'estremo iniziale del segmento
if ( AreSamePointApprox( ptMinDist, prev( itMinDistEnd)->first)) {
// direzione del segmento
Vector3d vtCurrTg = itMinDistEnd->first - prev( itMinDistEnd)->first ;
vtCurrTg.Normalize() ;
// direzione del segmento precedente
Vector3d vtPrevTg ;
if ( prev( itMinDistEnd) != List.begin())
vtPrevTg = prev( itMinDistEnd)->first - prev( itMinDistEnd, 2)->first ;
else
vtPrevTg = prev( itMinDistEnd)->first - prev( List.rbegin())->first ;
vtPrevTg.Normalize() ;
// tangente media
vtTang = vtPrevTg + vtCurrTg ;
vtTang.Normalize() ;
}
// se altrimenti minima distanza nell'estremo finale del segmento
else if ( AreSamePointApprox( ptMinDist, itMinDistEnd->first)) {
// direzione del segmento
Vector3d vtCurrTg = itMinDistEnd->first - prev( itMinDistEnd)->first ;
vtCurrTg.Normalize() ;
// direzione del segmento successivo
Vector3d vtNextTg ;
if ( next( itMinDistEnd) != List.end())
vtNextTg = next( itMinDistEnd)->first - itMinDistEnd->first ;
else
vtNextTg = next( List.begin())->first - itMinDistEnd->first ;
vtNextTg.Normalize() ;
// tangente media
vtTang = vtCurrTg + vtNextTg ;
vtTang.Normalize() ;
}
// altrimenti minima distanza con l'interno
else {
vtTang = itMinDistEnd->first - prev( itMinDistEnd)->first ;
}
// Determino la posizione del punto
Vector3d vtDiff = ptP - ptMinDist ;
Vector3d vtOut = vtTang ^ plPlane.GetVersN() ;
vtOut.Normalize() ;
return ( vtDiff * vtOut < -dToler) ;
// Se il punto non sta sul loop, lo segnalo.
if ( dMinSqDist > dTol * dTol)
return false ;
// Calcolo il parametro lungo il segmento.
Vector3d vtSeg = itMinDistEn->first - itMinDistSt->first ;
double dSegLen = vtSeg.Len() ;
if ( dSegLen < EPS_SMALL)
return false ;
vtSeg /= dSegLen ;
dParOnSeg = Clamp( ( ptPoint - itMinDistSt->first) * vtSeg, 0., dSegLen) ;
return true ;
}
//----------------------------------------------------------------------------
bool
GetPointParamOnPolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler, double& dPar)
/*static*/ bool
IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly)
{
// La polilinea deve contenere almeno due punti
if ( plPoly.GetPointNbr() < 2)
return false ;
// Ciclo sui punti della polilinea
int nSeg = -1 ;
double dMinSqDist = SQ_INFINITO ;
double dMinPar = -1 ;
Point3d ptStart, ptEnd ;
plPoly.GetFirstPoint( ptStart) ;
while ( plPoly.GetNextPoint( ptEnd)) {
// aggiorno l'indice
++ nSeg ;
// distanza del punto dal segmento della polilinea
DistPointLine dDistCalc( ptP, ptStart, ptEnd) ;
double dSqDist ;
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
double dSegPar ;
dDistCalc.GetParamAtMinDistPoint( dSegPar) ;
dMinPar = nSeg + dSegPar ;
}
// assegno nuovo inizio
ptStart = ptEnd ;
}
// Il punto è sulla linea se la sua distanza rispetta la tolleranza
return ( dMinSqDist < dToler * dToler) ;
}
//----------------------------------------------------------------------------
bool
ChangePolyLineStart( PolyLine& plPoly, const Point3d& ptNewStart, double dToler)
{
// La polilinea deve essere chiusa
// Se la PolyLine non è chiusa, il punto non può essere interno.
if ( ! plPoly.IsClosed())
return false ;
// Riferimento alla lista dei punti
PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
double dMinSqDist = SQ_INFINITO ;
auto itMinDistEnd = LoopList.end() ;
auto itStart = LoopList.begin() ;
auto itEnd = next( itStart) ;
for ( ; itEnd != LoopList.end() ; ++ itStart, ++ itEnd) {
// Distanza del punto dal segmento corrente
DistPointLine dDistCalc( ptNewStart, itStart->first, itEnd->first) ;
// Lista dei punti
PolyLine& MyPlPoly = const_cast< PolyLine&>( plPoly) ;
const PNTULIST& List = MyPlPoly.GetUPointList() ;
// Ciclo sui segmenti della PolyLine per cercarne il tratto più vicino al punto.
double dMinSqDist = DBL_MAX ;
Point3d ptMinDist ;
auto itMinDistSt = List.end() ;
auto itSt = List.begin() ;
auto itEn = itSt ;
++ itEn ;
for ( ; itSt != List.end() && itEn != List.end() ; ++ itSt, ++ itEn) {
// Estremi del segmento corrente del loop
Point3d ptSegSt = itSt->first ;
Point3d ptSegEn = itEn->first ;
// Distanza del punto dal segmento del loop
DistPointLine dDistCalc( ptP, ptSegSt, ptSegEn) ;
double dSqDist ;
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
itMinDistEnd = itEnd ;
dDistCalc.GetMinDistPoint( ptMinDist) ;
itMinDistSt = itSt ;
}
}
// Se il punto non sta sulla polilinea, non ha senso cambiare l'inizio
if ( dMinSqDist > dToler * dToler)
return false ;
// Se il punto non coincide con un vertice, lo aggiungo
auto itNewStart = LoopList.end() ;
if ( AreSamePointApprox( ptNewStart, prev( itMinDistEnd)->first))
itNewStart = prev( itMinDistEnd) ;
else if ( AreSamePointApprox( ptNewStart, itMinDistEnd->first))
itNewStart = itMinDistEnd ;
else
itNewStart = LoopList.emplace( itMinDistEnd, ptNewStart, 0) ;
// Cancello l'ultimo punto ( coincide con il primo)
LoopList.pop_back() ;
// Sposto la parte iniziale dei punti alla fine
LoopList.splice( LoopList.end(), LoopList, LoopList.begin(), itNewStart) ;
// Aggiungo il punto finale come copia dell'iniziale
LoopList.push_back( LoopList.front()) ;
return true ;
// Termine del segmento di minima distanza.
auto itMinDistEn = itMinDistSt ;
++ itMinDistEn ;
// Punto di minima distanza nell'estremo iniziale del segento
if ( AreSamePointApprox( ptMinDist, itMinDistSt->first)) {
auto itPrevSt = List.begin() ;
if ( itMinDistSt == List.begin()) {
auto itAuxNext = itPrevSt ;
++ ( ++ itAuxNext) ;
for ( ; itAuxNext != List.end() ; ++ itPrevSt, ++ itAuxNext)
;
}
else {
auto itAuxNext = itPrevSt ;
++ itAuxNext ;
for (; itAuxNext != itMinDistSt; ++itPrevSt, ++itAuxNext)
;
}
Vector3d vtPrevTan = itMinDistSt->first - itPrevSt->first ;
vtPrevTan.Normalize() ;
Vector3d vtTan = itMinDistEn->first - itMinDistSt->first ;
vtTan.Normalize() ;
Polygon3d AuxPolygon ;
AuxPolygon.FromPolyLine( plPoly) ;
Vector3d vtPolyNorm = AuxPolygon.GetVersN() ;
Vector3d vtPrevOut = vtPrevTan ^ vtPolyNorm ;
Vector3d vtOut = vtTan ^ vtPolyNorm ;
// Caso concavo
if ( vtTan * vtPrevOut > 0) {
Vector3d vtTest = ptP - ptMinDist ;
if ( vtTest * vtPrevOut < 0 || vtTest * vtOut < 0)
return true ;
}
// Caso convesso
else {
Vector3d vtTest = ptP - ptMinDist ;
if ( vtTest * vtPrevOut < 0 && vtTest * vtOut < 0)
return true ;
}
}
// Punto di minima distanza nell'estremo finale del segento
else if ( AreSamePointApprox( ptMinDist, itMinDistEn->first)) {
auto itNextEn = itMinDistEn ;
++ itNextEn ;
if ( itNextEn == List.end()) {
itNextEn = List.begin() ;
++ itNextEn ;
}
Vector3d vtTan = itMinDistEn->first - itMinDistSt->first ;
vtTan.Normalize() ;
Vector3d vtNextTan = itNextEn->first - itMinDistEn->first ;
vtNextTan.Normalize() ;
Polygon3d AuxPolygon ;
AuxPolygon.FromPolyLine( plPoly) ;
Vector3d vtPolyNorm = AuxPolygon.GetVersN() ;
Vector3d vtOut = vtTan ^ vtPolyNorm ;
Vector3d vtNextOut = vtNextTan ^ vtPolyNorm ;
// Caso concavo
if ( vtNextTan * vtOut > 0) {
Vector3d vtTest = ptP - ptMinDist ;
if ( vtTest * vtOut < 0 || vtTest * vtNextOut < 0)
return true ;
}
// Caso convesso
else {
Vector3d vtTest = ptP - ptMinDist ;
if ( vtTest * vtOut < 0 && vtTest * vtNextOut < 0)
return true ;
}
}
// Punto di minima distanza interno al segmeno
else {
Vector3d vtP = ptP - itMinDistSt->first ;
Vector3d vtTan = itMinDistEn->first - itMinDistSt->first ;
vtTan.Normalize() ;
Polygon3d AuxPolygon ;
AuxPolygon.FromPolyLine( plPoly) ;
Vector3d vtPolyNorm = AuxPolygon.GetVersN() ;
Vector3d vtOut = vtTan ^ vtPolyNorm ;
vtP -= ( vtP * vtTan) * vtTan ;
if ( vtP * vtOut < - EPS_SMALL)
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
SplitPolyLineAtPoint( const PolyLine& plPoly, const Point3d& ptP, double dToler, PolyLine& plPoly1, PolyLine& plPoly2)
DistPointPolyLine( const Point3d& ptP, const PolyLine& plPoly, double& dPointPolyLineDist)
{
// La polilinea deve contenere almeno due punti
if ( plPoly.GetPointNbr() < 2)
if ( plPoly.GetPointNbr() == 0)
return false ;
// Riferimento alla lista dei punti
const PNTULIST& LoopList = const_cast<PolyLine&>( plPoly).GetUPointList() ;
// Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto
double dMinSqDist = SQ_INFINITO ;
auto itMinDistEnd = LoopList.end() ;
auto itStart = LoopList.begin() ;
auto itEnd = next( itStart) ;
for ( ; itEnd != LoopList.end() ; ++ itStart, ++ itEnd) {
// Distanza del punto dal segmento corrente
DistPointLine dDistCalc( ptP, itStart->first, itEnd->first) ;
double dSqDist ;
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
itMinDistEnd = itEnd ;
}
dPointPolyLineDist = DBL_MAX ;
Point3d ptSt, ptEn ;
bool bContinue = plPoly.GetFirstPoint( ptSt) && plPoly.GetNextPoint( ptEn) ;
while ( bContinue) {
double dPoinLineDist ;
DistPointLine PointLineDistCalc( ptP, ptSt, ptEn) ;
PointLineDistCalc.GetDist( dPoinLineDist) ;
if ( dPoinLineDist < dPointPolyLineDist)
dPointPolyLineDist = dPoinLineDist ;
ptSt = ptEn ;
bContinue = plPoly.GetNextPoint( ptEn) ;
}
return true ;
}
//----------------------------------------------------------------------------
/*static*/ bool
SplitPolyLineAtPoint( const Point3d& ptPoint, /*const*/ PolyLine& Loop, PolyLine& Loop1, PolyLine& Loop2, double dTol)
{
// Rinomino la lista di punti della PolyLine.
/*const*/ PNTULIST& LoopList = Loop.GetUPointList() ;
// Ciclo sui segmenti del loop per cercare il tratto del loop chiuso più vicino al punto.
double dMinSqDist = DBL_MAX ;
auto itMinDistSt = LoopList.end() ;
auto itSt = LoopList.begin() ;
auto itEn = itSt ;
++ itEn ;
for ( ; itSt != LoopList.end() && itEn != LoopList.end() ; ++ itSt, ++ itEn) {
// Estremi del segmento corrente del loop
Point3d ptSegSt = itSt->first ;
Point3d ptSegEn = itEn->first ;
// Distanza del punto dal segmento del loop
DistPointLine dDistCalc( ptPoint, ptSegSt, ptSegEn) ;
double dSqDist ;
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
itMinDistSt = itSt ;
}
}
// Se il punto non sta sul loop, lo segnalo.
if ( dMinSqDist > dTol * dTol)
return false ;
// Se il punto di stop sta su un vertice non devo aggiungerlo e il
// punto di stop sarà uno degli estremi del segmento su cui giace.
auto itStop = itMinDistSt ;
auto itNext = itMinDistSt ;
++ itNext ;
if ( AreSamePointApprox( ptPoint, itStop->first))
;
else if ( AreSamePointApprox( ptPoint, itNext->first))
itStop = itNext ;
else {
itStop = LoopList.emplace( itNext, ptPoint, 0.) ;
}
// Creo i due loop
PNTULIST& LoopList1 = Loop1.GetUPointList() ;
PNTULIST& LoopList2 = Loop2.GetUPointList() ;
for ( auto it = LoopList.begin() ; it != itStop ; ++ it) {
LoopList1.emplace_back( it->first, it->second) ;
}
LoopList1.emplace_back( itStop->first, itStop->second) ;
for ( auto it = itStop ; it != LoopList.end() ; ++ it) {
LoopList2.emplace_back( it->first, it->second) ;
}
return true ;
}
//----------------------------------------------------------------------------
/*static*/ bool
AddPolyLineToPolyLine( PolyLine& Poly, PolyLine& PolyToAdd, double dTol)
{
// Se la PolyLine a cui devo aggiungere l'altra è chiusa, non posso aggiungere nulla.
if ( Poly.IsClosed())
return false ;
// Se la PolyLina che devo aggiungere è vuota, ho finito.
PNTULIST& PolyToAddList = PolyToAdd.GetUPointList() ;
if ( int( PolyToAddList.size()) == 0)
return true ;
// Se Poly non è vuota e la sua fine non coincide con l'inizio di PolyToAdd, non è possibile aggiungere nulla.
Point3d ptLast ;
Poly.GetLastPoint( ptLast) ;
auto it = PolyToAddList.begin() ;
if ( Poly.GetPointNbr() != 0 && ! AreSamePointEpsilon( it->first, ptLast, dTol))
return false ;
/*if ( Poly.GetPointNbr() == 0)
Poly.AddUPoint( 0., it->first) ;
++ it ;*/
// Aggiungo i punti.
for ( ; it != PolyToAddList.end() ; ++ it) {
Poly.AddUPoint( 0., it->first) ;
}
// Se il punto non sta sulla polilinea, non ha senso spezzare
if ( dMinSqDist > dToler * dToler)
return false ;
// Copio i punti opportuni nella prima parte
PNTULIST& LoopList1 = plPoly1.GetUPointList() ;
for ( auto it = LoopList.begin() ; it != itMinDistEnd ; ++ it)
LoopList1.emplace_back( it->first, it->second) ;
plPoly1.AddUPoint( 0, ptP) ;
// Copio i punti opportuni nella seconda parte
PNTULIST& LoopList2 = plPoly2.GetUPointList() ;
for ( auto it = itMinDistEnd ; it != LoopList.end() ; ++ it)
LoopList2.emplace_back( it->first, it->second) ;
plPoly2.AddUPoint( 0, ptP, false) ;
return true ;
}
+10 -46
View File
@@ -17,7 +17,6 @@
#include "CurveArc.h"
#include "CurveComposite.h"
#include "SurfFlatRegion.h"
#include "AdjustLoops.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EgkPolyLine.h"
#include "/EgtDev/Include/EgkBiArcs.h"
@@ -279,34 +278,13 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b
//----------------------------------------------------------------------------
ISurfFlatRegion*
GetSurfFlatRegionFromTriangle( const Triangle3d& Tria)
GetSurfFlatRegionFromPolyLine( const PolyLine& ContourPolyLine)
{
// Creo la regione.
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSfr))
return nullptr ;
// Creo curva composita.
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
if ( IsNull( pLoop))
return nullptr ;
if ( ! pLoop->AddPoint( Tria.GetP( 0)) ||
! pLoop->AddLine( Tria.GetP( 1)) ||
! pLoop->AddLine( Tria.GetP( 2)) ||
! pLoop->Close())
return nullptr ;
pSfr->AddExtLoop( Release( pLoop)) ;
return Release( pSfr) ;
}
//----------------------------------------------------------------------------
ISurfFlatRegion*
GetSurfFlatRegionFromPolyLine( const PolyLine& ContourPolyLine)
{
// Creo la regione.
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSfr))
return nullptr ;
// Creo curva composita.
// Creo curva composita.
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
if ( IsNull( pLoop))
return nullptr ;
@@ -328,13 +306,13 @@ GetSurfFlatRegionFromPolyLine( const PolyLine& ContourPolyLine)
ISurfFlatRegion*
GetSurfFlatRegionFromPolyLineVector( const POLYLINEVECTOR& vContoursPolyLineVec)
{
// Creo la regione.
// Creo la regione.
PtrOwner<SurfFlatRegion> pSfr( CreateBasicSurfFlatRegion()) ;
if ( IsNull( pSfr))
return nullptr ;
// Ciclo sulle PolyLine.
// Ciclo sulle PolyLine.
for ( int nL = 0 ; nL < int( vContoursPolyLineVec.size()) ; ++ nL) {
// Creo curva composita.
// Creo curva composita.
PtrOwner<CurveComposite> pLoop( CreateBasicCurveComposite()) ;
if ( IsNull( pLoop))
return nullptr ;
@@ -348,11 +326,11 @@ GetSurfFlatRegionFromPolyLineVector( const POLYLINEVECTOR& vContoursPolyLineVec)
ptSt = ptEn ;
bContinue = vContoursPolyLineVec[nL].GetNextPoint( ptEn) ;
}
// Loop esterno
// Loop esterno
if ( nL == 0) {
pSfr->AddExtLoop( Release( pLoop)) ;
}
// Loop interno
// Loop interno
else {
pSfr->AddIntLoop( Release( pLoop)) ;
}
@@ -385,20 +363,8 @@ SurfFlatRegionByContours::AddCurve( ICurve* pCrv)
// verifico sia chiusa
if ( ! pMyCrv->IsClosed())
return false ;
// verifico sia piana e imposto estrusione come normale al piano
double dArea ;
Plane3d plPlane ;
if ( ! pMyCrv->GetArea( plPlane, dArea))
return false ;
pMyCrv->SetExtrusion( plPlane.GetVersN()) ;
pMyCrv->SetThickness( 0) ;
// rimuovo eventuali sovrapposizioni (calcolate nel suo piano)
ICURVEPLIST CrvLst ;
if ( ! AdjustLoops( Release( pMyCrv), CrvLst))
return false ;
// la/le inserisco nel vettore delle curve
for ( auto& pSingCrv : CrvLst)
m_vpCrv.push_back( pSingCrv) ;
// la inserisco nel vettore delle curve
m_vpCrv.push_back( Release( pMyCrv)) ;
return true ;
}
@@ -452,7 +418,6 @@ SurfFlatRegionByContours::GetSurf( void)
if ( IsNull( pSfr))
return nullptr ;
// aggiungo le diverse curve
bool bExtLoop = false ;
bool bFirstCrv ;
do {
bFirstCrv = true ;
@@ -471,7 +436,6 @@ SurfFlatRegionByContours::GetSurf( void)
}
// provo a inserirla
if ( pSfr->AddExtLoop( Release( pCrv))) {
bExtLoop = true ;
bFirstCrv = false ;
delete m_vpCrv[j] ;
m_vpCrv[j] = nullptr ;
@@ -496,7 +460,7 @@ SurfFlatRegionByContours::GetSurf( void)
}
} while ( m_bAllowedMultiChunk && ! bFirstCrv) ;
// se non valida, errore
if ( ! bExtLoop || ! pSfr->IsValid())
if ( ! pSfr->IsValid())
return nullptr ;
// restituisco la superficie
return Release( pSfr) ;
+2 -5
View File
@@ -35,10 +35,8 @@ GEOOBJ_REGISTER( SRF_BEZIER, NGE_S_BEZ, SurfBezier) ;
//----------------------------------------------------------------------------
SurfBezier::SurfBezier(void)
: m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nDegU(), m_nDegV(), m_nSpanU(), m_nSpanV(), m_bRat( false),
m_bTrimmed( false), m_pTrimReg( nullptr)
m_bTrimmed( false), m_pTrimReg( nullptr), m_nTempProp( 0)
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -568,8 +566,7 @@ SurfBezier::CopyFrom( const SurfBezier& sbSrc)
m_vPtCtrl = sbSrc.m_vPtCtrl ;
if ( sbSrc.m_bRat)
m_vWeCtrl = sbSrc.m_vWeCtrl ;
m_nTempProp[0] = sbSrc.m_nTempProp[0] ;
m_nTempProp[1] = sbSrc.m_nTempProp[1] ;
m_nTempProp = sbSrc.m_nTempProp ;
return true ;
}
+5 -6
View File
@@ -53,11 +53,10 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // ISurf
bool IsSimple( void) const override
@@ -166,7 +165,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo
DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo
SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
} ;
//-----------------------------------------------------------------------------
+11 -15
View File
@@ -33,10 +33,8 @@ GEOOBJ_REGISTER( SRF_FLATRGN, NGE_S_FRG, SurfFlatRegion) ;
//----------------------------------------------------------------------------
SurfFlatRegion::SurfFlatRegion( void)
: m_pSTM( nullptr), m_nStatus( TO_VERIFY)
: m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nTempProp()
{
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -57,8 +55,7 @@ SurfFlatRegion::Clear( void)
delete pLoop ;
m_vpLoop.clear() ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
m_nTempProp = 0 ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -165,7 +162,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
for ( auto i : m_vExtInd) {
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
! ccInt.GetCurveClassification( 0, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_OUT) {
bOk = false ;
break ;
@@ -178,7 +175,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
continue ;
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
if ( ccInt.GetCrossOrOverlapIntersCount() == 0 &&
ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) &&
ccInt.GetCurveClassification( 0, ccClass) &&
! ccClass.empty() && ccClass[0].nClass == CRVC_OUT) {
bOk = true ;
break ;
@@ -298,7 +295,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[m_vExtInd[i]]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
! ccInt.GetCurveClassification( 0, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
@@ -309,7 +306,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
IntersCurveCurve ccInt2( *pMyCrv, *m_vpLoop[k]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 0, EPS_SMALL, ccClass2) ||
! ccInt2.GetCurveClassification( 0, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
@@ -400,8 +397,7 @@ SurfFlatRegion::CopyFrom( const SurfFlatRegion& sfrSrc)
m_vpLoop.push_back( pCrv) ;
}
m_vExtInd = sfrSrc.m_vExtInd ;
m_nTempProp[0] = sfrSrc.m_nTempProp[0] ;
m_nTempProp[1] = sfrSrc.m_nTempProp[1] ;
m_nTempProp = sfrSrc.m_nTempProp ;
m_nStatus = sfrSrc.m_nStatus ;
return ( m_nStatus == OK && ! m_vpLoop.empty()) ;
}
@@ -1150,7 +1146,7 @@ SurfFlatRegion::CloneChunk( int nChunk) const
//----------------------------------------------------------------------------
bool
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const
{
// la curva deve già essere nel riferimento intrinseco della regione
// verifico lo stato
@@ -1179,7 +1175,7 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRV
IntersCurveCurve ccInt( Crv, *pLoop) ;
// classificazione
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, dLenMin, ccPart))
if ( ! ccInt.GetCurveClassification( 0, ccPart))
return false ;
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
@@ -1272,7 +1268,7 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRV
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const
{
// verifico lo stato
if ( m_nStatus != OK || m_vpLoop.empty())
@@ -1293,7 +1289,7 @@ SurfFlatRegion::GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCV
pCrvLoc = pCopyCrv ;
}
// esecuzione classificazione nel riferimento intrinseco
return MyGetCurveClassification( *pCrvLoc, dLenMin, ccClass) ;
return MyGetCurveClassification( *pCrvLoc, ccClass) ;
}
//----------------------------------------------------------------------------
+7 -8
View File
@@ -51,11 +51,10 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // ISurf
bool IsSimple( void) const override
@@ -92,7 +91,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
const SurfTriMesh* GetAuxSurf( void) const override ;
SurfFlatRegion* CloneChunk( int nChunk) const override ;
bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ;
bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ;
bool GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const override ;
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
public : // IGeoObjRW
@@ -131,7 +130,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
ICurve* GetMyLoop( int nChunk, int nLoop) const ; // nChunk 0-based, nLoop 0-based (1°esterno, successivi interni)
void ResetAuxSurf( void) const ;
bool ConvertArcsToBezierCurves( void) ;
bool MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const ;
bool MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const ;
static bool MySelectCurves( const PCRV_DEQUE& vpLoop, const SurfFlatRegion& Other,
int nType1, bool bInvert1, int nType2, bool bInvert2, PCRV_DEQUE& vpCurve) ;
static bool MyChainCurves( PCRV_DEQUE& vpCurve, PCRV_DEQUE& vpLoop) ;
@@ -145,7 +144,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
Frame3d m_frF ; // riferimento intrinseco
PCRV_DEQUE m_vpLoop ; // deque delle curve che formano i loop
INTVECTOR m_vExtInd ; // indice dei loop esterni nel precedente vettore
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
} ;
//-----------------------------------------------------------------------------
+2 -2
View File
@@ -289,7 +289,7 @@ SurfFlatRegion::MySelectCurves( const PCRV_DEQUE& vpLoop, const SurfFlatRegion&
for ( auto& pLoop : vpLoop) {
// eseguo classificazione
CRVCVECTOR ccClass ;
if ( ! Other.MyGetCurveClassification( *pLoop, EPS_SMALL, ccClass))
if ( ! Other.MyGetCurveClassification( *pLoop, ccClass))
return false ;
// creo intervalli validi, tenendo classificazioni ricevute
Intervals inOk1( EPS_PARAM), inOk2( EPS_PARAM) ;
@@ -441,7 +441,7 @@ SurfFlatRegion::MyNewSurfFromLoops( PCRV_DEQUE& vpLoop)
CRVCVECTOR ccClass ;
IntersCurveCurve ccInt( *vpLoop[l], *pExtLoop) ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
! ccInt.GetCurveClassification( 0, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// lo inserisco
-3
View File
@@ -27,9 +27,6 @@ SurfFlatRegion::Offset( double dDist, int nType)
int nChunk = GetChunkCount() ;
if ( nChunk == 0)
return false ;
// se offset nullo, non devo fare alcunché
if ( abs( dDist) < 10 * EPS_SMALL)
return true ;
// creo una nuova regione
PtrOwner<SurfFlatRegion> pSfr( new( nothrow) SurfFlatRegion) ;
if ( IsNull( pSfr))
+305 -116
View File
@@ -18,10 +18,10 @@
#include "GeoObjFactory.h"
#include "NgeWriter.h"
#include "NgeReader.h"
#include "SurfFlatRegion.h"
#include "DistPointLine.h"
#include "Triangulate.h"
#include "GeoConst.h"
#include "SurfFlatRegion.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkPointGrid3d.h"
#include "/EgtDev/Include/EGkPolyLine.h"
@@ -41,12 +41,10 @@ GEOOBJ_REGISTER( SRF_TRIMESH, NGE_S_TRM, SurfTriMesh) ;
SurfTriMesh::SurfTriMesh( void)
: m_nStatus( TO_VERIFY), m_dLinTol( STM_STD_LIN_TOL), m_dBoundaryAng( STM_STD_BOUNDARY_ANG),
m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bOriented( false), m_bClosed( false), m_bFaceted( false),
m_nTimeStamp( 0), m_nMaxTFlag( 0), m_nParts( -1), m_pHGrd3d( nullptr)
m_nTimeStamp( 0), m_nTempProp( 0), m_nMaxTFlag( 0), m_nParts( -1), m_pHGrd3d( nullptr)
{
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
}
//----------------------------------------------------------------------------
@@ -239,7 +237,7 @@ SurfTriMesh::RemoveTriangle( int nId)
// indice vertice
int nV = m_vTria[nId].nIdVert[i] ;
// se vertice non c'è passo al prossimo
if ( nV < 0 || nV >= int( m_vVert.size()))
if ( nV < 0 || nV >= int( m_vTria.size()))
continue ;
if ( m_vVert[nV].nIdTria == nId) {
int nAdjP = m_vTria[nId].nIdAdjac[i] ;
@@ -991,7 +989,7 @@ SurfTriMesh::MarchOneTria( int& nT, int& nV, int nTimeStamp,
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL) const
SurfTriMesh::GetSilhouette( const Vector3d& vtDir, POLYLINEVECTOR& vPL) const
{
// Verifico lo stato
if ( m_nStatus != OK)
@@ -1002,19 +1000,6 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
if ( ! vtVers.Normalize())
return false ;
// Controlli su tolleranza
dTol = max( dTol, 100 * EPS_SMALL) ;
// Determino il riferimento di proiezione
Frame3d frOCS ; frOCS.Set( ORIG, vtVers) ;
Frame3d frBox = frOCS ; frBox.Invert() ;
BBox3d b3Box ;
GetBBox( frBox, b3Box) ;
frOCS.Translate( b3Box.GetMin().z * frOCS.VersZ()) ;
#if 0
// *** 1° Sfruttando le adiacenze ***
// Non funziona perchè genera loop con anelli
// Copio la superficie
PtrOwner<SurfTriMesh> pStm( Clone()) ;
if ( IsNull( pStm))
@@ -1026,100 +1011,14 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
if ( pStm->m_vTria[i].nIdVert[0] == SVT_DEL)
continue ;
// verifico la normale
if ( pStm->m_vTria[i].vtN * vtVers < EPS_ZERO)
if ( pStm->m_vTria[i].vtN * vtVers < - EPS_ZERO)
pStm->RemoveTriangle( i) ;
}
// dichiaro facce non calcolate
pStm->m_bFaceted = false ;
// Proietto la superficie
pStm->Scale( frOCS, 1, 1, 0) ;
// Recupero i loop della nuova superficie
POLYLINEVECTOR vMyPL ;
if ( pStm->GetLoops( vMyPL)) {
// calcolo la regione della superficie proiettata
bool bOk = true ;
PtrOwner<ISurfFlatRegion> pSfr ;
for ( int i = 0 ; i < int( vMyPL.size()) && bOk ; ++ i) {
// Regione di un loop
PtrOwner<ISurfFlatRegion> pSfrPart( GetSurfFlatRegionFromPolyLine( vMyPL[i])) ;
if ( ! IsNull( pSfrPart)) {
pSfrPart->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr))
if ( pSfrPart->GetNormVersor() * vtVers > 0)
bOk = pSfr.Set( Release( pSfrPart)) ;
else
bOk = false ;
else {
if ( pSfrPart->GetNormVersor() * vtVers > 0)
bOk = pSfr->Add( *pSfrPart) ;
else {
pSfrPart->Invert() ;
bOk = pSfr->Subtract( *pSfrPart) ;
}
}
}
else
bOk = false ;
}
// Verifico esistenza della regione
if ( bOk && ! IsNull( pSfr)) {
// Effettuo contro-offset
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
// Recupero i contorni della regione
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
PolyLine PL ;
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
vPL.emplace_back( PL) ;
}
}
return true ;
}
}
vPL.clear() ;
#endif
// *** 2° Mediante unione delle regioni dei triangoli proiettati ***
// calcolo la regione dei triangoli proiettati
PtrOwner<ISurfFlatRegion> pSfr ;
Triangle3d Tria ;
int nT = GetFirstTriangle( Tria) ;
while ( nT != SVT_NULL) {
// verifico la normale e il triangolo proiettato
if ( Tria.GetN() * vtVers > EPS_ZERO &&
Tria.Scale( frOCS, 1, 1, 0) && Tria.GetSqMinHeight() > SQ_EPS_SMALL) {
PtrOwner<ISurfFlatRegion> pSfrTria( GetSurfFlatRegionFromTriangle( Tria)) ;
if ( ! IsNull( pSfrTria)) {
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
if ( IsNull( pSfr))
pSfr.Set( Release( pSfrTria)) ;
else
pSfr->Add( *pSfrTria) ;
}
}
// passo al successivo
nT = GetNextTriangle( nT, Tria) ;
}
// Se non esiste la regione
if ( IsNull( pSfr))
return false ;
// Effettuo contro-offset
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
// Recupero i contorni della regione
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
PolyLine PL ;
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
vPL.emplace_back( PL) ;
}
}
return true ;
return pStm->GetLoops( vPL) ;
}
//----------------------------------------------------------------------------
@@ -1169,8 +1068,7 @@ SurfTriMesh::CopyFrom( const SurfTriMesh& stmSrc)
m_vTria = stmSrc.m_vTria ;
m_vFacet = stmSrc.m_vFacet ;
m_nTimeStamp = stmSrc.m_nTimeStamp ;
m_nTempProp[0] = stmSrc.m_nTempProp[0] ;
m_nTempProp[1] = stmSrc.m_nTempProp[1] ;
m_nTempProp = stmSrc.m_nTempProp ;
m_nMaxTFlag = stmSrc.m_nMaxTFlag ;
m_nParts = stmSrc.m_nParts ;
return true ;
@@ -1695,10 +1593,8 @@ SurfTriMesh::TestSealing( void)
// verifico le adiacenze
if ( m_vTria[i].nIdAdjac[0] == SVT_NULL ||
m_vTria[i].nIdAdjac[1] == SVT_NULL ||
m_vTria[i].nIdAdjac[2] == SVT_NULL) {
m_vTria[i].nIdAdjac[2] == SVT_NULL)
bClosed = false ;
break ;
}
}
}
// aggiorno la chiusura della superficie
@@ -1718,7 +1614,7 @@ SurfTriMesh::AdjustTopology( void)
return true ;
}
// dichiaro sfaccettatura da ricalcolare
m_bFaceted = false ;
ResetFaceting() ;
// invalido calcolo connessione
m_nParts = - 1 ;
// verifica indici
@@ -2932,7 +2828,7 @@ SurfTriMesh::DoCompacting( double dTol)
//----------------------------------------------------------------------------
bool
SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther, double dTol)
SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther)
{
// recupero l'altra superficie
const SurfTriMesh* pOther = dynamic_cast<const SurfTriMesh*>( &stmOther) ;
@@ -2974,7 +2870,7 @@ SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther, dou
ptOP.ToGlob( frOther) ;
// se non c'è già un vertice con la stessa posizione lo inserisco
int nNewId ;
if ( ! VertGrid.Find( ptOP, dTol, nNewId)) {
if ( ! VertGrid.Find( ptOP, 2 * EPS_SMALL, nNewId)) {
if ( ( nNewId = AddVertex( ptOP)) == SVT_NULL)
return false ;
VertGrid.InsertPoint( ptOP, nNewId) ;
@@ -2984,7 +2880,7 @@ SurfTriMesh::DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther, dou
}
int nVIdSize = int( vVId.size()) ;
// aggiungo i triangoli dell'altra trimesh
// inserisco i triangoli dell'altra trimesh
for ( int nOtId = 0 ; nOtId < pOther->GetTriangleSize() ; ++ nOtId) {
// recupero gli indici dei vertici del triangolo
int vOId[3] ;
@@ -3401,6 +3297,299 @@ SurfTriMesh::Invert( void)
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq)
{
#define UseTria 1
#if UseTria
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// classifico i vertici rispetto al piano
double dTol = max( min( 0.5 * m_dLinTol, 10 * EPS_SMALL), EPS_SMALL) ;
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
double dDist = DistPointPlane( m_vVert[i].ptP, plPlane) ;
if ( abs( dDist) < dTol) {
m_vVert[i].nTemp = 0 ;
if ( abs( dDist) > EPS_SMALL)
m_vVert[i].ptP -= plPlane.GetVersN() * dDist ;
}
else if ( dDist > 0)
m_vVert[i].nTemp = +1 ;
else
m_vVert[i].nTemp = -1 ;
}
// aggiorno timestamp dei triangoli
for ( auto& Tria : m_vTria)
Tria.nTemp = m_nTimeStamp ;
++ m_nTimeStamp ;
// sistemo i triangoli (eventualmente li elimino)
bool bModif = false ;
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
// salto i triangoli cancellati e quelli aggiunti
if ( m_vTria[i].nIdVert[0] == SVT_DEL || m_vTria[i].nTemp == m_nTimeStamp)
continue ;
// se flag abilita e giace sul piano ed equiverso, lo salvo
if ( bSaveOnEq &&
m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 0 &&
m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 0 &&
m_vVert[ m_vTria[i].nIdVert[2]].nTemp == 0 &&
AreSameVectorApprox( m_vTria[i].vtN, plPlane.GetVersN()))
;
// se giace sul piano o dalla parte esterna del piano, lo cancello
else if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp != -1 &&
m_vVert[ m_vTria[i].nIdVert[1]].nTemp != -1 &&
m_vVert[ m_vTria[i].nIdVert[2]].nTemp != -1) {
bModif = true ;
RemoveTriangle( i) ;
}
// se giace dalla parte interna con al massimo un lato sul piano, lo conservo
else if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp != 1 &&
m_vVert[ m_vTria[i].nIdVert[1]].nTemp != 1 &&
m_vVert[ m_vTria[i].nIdVert[2]].nTemp != 1)
;
// altrimenti attraversa il piano, devo modificarlo
else {
bModif = true ;
int nDisc = m_vVert[ m_vTria[i].nIdVert[0]].nTemp +
m_vVert[ m_vTria[i].nIdVert[1]].nTemp +
m_vVert[ m_vTria[i].nIdVert[2]].nTemp ;
// se ha un vertice all'interno e uno sul piano -> 1 nuovo vertice e 1 nuovo triangolo
if ( nDisc == 0) {
// classifico i vertici
int nVertOn, nVertIn, nVertOut ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 0) {
nVertOn = 0 ;
nVertIn = 1 ;
nVertOut = 2 ;
if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 0) {
nVertOn = 1 ;
nVertIn = 2 ;
nVertOut = 0 ;
if ( m_vVert[ m_vTria[i].nIdVert[2]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
else {
nVertOn = 2 ;
nVertIn = 0 ;
nVertOut = 1 ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
// calcolo il punto di intersezione del lato che attraversa il piano
double dDistIn = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP, plPlane) ;
double dDistOut = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP, plPlane) ;
Point3d ptInt = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
dDistIn / ( dDistIn + dDistOut)) ;
// inserisco il nuovo vertice
int nNewV = AddVertex( ptInt) ;
// inserisco il nuovo triangolo
int nIdVert[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
nIdVert[nVertOut] = nNewV ;
int nIdTria = AddTriangle( nIdVert) ;
if ( nIdTria == SVT_NULL)
return false ;
if ( nIdTria != SVT_DEL)
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( i) ;
}
// se ha un vertice all'interno e due all'esterno -> 2 nuovi vertici e 1 nuovo triangolo
else if ( nDisc == 1) {
// classifico i vertici
int nVertIn, nVertOut1, nVertOut2 ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == -1) {
nVertIn = 0 ;
nVertOut1 = 1 ;
nVertOut2 = 2 ;
}
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == -1) {
nVertIn = 1 ;
nVertOut1 = 2 ;
nVertOut2 = 0 ;
}
else {
nVertIn = 2 ;
nVertOut1 = 0 ;
nVertOut2 = 1 ;
}
// calcolo i punti di intersezione dei lati che attraversano il piano
double dDistIn = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP, plPlane) ;
double dDistOut1 = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut1]].ptP, plPlane) ;
double dDistOut2 = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut2]].ptP, plPlane) ;
Point3d ptInt1 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut1]].ptP,
dDistIn / ( dDistIn + dDistOut1)) ;
Point3d ptInt2 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut2]].ptP,
dDistIn / ( dDistIn + dDistOut2)) ;
// inserisco i nuovi vertici
int nNewV1 = AddVertex( ptInt1) ;
int nNewV2 = AddVertex( ptInt2) ;
// inserisco il nuovo triangolo
int nIdVert[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
nIdVert[nVertOut1] = nNewV1 ;
nIdVert[nVertOut2] = nNewV2 ;
int nIdTria = AddTriangle( nIdVert) ;
if ( nIdTria == SVT_NULL)
return false ;
if ( nIdTria != SVT_DEL)
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( i) ;
}
// altrimenti ha due vertici all'interno e uno all'esterno -> 2 nuovi vertici e 2 nuovi triangoli
else {
// classifico i vertici
int nVertIn1, nVertIn2, nVertOut ;
if ( m_vVert[ m_vTria[i].nIdVert[0]].nTemp == 1) {
nVertOut = 0 ;
nVertIn1 = 1 ;
nVertIn2 = 2 ;
}
else if ( m_vVert[ m_vTria[i].nIdVert[1]].nTemp == 1) {
nVertOut = 1 ;
nVertIn1 = 2 ;
nVertIn2 = 0 ;
}
else {
nVertOut = 2 ;
nVertIn1 = 0 ;
nVertIn2 = 1 ;
}
// calcolo i punti di intersezione dei lati che attraversano il piano
double dDistIn1 = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP, plPlane) ;
double dDistIn2 = - DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP, plPlane) ;
double dDistOut = DistPointPlane( m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP, plPlane) ;
Point3d ptInt1 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
dDistIn1 / ( dDistIn1 + dDistOut)) ;
Point3d ptInt2 = Media( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP,
m_vVert[m_vTria[i].nIdVert[nVertOut]].ptP,
dDistIn2 / ( dDistIn2 + dDistOut)) ;
// inserisco i nuovi vertici
int nNewV1 = AddVertex( ptInt1) ;
int nNewV2 = AddVertex( ptInt2) ;
// inserisco i nuovi triangoli
int nIdVert1[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
int nIdVert2[3] = { m_vTria[i].nIdVert[0], m_vTria[i].nIdVert[1], m_vTria[i].nIdVert[2]} ;
double dSqDist1 = SqDist( m_vVert[m_vTria[i].nIdVert[nVertIn1]].ptP, ptInt2) ;
double dSqDist2 = SqDist( m_vVert[m_vTria[i].nIdVert[nVertIn2]].ptP, ptInt1) ;
if ( dSqDist1 <= dSqDist2) {
nIdVert1[nVertOut] = nNewV1 ;
nIdVert1[nVertIn2] = nNewV2 ;
nIdVert2[nVertOut] = nNewV2 ;
}
else {
nIdVert1[nVertOut] = nNewV1 ;
nIdVert2[nVertOut] = nNewV2 ;
nIdVert2[nVertIn1] = nNewV1 ;
}
int nIdTria1 = AddTriangle( nIdVert1) ;
int nIdTria2 = AddTriangle( nIdVert2) ;
if ( nIdTria1 == SVT_NULL || nIdTria2 == SVT_NULL)
return false ;
if ( nIdTria1 != SVT_DEL)
m_vTria[nIdTria1].nTemp = m_nTimeStamp ;
if ( nIdTria2 != SVT_DEL)
m_vTria[nIdTria2].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( i) ;
}
}
}
// se effettuate modifiche
if ( bModif) {
// aggiorno tutto
if ( ! AdjustVertices() || ! DoCompacting())
return false ;
}
return true ;
#else
bool bModif = false ;
// Setto i triangoli come né fuori né dentro.
int nTriaNum = GetTriangleSize() ;
for ( int nT = 0 ; nT < nTriaNum ; ++ nT) {
m_vTria[nT].nTempPart = 0 ;
}
INTERSCHAINMAP IntersLineMap ;
// Ciclo su tutte le facce.
int nFacetNum = GetFacetCount() ;
for ( int nF = 0 ; nF < nFacetNum ; ++ nF) {
// Dati della faccia
POLYLINEVECTOR vLoopVec ;
GetFacetLoops( nF, vLoopVec) ;
if ( vLoopVec.empty())
continue ;
PtrOwner<SurfFlatRegion> pReg( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vLoopVec))) ;
if ( IsNull( pReg))
return false ;
LineFacetClassVector IntersLinePart ;
int nIntType = IntersFacetPlane( *pReg, vLoopVec[0], plPlane, IntersLinePart) ;
if ( nIntType == FacetPlaneIntersType::FPI_CUT) {
for ( int nPart = 0 ; nPart < int( IntersLinePart.size()) ; ++ nPart) {
// Salvo intersezione per la faccia.
auto it = IntersLineMap.find( nF) ;
if ( it != IntersLineMap.end()) {
it->second.emplace_back( IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn)) ;
}
else {
IntersLineMap.emplace( nF, IntersInnChain( 1, IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn))) ;
}
}
}
else if ( nIntType == FacetPlaneIntersType::FPI_ON) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = pReg->GetNormVersor() * plPlane.GetVersN() > 0. ? 2 : - 2 ;
}
else if ( nIntType == FacetPlaneIntersType::FPI_INN) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = 1 ;
}
else if ( nIntType == FacetPlaneIntersType::FPI_OUT) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = - 1 ;
}
else
;
}
// Divido le facce.
PieceMap NewFacet ;
SplitFacet( IntersLineMap, NewFacet) ;
INTERSEDGEMAP EdgeInterLineMap, EdgeEdgeLineMap ;
RetriangulateFacetPieces( NewFacet, EdgeInterLineMap, EdgeEdgeLineMap) ;
int nNumTria = GetTriangleSize() ;
for ( int nT = 0 ; nT < nNumTria ; ++ nT)
if ( m_vTria[nT].nTempPart == - 1 || m_vTria[nT].nTempPart == - 2 || ( ! bSaveOnEq && m_vTria[nT].nTempPart == 2))
RemoveTriangle( nT) ;
return AdjustVertices() && DoCompacting() ;
#endif
}
//----------------------------------------------------------------------------
void
SurfTriMesh::ResetHashGrids3d( void) const
+48 -39
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2021
// EgalTech 2014-2019
//----------------------------------------------------------------------------
// File : SurfTriMesh.h Data : 26.09.21 Versione : 2.3i2
// File : SurfTriMesh.h Data : 12.02.19 Versione : 2.1b2
// Contenuto : Dichiarazione della classe Superficie TriMesh.
//
//
@@ -94,15 +94,34 @@ typedef std::unordered_map< int, Chain> CHAINMAP ;
typedef std::unordered_map< int, TRIA3DVECTOR> TRIA3DVECTORMAP ;
//----------------------------------------------------------------------------
// Struttura intersezione linea-faccia
// Struttura per la ricerca delle T-Junction
struct TEdgeId {
int nTriaId ;
int nEdge ;
} ;
// Overloading dell'operatore < per TEdgeSet
inline bool operator<( const TEdgeId& TEdgeA, const TEdgeId& TEdgeB) {
if ( TEdgeA.nTriaId != TEdgeB.nTriaId)
return ( TEdgeA.nTriaId < TEdgeB.nTriaId) ;
return ( TEdgeA.nEdge < TEdgeB.nEdge) ;
}
// Loop con T-Junction
typedef std::vector<TEdgeId> TJuncLoop ;
// Vettore di loop con T-Junction
typedef std::vector<TJuncLoop> TJuncLoopVec ;
// Set di TEdgeId
typedef std::set<TEdgeId> TJEdgeSet ;
// Definizione strutture intersezione linea-faccia
//----------------------------------------------------------------------------
struct LineFacetClass {
Point3d ptSt, ptEn ;
int nTypeA, nTypeB ;
LineFacetClass( void) {
LineFacetClass() {
nTypeA = 0 ;
nTypeB = 0 ;
}
LineFacetClass( const Point3d& ptS, const Point3d& ptE, int nTpA, int nTpB) {
LineFacetClass( const Point3d& ptS, const Point3d ptE, int nTpA, int nTpB) {
ptSt = ptS ;
ptEn = ptE ;
nTypeA = nTpA ;
@@ -112,27 +131,28 @@ struct LineFacetClass {
typedef std::vector<LineFacetClass> LineFacetClassVector ;
//----------------------------------------------------------------------------
enum FacetPlaneIntersType { FPI_ERROR = 0, FPI_CUT = 1, FPI_IN = 2, FPI_OUT = 3, FPI_ON = 4 } ;
enum FacetPlaneIntersType { FPI_ERROR = 0, FPI_CUT = 1, FPI_INN = 2, FPI_OUT = 3, FPI_ON = 4 } ;
//----------------------------------------------------------------------------
// Strutture e contenitori contatti interno-interno
// Definizione strutture e contenitori
// Contatti interno-interno
struct IntersInnSeg {
Point3d ptSt ;
Point3d ptEn ;
Vector3d vtOuter ;
IntersInnSeg( void) {
IntersInnSeg(void) {
;
}
IntersInnSeg( const Point3d& ptS, const Point3d& ptE) {
ptSt = ptS ;
ptEn = ptE ;
IntersInnSeg(const Point3d& ptS, const Point3d& ptE) {
ptSt = ptS;
ptEn = ptE;
}
IntersInnSeg( const Point3d& ptS, const Point3d& ptE, const Vector3d& vtO) {
ptSt = ptS ;
ptEn = ptE ;
vtOuter = vtO ;
IntersInnSeg(const Point3d& ptS, const Point3d& ptE, const Vector3d& vtO) {
ptSt = ptS;
ptEn = ptE;
vtOuter = vtO;
}
} ;
};
typedef std::vector<IntersInnSeg> IntersInnChain ;
typedef std::vector<IntersInnChain> INNCHAINVECTOR ;
typedef std::unordered_map<int, IntersInnChain> INTERSCHAINMAP ;
@@ -144,7 +164,7 @@ struct IntersEdge {
IntersEdge( const Point3d& ptS, const Point3d& ptE, const INTVECTOR& vOFI) {
ptSt = ptS;
ptEn = ptE;
vOthFacetIndex = vOFI ;
vOthFacetIndex = vOFI;
}
} ;
typedef std::vector<IntersEdge> IntersEdgeVec ;
@@ -186,11 +206,10 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // ISurf
bool IsSimple( void) const override
@@ -229,7 +248,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool CreateByScrewing( const PolyLine& PL, const Point3d& ptAx, const Vector3d& vtAx,
double dAngRot, double dStepRot, double dMove) override ;
bool DoCompacting( double dTol = EPS_SMALL) override ;
bool DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther = GLOB_FRM, double dTol = 2 * EPS_SMALL) override ;
bool DoSewing( const ISurfTriMesh& stmOther, const Frame3d& frOther = GLOB_FRM) override ;
int GetVertexCount( void) const override ;
int GetTriangleCount( void) const override ;
int GetTriangleCount( int nTFlag) const override ;
@@ -258,7 +277,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetTriangleBoundaryEdges( int nId, TriFlags3d& TFlags) const override ;
bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const override ;
bool GetLoops( POLYLINEVECTOR& vPL) const override ;
bool GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR& vPL) const override ;
bool GetSilhouette( const Vector3d& vtDir, POLYLINEVECTOR& vPL) const override ;
int GetFacetCount( void) const override ;
int GetFacetSize( void) const override
{ return int( m_vFacet.size()) ; }
@@ -285,7 +304,6 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetSurfClassification( const ISurfTriMesh& ClassifierSurf,
INTVECTOR& vTriaIn, INTVECTOR& vTriaOut, INTVECTOR& vTriaOnP, INTVECTOR& vTriaOnM, INTVECTOR& vTriaIndef) override ;
bool CutWithOtherSurf( const ISurfTriMesh& CutterSurf, bool bInVsOut, bool bSaveOnEq) override ;
bool Repair( double dMaxEdgeLen = MAX_EDGE_LEN_STD) override ;
bool GetAllTriaOverlapBox( const BBox3d& b3Box, INTVECTOR& vT) const override ;
const BBox3d& GetAllTriaBox( void) const override ;
int GetPartCount( void) const override ;
@@ -351,9 +369,9 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool MarchOneTria( int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ;
bool VerifyPolylinesForTwoCurves( const PolyLine& PL1, const PolyLine& PL2) const ;
bool AddBiTriangle( const int nIdVert[4]) ;
bool ResetFaceting( void) ;
bool VerifyFaceting( void) const ;
bool UpdateFaceting( void) ;
bool UpdateOneFace( int nFacet, int nT) ;
bool UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane, int nT) ;
bool SetFacet( int nInd, int nT) ;
bool VerifyAdjacTriaFacet( int nT, INTVECTOR& vT) const ;
@@ -362,20 +380,16 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
void ResetHashGrids3d( void) const ;
bool VerifyHashGrids3d( void) const ;
bool VerifyConnection( void) const ;
bool CutTriangleByPlane( int nTriaId, const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool CutByFacets( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ;
bool DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMATRIX& cvBoundClosedLoopVec, BOOLVECTOR& vbInOut) ;
bool RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf, bool& bModif) ;
bool AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf) ;
bool IntersectTriMeshTriangle( SurfTriMesh& Other) ;
int VerifyLoopPlane( const PolyLine& ExtLoop, const Plane3d& plCutPlane) ;
int IntersFacetPlane( const SurfFlatRegion& Region, const Plane3d& plCutPlane,
LineFacetClassVector& IntersLinePart) ;
int IntersFacetPlane( const SurfFlatRegion& Region, const PolyLine& ExtLoop, const Plane3d& plCutPlane,
LineFacetClassVector& IntersLinePart) ;
bool IntersFacetFacet( const SurfFlatRegion& RegionA, const PolyLine& ExtLoopA,
const SurfFlatRegion& RegionB, const PolyLine& ExtLoopB,
LineFacetClassVector& IntersLinePart) ;
bool IntersectTriMeshFacets( SurfTriMesh& Other) ;
bool ItersectTriMeshFacets( SurfTriMesh& Other) ;
bool RetriangulateFacetPieces( const PieceMap& NewFacet,
const INTERSEDGEMAP& EdgeInterLineMap,
const INTERSEDGEMAP& EdgeEdgeLineMap) ;
@@ -392,11 +406,6 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool RemoveTripleTriangles( void) ;
bool ScanForTripleTriangles( bool& bModified) ;
bool FlipTriangles( int nTA, int nTB) ;
bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true) ;
bool AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) ;
bool DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist) ;
bool ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop) ;
bool SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2) ;
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
@@ -413,7 +422,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
TRIAVECTOR m_vTria ; // vettore dei triangoli
INTVECTOR m_vFacet ; // vettore delle sfaccettature
mutable int m_nTimeStamp ; // orologio locale
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
int m_nMaxTFlag ; // massimo valore dei TFlag dei triangoli
mutable int m_nParts ; // numero di parti connesse (-1 se da calcolare)
mutable HashGrids3d* m_pHGrd3d ; // Hash Grid 3d nel suo riferimento
+1223 -418
View File
File diff suppressed because it is too large Load Diff
-874
View File
@@ -1,874 +0,0 @@
//----------------------------------------------------------------------------
// EgalTech 2019-2021
//----------------------------------------------------------------------------
// File : SurfTriMeshCuts.cpp Data : 06.11.21 Versione : 2.3k3
// Contenuto : Implementazione delle funzioni di taglio per SurfFTrimesh.
//
//
//
// Modifiche : 06.11.21 DS Creazione modulo.
//
//
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "CurveComposite.h"
#include "SurfTriMesh.h"
#include "SurfFlatRegion.h"
#include "DistPointLine.h"
#include "Triangulate.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EgkSfrCreate.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
using namespace std ;
//----------------------------------------------------------------------------
const double CUT_SCALE = 1024 ;
//----------------------------------------------------------------------------
bool
SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq)
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// recupero il numero originale di triangoli e di facce
int nTriaOriCnt = GetTriangleCount() ;
int nFacetOriCnt = GetFacetCount() ;
// eseguo il taglio con il metodo delle faccette o dei triangoli (per ora solo coi triangoli)
bool bModif = false ;
if ( true || ! CutByFacets( plPlane, bSaveOnEq, bModif)) {
bModif = false ;
if ( ! CutByTriangles( plPlane, bSaveOnEq, bModif))
return false ;
}
// se effettuate modifiche
if ( bModif) {
// aggiorno tutto
if ( ! AdjustVertices() || ! DoCompacting())
return false ;
}
// se superficie originale a facce, cerco di semplificarle in ogni caso
if ( nFacetOriCnt < 200 || double( nTriaOriCnt) / nFacetOriCnt > 4) {
if ( ! SimplifyFacets())
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Cut")
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
{
// la superficie deve essere validata
if ( m_nStatus != OK)
return false ;
// classifico i vertici rispetto al piano
double dTol = max( min( 0.5 * m_dLinTol, 10 * EPS_SMALL), EPS_SMALL) ;
for ( int i = 0 ; i < GetVertexSize() ; ++ i) {
double dDist = DistPointPlane( m_vVert[i].ptP, plPlane) ;
if ( abs( dDist) < dTol) {
m_vVert[i].nTemp = 0 ;
if ( abs( dDist) > EPS_SMALL)
m_vVert[i].ptP -= plPlane.GetVersN() * dDist ;
}
else if ( dDist > 0)
m_vVert[i].nTemp = +1 ;
else
m_vVert[i].nTemp = -1 ;
}
// aggiorno timestamp dei triangoli
for ( auto& Tria : m_vTria)
Tria.nTemp = m_nTimeStamp ;
++ m_nTimeStamp ;
// sistemo i triangoli (eventualmente li elimino)
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
// salto i triangoli cancellati e quelli aggiunti
if ( m_vTria[i].nIdVert[0] == SVT_DEL || m_vTria[i].nTemp == m_nTimeStamp)
continue ;
CutTriangleByPlane( i, plPlane, bSaveOnEq, bModif) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::CutTriangleByPlane( int nT, const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
{
// se flag abilita e giace sul piano ed equiverso, lo salvo
if ( bSaveOnEq &&
m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == 0 &&
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == 0 &&
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp == 0 &&
AreSameVectorApprox( m_vTria[nT].vtN, plPlane.GetVersN()))
;
// se giace sul piano o dalla parte esterna del piano, lo cancello
else if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp != -1 &&
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp != -1 &&
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp != -1) {
bModif = true ;
RemoveTriangle( nT) ;
}
// se giace dalla parte interna con al massimo un lato sul piano, lo conservo
else if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp != 1 &&
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp != 1 &&
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp != 1)
;
// altrimenti attraversa il piano, devo modificarlo
else {
bModif = true ;
int nDisc = m_vVert[ m_vTria[nT].nIdVert[0]].nTemp +
m_vVert[ m_vTria[nT].nIdVert[1]].nTemp +
m_vVert[ m_vTria[nT].nIdVert[2]].nTemp ;
// se ha un vertice all'interno e uno sul piano -> 1 nuovo vertice e 1 nuovo triangolo
if ( nDisc == 0) {
// classifico i vertici
int nVertOn, nVertIn, nVertOut ;
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == 0) {
nVertOn = 0 ;
nVertIn = 1 ;
nVertOut = 2 ;
if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
else if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == 0) {
nVertOn = 1 ;
nVertIn = 2 ;
nVertOut = 0 ;
if ( m_vVert[ m_vTria[nT].nIdVert[2]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
else {
nVertOn = 2 ;
nVertIn = 0 ;
nVertOut = 1 ;
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp > 0)
swap( nVertIn, nVertOut) ;
}
// calcolo il punto di intersezione del lato che attraversa il piano
double dDistIn = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP, plPlane) ;
double dDistOut = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP, plPlane) ;
Point3d ptInt = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP,
dDistIn / ( dDistIn + dDistOut)) ;
// inserisco il nuovo vertice
int nNewV = AddVertex( ptInt) ;
// inserisco il nuovo triangolo
int nIdVert[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
nIdVert[nVertOut] = nNewV ;
int nIdTria = AddTriangle( nIdVert) ;
if ( nIdTria == SVT_NULL)
return false ;
if ( nIdTria != SVT_DEL)
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( nT) ;
}
// se ha un vertice all'interno e due all'esterno -> 2 nuovi vertici e 1 nuovo triangolo
else if ( nDisc == 1) {
// classifico i vertici
int nVertIn, nVertOut1, nVertOut2 ;
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == -1) {
nVertIn = 0 ;
nVertOut1 = 1 ;
nVertOut2 = 2 ;
}
else if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == -1) {
nVertIn = 1 ;
nVertOut1 = 2 ;
nVertOut2 = 0 ;
}
else {
nVertIn = 2 ;
nVertOut1 = 0 ;
nVertOut2 = 1 ;
}
// calcolo i punti di intersezione dei lati che attraversano il piano
double dDistIn = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP, plPlane) ;
double dDistOut1 = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut1]].ptP, plPlane) ;
double dDistOut2 = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut2]].ptP, plPlane) ;
Point3d ptInt1 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[nT].nIdVert[nVertOut1]].ptP,
dDistIn / ( dDistIn + dDistOut1)) ;
Point3d ptInt2 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn]].ptP,
m_vVert[m_vTria[nT].nIdVert[nVertOut2]].ptP,
dDistIn / ( dDistIn + dDistOut2)) ;
// inserisco i nuovi vertici
int nNewV1 = AddVertex( ptInt1) ;
int nNewV2 = AddVertex( ptInt2) ;
// inserisco il nuovo triangolo
int nIdVert[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
nIdVert[nVertOut1] = nNewV1 ;
nIdVert[nVertOut2] = nNewV2 ;
int nIdTria = AddTriangle( nIdVert) ;
if ( nIdTria == SVT_NULL)
return false ;
if ( nIdTria != SVT_DEL)
m_vTria[nIdTria].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( nT) ;
}
// altrimenti ha due vertici all'interno e uno all'esterno -> 2 nuovi vertici e 2 nuovi triangoli
else {
// classifico i vertici
int nVertIn1, nVertIn2, nVertOut ;
if ( m_vVert[ m_vTria[nT].nIdVert[0]].nTemp == 1) {
nVertOut = 0 ;
nVertIn1 = 1 ;
nVertIn2 = 2 ;
}
else if ( m_vVert[ m_vTria[nT].nIdVert[1]].nTemp == 1) {
nVertOut = 1 ;
nVertIn1 = 2 ;
nVertIn2 = 0 ;
}
else {
nVertOut = 2 ;
nVertIn1 = 0 ;
nVertIn2 = 1 ;
}
// calcolo i punti di intersezione dei lati che attraversano il piano
double dDistIn1 = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn1]].ptP, plPlane) ;
double dDistIn2 = - DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertIn2]].ptP, plPlane) ;
double dDistOut = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP, plPlane) ;
Point3d ptInt1 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn1]].ptP,
m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP,
dDistIn1 / ( dDistIn1 + dDistOut)) ;
Point3d ptInt2 = Media( m_vVert[m_vTria[nT].nIdVert[nVertIn2]].ptP,
m_vVert[m_vTria[nT].nIdVert[nVertOut]].ptP,
dDistIn2 / ( dDistIn2 + dDistOut)) ;
// inserisco i nuovi vertici
int nNewV1 = AddVertex( ptInt1) ;
int nNewV2 = AddVertex( ptInt2) ;
// inserisco i nuovi triangoli
int nIdVert1[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
int nIdVert2[3] = { m_vTria[nT].nIdVert[0], m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]} ;
double dSqDist1 = SqDist( m_vVert[m_vTria[nT].nIdVert[nVertIn1]].ptP, ptInt2) ;
double dSqDist2 = SqDist( m_vVert[m_vTria[nT].nIdVert[nVertIn2]].ptP, ptInt1) ;
if ( dSqDist1 <= dSqDist2) {
nIdVert1[nVertOut] = nNewV1 ;
nIdVert1[nVertIn2] = nNewV2 ;
nIdVert2[nVertOut] = nNewV2 ;
}
else {
nIdVert1[nVertOut] = nNewV1 ;
nIdVert2[nVertOut] = nNewV2 ;
nIdVert2[nVertIn1] = nNewV1 ;
}
int nIdTria1 = AddTriangle( nIdVert1) ;
int nIdTria2 = AddTriangle( nIdVert2) ;
if ( nIdTria1 == SVT_NULL || nIdTria2 == SVT_NULL)
return false ;
if ( nIdTria1 != SVT_DEL)
m_vTria[nIdTria1].nTemp = m_nTimeStamp ;
if ( nIdTria2 != SVT_DEL)
m_vTria[nIdTria2].nTemp = m_nTimeStamp ;
// cancello il vecchio triangolo
RemoveTriangle( nT) ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::CutByFacets( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif)
{
// Setto posizione triangoli non definita
for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT)
m_vTria[nT].nTempPart = 0 ;
INTERSCHAINMAP IntersLineMap ;
// Ciclo su tutte le facce.
for ( int nF = 0 ; nF < GetFacetCount() ; ++ nF) {
// Dati della faccia
POLYLINEVECTOR vLoopVec ;
GetFacetLoops( nF, vLoopVec) ;
if ( vLoopVec.empty())
continue ;
// Verifico la posizione del loop esterno
int nIntType = VerifyLoopPlane( vLoopVec[0], plPlane) ;
// Se interseca il piano di taglio, calcolo la divisione della faccia
LineFacetClassVector IntersLinePart ;
if ( nIntType == FPI_CUT) {
PtrOwner<SurfFlatRegion> pReg( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vLoopVec))) ;
if ( IsNull( pReg) || ! pReg->IsValid())
return false ;
nIntType = IntersFacetPlane( *pReg, plPlane, IntersLinePart) ;
}
// Gestione dei risultati
if ( nIntType == FPI_CUT) {
for ( int nPart = 0 ; nPart < int( IntersLinePart.size()) ; ++ nPart) {
// Salvo intersezione per la faccia.
auto it = IntersLineMap.find( nF) ;
if ( it != IntersLineMap.end()) {
it->second.emplace_back( IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn)) ;
}
else {
IntersLineMap.emplace( nF, IntersInnChain( 1, IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn))) ;
}
}
}
else if ( nIntType == FPI_ON) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
Vector3d vtNf ;
GetFacetNormal( nF, vtNf) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = ( vtNf * plPlane.GetVersN() > 0 ? 2 : -2) ;
}
else if ( nIntType == FPI_IN) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = 1 ;
}
else if ( nIntType == FPI_OUT) {
INTVECTOR vT ;
GetAllTriaInFacet( nF, vT) ;
for ( auto& nT : vT)
m_vTria[nT].nTempPart = -1 ;
}
else
return false ;
}
// Divido le facce.
PieceMap NewFacet ;
SplitFacet( IntersLineMap, NewFacet) ;
INTERSEDGEMAP EdgeInterLineMap, EdgeEdgeLineMap ;
RetriangulateFacetPieces( NewFacet, EdgeInterLineMap, EdgeEdgeLineMap) ;
// Elimino i triangoli superflui
for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT) {
if ( m_vTria[nT].nTempPart == 0 ||
m_vTria[nT].nTempPart == -1 ||
m_vTria[nT].nTempPart == -2 ||
( ! bSaveOnEq && m_vTria[nT].nTempPart == 2)) {
RemoveTriangle( nT) ;
bModif = true ;
}
}
return true ;
}
//----------------------------------------------------------------------------
// Risultato : 0=nessuna intersezione, 1=intersezione è un punto, 2=intersezione è un segmento
static int
IntersRectangleTriangle( const Point3d& ptP, const Vector3d& vtL1, const Vector3d& vtL2,
const Triangle3d& trTria, Point3d& ptStSeg, Point3d& ptEnSeg)
{
// Assegno tolleranza lineare
double dTol = EPS_SMALL ;
// Definisco il piano del rettangolo
Plane3d plRectanglePlane ;
if ( ! plRectanglePlane.Set( ptP, vtL1 ^ vtL2))
return -1 ;
// Interseco il piano con il triangolo (recupero estremi in ordine inverso per mantenere l'esterno a destra nei loop)
int nPlTrIntRes = IntersPlaneTria( plRectanglePlane, trTria, ptEnSeg, ptStSeg) ;
if ( nPlTrIntRes != IntPlaneTriaType::IPTT_YES)
return 0 ;
// Limito il segmento col rettangolo
Vector3d vtSegDir = ptEnSeg - ptStSeg ;
double dSegLen = vtSegDir.Len() ;
vtSegDir /= dSegLen ;
// utilizzo piani ortogonali al rettangolo passanti per i suoi estremi
Plane3d plTrim1 ; plTrim1.Set( ptP, -vtL1) ;
Plane3d plTrim2 ; plTrim2.Set( ptP + vtL1, vtL1) ;
if ( vtSegDir * vtL1 < 0.)
swap( plTrim1, plTrim2) ;
Point3d ptInt1 ;
int nLnPl1IntRes = IntersLinePlane( ptStSeg, vtSegDir, dSegLen, plTrim1, ptInt1, false) ;
Point3d ptInt2 ;
int nLnPl2IntRes = IntersLinePlane( ptStSeg, vtSegDir, dSegLen, plTrim2, ptInt2, false) ;
// Se il segmento giace in uno dei due piani
if ( ( nLnPl1IntRes == ILPT_NO && nLnPl2IntRes == ILPT_INPLANE) ||
( nLnPl2IntRes == ILPT_NO && nLnPl1IntRes == ILPT_INPLANE))
return ( AreSamePointEpsilon( ptStSeg, ptEnSeg, dTol) ? 1 : 2) ;
// Se non ci sono intersezioni
if ( nLnPl1IntRes == ILPT_NO && nLnPl2IntRes == ILPT_NO) {
// se è tra i due piani
if (( ptStSeg - plTrim1.GetPoint()) * plTrim1.GetVersN() < 0. &&
( ptStSeg - plTrim2.GetPoint()) * plTrim2.GetVersN() < 0.)
return ( AreSamePointEpsilon( ptStSeg, ptEnSeg, dTol) ? 1 : 2) ;
// altrimenti è esterno
else
return 0 ;
}
// Posizioni parametriche delle intersezioni sul segmento
double dLen1 = ( ptInt1 - ptStSeg) * vtSegDir ;
double dLen2 = ( ptInt2 - ptStSeg) * vtSegDir ;
// Se la prima intersezione supera la fine o la seconda viene prima dell'inizio, non ci sono intersezioni
if ( dLen1 > dSegLen + EPS_ZERO || dLen2 < -EPS_ZERO)
return 0 ;
// Eventuale aggiustamento inizio
if ( dLen1 > 0.) {
ptStSeg = ptInt1 ;
dSegLen -= dLen1 ;
dLen2 -= dLen1 ;
}
// Eventuale aggiustamento fine
if ( dLen2 < dSegLen) {
ptEnSeg = ptInt2 ;
dSegLen = dLen2 ;
}
// Assegno il tipo di intersezione
return ( dSegLen > dTol ? 2 : 1) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GeneralizedCut( const ICurve& cvCurve, bool bSaveOnEq)
{
// La superficie deve essere valida
if ( m_nStatus != OK)
return false ;
// La curva deve essere valida e chiusa, il vettore estrusione deve essere non nullo
Vector3d vtExtr ;
if ( ! cvCurve.GetExtrusion( vtExtr) || vtExtr.IsSmall() || ! cvCurve.IsClosed())
return false ;
// Recupero il numero originale di triangoli e di facce
int nTriaOriCnt = GetTriangleCount() ;
int nFacetOriCnt = GetFacetCount() ;
// Approssimo la curva con segmenti
CurveComposite cvCompo ;
{
PolyLine PL ;
if ( ! cvCurve.ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurve::APL_STD, PL) || ! cvCompo.FromPolyLine( PL))
return false ;
}
// Eseguo scalature
Frame3d frScalingRef;
frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ;
Scale( frScalingRef, CUT_SCALE, CUT_SCALE, CUT_SCALE) ;
cvCompo.Scale( frScalingRef, CUT_SCALE, CUT_SCALE, CUT_SCALE) ;
// Appiattisco la polilinea nel piano perpendicolare all'estrusione
Frame3d frCurve ;
Point3d ptStart ; cvCompo.GetStartPoint( ptStart) ;
frCurve.Set( ptStart, vtExtr) ;
cvCompo.ToLoc( frCurve) ;
if ( ! cvCompo.Scale( GLOB_FRM, 1, 1, 0)) {
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
return false ;
}
double dArea ;
cvCompo.GetAreaXY( dArea) ;
BBox3d b3Crv ;
cvCompo.GetLocalBBox( b3Crv) ;
cvCompo.ToGlob( frCurve) ;
// Assegno il senso di rotazione della curva (visto dalla punta del vettore estrusione)
bool bCCW = ( dArea > 0) ;
// Recupero Bounding-box della trimesh
BBox3d b3SurfBox ;
GetLocalBBox( b3SurfBox) ;
// Trovo minima e massima distanza dei vertici del bounding-box della TriMesh dal piano della curva
b3SurfBox.ToLoc( frCurve) ;
Point3d ptMin, ptMax ;
b3SurfBox.GetMinMax( ptMin, ptMax) ;
Vector3d vtMax = ( ptMax.z + 10) * vtExtr ;
Vector3d vtMin = ( ptMin.z - 10) * vtExtr ;
// Ciclo sui triangoli
bool bModif = false ;
int nNumTria = GetTriangleSize() ;
for ( int nT = 0 ; nT < nNumTria ; ++ nT) {
// Recupero il triangolo
Triangle3d trTria ;
if ( ! GetTriangle( nT, trTria))
continue ;
// Box del triangolo nel riferimento locale della curva
BBox3d b3Tria ;
trTria.GetLocalBBox( b3Tria) ;
b3Tria.ToLoc( frCurve) ;
// Se il box del triangolo non interseca quello locale della curva
if ( ! b3Crv.OverlapsXY( b3Tria)) {
// Se la parte da conservare è quella all'interno della curva, elimino il triangolo
if ( bCCW) {
RemoveTriangle( nT) ;
bModif = true ;
}
continue ;
}
// Determino se il centro del triangolo cade all'interno della curva
bool bTriaCenIn = false ;
{
// centro proiettato sul piano della curva
Point3d ptCen = trTria.GetCentroid() ;
ptCen = ptCen - ( ptCen - ptStart) * vtExtr * vtExtr ;
// calcolo distanza
DistPointCurve dstPC( ptCen, cvCompo) ;
double dDist ; dstPC.GetDist( dDist) ;
// se maggiore oltre il limite originale
if ( dDist > CUT_SCALE * EPS_SMALL) {
int nSide ;
if ( dstPC.GetSideAtMinDistPoint( 0, vtExtr, nSide))
bTriaCenIn = ( nSide == MDS_LEFT) ;
}
// altrimenti ricalcolo con centro del triangolo spostato all'interno sulla normale
else {
Point3d ptCen2 = trTria.GetCentroid() - CUT_SCALE * EPS_SMALL * trTria.GetN() ;
DistPointCurve dstP2C( ptCen2, cvCompo) ;
int nSide2 ;
if ( dstP2C.GetSideAtMinDistPoint( 0, vtExtr, nSide2))
bTriaCenIn = ( nSide2 == MDS_LEFT && bSaveOnEq) ;
}
}
// Vettore di catene di punti e flag sulla complanarità del triangolo con uno dei rettangoli
CHAINVECTOR vChain ;
bool bTriaOn = false ;
// Segnalatore di taglio piccolo, punto e vettore per costruire il piano per eseguirlo
int nSmallCutState = 0 ;
Point3d ptSmallCutPnt ;
Vector3d vtSmallCutVec ;
// Ciclo sui segmenti
int nChainCnt = 0 ;
bool bChain = false ;
Point3d ptChSt, ptChEn ;
const ICurve* pCrv = cvCompo.GetFirstCurve() ;
while ( pCrv != nullptr) {
// estremi del segmento
Point3d ptSt ; pCrv->GetStartPoint( ptSt) ;
Point3d ptEn ; pCrv->GetEndPoint( ptEn) ;
// Se il segmento giace sul piano del triangolo, lo segnalo.
if ( abs( ( ptSt - trTria.GetCentroid()) * trTria.GetN()) < CUT_SCALE * EPS_SMALL &&
abs( ( ptEn - trTria.GetCentroid()) * trTria.GetN()) < CUT_SCALE * EPS_SMALL &&
abs( trTria.GetN() * vtExtr) < EPS_SMALL)
bTriaOn = true ;
// Intersezione fra il rettangolo (ottenuto dall'estrusione del segmento corrente) e il triangolo
Point3d ptSegSt, ptSegEn ;
int nInt = IntersRectangleTriangle( ptSt + vtMin, ptEn - ptSt, vtMax - vtMin, trTria, ptSegSt, ptSegEn) ;
if ( nInt == 2) {
// Creo nuova catena se non c'è già o se discontinuità
if ( ! bChain || ( ! AreSamePointApprox( ptSegSt, ptChEn) && ! AreSamePointApprox( ptSegEn, ptChSt))) {
++ nChainCnt ;
vChain.resize( nChainCnt) ;
bChain = false ;
}
// Assegno i dati di intersezione
IntSegment CurInters ;
CurInters.ptSt = ptSegSt ;
CurInters.ptEn = ptSegEn ;
// Inserisco nella catena
if ( ! bChain) {
vChain[nChainCnt - 1].emplace_back( CurInters) ;
ptChSt = CurInters.ptSt ;
ptChEn = CurInters.ptEn ;
}
else if ( AreSamePointApprox(ptSegSt, ptChEn)) {
vChain[nChainCnt - 1].emplace_back(CurInters) ;
ptChEn = CurInters.ptEn ;
}
else {
vChain[nChainCnt - 1].insert(vChain[nChainCnt - 1].begin(), CurInters) ;
ptChSt = CurInters.ptSt ;
}
bChain = true ;
}
else {
// Taglio piccolo
if ( nInt == 1) {
if ( nSmallCutState == 0)
nSmallCutState = 1 ;
else
nSmallCutState = 2 ;
ptSmallCutPnt = ptSt ;
vtSmallCutVec = ptEn - ptSt ;
}
bChain = false ;
}
pCrv = cvCompo.GetNextCurve() ;
}
// Gestisco il taglio piccolo.
if ( nSmallCutState == 1 && int( vChain.size()) == 0) {
Plane3d plPlane ;
plPlane.Set( ptSmallCutPnt, vtSmallCutVec ^ ( vtMax - vtMin)) ;
for ( int nV = 0 ; nV < 3 ; ++ nV) {
double dDist = DistPointPlane( m_vVert[m_vTria[nT].nIdVert[nV]].ptP, plPlane) ;
if ( abs( dDist) < EPS_SMALL) {
m_vVert[m_vTria[nT].nIdVert[nV]].nTemp = 0 ;
if ( abs( dDist) > EPS_SMALL)
m_vVert[m_vTria[nT].nIdVert[nV]].ptP -= plPlane.GetVersN() * dDist ;
}
else if ( dDist > 0)
m_vVert[m_vTria[nT].nIdVert[nV]].nTemp = +1 ;
else
m_vVert[m_vTria[nT].nIdVert[nV]].nTemp = -1 ;
}
CutTriangleByPlane( nT, plPlane, bSaveOnEq, bModif) ;
continue ;
}
for ( auto itI = vChain.begin() ; itI != vChain.end() ; ) {
bool bErased = false ;
auto itJ = itI ;
++ itJ ;
for ( ; itJ != vChain.end() && ! bErased ; ) {
if ( int( itI->size()) == 1 && int( itJ->size()) == 1 &&
AreSamePointEpsilon( itI->back().ptSt, itJ->back().ptEn, 2 * EPS_SMALL) &&
AreSamePointEpsilon( itI->back().ptEn, itJ->back().ptSt, 2 * EPS_SMALL)) {
itJ = vChain.erase( itJ) ;
bErased = true ;
}
else
++ itJ ;
}
if ( bErased) {
itI = vChain.erase( itI) ;
bErased = false ;
}
else
++ itI ;
}
nChainCnt = int( vChain.size()) ;
// 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()) ;
vChain.pop_back() ;
-- nChainCnt ;
}
else if ( AreSamePointApprox( vChain[0].back().ptEn, vChain[nChainCnt - 1].front().ptSt)) {
vChain[0].insert(vChain[0].end(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ;
vChain.pop_back() ;
-- nChainCnt ;
}
}
// Elimino la seconda copia di catene doppie
for ( int nI = 0 ; nI < nChainCnt ; ++ nI) {
for ( int nJ = nI + 1 ; nJ < nChainCnt ; ++ nJ) {
if ( vChain[nI].size() == vChain[nJ].size()) {
bool bSame = true ;
for ( int nK = 0 ; nK < int( vChain[nI].size()) ; ++ nK) {
if ( ! AreSamePointApprox( vChain[nI][nK].ptSt, vChain[nJ][nK].ptSt) ||
! AreSamePointApprox( vChain[nI][nK].ptEn, vChain[nJ][nK].ptEn)) {
bSame = false ;
break ;
}
}
if ( bSame) {
vChain.erase( vChain.begin() + nJ) ;
-- nChainCnt ;
-- nJ ;
}
}
}
}
// Fra le catene trovate separo le aperte dalle chiuse
CHAINVECTOR cvClosedChain ;
CHAINVECTOR cvOpenChain ;
for ( int nL = 0 ; nL < int( vChain.size()) ; ++ nL) {
int nCurLoopLast = max( int(vChain[nL].size()) - 1, 0) ;
if ( AreSamePointApprox( vChain[nL][0].ptSt, vChain[nL][nCurLoopLast].ptEn) && nCurLoopLast > 0)
cvClosedChain.emplace_back( vChain[nL]) ;
else {
cvOpenChain.emplace_back( vChain[nL]) ;
}
}
for ( auto it = cvClosedChain.begin() ; it != cvClosedChain.end() ; ) {
if ( int( it->size()) < 3)
it = cvClosedChain.erase( it) ;
else
++ it ;
}
// Se più di una catena chiusa oppure catene chiuse e aperte, errore
if ( cvClosedChain.size() > 1 || ( cvClosedChain.size() > 0 && int( cvOpenChain.size()) > 0)) {
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
return false ;
}
// Se c'è una catena chiusa
if ( cvClosedChain.size() == 1) {
// Ne ricavo una PolyLine
PolyLine plInLoop ;
for ( int nLine = 0 ; nLine < int( cvClosedChain[0].size()) ; ++ nLine) {
plInLoop.AddUPoint( 0., cvClosedChain[0][nLine].ptSt) ;
plInLoop.AddUPoint( 0., cvClosedChain[0][nLine].ptEn) ;
}
// I tre vertici sono dalla parte interna della curva (triangolo con buco)
if ( ! bCCW) {
// Rimuovo il triangolo corrente
RemoveTriangle( nT) ;
// Definisco il loop esterno (è il triangolo)
PolyLine plExtLoop ;
plExtLoop.AddUPoint( 0., trTria.GetP( 0)) ;
plExtLoop.AddUPoint( 0., trTria.GetP( 1)) ;
plExtLoop.AddUPoint( 0., trTria.GetP( 2)) ;
plExtLoop.AddUPoint( 0., trTria.GetP( 0)) ;
// Eseguo triangolazione
POLYLINEVECTOR vPL ;
vPL.emplace_back( plExtLoop) ;
vPL.emplace_back( plInLoop) ;
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( vPL, 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] = { AddVertex( vPt[nNewTriaVertId[0]]),
AddVertex( vPt[nNewTriaVertId[1]]),
AddVertex( vPt[nNewTriaVertId[2]]) } ;
AddTriangle( nNewId) ;
bModif = true ;
}
}
}
// Se nessun vertice dalla parte interna della curva (rimane solo l'area della curva)
else {
// Rimuovo il triangolo corrente
RemoveTriangle( nT) ;
// Eseguo triangolazione
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( plInLoop, 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] = { AddVertex(vPt[nNewTriaVertId[0]]),
AddVertex(vPt[nNewTriaVertId[1]]),
AddVertex(vPt[nNewTriaVertId[2]]) } ;
AddTriangle( nNewId) ;
bModif = true ;
}
}
}
}
// Loop aperti, devo chiuderli
else if ( cvOpenChain.size() > 0) {
// 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 ;
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
BOOLVECTOR vbInOut ;
vbInOut.push_back( true) ;
// Divido il loop di partenza in sotto-loop
while ( cvOpenChain.size() > 0) {
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
for ( int nLoop = 0 ; nLoop < int( cvBoundClosedLoopVec.size()) ; ++ nLoop) {
// Estremi del loop aperto
int nLastOpenLoopPoint = max( int( cvOpenChain[nLastOpenLoopN].size()) - 1, 0) ;
Point3d ptOpenLoopStP = cvOpenChain[nLastOpenLoopN][0].ptSt ;
Point3d ptOpenLoopEnP = cvOpenChain[nLastOpenLoopN][nLastOpenLoopPoint].ptEn ;
PNTVECTOR Loop1, Loop2 ;
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
if ( ! ( bChangedStart && bSplitted))
continue ;
Chain cvCounterChain ;
for ( int nPt = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nPt >= 0 ; -- nPt) {
IntSegment CurSeg ;
CurSeg.ptSt = cvOpenChain[nLastOpenLoopN][nPt].ptEn ;
CurSeg.ptEn = cvOpenChain[nLastOpenLoopN][nPt].ptSt ;
cvCounterChain.emplace_back( CurSeg) ;
}
bool bAdded1 = AddChainToChain( cvCounterChain, Loop1) ;
bool bAdded2 = AddChainToChain( cvOpenChain[nLastOpenLoopN], Loop2) ;
if ( ! ( bAdded1 && bAdded2))
continue ;
// Aggiungo i nuovi loop nel vettore
int nCurSize = int( cvBoundClosedLoopVec.size()) ;
cvBoundClosedLoopVec.resize( nCurSize + 1) ;
vbInOut.resize( nCurSize + 1) ;
for ( int nCL = nCurSize - 1 ; nCL > nLoop ; -- nCL) {
cvBoundClosedLoopVec[nCL + 1] = cvBoundClosedLoopVec[nCL] ;
vbInOut[nCL + 1] = vbInOut[nCL] ;
}
cvBoundClosedLoopVec[nLoop] = Loop1 ;
cvBoundClosedLoopVec[nLoop + 1] = Loop2 ;
vbInOut[nLoop] = false ;
vbInOut[nLoop + 1] = true ;
++ nLoop ;
}
cvOpenChain.resize( nLastOpenLoopN) ;
}
// Rimuovo il triangolo corrente
RemoveTriangle( nT) ;
// Se il triangolo originale aveva il centro interno alla curva oppure devo tenere le parti
// di superficie che hanno una parte giacente sul rettangolo della superficie di taglio,
// aggiungo i nuovi triangoli.
if ( ! bTriaOn || bSaveOnEq) {
// Trasformo i loop compositi in loop polyline
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) {
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ;
}
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][0]) ;
if ( vbInOut[nLoop]) {
// Eseguo triangolazione
Triangulate CreateTriangulation ;
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( vplPolyVec[nLoop], 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] = { AddVertex(vPt[nNewTriaVertId[0]]),
AddVertex(vPt[nNewTriaVertId[1]]),
AddVertex(vPt[nNewTriaVertId[2]]) } ;
AddTriangle( nNewId) ;
bModif = true ;
}
}
}
}
}
}
// da eliminare
else if ( ! bTriaCenIn) {
RemoveTriangle( nT) ;
bModif = true ;
}
}
// Se avvenuta modifica, aggiorno tutto
if ( bModif) {
// aggiorno tutto
if ( ! AdjustVertices() || ! DoCompacting()) {
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
return false ;
}
}
// Ripristino scala originale
Scale( frScalingRef, 1. / CUT_SCALE, 1. / CUT_SCALE, 1. / CUT_SCALE) ;
// se superficie originale a facce, cerco di semplificarle in ogni caso
if ( nFacetOriCnt < 200 || double( nTriaOriCnt) / nFacetOriCnt > 4) {
if ( ! SimplifyFacets())
LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::GeneralizedCut")
}
return true ;
}
+37 -61
View File
@@ -22,6 +22,15 @@
using namespace std ;
//----------------------------------------------------------------------------
bool
SurfTriMesh::ResetFaceting( void)
{
m_bFaceted = false ;
m_vFacet.clear() ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::VerifyFaceting( void) const
@@ -35,36 +44,14 @@ SurfTriMesh::VerifyFaceting( void) const
bool
SurfTriMesh::UpdateFaceting( void)
{
// salvo vecchio vettore facce
INTVECTOR vOldFacet = m_vFacet ;
// reset faceting
m_bFaceted = false ;
m_vFacet.clear() ;
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i)
m_vTria[i].nIdFacet = SVT_NULL ;
// indice faccia corrente
int nFacet = -1 ;
// ricostruisco le sfaccettature come definite in precedenza (dove possibile)
// ricostruisco le sfaccettature
bool bOk = true ;
for ( int j = 0 ; j < int( vOldFacet.size()) ; ++ j) {
int i = vOldFacet[j] ;
// salto triangoli inesistenti o già assegnati
if ( i >= int( m_vTria.size()) ||
m_vTria[i].nIdVert[0] == SVT_DEL ||
m_vTria[i].nIdFacet != SVT_NULL)
continue ;
// assegno indice di faccia al triangolo
m_vTria[i].nIdFacet = ++ nFacet ;
m_vFacet.push_back( i) ;
// aggiorno faccia
if ( ! UpdateOneFace( nFacet, i))
bOk = false ;
}
// ricostruisco le altre sfaccettature
int nFacet = -1 ;
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// salto triangoli cancellati o già assegnati
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
@@ -73,9 +60,32 @@ SurfTriMesh::UpdateFaceting( void)
// assegno indice di faccia al triangolo
m_vTria[i].nIdFacet = ++ nFacet ;
m_vFacet.push_back( i) ;
// aggiorno faccia
if ( ! UpdateOneFace( nFacet, i))
bOk = false ;
// piano del triangolo
Plane3d plPlane ;
if ( ! plPlane.Set( m_vVert[m_vTria[i].nIdVert[0]].ptP, m_vTria[i].vtN)) {
LOG_ERROR( GetEGkLogger(), "SurfTM : UpdateFaceting error in triangle data")
return false ;
}
// set di triangoli da aggiornare
set<int> stTria ;
stTria.insert( i) ;
// finchè set non vuoto
while ( ! stTria.empty()) {
// tolgo un triangolo dal set
const auto iIt = stTria.begin() ;
int nT = *iIt ;
stTria.erase( iIt) ;
// aggiorno i triangoli adiacenti
for ( int j = 0 ; j < 3 ; ++ j) {
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nIdFacet == SVT_NULL) {
if ( ! UpdateTriaFaceting( nT, nFacet, plPlane, nAdjT))
bOk = false ;
if ( m_vTria[nAdjT].nIdFacet == nFacet)
stTria.insert( nAdjT) ;
}
}
}
}
// se ci sono stati problemi, salvo nel log
@@ -87,40 +97,6 @@ SurfTriMesh::UpdateFaceting( void)
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::UpdateOneFace( int nFacet, int nT)
{
// piano del triangolo
Plane3d plPlane ;
if ( ! plPlane.Set( m_vVert[m_vTria[nT].nIdVert[0]].ptP, m_vTria[nT].vtN)) {
LOG_ERROR( GetEGkLogger(), "SurfTM : UpdateFaceting error in triangle data")
return false ;
}
// set di triangoli da aggiornare
set<int> stTria ;
stTria.insert( nT) ;
// finchè set non vuoto
bool bOk = true ;
while ( ! stTria.empty()) {
// tolgo un triangolo dal set
const auto iIt = stTria.begin() ;
int nT = *iIt ;
stTria.erase( iIt) ;
// aggiorno i triangoli adiacenti
for ( int j = 0 ; j < 3 ; ++ j) {
int nAdjT = m_vTria[nT].nIdAdjac[j] ;
if ( nAdjT != SVT_NULL && m_vTria[nAdjT].nIdFacet == SVT_NULL) {
if ( ! UpdateTriaFaceting( nT, nFacet, plPlane, nAdjT))
bOk = false ;
if ( m_vTria[nAdjT].nIdFacet == nFacet)
stTria.insert( nAdjT) ;
}
}
}
return bOk ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane, int nT)
-604
View File
@@ -1,604 +0,0 @@
//----------------------------------------------------------------------------
// EgalTech 2021-2021
//----------------------------------------------------------------------------
// File : SurfTriMeshUtilities.cpp Data : 01.11.21 Versione : 2.3k1
// Contenuto : Implementazione funzioni di utilità di Superfici TriMesh.
//
//
//
// Modifiche : 25.10.21 LM Creazione modulo.
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "Triangulate.h"
#include "SurfTriMesh.h"
#include "DistPointLine.h"
#include <unordered_map>
using namespace std ;
//----------------------------------------------------------------------------
bool
SurfTriMesh::RemoveTJunctions(void)
{
// Vettore di indici dei vertici sui lati del triangolo corrente
unordered_map< int, INTVECTOR> TriaMap ;
// Ciclo sui triangoli della superficie per determinare gli altri vertici sul loro perimetro
for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) {
// Se il triangolo non è valido, passo al successivo
Triangle3d trTria ;
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
continue ;
// Vettore degli altri vertici sul contorno del triangolo
INTVECTOR vVertOtl ;
// Box del triangolo
BBox3d b3Tria ;
trTria.GetLocalBBox( b3Tria) ;
INTVECTOR vNearTria ;
GetAllTriaOverlapBox( b3Tria, vNearTria) ;
// Ciclo sui lati del triangolo
for ( int nSeg = 0 ; nSeg < 3 ; ++ nSeg) {
// aggiungo al vettore il vertice iniziale del lato
vVertOtl.emplace_back( m_vTria[nT].nIdVert[nSeg]) ;
// Se in questo lato il triangolo è adiacente a un altro, lo salto.
if ( m_vTria[nT].nIdAdjac[nSeg] != SVT_DEL && m_vTria[nT].nIdAdjac[nSeg] != SVT_NULL)
continue ;
int nPrevSize = int( vVertOtl.size()) ;
// recupero la geometria del lato
Point3d ptSegSt = trTria.GetP( nSeg) ;
Point3d ptSegEn = trTria.GetP( ( nSeg + 1) % 3) ;
Vector3d vtSeg = ptSegEn - ptSegSt ;
double dSegLen = vtSeg.Len() ;
if ( dSegLen < EPS_SMALL)
continue ;
vtSeg /= dSegLen ;
// Ciclo sui triangoli vicini
for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) {
// Salto il triangolo se è quello di riferimento
if ( vNearTria[nI] == nT)
continue ;
// Cerco i vertici che stanno sul lato del triangolo
for ( int nVert = 0 ; nVert < 3 ; ++ nVert) {
Point3d ptVert ;
if ( ! GetVertex( m_vTria[vNearTria[nI]].nIdVert[nVert], ptVert))
continue ;
double dProj = ( ptVert - ptSegSt) * vtSeg ;
double dOrt = ( ( ptVert - ptSegSt) - dProj * vtSeg).SqLen() ;
if ( dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL && dOrt < SQ_EPS_TRIA_H)
vVertOtl.emplace_back( m_vTria[vNearTria[nI]].nIdVert[nVert]) ;
}
}
// Riordino i vertici sul segmento
auto SortVerteces = [ this, &ptSegSt, &vtSeg]( const int nV1, const int nV2)
{ Point3d ptV1, ptV2 ;
GetVertex( nV1, ptV1) ;
GetVertex( nV2, ptV2) ;
return ( ( ptV1 - ptSegSt) * vtSeg < ( ptV2 - ptSegSt) * vtSeg) ;
} ;
sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVerteces) ;
}
// Se ci sono più di 3 vertici
if ( vVertOtl.size() > 3) {
// Elimino i vertici ripetuti
vVertOtl.erase( unique( vVertOtl.begin(), vVertOtl.end()), vVertOtl.end()) ;
// Se ci sono ancora più di 3 vertici, inserisco nel Map
if ( vVertOtl.size() > 3)
TriaMap.emplace( nT, vVertOtl) ;
}
}
// Ciclo sui triangoli da sistemare
for ( auto itT = TriaMap.begin() ; itT != TriaMap.end() ; ++ itT) {
// Indice del triangolo
int nT = itT->first ;
// Vettore degli altri vertici sul perimetro
const INTVECTOR& vVertOtl = itT->second ;
// Se il triangolo non è valido, passo al successivo
Triangle3d trTria ;
if ( ! GetTriangle( nT, trTria) || ! trTria.Validate( true))
continue ;
// Salvo eventuale indice di faccetta
int nFacet = m_vTria[nT].nIdFacet ;
if ( nFacet > int( m_vFacet.size()) || m_vFacet[nFacet] != nT)
nFacet = SVT_NULL ;
// Rimuovo il triangolo
int nTFlag = m_vTria[nT].nTFlag ;
RemoveTriangle( nT) ;
// Aggiungo i nuovi triangoli
int nLastNewTria = SVT_NULL ;
// Se ci sono 4 vertici, inserisco due triangoli
if ( vVertOtl.size() == 4) {
// se 1-2-3 è triangolo (e quindi 0-1-3)
int nNew1Id[3] = { vVertOtl[1], vVertOtl[2], vVertOtl[3]} ;
int nNew1Tria = AddTriangle( nNew1Id, nTFlag) ;
if ( nNew1Tria != SVT_NULL && nNew1Tria != SVT_DEL) {
nLastNewTria = nNew1Tria ;
int nNew2Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[3]} ;
int nNew2Tria = AddTriangle( nNew2Id, nTFlag) ;
if ( nNew2Tria != SVT_NULL && nNew2Tria != SVT_DEL)
nLastNewTria = nNew2Tria ;
}
// altrimenti 0-1-2 e 2-3-0
else {
int nNew3Id[3] = { vVertOtl[0], vVertOtl[1], vVertOtl[2]} ;
int nNew3Tria = AddTriangle( nNew3Id, nTFlag) ;
if ( nNew3Tria != SVT_NULL && nNew3Tria != SVT_DEL)
nLastNewTria = nNew3Tria ;
int nNew4Id[3] = { vVertOtl[2], vVertOtl[3], vVertOtl[0]} ;
int nNew4Tria = AddTriangle( nNew4Id, nTFlag) ;
if ( nNew4Tria != SVT_NULL && nNew4Tria != SVT_DEL)
nLastNewTria = nNew4Tria ;
}
}
// altrimenti inserisco un ventaglio di triangoli dal centro ai vertici
else {
Point3d ptTriaCen = trTria.GetCentroid() ;
int nCenIndex = AddVertex( ptTriaCen) ;
int nVertNum = int( vVertOtl.size()) ;
for ( int nStV = 0 ; nStV < nVertNum ; ++ nStV) {
int nEnV = ( nStV + 1) % nVertNum ;
int nNewId[3] = { nCenIndex, vVertOtl[nStV], vVertOtl[nEnV]} ;
int nNewTria = AddTriangle( nNewId, nTFlag) ;
if ( nNewTria != SVT_NULL && nNewTria != SVT_DEL)
nLastNewTria = nNewTria ;
}
}
// Eventuale aggiustamento per indice di faccetta
if ( nFacet != SVT_NULL && nLastNewTria != SVT_NULL)
m_vFacet[nFacet] = nLastNewTria ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
IsVertex( PNTULIST& PointList, PNTULIST::const_iterator itCurr)
{
// recupero il punto precedente
PNTULIST::const_iterator itPrev ;
if ( itCurr == PointList.begin())
itPrev = prev( PointList.end(), 2) ;
else
itPrev = prev( itCurr) ;
// recupero il punto successivo
auto itNext = next( itCurr) ;
if ( itNext == PointList.end())
itNext = next( PointList.begin()) ;
// se cambia faccia adiacente tra prima e dopo, va bene
if ( itPrev->second != itCurr->second)
return true ;
// se lati aperti e cambia direzione tra prima e dopo, va bene
if ( itPrev->second == -1) {
DistPointLine PointLineDistCalc( itCurr->first, itPrev->first, itNext->first) ;
double dDist ;
if ( PointLineDistCalc.GetDist( dDist) && dDist > EPS_SMALL)
return true ;
}
// altrimenti non va bene
return false ;
}
//----------------------------------------------------------------------------
static bool
ChooseGoodStartPoint( PNTULIST& PointList)
{
// se il punto iniziale è un vertice, non devo fare alcunché
if ( IsVertex( PointList, PointList.begin()))
return true ;
// altrimenti cerco il vertice più vicino
for ( auto it = next( PointList.begin()) ; it != PointList.end() ; ++it) {
if ( IsVertex( PointList, it)) {
// se ultimo punto non devo fare alcunché
if ( next( it) == PointList.end())
return false ;
// cancello ultimo punto ( coincide con primo)
PointList.pop_back() ;
// sposto la parte iniziale dei punti alla fine
PointList.splice( PointList.end(), PointList, PointList.begin(), it) ;
// aggiungo punto finale come copia dell'iniziale
PointList.push_back( PointList.front()) ;
// ho finito
return true ;
}
}
return false ;
}
//----------------------------------------------------------------------------
static bool
AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
{
// Ciclo sui punti del loop
auto itLast = PointList.begin() ;
for ( auto it = next( itLast) ; it != PointList.end() ; ++ it) {
// Se dal punto corrente inizia un segmento adiacente a un'altra faccia
if ( itLast->second != it->second) {
// Elimino i punti interni
auto itNextToLast = next( itLast) ;
for ( auto itInn = itNextToLast ; itInn != it ; ) {
itInn = PointList.erase( itInn) ;
bModif = true ;
}
// Se la lunghezza del segmento supera il limite imposto
double dSegLen = Dist( it->first, itLast->first) ;
if ( dSegLen > dMaxEdgeLen) {
// determino il numero di step
double dRatio = dSegLen / dMaxEdgeLen ;
int nStepCount = int( dRatio) + 1 ;
// inserisco i punti
auto itAdd = it ;
for ( int nP = 1 ; nP < nStepCount ; ++ nP) {
double dCoeff = double( nP) / nStepCount ;
itAdd = PointList.insert( itAdd, POINTU( Media( itLast->first, it->first, 1 - dCoeff), itLast->second)) ;
bModif = true ;
}
}
// Nuovo punto di riferimento
itLast = it ;
}
// Se sono due segmenti liberi non allineati
else if ( itLast->second == - 1) {
// Calcolo se i punti compresi fra gli estremi sono allineati
bool bAreAligned = true ;
auto itNextToLast = next( itLast) ;
for ( auto itInn = itNextToLast ; itInn != it && bAreAligned ; ++ itInn) {
DistPointLine PointLineDistCalc( itInn->first, itLast->first, it->first) ;
double dDist ;
if ( PointLineDistCalc.GetDist( dDist))
bAreAligned = ( dDist < EPS_SMALL) ;
}
// Se i punti sono allineati
if ( bAreAligned) {
// Verifico se il successivo punto non è più allineato
auto itNextToCurr = next( it) ;
if ( itNextToCurr != PointList.end()) {
for ( auto itInn = itNextToLast ; itInn != itNextToCurr && bAreAligned ; ++ itInn) {
DistPointLine PointLineDistCalc( itInn->first, itLast->first, itNextToCurr->first) ;
double dDist ;
if ( PointLineDistCalc.GetDist( dDist))
bAreAligned = ( dDist < EPS_SMALL) ;
}
}
// Se ho trovato un insieme massimale di punti allineati li processo
if ( ! bAreAligned || itNextToCurr == PointList.end()) {
// Elimino i punti interni
for ( auto itInn = itNextToLast ; itInn != it ; ) {
itInn = PointList.erase( itInn) ;
bModif = true ;
}
// Se la lunghezza del segmento supera il limite imposto
double dSegLen = Dist( it->first, itLast->first) ;
if ( dSegLen > dMaxEdgeLen) {
// determino il numero di step
double dRatio = dSegLen / dMaxEdgeLen ;
int nStepCount = int( dRatio) + 1 ;
// inserisco i punti
auto itAdd = it ;
for ( int nP = 1 ; nP < nStepCount ; ++ nP) {
double dCoeff = double( nP) / nStepCount ;
itAdd = PointList.insert( itAdd, POINTU( Media( itLast->first, it->first, 1 - dCoeff), itLast->second)) ;
bModif = true ;
}
}
// Nuovo punto di riferimento
itLast = it ;
}
}
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
{
// La trimesh deve essere valida
if ( ! IsValid())
return false ;
// Se la lunghezza massima del lato del triangolo sul bordo della faccia è nulla e non forzata, non devo fare alcunché
if ( dMaxEdgeLen < EPS_SMALL && ! bForced)
return true ;
// Recupero il numero delle facce (esegue anche una verifica delle stesse)
int nFacetCnt = GetFacetCount() ;
// Ciclo sulle facce della mesh per trovare quelle da ritriangolare
unordered_map< int, pair< PNTVECTOR, INTVECTOR>> FacetMap ;
for ( int nF = 0 ; nF < nFacetCnt ; ++ nF) {
// Recupero i loop della faccia (il parametro indica la faccia adiacente)
POLYLINEVECTOR LoopVec ;
GetFacetLoops( nF, LoopVec) ;
// Ciclo sui loop della faccia
bool bToRetriangulate = bForced ;
for ( int nL = 0 ; nL < int( LoopVec.size()) ; ++ nL) {
// Lista dei punti del loop
PNTULIST& PointList = LoopVec[nL].GetUPointList() ;
// Mi assicuro che il punto iniziale/finale non sia all'interno di un possibile segmento
if ( ! ChooseGoodStartPoint( PointList))
continue ;
// Sistemo il loop
bool bModif = false ;
if ( ! AdjustLoop( PointList, dMaxEdgeLen, bModif))
return false ;
if ( bModif)
bToRetriangulate = true ;
}
// Se non richiesta ritriangolazione dai bordi, verifico se ci sono vertici di triangoli interni (*** disabilitato ***)
if ( false && ! bToRetriangulate) {
// numero dei triangoli nella faccia
INTVECTOR vFacetTria ;
GetAllTriaInFacet( nF, vFacetTria) ;
int nTriaCnt = int( vFacetTria.size()) ;
// numero dei lati di contorno della faccia
int nSideCnt = 0 ;
for ( int nL = 0 ; nL < int( LoopVec.size()) ; ++ nL)
nSideCnt += LoopVec[nL].GetLineNbr() ;
// numero dei buchi della faccia
int nHoleCnt = int( LoopVec.size()) - 1 ;
// dalla formula di Eulero adattata al caso ( nTriaCnt = nSideCnt + 2 * ( nHoleCnt - 1))
if ( nTriaCnt != nSideCnt + 2 * ( nHoleCnt - 1))
bToRetriangulate = true ;
}
// Se da ritriangolare
if ( bToRetriangulate) {
// Eseguo la ritriangolazione della faccia
PNTVECTOR vPt ;
INTVECTOR vTr ;
if ( Triangulate().Make( LoopVec, vPt, vTr)) {
FacetMap.emplace( nF, make_pair( vPt, vTr)) ;
}
// Se non riesco a triangolare anche solo questa faccia, interrompo tutto
else
return false ;
}
}
// Ciclo sulle facce da ritriangolare per eliminare i triangoli (nel contempo salvo flag colore)
INTVECTOR vDelTria ;
unordered_map< int, int> ColorMap ;
for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) {
// Recupero i triangoli della faccia
INTVECTOR vFacetTria ;
GetAllTriaInFacet( itF->first, vFacetTria) ;
vDelTria.insert( vDelTria.end(), vFacetTria.begin(), vFacetTria.end()) ;
// Salvo il colore della faccia da flag di un suo triangolo
ColorMap.emplace( itF->first, m_vTria[m_vFacet[itF->first]].nTFlag) ;
}
// Cancello i triangoli
for ( int nT : vDelTria)
RemoveTriangle( nT) ;
// Applico le nuove triangolazioni delle facce
for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) {
const PNTVECTOR& vPt = itF->second.first ;
const INTVECTOR& vTr = itF->second.second ;
// Inserisco i nuovi triangoli
bool bFirstTria = true ;
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
int nNewId[3] = { AddVertex( vPt[vTr[n]]),
AddVertex( vPt[vTr[n + 1]]),
AddVertex( vPt[vTr[n + 2]])} ;
auto itCol = ColorMap.find( itF->first) ;
int nTFlag = ( itCol != ColorMap.end() ? itCol->second : 0) ;
int nNewTriaId = AddTriangle( nNewId, nTFlag) ;
if ( nNewTriaId != SVT_NULL && nNewTriaId != SVT_DEL) {
m_vTria[nNewTriaId].nIdFacet = itF->first ;
if ( bFirstTria) {
m_vFacet[itF->first] = nNewTriaId ;
bFirstTria = false ;
}
}
}
}
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
// Eseguo aggiustamenti
return ( AdjustVertices() && DoCompacting()) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
{
// Se la catena da aggiungere è vuota, non devo fare alcunchè
if ( ChainToAdd.size() == 0)
return true ;
// Se la catena originale è vuota, non è possibile aggiungere nulla
if ( OrigChain.size() == 0)
return false ;
// Se la catena originale è chiusa non posso aggiungere nulla
int nLastOrig = max( int( OrigChain.size()) - 1, 0) ;
if ( AreSamePointApprox( OrigChain[0], OrigChain[nLastOrig]))
return false ;
int nLastToAdd = max( int( ChainToAdd.size()) - 1, 0) ;
if ( AreSamePointApprox( OrigChain[nLastOrig], ChainToAdd[0].ptSt)) {
for ( int nPt = 1 ; nPt <= nLastToAdd ; ++ nPt) {
if ( nPt == nLastToAdd) {
if ( ! AreSamePointApprox(OrigChain[0], ChainToAdd[nPt].ptSt))
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
}
else if ( nPt == 1) {
if ( ! AreSamePointApprox( OrigChain[nLastOrig], ChainToAdd[nPt].ptSt))
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
}
else
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
}
return true ;
}
else
return false ;
}
//----------------------------------------------------------------------------
// Una faccia di una trimesh ha una sola componente connessa, con un loop esterno e possibili loop interni
bool
SurfTriMesh::DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist)
{
// Verifico la presenza del loop esterno
if ( vPolyVec.size() < 1)
return false ;
// Proietto il punto sul piano della faccia, utilizzando il loop esterno
Plane3d plPlane ;
double dArea ;
if ( ! vPolyVec[0].IsClosedAndFlat( plPlane, dArea))
return false ;
double dDistPtPl = DistPointPlane( ptP, plPlane) ;
Point3d ptProjP = ptP + dDistPtPl * plPlane.GetVersN() ;
// Verifico se il punto proiettato è esterno al loop esterno
int nPtOut = -1 ;
if ( ! IsPointInsidePolyLine( ptProjP, vPolyVec[0], EPS_SMALL))
nPtOut = 0 ;
// Verifico se il punto proiettato è interno ai loop interni (quindi esterno alla faccia)
for ( int nLoop = 1 ; nLoop < int( vPolyVec.size()) && nPtOut < 0 ; ++ nLoop) {
Plane3d plPlane ;
double dArea ;
if ( ! vPolyVec[nLoop].IsClosedAndFlat( plPlane, dArea))
return false ;
if ( IsPointInsidePolyLine( ptProjP, vPolyVec[nLoop], EPS_SMALL))
nPtOut = nLoop ;
}
// Se il punto si proietta sulla faccia, la distanza dalla faccia coincide con quella dal piano
if ( nPtOut < 0) {
dPointFacetDist = abs( dDistPtPl) ;
return true ;
}
// Altrimenti calcolo la minima distanza del punto dalla polilinea del contorno a cui è esterno
double dDist ;
if ( DistPointPolyLine( ptP, vPolyVec[nPtOut], dDist)) {
dPointFacetDist = dDist ;
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop)
{
// Cerco il tratto del loop chiuso più vicino al punto
int nMinSeg = - 1 ;
double dMinSqDinst = DBL_MAX ;
for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) {
// Estremi del segmento corrente del loop
Point3d ptSegSt = Loop[nPt] ;
Point3d ptSegEn = Loop[( nPt + 1) % int( Loop.size())] ;
// Distanza del punto dal segmento del loop
DistPointLine dDistCalc( ptNewStart, ptSegSt, ptSegEn) ;
double dSqDist ;
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDinst) {
dMinSqDinst = dSqDist ;
nMinSeg = nPt ;
}
}
// Se il punto non sta sul loop, errore
if ( dMinSqDinst > SQ_EPS_SMALL)
return false ;
// Verifico che il punto stia su un vertice, in tal caso non devo fare nulla
bool bOnStart = AreSamePointApprox( Loop[nMinSeg], ptNewStart) ;
bool bOnEnd = AreSamePointApprox( Loop[( nMinSeg + 1) % int( Loop.size())], ptNewStart) ;
if ( bOnStart || bOnEnd) {
if ( bOnEnd) {
++ nMinSeg ;
if ( nMinSeg % int( Loop.size()) == 0)
return true ;
}
PNTVECTOR vTempVec ;
for ( int nPt = 0 ; nPt < nMinSeg ; ++ nPt)
vTempVec.emplace_back( Loop[nPt]) ;
int nSize = int( Loop.size()) ;
for ( int nPt = 0 ; nPt < nSize - nMinSeg ; ++ nPt) {
Loop[nPt] = Loop[nPt + nMinSeg] ;
}
for ( int nPt = 0 ; nPt < int( vTempVec.size()) ; ++ nPt) {
Loop[nPt + nSize - nMinSeg] = vTempVec[nPt] ;
}
return true ;
}
// Ridimensiono il loop
Loop.resize( Loop.size() + 1) ;
// Copio i primi punti
PNTVECTOR LoopTemp ;
for ( int nPt = 0 ; nPt <= nMinSeg ; ++ nPt)
LoopTemp.emplace_back( Loop[nPt]) ;
// Aggiungo il nuovo punto all'inizio
Loop[0] = ptNewStart ;
// Sposto gli ultimi in testa
int nLastPointNum = int( Loop.size()) - 1 - nMinSeg ;
for ( int nPt = 1 ; nPt <= nLastPointNum ; ++ nPt) {
Loop[nPt] = Loop[nPt + nMinSeg] ;
}
// Porto i primi in fondo
for ( int nPt = 0 ; nPt < int( LoopTemp.size()) ; ++ nPt) {
Loop[nPt + nLastPointNum] = LoopTemp[nPt] ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2)
{
// Cerco il tratto del loop chiuso più vicino al punto
int nMinSeg = -1 ;
double dMinSqDinst = DBL_MAX ;
for ( int nPt = 0 ; nPt < int( Loop.size()) ; ++ nPt) {
// Estremi del segmento corrente del loop
Point3d ptSegSt = Loop[nPt] ;
Point3d ptSegEn = Loop[( nPt + 1) % int(Loop.size())] ;
// Distanza del punto dal segmento del loop
DistPointLine dDistCalc( ptStop, ptSegSt, ptSegEn) ;
double dSqDist ;
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDinst) {
dMinSqDinst = dSqDist ;
nMinSeg = nPt ;
}
}
// Se il punto non sta sul loop, errore
if ( dMinSqDinst > SQ_EPS_SMALL)
return false ;
// Verifico che il punto stia su un vertice, in tal caso non devo aggiungerlo
bool bFirst = AreSamePointApprox( Loop[nMinSeg], ptStop) ;
bool bLast = AreSamePointApprox( Loop[( nMinSeg + 1) % int( Loop.size())], ptStop) ;
// Se il punto è sul vertice finale del segmento, aggiungo il vertice alla lista da inglobare al primo loop
if ( bLast)
++ nMinSeg ;
// Inglobo fino a nSeg nel primo loop
for ( int nPt = 0 ; nPt <= nMinSeg && nPt < int( Loop.size()) ; ++ nPt)
Loop1.emplace_back( Loop[nPt]) ;
// Se il punto è interno al segmento, lo inglobo in entrambi i loop
if ( ! ( bFirst || bLast)) {
Loop1.emplace_back( ptStop) ;
Loop2.emplace_back( ptStop) ;
}
else {
if ( nMinSeg != int( Loop.size()) )
Loop2.emplace_back( Loop[nMinSeg]) ;
}
// Inglobo gli ultimi vertici in Loop2
for ( int nPt = nMinSeg + 1 ; nPt < int( Loop.size()) ; ++ nPt)
Loop2.emplace_back( Loop[nPt]) ;
Loop2.emplace_back( Loop[0]) ;
return true ;
}
+21 -184
View File
@@ -27,9 +27,9 @@ using namespace std ;
//----------------------------------------------------------------------------
Tool::Tool( bool bApproxWithLines)
: m_bApproxWithLines( bApproxWithLines), m_dLinTol( LIN_TOL_STD), m_dAngTolDeg( ANG_TOL_APPROX_DEG),
m_nType( UNDEF), m_nCurrentNum( 0), m_dHeight( 0), m_dTipHeight( 0), m_dRadius( 0), m_dRCorner( 0),
m_dTipRadius( 0), m_dRefRadius( 0), m_dCutterHeight( 0), m_dMrtChsWidth( 0), m_dMrtChsThickness( 0)
: m_dLinTol( LIN_TOL_STD), m_dAngTolDeg( ANG_TOL_APPROX_DEG), m_nType( UNDEF), m_nCurrentNum( 0), m_dHeight( 0), m_dTipHeight( 0),
m_dRadius( 0), m_dRCorner( 0), m_dTipRadius( 0), m_dRefRadius( 0), m_dCutterHeight( 0), m_dMrtChsWidth( 0), m_dMrtChsThickness( 0),
m_bApproxWithLines( bApproxWithLines)
{
}
@@ -100,13 +100,9 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR,
Point3d pt3( m_dRadius, - m_dHeight, 0) ;
Point3d pt4( 0, - m_dHeight, 0) ;
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt1);
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt4) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// utensile naso di toro
else if ( dCornR < dR - EPS_SMALL) {
@@ -124,15 +120,10 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR,
Point3d pt3( m_dTipRadius, - m_dHeight, 0) ;
Point3d pt4( 0, - m_dHeight, 0) ;
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt1);
m_Outline.AddLine( pt2);
m_Outline.AddArcTg( pt3) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddLine( pt4) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
// se da approosimare
if ( m_bApproxWithLines)
return SetGenTool( sToolName, &m_Outline, nToolNum) ;
@@ -152,13 +143,9 @@ Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR,
Point3d pt2( m_dRadius, - m_dHeight + m_dTipHeight, 0) ;
Point3d pt4( 0, - m_dHeight, 0) ;
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt1);
m_Outline.AddLine( pt2);
m_Outline.AddArcTg( pt4) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// impossibile
else
@@ -214,14 +201,9 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
// profilo
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( Point3d( m_dTipRadius, - m_dHeight, 0)) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
// eventuali sistemazioni per altezza tagliente
if ( ModifyForCutterHeight())
return SetGenTool( sToolName, &m_Outline, nToolNum) ;
@@ -231,7 +213,7 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
// Altrimenti utensile generico
// se Tip a punta ( TipRadius raggio teorico della parte finale dell'utensile senza raccordo)
// se Tip a punta ( TipRadius è raggio teorico della parte finale dell'utensile senza raccordo)
if ( m_dTipRadius < m_dRadius) {
// se punta a sfera
if ( m_dTipRadius < EPS_SMALL) {
@@ -260,16 +242,10 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
// creazione curva composita
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// altrimenti punta a naso di toro
else {
@@ -295,22 +271,16 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
// creazione curva composita
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddCurve( Release( pArc)) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
}
// altrimenti Tip a coda di rondine ( TipRadius raggio misurabile della parte finale dell'utensile)
// altrimenti Tip a coda di rondine ( TipRadius è raggio misurabile della parte finale dell'utensile)
else {
// il raggio della punta non pu essere inferiore al raggio corner
// il raggio della punta non può essere inferiore al raggio corner
if ( m_dTipRadius < m_dRCorner)
return false ;
// Assegno il raggio di riferimento
@@ -335,16 +305,10 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
// creazione curva composita
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// eventuali sistemazioni per altezza tagliente
@@ -357,7 +321,7 @@ Tool::SetAdvTool( const string& sToolName, double dH, double dR,
bool
Tool::ModifyForCutterHeight( void)
{
// Se altezza tagliente non definita o superiore alla altezza utensile non devo fare alcunch
// Se altezza tagliente non definita o superiore alla altezza utensile non devo fare alcunché
if ( m_dCutterHeight < EPS_SMALL || m_dCutterHeight > m_dHeight - EPS_SMALL)
return false ;
// quota di taglio
@@ -376,8 +340,6 @@ Tool::ModifyForCutterHeight( void)
m_Outline.TrimStartAtParam( dU) ;
m_Outline.AddLine( Point3d( 0, dYtrim, 0), false) ;
m_Outline.AddLine( ORIG, false) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
return true ;
}
return false ;
@@ -413,36 +375,22 @@ Tool::SetSawTool( const string& sToolName, double dH, double dR,
// creazione profilo
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddLine( pt4) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// altrimenti con raggio corner
else {
// creazione profilo
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt1) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt2) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( pt3 - X_AX * dCornR) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddArcTg( pt3 - Y_AX * dCornR) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.AddLine( pt4 + Y_AX * dCornR) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddArcTg( pt4 - X_AX * dCornR) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 5, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
}
// altrimenti senza gambo
@@ -457,28 +405,18 @@ Tool::SetSawTool( const string& sToolName, double dH, double dR,
// creazione profilo
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt3) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt4) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
// altrimenti con raggio corner
else {
// creazione profilo
m_Outline.AddPoint( pt0) ;
m_Outline.AddLine( pt3 - X_AX * dCornR) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddArcTg( pt3 - Y_AX * dCornR) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt4 + Y_AX * dCornR) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddArcTg( pt4 - X_AX * dCornR) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( pt5) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
}
}
// Assegno il raggio di riferimento
@@ -498,30 +436,17 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
if ( pToolOutline != &m_Outline)
m_Outline.Clear() ;
m_ArcLineApprox.Clear() ;
// Copio il profilo e garantisco sia di soli archi e rette (converto eventuali curve di Bezier)
if ( ! m_Outline.CopyFrom( pToolOutline) ||
! m_Outline.ArcsBezierCurvesToArcsPerpExtr( m_dLinTol, m_dAngTolDeg))
return false ;
// Valuto se tutte le curve tagliano
m_ArcLineApprox.SetTempProp( 1, 1) ;
const ICurve* pCurve = m_Outline.GetFirstCurve() ;
while ( pCurve != nullptr && m_ArcLineApprox.GetTempProp( 1) == 1) {
int nCutTempProp = pCurve->GetTempProp( 1) ;
if ( nCutTempProp == 0) {
m_ArcLineApprox.SetTempProp( 0, 1) ;
}
pCurve = m_Outline.GetNextCurve() ;
}
// Ciclo sulle curve componenti
pCurve = m_Outline.GetFirstCurve() ;
const ICurve* pCurve = m_Outline.GetFirstCurve() ;
while ( pCurve != nullptr) {
int nCutTempProp = pCurve->GetTempProp( 1) ;
// Se la curva un arco ed richiesto la verifica per l'approssimazione,
// Se la curva è un arco ed è richiesto la verifica per l'approssimazione,
// verifico se approssimarlo
if ( m_bApproxWithLines && pCurve->GetType() == CRV_ARC) {
@@ -529,11 +454,11 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
Point3d ptO = GetBasicCurveArc( pCurve)->GetCenter() ;
double dRadius = GetBasicCurveArc( pCurve)->GetRadius() ;
// Se il centro fuori dall'asse devo approssimare
// Se il centro è fuori dall'asse devo approssimare
bool bCurrApprox = ( abs( ptO.x) > EPS_SMALL) ;
// Se una delle altre curve dista dal centro meno del raggio, devo approssimare
for ( int nI = 0 ; ! bCurrApprox && nI < m_Outline.GetCurveCount() && m_ArcLineApprox.GetTempProp( 1) == 1 ; ++ nI) {
for ( int nI = 0 ; ! bCurrApprox && nI < m_Outline.GetCurveCount() ; ++ nI) {
const ICurve* pOtherCrv = m_Outline.GetCurve( nI) ;
if ( pOtherCrv != pCurve) {
DistPointCurve CalcDist( ptO, *pOtherCrv) ;
@@ -568,7 +493,6 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
m_vArcNormals.emplace_back( vtExtN) ;
int nCvCount = m_ArcLineApprox.GetCurveCount() ;
m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, int( m_vArcNormals.size()) - 1) ;
m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, nCutTempProp, 1) ;
}
}
// altrimenti lo aggiungo semplicemente
@@ -576,20 +500,16 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
m_ArcLineApprox.AddCurve( *pCurve, true) ;
int nCvCount = m_ArcLineApprox.GetCurveCount() ;
m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, - 1) ;
m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, nCutTempProp, 1) ;
}
}
// altrimenti segmento e lo aggiungo semplicemente
else {
// altrimenti è segmento e lo aggiungo semplicemente
else
m_ArcLineApprox.AddCurve( *pCurve, true) ;
int nCvCount = m_ArcLineApprox.GetCurveCount() ;
m_ArcLineApprox.SetCurveTempProp( nCvCount - 1, nCutTempProp, 1) ;
}
pCurve = m_Outline.GetNextCurve() ;
}
// Il profilo dell'utensile deve stare nel 1 e 4 quadrante del piano XY
// Il profilo dell'utensile deve stare nel 1° e 4° quadrante del piano XY
BBox3d Bounding ;
m_Outline.GetLocalBBox( Bounding) ;
if ( Bounding.GetMin().x < - 10 * EPS_SMALL)
@@ -601,7 +521,7 @@ Tool::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline,
// Assegno le dimensioni dell'utensile
m_dHeight = - Bounding.GetMin().y ;
m_dRadius = Bounding.GetMax().x ;
// Assegno il raggio di riferimento se non gi assegnato
// Assegno il raggio di riferimento se non già assegnato
if ( m_dRefRadius < EPS_SMALL)
m_dRefRadius = 0.25 * m_dRadius ;
@@ -659,86 +579,3 @@ Tool::SetChiselTool( const string& sToolName, double dH, double dW, double dTh,
return true ;
}
//----------------------------------------------------------------------------
bool
Tool::SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRC, int nToolNum)
{
// Impostazioni generali
m_sName = sToolName ;
m_nCurrentNum = nToolNum ;
m_nType = UNDEF ;
m_Outline.Clear() ;
m_ArcLineApprox.Clear() ;
// verifica sulle minime dimensioni globali
if ( dH < EPS_SMALL || dR < EPS_SMALL || dRC < - EPS_SMALL)
return false ;
m_dHeight = dH ;
m_dRadius = dR ;
m_dRCorner = dRC ;
m_dTipHeight = 0 ;
m_dTipRadius = 0 ;
m_dRefRadius = 0 ;
m_dCutterHeight = dH ;
bool bToolDefined = true ;
double dSquareCornerRadProj = m_dRCorner * m_dRCorner - 0.25 * m_dHeight * m_dHeight ;
// Utensile sfiancato
if ( dSquareCornerRadProj > 0) {
double dCenX = m_dRadius - m_dRCorner ;
double dCylRad = dCenX + sqrt( dSquareCornerRadProj) ;
// Utensile mal definito
if ( dCylRad < EPS_SMALL)
return false ;
// Profilo
m_Outline.AddPoint( Point3d( 0, 0, 0)) ;
m_Outline.AddLine( Point3d( dCylRad, 0, 0)) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
CurveArc cvArc ;
cvArc.SetC2P( Point3d( dCenX, - 0.5 * m_dHeight, 0), Point3d( dCylRad, 0, 0), Point3d( dCylRad, - m_dHeight, 0)) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( Point3d( 0, - m_dHeight, 0)) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
bToolDefined = SetGenTool( sToolName, &m_Outline, nToolNum) ;
}
// Utensile cilindrico con eventuale raggio corner
else {
// Utensile mal definito
if ( m_dRadius - m_dRCorner < 0)
return false ;
// Utensile sferico
else if ( m_dRadius - m_dRCorner < EPS_SMALL)
;
// Raggio corner nullo: cilindro
else if ( m_dRCorner < EPS_SMALL) {
;
}
else {
// Profilo
m_Outline.AddPoint( Point3d( 0, 0, 0)) ;
m_Outline.AddLine( Point3d( m_dRadius - m_dRCorner, 0, 0)) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
CurveArc cvArc ;
cvArc.SetC2P( Point3d( m_dRadius - m_dRCorner, - m_dRCorner, 0), Point3d( m_dRadius - m_dRCorner, 0, 0), Point3d( m_dRadius, - m_dRCorner, 0)) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( Point3d( m_dRadius, - m_dHeight + m_dRCorner, 0)) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
cvArc.SetC2P( Point3d( m_dRadius - m_dRCorner, - m_dHeight + m_dRCorner, 0), Point3d( m_dRadius, - m_dHeight + m_dRCorner, 0), Point3d( m_dRadius - m_dRCorner, - m_dHeight, 0)) ;
m_Outline.AddCurve( cvArc) ;
m_Outline.SetCurveTempProp( 3, 1, 1) ;
m_Outline.AddLine( Point3d( 0, - m_dHeight, 0)) ;
m_Outline.SetCurveTempProp( 4, 1, 1) ;
m_Outline.SetTempProp( 1, 1) ;
bToolDefined = SetGenTool( sToolName, &m_Outline, nToolNum) ;
}
}
m_nType = ADDITIVE ;
return bToolDefined ;
}
+2 -6
View File
@@ -16,7 +16,7 @@
#include "CurveComposite.h"
//----------------------------------------------------------------------------
class Tool
class Tool
{
public :
Tool( bool bApproxWithLines = false) ;
@@ -33,7 +33,6 @@ class Tool
bool SetGenTool( const std::string& sToolName, const ICurveComposite* pToolOutline, int nToolNum) ;
bool SetMortiserTool( const std::string& sToolName, double dH, double dW, double dTh, double dRc, int nToolNum) ;
bool SetChiselTool( const std::string& sToolName, double dH, double dW, double dTh, int nToolNum) ;
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRC, int nToolNum) ;
bool SetToolNum( int nToolNum)
{ m_nCurrentNum = nToolNum ; return true ; }
int GetType() const
@@ -62,8 +61,6 @@ class Tool
{ return ( m_ArcLineApprox.GetCurveCount() == 0 ? m_Outline : m_ArcLineApprox) ; }
const VCT3DVECTOR& GetArcNormalVec( void) const
{ return m_vArcNormals ; }
bool GetCuttingFlag() const
{ return ( m_nType == GEN ? m_ArcLineApprox.GetTempProp( 1) == 1 : true ) ; }
public :
enum ToolType { UNDEF = 0, // Utensile indefinito
@@ -73,8 +70,7 @@ class Tool
BULLNOSEMILL = 4, // Naso di toro
CONEMILL = 5, // Con parte terminale conica
MORTISER = 6, // Mortasatrice
CHISEL = 7, // Scalpello
ADDITIVE = 8} ; // Additivo
CHISEL = 7} ; // Scalpello
private :
bool ModifyForCutterHeight( void) ;
+473 -210
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2021
// EgalTech 2014-2014
//----------------------------------------------------------------------------
// File : Triangulate.cpp Data : 18.12.21 Versione : 2.3l
// File : Triangulate.cpp Data : 23.06.14 Versione : 1.5f6
// Contenuto : Implementazione della classe Triangulate.
//
//
@@ -16,13 +16,21 @@
#include "DllMain.h"
#include "Triangulate.h"
#include "ProjPlane.h"
#include "earcut.hpp"
#include "CurveComposite.h"
#include "CurveLine.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "Mathematics/TriangulateCDT.h"
#include <algorithm>
#include "tpp_interface.hpp"
using namespace std ;
using namespace tpp ;
using namespace gte ;
//----------------------------------------------------------------------------
enum EarStatus{ EAS_NULL = -1, EAS_NO = 0, EAS_OK = 1} ;
@@ -30,36 +38,29 @@ enum EarStatus{ EAS_NULL = -1, EAS_NO = 0, EAS_OK = 1} ;
//----------------------------------------------------------------------------
static bool ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi) ;
//----------------------------------------------------------------------------
static bool FORCE_EARCUT_HPP = false ;
//----------------------------------------------------------------------------
// In : PolyLine
// Out : PNTVECTOR (Point3d Vector) : points of the polyline
// INTVECTOR (int Vector) : 3*T indices of above points for T triangles
//----------------------------------------------------------------------------
bool
Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr, TrgType trgType)
{
// pulisco i vettori di ritorno
vPt.clear() ;
vTr.clear() ;
// verifico che la polilinea sia chiusa e piana e calcolo il piano medio del poligono
// verifico che la polilinea sia chiusa e piana e calcolo il piano medio del poligono
double dArea ;
Plane3d plPlane ;
if ( ! PL.IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
// determino il piano ottimale di proiezione e il relativo senso di rotazione
if ( trgType != TRG_STANDARD)
return Make( POLYLINEVECTOR{ PL}, vPt, vTr, trgType) ;
// determino il piano ottimale di proiezione e il relativo senso di rotazione
bool bCCW ;
if ( ! CalcProjPlane( plPlane.GetVersN(), m_nPlane, bCCW))
return false ;
// forzo esecuzione triangolazione con earcut.hpp
if ( FORCE_EARCUT_HPP) {
return MakeByEC_HPP( PL, bCCW, vPt, vTr) ;
}
// riempio il vettore con i vertici del poligono da triangolare
// riempio il vettore con i vertici del poligono da triangolare
vPt.clear() ;
vPt.reserve( PL.GetPointNbr() - 1) ;
// salto il primo punto (coincide con l'ultimo)
Point3d ptP ;
@@ -68,18 +69,24 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
// inserisco i punti
while ( PL.GetNextPoint( ptP))
vPt.push_back( ptP) ;
// se non CCW inverto il vettore dei punti
// se non CCW inverto il vettore dei punti
if ( ! bCCW)
reverse( vPt.begin(), vPt.end()) ;
// creo il vettore degli indici del Poligono
INTVECTOR vPol ;
int n = int( vPt.size()) ;
vPol.reserve( n) ;
for ( int i = 0 ; i < n ; ++ i)
vPol.push_back( i) ;
// eseguo la triangolazione
if ( ! MakeByEC2( vPt, vTr) &&
! MakeByEC3( vPt, vTr)) {
// eseguo la triangolazione
if ( ! MakeByEC2( vPt, vPol, vTr) &&
! MakeByEC3( vPt, vPol, vTr)) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC23(1)")
return MakeByEC_HPP( PL, bCCW, vPt, vTr) ;
return false ;
}
// se era CW, devo invertire il senso dei triangoli
// se era CW, devo invertire il senso dei triangoli
if ( ! bCCW)
reverse( vTr.begin(), vTr.end()) ;
@@ -92,7 +99,7 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
// INTVECTOR (int Vector) : 3*T indices of above points for T triangles
//----------------------------------------------------------------------------
bool
Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, TrgType trgType)
{
// pulisco i vettori di ritorno
vPt.clear() ;
@@ -122,11 +129,37 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
return false ;
}
// forzo esecuzione triangolazione con earcut.hpp
if ( FORCE_EARCUT_HPP) {
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
// triangolazione Delaunay
if ( trgType == TRG_DEL_CONFORMING) {
if ( ! MakeByDelaunay( vPL, vPt, vTr, true, true)) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByDelaunay ( conforming)") ;
return false ;
}
return true ;
}
else if ( trgType == TRG_DEL_QUALITY) {
if ( ! MakeByDelaunay( vPL, vPt, vTr, false, true)) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByDelaunay ( quality)") ;
return false ;
}
return true ;
}
else if ( trgType == TRG_DEL_NOQUALITY) {
if ( ! MakeByDelaunay( vPL, vPt, vTr, false, false)) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByDelaunay ( no quality)") ;
return false ;
}
return true ;
}
else if ( trgType == TRG_DEL_GTE) {
if ( ! MakeByDelaunayGTE( vPL, vPt, vTr)) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByDelaunay ( Geometric Tools Engine)") ;
return false ;
}
return true ;
}
// ear clipping
// se non CCW inverto tutte le polilinee
if ( ! bCCW) {
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
@@ -134,7 +167,8 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
}
// calcolo ordine decrescente su Xmax o Ymax o Zmax secondo m_nPlane per le curve interne
INTVECTOR vOrd ;
bool bOk = SortInternalLoops( vPL, vOrd) ;
if ( ! SortInternalLoops( vPL, vOrd))
return false ;
// riempio il vettore con i punti dei poligoni da triangolare
// calcolo spazio totale e spazio massimo per un percorso interno
int nTot = vPL[0].GetPointNbr() - 1 ;
@@ -147,27 +181,22 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
// riservo spazio pari al totale dei punti (anche quelli ripetuti di chiusura che servono per i link)
vPt.reserve( nTot) ;
// inserisco i punti del contorno esterno (tranne il primo che coincide con l'ultimo)
bOk = bOk && GetPntVectorFromPolyline( vPL[0], false, vPt) ;
if ( ! GetPntVectorFromPolyline( vPL[0], false, vPt))
return false ;
// ciclo sui percorsi interni ordinati secondo Xmax decrescente
PNTVECTOR vPi ;
vPi.reserve( nMax) ;
for ( int i = 1 ; bOk && i < int( vPL.size()) ; ++ i) {
for ( int i = 1 ; i < int( vPL.size()) ; ++ i) {
// riordino il percorso per avere punto iniziale con Xmax
if ( ! GetPntVectorFromPolyline( vPL[vOrd[i]], true, vPi)) {
bOk = false ;
break ;
}
if ( ! GetPntVectorFromPolyline( vPL[vOrd[i]], true, vPi))
return false ;
// cerco un punto del percorso esterno visibile dal punto iniziale del precedente interno
int nI ;
if ( ! GetOuterPntToJoin( vPt, vPi[0], nI)) {
bOk = false ;
break ;
}
if ( ! GetOuterPntToJoin( vPt, vPi[0], nI))
return false ;
// riordino percorso esterno per avere questo punto all'inizio
if ( ! ChangeStartPntVector( nI, vPt)) {
bOk = false ;
break ;
}
if ( ! ChangeStartPntVector( nI, vPt))
return false ;
// ripeto punto iniziale
vPt.push_back( vPt[0]) ;
// accodo percorso interno
@@ -183,14 +212,20 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
const_cast<PolyLine&>(vPL[i]).Invert( true) ;
}
if ( ! bOk)
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
// creo il vettore degli indici del Poligono
INTVECTOR vPol ;
int n = int( vPt.size()) ;
vPol.reserve( n) ;
// non devo gestire separatamente CCW perch ho gi invertito i punti
for ( int i = 0 ; i < n ; ++ i)
vPol.push_back( i) ;
// eseguo la triangolazione
if ( ! MakeByEC2( vPt, vTr) &&
! MakeByEC3( vPt, vTr)) {
if ( ! MakeByEC2( vPt, vPol, vTr) &&
! MakeByEC3( vPt, vPol, vTr)) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC23(N)")
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
return false ;
}
// se era CW, devo invertire il senso dei triangoli
@@ -201,112 +236,388 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
}
//----------------------------------------------------------------------------
// Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0])
// Ear Clipping algorithm from mapbox
// Delaunay Triangulation ( Triangle library)
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr)
bool
Triangulate::MakeByDelaunay( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, bool bConforming, bool bQuality)
{
// pulisco i vettori di ritorno
vPt.clear() ;
vTr.clear() ;
// riempio il vettore con i vertici del poligono da triangolare
vPt.reserve( PL.GetPointNbr() - 1) ;
// salto il primo punto (coincide con l'ultimo)
Point3d ptP ;
if ( ( bCCW && ! PL.GetFirstPoint( ptP)) ||
( ! bCCW && ! PL.GetLastPoint( ptP)))
// sistema di riferimento locale sul piano della polyline
Plane3d plPlane ;
double dArea;
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
// inserisco i punti
while ( ( bCCW && PL.GetNextPoint( ptP)) ||
( ! bCCW && PL.GetPrevPoint( ptP)))
vPt.push_back( ptP) ;
// Create array
using Point = array<double, 2> ;
vector<vector<Point>> polygon ;
// Fill polygon structure with actual data. Any winding order works.
// The first polyline defines the main polygon.
polygon.resize( 1) ;
polygon[0].reserve( vPt.size()) ;
for ( int i = 0 ; i < int( vPt.size()) ; ++i) {
switch ( m_nPlane) {
default : // PL_XY
polygon[0].push_back( { vPt[i].x, vPt[i].y}) ;
break ;
case PL_YZ :
polygon[0].push_back( { vPt[i].y, vPt[i].z}) ;
break ;
case PL_ZX :
polygon[0].push_back( { vPt[i].z, vPt[i].x}) ;
break ;
}
}
// Run tessellation
// Returns array of indices that refer to the vertices of the input polygon.
// Three subsequent indices form a triangle. Output triangles are counterclockwise.
vTr = mapbox::earcut<int32_t>( polygon) ;
if ( vTr.empty()) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC_HPP(1)")
return false ;
}
if ( ! bCCW)
reverse( vTr.begin(), vTr.end()) ;
return true ;
}
Frame3d frLoc ;
frLoc.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC_HPP( const POLYLINEVECTOR& vPL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// pulisco i vettori di ritorno
vPt.clear() ;
vTr.clear() ;
// Creo il vettore con i punti dei poligoni da triangolare
// calcolo spazio totale e spazio massimo per un percorso interno
int nTot = vPL[0].GetPointNbr() - 1 ;
for ( int i = 1 ; i < int( vPL.size()) ; ++i)
nTot += vPL[i].GetPointNbr() - 1 ;
// riservo spazio pari al totale dei punti (esclusi quelli ripetuti)
vPt.reserve( nTot) ;
// Create array
using Point = array<double, 2> ;
vector<vector<Point>> polygon ;
polygon.resize( vPL.size()) ;
// Eseguo riempimento di vettore e array
for ( int i = 0 ; i < int( vPL.size()) ; ++i) {
polygon[i].reserve( vPL[i].GetPointNbr() - 1) ;
// salto il primo punto (coincide con l'ultimo)
Point3d ptP ;
if ( ( bCCW && ! vPL[i].GetFirstPoint( ptP)) ||
( ! bCCW && ! vPL[i].GetLastPoint( ptP)))
POLYLINEVECTOR vMyPL = vPL ;
for ( size_t t = 0 ; t < vPL.size() ; ++ t) {
vMyPL[t].ToLoc( frLoc) ;
if ( vMyPL[t].GetPointNbr() < 4) // per poter triangolare devo avere almeno tre punti distinti
return false ;
// inserisco i punti
while ( ( bCCW && vPL[i].GetNextPoint( ptP)) ||
( ! bCCW && vPL[i].GetPrevPoint( ptP))) {
vPt.push_back( ptP) ;
switch ( m_nPlane) {
default : // PL_XY
polygon[i].push_back( { ptP.x, ptP.y}) ;
break ;
case PL_YZ :
polygon[i].push_back( { ptP.y, ptP.z}) ;
break ;
case PL_ZX :
polygon[i].push_back( { ptP.z, ptP.x}) ;
break ;
}
// vertici e constraint per la triangolazione
vector<Delaunay::Point> vDelaunayVert ;
INTVECTOR vDelaunayConstr ;
for ( size_t i = 0 ; i < vMyPL.size() ; i++) {
Point3d ptFirst, pt ;
vMyPL[i].GetFirstPoint( ptFirst) ;
vDelaunayVert.push_back( Delaunay::Point( ptFirst.x, ptFirst.y)) ;
int nFirst = ( int)vDelaunayVert.size() - 1 ; // indice del primo punto della polyline fra i vertici della triangolazione
vDelaunayConstr.push_back( nFirst) ;
while ( vMyPL[i].GetNextPoint( pt)) {
vDelaunayVert.push_back( Delaunay::Point( pt.x, pt.y)) ;
// nei constraint gli indici vanno inseriti due volte perchè vengono letti a due a due per definire un segmento
vDelaunayConstr.push_back( ( int)vDelaunayVert.size() - 1) ;
vDelaunayConstr.push_back( ( int)vDelaunayVert.size() - 1) ;
}
// impongo che l'ultimo vertice coincida con il primo ( curva chiusa)
vDelaunayVert.pop_back() ;
vDelaunayConstr.erase(vDelaunayConstr.end() - 2, vDelaunayConstr.end()) ;
vDelaunayConstr.push_back( nFirst) ;
}
// holes : sono definiti da un punto interno al buco
std::vector<Delaunay::Point> vDelaunayHoles ;
for ( size_t i = 1 ; i < vMyPL.size() ; i++) {
Point3d pt ;
CurveComposite * pCrvHole = CreateBasicCurveComposite() ;
pCrvHole->FromPolyLine( vMyPL[i]) ;
pCrvHole->GetCentroid( pt) ;
// se il centroide fosse esterno, cerco per tentativi un punto qualsiasi all'interno della curva
double dPar = 0.5 ;
while ( ! IsPointInsidePolyLine( pt, vMyPL[i])) {
double dParS, dParE ;
pCrvHole->GetDomain( dParS, dParE) ;
if ( dPar > dParE)
return false ;
Vector3d vtDir ;
pCrvHole->GetPointTang( dPar, ICurve::FROM_MINUS, pt, vtDir) ;
vtDir.Rotate( Z_AX, 0, -1) ;
pt += 2 * EPS_SMALL * vtDir ;
// tento con un nuovo punto
dPar += 10 * EPS_SMALL ;
}
vDelaunayHoles.push_back( Delaunay::Point( pt.x, pt.y)) ;
}
// parti concave
PNTVECTOR vPtConvexHull ;
vMyPL[0].GetConvexHullXY( vPtConvexHull) ;
CurveComposite* pCrv = CreateBasicCurveComposite() ;
pCrv->FromPolyLine( vMyPL[0]) ;
for ( size_t i = 0 ; i < vPtConvexHull.size() ; i ++) {
size_t NextIdx = ( i == vPtConvexHull.size() - 1) ? 0 : i + 1 ;
CurveLine * pLine = CreateBasicCurveLine() ;
pLine->Set( vPtConvexHull[i], vPtConvexHull[NextIdx]) ;
// verifico se ho regioni da eliminare
IntersCurveCurve intCC( *pLine, *pCrv) ;
CRVCVECTOR ccClass ;
intCC.GetCurveClassification( 0, ccClass) ;
for ( size_t j = 0 ; j < ccClass.size() ; j ++) {
if ( ccClass[j].nClass == CRVC_OUT) {
// cerco per tentativi un punto a caso all'interno della regione da eliminare
double dPar = ( ccClass[j].dParS + ccClass[j].dParE) / 2 ;
double dDist = 0 ;
Point3d pt ;
Vector3d vtDir ;
while ( dDist < EPS_SMALL) {
if ( dPar > ccClass[j].dParE)
return false ;
pLine->GetPointTang( dPar, ICurve::FROM_MINUS, pt, vtDir) ;
vtDir.Rotate( Z_AX, 0, 1) ;
DistPointCurve distPtCrv( pt, *pCrv) ;
dDist = 0.0 ;
distPtCrv.GetDist( dDist) ;
if ( dDist > EPS_SMALL) {
pt += EPS_SMALL * ( vtDir) ;
vDelaunayHoles.push_back( Delaunay::Point( pt.x , pt.y)) ;
}
// tento con nuovo punto
dPar += 10 * EPS_SMALL ;
}
}
}
}
// Run tessellation
// Returns array of indices that refer to the vertices of the input polygon.
// Three subsequent indices form a triangle. Output triangles are counterclockwise.
vTr = mapbox::earcut<int32_t>( polygon) ;
if ( vTr.empty()) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC_HPP(N)")
// triangolazione
Delaunay trGenerator( vDelaunayVert) ;
trGenerator.setSegmentConstraint( vDelaunayConstr) ;
trGenerator.setHolesConstraint( vDelaunayHoles) ;
if ( bConforming)
trGenerator.TriangulateConf( true) ;
else
trGenerator.Triangulate( bQuality) ;
// se non ho generato triangoli, errore
if ( trGenerator.ntriangles() == 0)
return false ;
// vertici
std::vector< Delaunay::Point> vVertex = trGenerator.MyVertexTraverse() ;
for (size_t i = 0; i < vVertex.size(); i++) {
Point3d pt( vVertex[i][0], vVertex[i][1]) ;
pt.ToGlob( frLoc) ;
vPt.push_back( pt) ;
}
if ( ! bCCW)
reverse( vTr.begin(), vTr.end()) ;
// triangoli
vTr = trGenerator.MyTriangleTraverse() ;
return true ;
}
//----------------------------------------------------------------------------
// Delaunay Triangulation ( Geometric Tools Engine library)
//----------------------------------------------------------------------------
bool
Triangulate::MakeByDelaunayGTE( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// sistema di riferimento locale sul piano della polyline
Plane3d plPlane ;
double dArea;
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
Frame3d frLoc ;
frLoc.Set( plPlane.GetPoint(), plPlane.GetVersN()) ;
POLYLINEVECTOR vMyPL = vPL ;
for ( size_t t = 0 ; t < vPL.size() ; ++ t) {
vMyPL[t].ToLoc( frLoc) ;
if ( vMyPL[t].GetPointNbr() < 4)
return false ;
}
CurveComposite * pCrvPL = CreateBasicCurveComposite() ;
pCrvPL->FromPolyLine( vMyPL[0]) ;
// controllo che holes siano contenuti nel loop esterno
for ( size_t i = 1 ; i < vMyPL.size() ; i ++) {
CurveComposite * pCrvHole = CreateBasicCurveComposite() ;
pCrvHole->FromPolyLine( vMyPL[i]) ;
IntersCurveCurve intCC( *pCrvPL, *pCrvHole) ;
CRVCVECTOR ccClass ;
intCC.GetCurveClassification( 1, ccClass) ;
if ( ccClass.size() > 1 || ccClass[0].nClass != CRVC_IN)
return false ;
}
// Verifico non ci siano autointersezioni
SelfIntersCurve Inters( *pCrvPL) ;
if ( Inters.GetIntersCount() > 0 && Inters.GetOverlaps() == 0)
return false ;
// Gestione autointersezione
// if ( Inters.GetIntersCount() > 0 && Inters.GetOverlaps() == 0) {
//
// // vertici della triangolazione
// vector<Vector2<double>> vPoints ;
// Point3d pt ;
// vMyPL[0].GetFirstPoint( pt) ;
// vPoints.push_back( {pt.x, pt.y}) ;
// pt.ToGlob( frLoc) ;
// vPt.push_back( pt) ;
// while ( vMyPL[0].GetNextPoint( pt) ) {
// vPoints.push_back( {pt.x, pt.y}) ;
// pt.ToGlob( frLoc) ;
// vPt.push_back( pt) ;
// }
// vPt.pop_back() ;
// vPoints.pop_back() ;
//
// // i punti di autointersezione P sono salvati come pair: parametro di P, indice posizione di P in vPoints
// vector<pair<double,int>> dParams ;
// for ( int i = 0 ; i < Inters.GetIntersCount() ; i++) {
//
// IntCrvCrvInfo aInfo ;
// Inters.GetIntCrvCrvInfo( i, aInfo) ;
//
// Point3d pt ;
// pt = aInfo.IciA[0].ptI ;
// pt.ToGlob( frLoc) ;
//
// auto it = find_if( vPt.begin(), vPt.end(), [pt]( const Point3d& ptCrv){ return AreSamePointApprox( ptCrv, pt) ;} ) ;
// // se il punto di interezione è uno dei vertici
// if ( it != vPt.end()) {
// dParams.push_back( pair<double, int> (aInfo.IciA[0].dU, it - vPt.begin())) ;
// dParams.push_back( pair<double, int> (aInfo.IciB[0].dU, it - vPt.begin())) ;
// }
// // se non è uno dei vertici, lo aggiungo in vPt e in vPoints
// else {
// vPt.push_back( pt) ;
// pt.ToLoc( frLoc) ;
// vPoints.push_back( { pt.x, pt.y}) ;
// dParams.push_back( pair<double, int> (aInfo.IciA[0].dU, vPoints.size() - 1)) ;
// dParams.push_back( pair<double, int> (aInfo.IciB[0].dU, vPoints.size() - 1)) ;
// }
// }
// sort( dParams.begin(), dParams.end(), []( const pair<double, int>& a, const pair<double, int>& b){ return a.first < b.first ; }) ;
//
// // lati del poligono :
// INTVECTOR vPolygonIdx ;
// for ( int i = 0 ; i < vMyPL[0].GetPointNbr() ; i++)
// vPolygonIdx.push_back( i) ;
//
// // inserisco i nuovi lati determinati dai punti di intersezione
// for ( int i = 0 ; i < dParams.size() ; i++) {
// // se il parametro c'è già, non lo inserisco
// if ( find_if( vPolygonIdx.begin(), vPolygonIdx.end(),
// [dParams, i]( const int& val) { return abs( val - dParams[i].first) < 0 ; }) != vPolygonIdx.end())
// break ;
// // altrimenti lo inserisco in modo ordinato nel vettore
// auto it = lower_bound( vPolygonIdx.begin(), vPolygonIdx.end(), dParams[i].first,
// []( const int& a , const int& b) { return a < b ; }) ;
// vPolygonIdx.insert( it, dParams[i].second) ;
// }
//
// auto pPolygon = std::make_shared<PolygonTree>() ;
// pPolygon->polygon = vPolygonIdx ;
//
// // holes
// int k = vPoints.size() ;
// for ( size_t i = 1 ; i < vMyPL.size() ; i++) {
//
// auto pHole = std::make_shared<PolygonTree>() ;
// Point3d pt ;
// vMyPL[i].GetFirstPoint( pt) ;
// vPoints.push_back( { pt.x, pt.y}) ;
// pHole->polygon.push_back( k) ;
// k ++ ;
// while ( vMyPL[i].GetNextPoint( pt)) {
// vPoints.push_back( { pt.x, pt.y}) ;
// pHole->polygon.push_back( k) ;
// k ++ ;
// }
//
// vPoints.pop_back() ;
// pHole->polygon.pop_back() ;
// k -- ;
//
// pPolygon->child.push_back( pHole) ;
//
// }
//
// // Triangolazione
// PolygonTreeEx PTOutput ;
// TriangulateCDT<double> triangulator ;
// triangulator( vPoints, pPolygon, PTOutput) ;
//
// for ( auto const& tri : PTOutput.interiorTriangles) {
// vTr.push_back( tri[0]) ;
// vTr.push_back( tri[1]) ;
// vTr.push_back( tri[2]) ;
// }
//
// return true ;
//
// }
// i vertici della triangolazione vPt sono i punti delle polyline nel sistema globale
for ( size_t i = 0 ; i < vPL.size() ; i++) {
Point3d pt ;
vPL[i].GetFirstPoint( pt) ;
vPt.push_back( Point3d( pt.x, pt.y, pt.z)) ;
while ( vPL[i].GetNextPoint( pt ) )
vPt.push_back( Point3d( pt.x, pt.y, pt.z)) ;
// ultimo punto della polyline coincide con il primo, quindi non serve
vPt.pop_back() ;
}
vector<Vector2<double>> vPoints ; // vertici per la triangolazione
auto pPolygon = std::make_shared<PolygonTree>() ; // poligono da triangolare
Point3d pt ;
int k = 0 ;
vMyPL[0].GetFirstPoint( pt) ;
vPoints.push_back( { pt.x, pt.y}) ;
pPolygon->polygon.push_back( k) ;
k ++ ;
while ( vMyPL[0].GetNextPoint( pt) ) {
vPoints.push_back( { pt.x, pt.y}) ;
pPolygon->polygon.push_back( k) ;
k ++ ;
}
// ultimo punto della polyline coincide con il primo, quindi non serve
vPoints.pop_back() ;
pPolygon->polygon.pop_back() ;
k -- ;
// holes
for ( size_t i = 1 ; i < vMyPL.size() ; i++) {
auto pHole = std::make_shared<PolygonTree>() ;
vMyPL[i].GetFirstPoint( pt) ;
vPoints.push_back( { pt.x, pt.y}) ;
pHole->polygon.push_back( k) ;
k ++ ;
while ( vMyPL[i].GetNextPoint( pt)) {
vPoints.push_back( { pt.x, pt.y}) ;
pHole->polygon.push_back( k) ;
k ++ ;
}
vPoints.pop_back() ;
pHole->polygon.pop_back() ;
k -- ;
pPolygon->child.push_back( pHole) ;
}
// Triangolazione
PolygonTreeEx PTOutput ;
TriangulateCDT<double> triangulator ;
triangulator( vPoints, pPolygon, PTOutput) ;
for ( auto const & tri : PTOutput.interiorTriangles) {
vTr.push_back( tri[0]) ;
vTr.push_back( tri[1]) ;
vTr.push_back( tri[2]) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
Triangulate::PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
const INTVECTOR& vPrev, const INTVECTOR& vNext)
{
// points number
int n = int( vPol.size()) ;
// overall box
BBox3d b3All ;
for ( int j = 0 ; j < n ; ++ j)
b3All.Add( vPt[vPol[j]]) ;
// grid cell dimension
double dCellDim ;
b3All.GetRadius( dCellDim) ;
dCellDim *= 2 / sqrt( n) ;
// grid
if ( ! m_VertGrid.Init( 2 * n, dCellDim))
return false ;
for ( int j = 0 ; j < n ; ++ j) {
// insert only reflex vertex
if ( ! TriangleIsCCW( vPt[vPol[vPrev[j]]], vPt[vPol[j]], vPt[vPol[vNext[j]]])) {
if ( ! m_VertGrid.InsertPoint( vPt[vPol[j]], j))
return false ;
}
}
m_vVert.reserve( n / 5) ;
return true ;
}
@@ -315,22 +626,16 @@ Triangulate::MakeByEC_HPP( const POLYLINEVECTOR& vPL, bool bCCW, PNTVECTOR& vPt,
// Ear Clipping algorithm
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr)
Triangulate::MakeByEC( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
{
// Clear triangle vector
vTr.clear() ;
// At least 3 points
int n = int( vPt.size()) ;
int n = int( vPol.size()) ;
if ( n < 3)
return false ;
// Creo il vettore degli indici del Poligono
INTVECTOR vPol ;
vPol.reserve( n) ;
for ( int i = 0 ; i < n ; ++ i)
vPol.push_back( i) ;
// Preallocate triangle vector ( #triangles = n - 2)
vTr.reserve( 3 * ( n - 2)) ;
@@ -369,7 +674,7 @@ Triangulate::MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr)
vTr.push_back( vPol[i]) ;
vTr.push_back( vPol[vNext[i]]) ;
}
// Delete vertex v[i] by redirecting next and previous links
// Delete vertex v[i] by redirecting next and previous links
// of neighboring verts past it. Decrement vertex count
vNext[vPrev[i]] = vNext[i] ;
vPrev[vNext[i]] = vPrev[i] ;
@@ -393,22 +698,16 @@ Triangulate::MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr)
// Ear Clipping algorithm enhanced, choose smaller diagonal
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr)
Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
{
// Clear triangle vector
vTr.clear() ;
// At least 3 points
int n = int( vPt.size()) ;
int n = int( vPol.size()) ;
if ( n < 3)
return false ;
// Creo il vettore degli indici del Poligono
INTVECTOR vPol ;
vPol.reserve( n) ;
for ( int i = 0 ; i < n ; ++ i)
vPol.push_back( i) ;
// Preallocate triangle vector ( #triangles = n - 2)
vTr.reserve( 3 * ( n - 2)) ;
@@ -495,7 +794,7 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr)
// Reset earity of diagonal endpoints
vEar[vPrev[i]] = EAS_NULL ;
vEar[vNext[i]] = EAS_NULL ;
// Delete vertex v[i] by redirecting next and previous links
// Delete vertex v[i] by redirecting next and previous links
// of neighboring verts past it. Decrement vertex count
vNext[vPrev[i]] = vNext[i] ;
vPrev[vNext[i]] = vPrev[i] ;
@@ -520,22 +819,16 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr)
// AR = ( Lmax * Lmax) / ( 2 * Area) = SqLenMax / L1 * L2
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr)
Triangulate::MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
{
// Clear triangle vector
vTr.clear() ;
// At least 3 points
int n = int( vPt.size()) ;
int n = int( vPol.size()) ;
if ( n < 3)
return false ;
// Creo il vettore degli indici del Poligono
INTVECTOR vPol ;
vPol.reserve( n) ;
for ( int i = 0 ; i < n ; ++ i)
vPol.push_back( i) ;
// Preallocate triangle vector ( #triangles = n - 2)
vTr.reserve( 3 * ( n - 2)) ;
@@ -614,7 +907,7 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr)
// Reset earity of diagonal endpoints
vEar[vPrev[i]] = EAS_NULL ;
vEar[vNext[i]] = EAS_NULL ;
// Delete vertex v[i] by redirecting next and previous links
// Delete vertex v[i] by redirecting next and previous links
// of neighboring verts past it. Decrement vertex count
vNext[vPrev[i]] = vNext[i] ;
vPrev[vNext[i]] = vPrev[i] ;
@@ -633,36 +926,6 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr)
return true ;
}
//----------------------------------------------------------------------------
bool
Triangulate::PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
const INTVECTOR& vPrev, const INTVECTOR& vNext)
{
// points number
int n = int( vPol.size()) ;
// overall box
BBox3d b3All ;
for ( int j = 0 ; j < n ; ++ j)
b3All.Add( vPt[vPol[j]]) ;
// grid cell dimension
double dCellDim ;
b3All.GetRadius( dCellDim) ;
dCellDim *= 2 / sqrt( n) ;
// grid
if ( ! m_VertGrid.Init( 2 * n, dCellDim))
return false ;
for ( int j = 0 ; j < n ; ++ j) {
// insert only reflex vertex
if ( ! TriangleIsCCW( vPt[vPol[vPrev[j]]], vPt[vPol[j]], vPt[vPol[vNext[j]]])) {
if ( ! m_VertGrid.InsertPoint( vPt[vPol[j]], j))
return false ;
}
}
m_vVert.reserve( n / 5) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
@@ -708,7 +971,7 @@ Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
}
}
else {
// The ear triangle is clockwise so v[i] is not an ear
// The ear triangle is clockwise so v[i] is not an ear
bIsEar = false ;
}
@@ -938,7 +1201,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
// indice punto successivo
int j = ( i + 1 < nNumPt) ? i + 1 : 0 ;
// mi metto nel piano principale
switch ( m_nPlane) {
switch (m_nPlane) {
default : // PL_XY
// se i punti coincidono
if ( abs( vPt[i].x - ptP.x) < EPS_SMALL && abs( vPt[i].y - ptP.y) < EPS_SMALL) {
@@ -1034,14 +1297,14 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
break ;
}
}
// non ho trovato alcunché, errore
// non ho trovato alcunch, errore
if ( nI == - 1)
return false ;
// se ho trovato un punto esatto del contorno, non devo fare altri controlli
if ( AreSamePointApprox( ptInt, vPt[nI]))
return true ;
// devo ora verificare che il segmento che unisce i punti non intersechi altri lati del contorno esterno
// altrimenti tengo il punto con raggio più vicino a X_AX o Y_AX o Z_AX secondo m_nPlane
// altrimenti tengo il punto con raggio pi vicino a X_AX o Y_AX o Z_AX secondo m_nPlane
int nJ = nI ;
Point3d ptPa = ptP ;
Point3d ptPb = vPt[nI] ;
@@ -1057,7 +1320,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
double dMinTan = INFINITO ;
double dMinSqDist = SQ_INFINITO ;
for ( int i = 0 ; i < nNumPt ; ++ i) {
// salto il punto già trovato
// salto il punto gi trovato
if ( i == nJ)
continue ;
// verifico se sta nel triangolo
@@ -1093,7 +1356,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
bool
Triangulate::PointInSector( const Point3d& ptTest, const Point3d& ptPrev, const Point3d& ptCorn, const Point3d& ptNext)
{
// la parte valida del settore è a sinistra dei segmenti ptPrev --> ptCorn --> ptNext
// la parte valida del settore a sinistra dei segmenti ptPrev --> ptCorn --> ptNext
// se corner convesso
if ( TriangleIsCCW( ptPrev, ptCorn, ptNext, 0))
return ( TriangleIsCCW( ptPrev, ptCorn, ptTest) &&
@@ -1108,10 +1371,10 @@ Triangulate::PointInSector( const Point3d& ptTest, const Point3d& ptPrev, const
bool
ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi)
{
// se il nuovo inizio coincide col vecchio, non devo fare alcunché
// se il nuovo inizio coincide col vecchio, non devo fare alcunch
if ( nNewStart == 0)
return true ;
// se il nuovo indice è oltre la dimensione del vettore, errore
// se il nuovo indice oltre la dimensione del vettore, errore
if ( nNewStart >= int( vPi.size()))
return false ;
// ciclo di aggiustamento
+15 -7
View File
@@ -16,21 +16,29 @@
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkPointGrid3d.h"
//
enum TrgType { TRG_STANDARD, // ear clipping
TRG_DEL_CONFORMING, // conforming constrained Delaunay ( with quality constraint)
TRG_DEL_QUALITY, // constrained Delaunay with quality constraints ( no angle smaller than 20 degrees)
TRG_DEL_NOQUALITY, // constrained Delaunay without quality constraints
TRG_DEL_GTE // constrained Delaunay with Geomtric Tools Engine library
} ;
//----------------------------------------------------------------------------
class Triangulate
{
public :
bool Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr, TrgType trgType = TRG_STANDARD) ;
bool Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, TrgType trgType = TRG_STANDARD) ;
private :
bool MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeByEC_HPP( const POLYLINEVECTOR& vPL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
const INTVECTOR& vPrev, const INTVECTOR& vNext) ;
bool MakeByEC( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr) ;
bool MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr) ;
bool MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr) ;
bool MakeByDelaunay( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, bool bConforming, bool bQuality) ;
bool MakeByDelaunayGTE( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
const INTVECTOR& vPrev, INTVECTOR& vNext, int i) ;
double CalcTriangleAspectRatio( const Point3d& ptPa, const Point3d& ptPb, const Point3d& ptPc) ;
+18 -96
View File
@@ -34,8 +34,8 @@ GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
//----------------------------------------------------------------------------
VolZmap::VolZmap(void)
: m_nStatus( TO_VERIFY), m_dStep( 10.0), m_nMapNum( 0), m_nShape( GENERIC), m_nVoxNumPerBlock( N_VOXBLOCK),
m_nDexVoxRatio( 1), m_nNumBlock( 0), m_nConnectedCompoCount( 0), m_nCurrTool( - 1)
: m_nStatus( TO_VERIFY), m_nMapNum( 0), m_nNumBlock( 0), m_nConnectedCompoCount( 0), m_dStep( 10.0),
m_nVoxNumPerBlock( N_VOXBLOCK), m_nDexVoxRatio( 1), m_nShape( GENERIC), m_nTempProp( 0), m_Tool( true)
{
for ( int i = 0 ; i < N_MAPS ; ++ i) {
m_nNx[i] = 0 ;
@@ -45,8 +45,7 @@ VolZmap::VolZmap(void)
m_dMaxZ[i] = 0 ;
m_nFracLin[i] = 0 ;
}
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
m_Tool.SetTolerances( LIN_TOL_STD, ANG_TOL_APPROX_DEG) ;
}
//----------------------------------------------------------------------------
@@ -73,9 +72,8 @@ VolZmap::Clear( void)
m_Values[i].clear() ;
}
m_dStep = EPS_SMALL ;
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
ResetAllTools() ;
m_nTempProp = 0 ;
m_Tool.Clear() ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -140,8 +138,7 @@ VolZmap::CopyFrom( const VolZmap& vzmSrc)
m_dStep = vzmSrc.m_dStep ;
m_nStatus = vzmSrc.m_nStatus ;
m_nTempProp[0] = vzmSrc.m_nTempProp[0] ;
m_nTempProp[1] = vzmSrc.m_nTempProp[1] ;
m_nTempProp = vzmSrc.m_nTempProp ;
// dimensiono membri legati ai blocchi
m_BlockToUpdate = vzmSrc.m_BlockToUpdate ;
@@ -761,6 +758,7 @@ VolZmap::CheckMapConnection( void)
int tStopIntZ = int( m_Values[0][tDexZ].size()) ;
// Ciclo sugli intervalli del dexel
for ( int tIntZ = 0 ; tIntZ < tStopIntZ ; ++ tIntZ) {
if ( m_Values[0][tDexZ][tIntZ].nCompo == 0) {
++ m_nConnectedCompoCount ;
m_Values[0][tDexZ][tIntZ].nCompo = m_nConnectedCompoCount ;
@@ -1679,10 +1677,8 @@ VolZmap::Cut( const Plane3d& plPlane)
Plane3d plMyPlane = plPlane ;
plMyPlane.ToLoc( m_MapFrame) ;
// Imposto numero fittizio di utensile per avere il colore di sezione opportuno
if ( m_nCurrTool < 0)
return false ;
int nToolNumOld = m_vTool[m_nCurrTool].GetCurrentToolNum() ;
m_vTool[m_nCurrTool].SetToolNum( 1) ;
int nToolNumOld = m_Tool.GetCurrentToolNum() ;
m_Tool.SetToolNum( 1) ;
// Interseco lo Zmap col piano, ciclando sulle griglie
bool bModified = false ;
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
@@ -1736,7 +1732,7 @@ VolZmap::Cut( const Plane3d& plPlane)
}
// Ripristino numero utensile
m_vTool[m_nCurrTool].SetToolNum( nToolNumOld) ;
m_Tool.SetToolNum( nToolNumOld) ;
if ( bModified == true) {
// Imposto forma generica
@@ -1971,18 +1967,14 @@ VolZmap::CalcBlockNum( void)
bool
VolZmap::SetToolTolerances( double dLinTol, double dAngTolDeg)
{
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetTolerances( dLinTol, dAngTolDeg) ;
return m_Tool.SetTolerances( dLinTol, dAngTolDeg) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetStdTool( const string& sToolName, double dH, double dR, double dCornR, double dCutterH, int nFlag)
{
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetStdTool( sToolName, dH, dR, dCornR, dCutterH, nFlag) ;
return m_Tool.SetStdTool( sToolName, dH, dR, dCornR, dCutterH, nFlag) ;
}
//----------------------------------------------------------------------------
@@ -1990,9 +1982,7 @@ bool
VolZmap::SetAdvTool( const string& sToolName,
double dH, double dR, double dTipH, double dTipR, double dCornR, double dCutterH, int nFlag)
{
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetAdvTool( sToolName, dH, dR, dTipH, dTipR, dCornR, dCutterH, nFlag) ;
return m_Tool.SetAdvTool( sToolName, dH, dR, dTipH, dTipR, dCornR, dCutterH, nFlag) ;
}
//----------------------------------------------------------------------------
@@ -2000,101 +1990,33 @@ bool
VolZmap::SetSawTool( const string& sToolName,
double dH, double dR, double dThick, double dStemR, double dCornR, int nFlag)
{
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetSawTool( sToolName, dH, dR, dThick, dStemR, dCornR, nFlag) ;
return m_Tool.SetSawTool( sToolName, dH, dR, dThick, dStemR, dCornR, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetGenTool( const string& sToolName, const ICurveComposite* pToolOutline, int nFlag)
{
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetGenTool( sToolName, pToolOutline, nFlag) ;
return m_Tool.SetGenTool( sToolName, pToolOutline, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetMortiserTool( const string& sToolName, double dH, double dW, double dTh, double dRc, int nFlag)
{
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetMortiserTool( sToolName, dH, dW, dTh, dRc, nFlag) ;
return m_Tool.SetMortiserTool( sToolName, dH, dW, dTh, dRc, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetChiselTool( const string& sToolName, double dH, double dW, double dTh, int nFlag)
{
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetChiselTool( sToolName, dH, dW, dTh, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetAdditiveTool(const std::string& sToolName, double dH, double dR, double dRC, int nFlag)
{
if ( m_nCurrTool < 0)
return false ;
return m_vTool[m_nCurrTool].SetAdditiveTool( sToolName, dH, dR, dRC, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::SetCurrTool( int nCurrTool)
{
if ( nCurrTool < 0 || nCurrTool >= int( m_vTool.size()))
return false ;
m_nCurrTool = nCurrTool ;
return true ;
}
//----------------------------------------------------------------------------
int
VolZmap::GetToolCount( void) const
{
return int( m_vTool.size()) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::AddTool( void)
{
m_vTool.emplace_back( true) ;
m_vTool.back().SetTolerances( LIN_TOL_STD, ANG_TOL_APPROX_DEG) ;
return true ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ResetAllTools( void)
{
bool bOk = true ;
for ( int n = 0 ; n < int( m_vTool.size()) ; ++ n) {
bOk = bOk || m_vTool[n].Clear() ;
}
m_vTool.clear() ;
return bOk ;
return m_Tool.SetChiselTool( sToolName, dH, dW, dTh, nFlag) ;
}
//----------------------------------------------------------------------------
bool
VolZmap::ResetTool( void)
{
if ( m_vTool.empty())
return true ;
bool bOk = m_vTool.back().Clear() ;
m_vTool.erase( m_vTool.begin() + int( m_vTool.size()) - 1) ;
return bOk ;
}
//----------------------------------------------------------------------------
const ICurveComposite&
VolZmap::GetToolOutline( bool bApprox) const
{
if ( m_nCurrTool < 0)
return cvEmptyOutline ;
return ( bApprox ? m_vTool[m_nCurrTool].GetApproxOutline() : m_vTool[m_nCurrTool].GetOutline()) ;
return m_Tool.Clear() ;
}
+13 -87
View File
@@ -60,11 +60,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
{ return m_OGrMgr.GetObjGraphics() ; }
const IObjGraphics* GetObjGraphics( void) const override
{ return m_OGrMgr.GetObjGraphics() ; }
void SetTempProp( int nProp, int nPropInd = 0) override
{ if ( nPropInd >= 0 && nPropInd < 2)
m_nTempProp[nPropInd] = nProp ; }
int GetTempProp( int nPropInd = 0) const override
{ return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; }
void SetTempProp( int nProp) override
{ m_nTempProp = nProp ; }
int GetTempProp( void) const override
{ return m_nTempProp ; }
public : // IVolZmap
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
@@ -72,7 +71,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex) override ;
bool CreateEmptyMap( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex) override ;
int GetBlockCount( void) const override ;
int GetBlockUpdatingCounter( int nBlock) const override ;
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
@@ -91,15 +89,9 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool SetGenTool( const std::string& sToolName, const ICurveComposite* pToolOutline, int nFlag) override ;
bool SetMortiserTool( const std::string& sToolName, double dH, double dW, double dTh, double dRc, int nFlag) override ;
bool SetChiselTool( const std::string& sToolName, double dH, double dW, double dTh, int nFlag) override ;
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRC, int nFlag) override ;
bool SetCurrTool( int nCurrTool) override ;
int GetToolCount( void) const override ;
int GetCurrTool( void) const override
{ return m_nCurrTool ; }
bool AddTool( void) override ;
bool ResetAllTools( void) override ;
bool ResetTool( void) override ;
const ICurveComposite& GetToolOutline( bool bApprox = false) const override ;
const ICurveComposite& GetToolOutline( bool bApprox = false) const override
{ return ( bApprox ? m_Tool.GetApproxOutline() : m_Tool.GetOutline()) ;}
bool MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Point3d& ptPe, const Vector3d& vtDe) override ;
bool MillingStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs,
const Point3d& ptPe, const Vector3d& vtDe, const Vector3d& vtAe) override ;
@@ -310,45 +302,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
inline bool TestParaBBox( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtD, const Vector3d& vtA,
double dLenX, double dLenY, double dLenZ,
int& nStI, int& nStJ, int& nEnI, int& nEnJ) ;
// Asportazioni superfici elementari vuote
bool SurfCircCrown_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) ;
bool SurfCircCrown_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) ;
bool SurfCircCrown_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) ;
bool SurfCircCrown_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dMaxRad, double dMinRad) ;
/*bool SurfCyl_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dRad, bool bTapB, bool bTapT) ;
bool SurfCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dRad, bool bTapB, bool bTapT) ;*/
bool SurfCyl_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dRad, bool bOuterCutter) ;
bool SurfCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
const Vector3d& vtToolDir, double dHei, double dRad, bool bOuterCutter, bool bTapB, bool bTapT) ;
bool SurfConus_ZDrilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad,
bool bOuterCutter, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool SurfConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir,
double dHei, double dMaxRad, double dMinRad, bool bOuterCutter, bool bTapB, bool bTapT,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool SurfConus_ZMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtToolDir, double dHei, double dMaxRad, double dMinRad,
bool bOuterCutter, const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool SurfConus_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dHei, double dMaxRad, double dMinRad, bool bOuterCutter, bool bTapB, bool bTapT,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool SurfSphericalShellPart_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dRad, double dInfH, double dSupH, bool bOuterCutter) ;
bool SurfSphericalShell_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dRad, double dHei, bool bOuterCutter) ;
// Additivo
bool AddingMotion( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx) ;
bool AddingCylinder( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx, double dHei, double dRad) ;
bool AddingTruncatedCone( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx,
double dMaxRad, double dMinRad, double dHei,
const Vector3d& vtArcNormMaxR, const Vector3d& vtArcNormMinR) ;
bool AddingSphere( int nGrid, const Point3d& ptS, const Point3d& ptE, double dRad) ;
bool AddingGeneral( int nGrid, const Point3d& ptS, const Point3d& ptE, const Vector3d& vtAx) ;
// Intersezioni
bool IntersLineBox( const Point3d& ptP, const Vector3d& vtV, const Point3d& ptMin, const Point3d& ptMax) const ;
bool IntersLineBox( const Point3d& ptP, const Vector3d& vtV, const Point3d& ptMin, const Point3d& ptMax,
double& dU1, double& dU2) const ;
bool IntersLineZMapLattice( const Point3d& ptP, const Vector3d& vtV, double& dU1, double& dU2) const ;
bool IntersLineZMapBBox( const Point3d& ptP, const Vector3d& vtV, double& dU1, double& dU2) const ;
bool IntersLineDexel( const Point3d& ptP, const Vector3d& vtV, int nGrid, int nI, int nJ,
@@ -359,7 +316,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
bool GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
bool IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting = true) const ;
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen,
bool bTapLow, bool bTapUp,
@@ -369,39 +326,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
bool IntersLineMyPolyhedron( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& PolyFrame, double dLenX, double dLenY, double dLenZ, double dDeltaX,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting = true) const ;
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
bool IntersLineTruncatedPyramid( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& frTruncPyramFrame, double dSegMin, double dSegMax, double dHeight,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
bool TestIntersPlaneZmapBBox( const Plane3d& plPlane) const ;
// Intersezioni per asportazioni avanzate
int IntersLineCircCrown( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptCen, const Vector3d& vtAx, double dMaxRad, double dMinRad,
Point3d& ptInt, Vector3d& vtN) const ;
int IntersLineParallelogram( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptParOrig, const Vector3d& vtSeg1, const Vector3d& vtSeg2,
bool bExtNorm, Point3d& ptInt, Vector3d& vtN) const ;
int IntersLineCylinderCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptBaseCen, const Vector3d& vtAx, double dRad, double dH, bool bInOut,
const std::vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
int IntersLineCircSweptSurfCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptCen, const Vector3d& vtAx, double dRad, const Vector3d& vtSweptVec, bool bInOut,
const std::vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
int IntersLineConeCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineDir,
const Point3d& ptVert, const Vector3d& vtAx, double dRad, double dH, bool bInOut,
const std::vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
int IntersLineSphereCuttedByPlanes( const Point3d& ptLineP, const Vector3d& vtLineD,
const Point3d& ptCen, double dRad, bool bInOut,
const std::vector<Plane3d>& vPlanesVec,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
int IntersLineCatTongue( const Point3d& ptLineP, const Vector3d& vtLineD,
const Point3d& ptCenSt, const Point3d& ptCenEn, const Vector3d& vtNorm, double dRad,
Point3d& ptInt, Vector3d& vtN) const ;
// Voxel: esistenza e passaggio da N a ijk per i voxel
bool IsValidVoxel( int nN) const ;
bool IsValidVoxel( int nI, int nJ, int nK) const ;
@@ -472,7 +401,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
Status m_nStatus ; // stato
int m_nTempProp[2] ; // vettore proprietà temporanee
int m_nTempProp ; // proprietà temporanea
double m_dStep ; // passo delle griglie
int m_nMapNum ; // numero di griglie ( 1 o 3)
Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap
@@ -522,10 +451,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
mutable std::atomic<bool> m_bBreak ;
std::atomic<bool> m_bIsBox ;
// Utensili
std::vector<Tool> m_vTool ;
int m_nCurrTool ;
CurveComposite cvEmptyOutline ;
Tool m_Tool ;
} ;
+123 -30
View File
@@ -16,12 +16,10 @@
#include "CurveLine.h"
#include "VolZmap.h"
#include "GeoConst.h"
#include "IntersLineBox.h"
#include "IntersLineSurfStd.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSphere.h"
#include "/EgtDev/Include/EGkIntersPlaneBox.h"
#include "/EgtDev/Include/EGkIntersPlaneTria.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h"
@@ -32,6 +30,103 @@
using namespace std ;
//----------------------------------------------------------------------------
// Box e piano devono essere nello stesso riferimento. Il box deve essere axis aligned.
static bool
TestIntersPlaneBox( const BBox3d& b3Box, const Plane3d& plPlane)
{
// Calcolo le distanze con segno dei punti dal piano
Point3d ptE0 = b3Box.GetMin() ;
double dDist0 = DistPointPlane( ptE0, plPlane) ;
Point3d ptE1( b3Box.GetMax().x, b3Box.GetMin().y, b3Box.GetMin().z) ;
double dDist1 = DistPointPlane( ptE1, plPlane) ;
Point3d ptE2( b3Box.GetMax().x, b3Box.GetMax().y, b3Box.GetMin().z) ;
double dDist2 = DistPointPlane( ptE2, plPlane) ;
Point3d ptE3( b3Box.GetMin().x, b3Box.GetMax().y, b3Box.GetMin().z) ;
double dDist3 = DistPointPlane( ptE3, plPlane) ;
Point3d ptE4( b3Box.GetMin().x, b3Box.GetMin().y, b3Box.GetMax().z) ;
double dDist4 = DistPointPlane( ptE4, plPlane) ;
Point3d ptE5( b3Box.GetMax().x, b3Box.GetMin().y, b3Box.GetMax().z) ;
double dDist5 = DistPointPlane( ptE5, plPlane) ;
Point3d ptE6 = b3Box.GetMax() ;
double dDist6 = DistPointPlane( ptE6, plPlane) ;
Point3d ptE7( b3Box.GetMin().x, b3Box.GetMax().y, b3Box.GetMax().z) ;
double dDist7 = DistPointPlane( ptE7, plPlane) ;
// Distanze tutte positive
if ( dDist0 > EPS_SMALL && dDist1 > EPS_SMALL && dDist2 > EPS_SMALL && dDist3 > EPS_SMALL &&
dDist4 > EPS_SMALL && dDist5 > EPS_SMALL && dDist6 > EPS_SMALL && dDist7 > EPS_SMALL)
return false ;
// Distanze tutte negative
if ( dDist0 < - EPS_SMALL && dDist1 < - EPS_SMALL && dDist2 < - EPS_SMALL && dDist3 < - EPS_SMALL &&
dDist4 < - EPS_SMALL && dDist5 < - EPS_SMALL && dDist6 < - EPS_SMALL && dDist7 < - EPS_SMALL)
return false ;
// Il piano interseca il box
return true ;
}
//----------------------------------------------------------------------------
// Punti e vettore devono esse espressi nel medesimo sistema di riferimento.
// Il box è allineato con gli assi di tale sistema di riferimento.
// Viene restituito true in caso di intersezione, false altrimenti.
bool
VolZmap::IntersLineBox( const Point3d& ptP, const Vector3d& vtV, const Point3d& ptMin, const Point3d& ptMax) const
{
double dU1, dU2 ;
return IntersLineBox( ptP, vtV, ptMin, ptMax, dU1, dU2) ;
}
//----------------------------------------------------------------------------
// Punti e vettore devono esse espressi nel medesimo sistema di riferimento.
// Il box è allineato con gli assi di tale sistema di riferimento.
// In dU1, dU2 vengono restituiti i parametri a cui si trovano le intersezioni.
// Viene restituito true in caso di intersezione, false altrimenti.
bool
VolZmap::IntersLineBox( const Point3d& ptP, const Vector3d& vtV,
const Point3d& ptMin, const Point3d& ptMax, double& dU1, double& dU2) const
{
// Il box è allineato agli assi
dU1 = - INFINITO ;
dU2 = INFINITO ;
// confronto con piani YZ (perpendicolari ad asse X)
if ( vtV.x > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.x - ptP.x) / vtV.x) ;
dU2 = min( dU2, ( ptMax.x - ptP.x) / vtV.x) ;
}
else if ( vtV.x < - EPS_ZERO) {
dU1 = max( dU1, ( ptMax.x - ptP.x) / vtV.x) ;
dU2 = min( dU2, ( ptMin.x - ptP.x) / vtV.x) ;
}
else if ( ptP.x < ptMin.x - EPS_SMALL || ptP.x > ptMax.x + EPS_SMALL)
return false ;
// confronto con piani ZX (perpendicolari ad asse Y)
if ( vtV.y > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.y - ptP.y) / vtV.y) ;
dU2 = min( dU2, ( ptMax.y - ptP.y) / vtV.y) ;
}
else if ( vtV.y < - EPS_ZERO) {
dU1 = max( dU1, ( ptMax.y - ptP.y) / vtV.y) ;
dU2 = min( dU2, ( ptMin.y - ptP.y) / vtV.y) ;
}
else if ( ptP.y < ptMin.y - EPS_SMALL || ptP.y > ptMax.y + EPS_SMALL)
return false ;
// confronto con piani XY (perpendicolari ad asse Z)
if ( vtV.z > EPS_ZERO) {
dU1 = max( dU1, ( ptMin.z - ptP.z) / vtV.z) ;
dU2 = min( dU2, ( ptMax.z - ptP.z) / vtV.z) ;
}
else if ( vtV.z < - EPS_ZERO) {
dU1 = max( dU1, ( ptMax.z - ptP.z) / vtV.z) ;
dU2 = min( dU2, ( ptMin.z - ptP.z) / vtV.z) ;
}
else if ( ptP.z < ptMin.z - EPS_SMALL || ptP.z > ptMax.z + EPS_SMALL)
return false ;
return ( dU2 >= dU1) ;
}
//----------------------------------------------------------------------------
// La retta è rappresentata da un punto e dal versore espressi nel riferimento dello Zmap.
// Se non vi è intersezione, viene restituito falso
@@ -154,7 +249,7 @@ VolZmap::IntersRayDexel( const Point3d& ptP, const Vector3d& vtV, int nGrid, int
}
//----------------------------------------------------------------------------
// Calcola la profondità del materiale lungo un raggio, identificato da un punto e un versore.
// Calcola la profondità del materiale lungo un raggio, identificato da un punto e un versoreore.
// Punto e versore devono essere espressi nel sistema di riferimento locale, in cui è immerso quello dello Zmap.
// InLength = distanza di ingresso (se -1 il punto è interno, se -2 il punto è esterno e il raggio non interseca lo Zmap)
// OutLength = distanza di uscita
@@ -198,7 +293,7 @@ VolZmap::GetDepthWithDexel( const Point3d& ptPLoc, const Vector3d& vtDLoc, doubl
double dOutLen[N_MAPS] ;
// Ciclo sulle griglie
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
Point3d ptP0 = ptP ;
Vector3d vtV0 = vtD ;
@@ -322,7 +417,7 @@ VolZmap::GetDepthWithDexel( const Point3d& ptPLoc, const Vector3d& vtDLoc, doubl
else {
dInLength = INFINITO ;
dOutLength = - INFINITO ;
for ( int nGr = 0 ; nGr < m_nMapNum ; ++ nGr) {
for ( int nGr = 0 ; nGr < 3 ; ++ nGr) {
if ( dInLen[nGr] > -2 && dInLen[nGr] < dInLength)
dInLength = dInLen[nGr] ;
if ( dOutLen[nGr] > -2 && dOutLen[nGr] > dOutLength)
@@ -2281,7 +2376,7 @@ VolZmap::AvoidSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecis
bool
VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting) const
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
{
// Porto la linea nel riferimento del cilindro
Point3d ptP = ptLineSt ; ptP.ToLoc( CylFrame) ;
@@ -2291,14 +2386,14 @@ VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
int nBasInt = 0 ;
if ( abs( vtV.z) > EPS_ZERO) {
// le linee tangenti al cilindro non sono considerate intersecanti
double dEpsRad = ( bSubtracting ? ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) : EPS_SMALL) ;
double EpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * EpsRad) {
nBasInt += 1 ;
vtN1 = Z_AX ;
}
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * EpsRad) {
nBasInt += 2 ;
vtN2 = - Z_AX ;
}
@@ -2681,7 +2776,7 @@ VolZmap::IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d&
bool
VolZmap::IntersLineMyPolyhedron( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& PolyFrame, double dLenX, double dLenY, double dLenZ, double dDeltaZ,
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting) const
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
{
// Controllo sulle dimensioni lineari affinché sia valido il poliedro
if ( dLenX <= EPS_SMALL || dLenY <= EPS_SMALL || dLenZ <= EPS_SMALL)
@@ -2705,19 +2800,17 @@ VolZmap::IntersLineMyPolyhedron( const Point3d& ptLineSt, const Vector3d& vtLine
// Controlli affinché non vengano tagliati dexel a filo
// con il passaggio dell'utensile:
if ( bSubtracting) {
// Controllo sulle facce 1 e 2
if ( abs( vtV.y) < EPS_ZERO && abs( ptP.y) > ptFacet135.y)
return false ;
// Controllo sulle facce 3 e 4
if ( abs( vtV.x) < EPS_ZERO && ( ptP.x < ptFacet135.x || ptP.x > ptFacet246.x))
return false ;
// Controllo sulle facce 5 e 6
double dP1 = abs ( ( ptFacet135 - ptP) * vtOb) ;
double dP2 = abs ( ( ptFacet246 - ptP) * vtOb) ;
if ( abs( vtV * vtOb) < EPS_ZERO && ( dP1 < EPS_SMALL || dP2 < EPS_SMALL))
return false ;
}
// Controllo sulle facce 1 e 2
if ( abs( vtV.y) < EPS_ZERO && abs( ptP.y) > ptFacet135.y)
return false ;
// Controllo sulle facce 3 e 4
if ( abs( vtV.x) < EPS_ZERO && ( ptP.x < ptFacet135.x || ptP.x > ptFacet246.x))
return false ;
// Controllo sulle facce 5 e 6
double dP1 = abs ( ( ptFacet135 - ptP) * vtOb) ;
double dP2 = abs ( ( ptFacet246 - ptP) * vtOb) ;
if ( abs( vtV * vtOb) < EPS_ZERO && ( dP1 < EPS_SMALL || dP2 < EPS_SMALL))
return false ;
// Punti notevoli
Point3d ptI1 = ptP + ( ( ptFacet135.y - ptP.y) / vtV.y) * vtV ;
@@ -3037,8 +3130,8 @@ VolZmap::GetPartVolume( int nPart, double& dVol) const
// Eseguo il calcolo della lunghezza totale degli spilloni
double dLen = 0 ;
for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) {
for ( int nDex = 0 ; nDex < m_nDim[nMap] ; ++ nDex) {
for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) {
for ( int nDex = 0 ; nDex < int( m_Values[nMap].size()) ; ++ nDex) {
for ( int nInt = 0 ; nInt < int( m_Values[nMap][nDex].size()) ; ++ nInt) {
// se il pezzo di spillone appartiene alla parte, ne aggiungo la lunghezza
if ( m_Values[nMap][nDex][nInt].nCompo == nPart + 1) {
@@ -3095,7 +3188,7 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
if ( ! GetBlockBox( nBlockIJK, b3BlockBox))
return false ;
// Se c'è intersezione valuto tutti i voxel interni
if ( TestIntersLineBox( ptLocP, vtDirL, b3BlockBox.GetMin(), b3BlockBox.GetMax())) {
if ( IntersLineBox( ptLocP, vtDirL, b3BlockBox.GetMin(), b3BlockBox.GetMax())) {
// Ciclo sui voxel del blocco.
// Triangoli smooth
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
@@ -3106,7 +3199,7 @@ VolZmap::GetLineIntersection( const Point3d& ptP, const Vector3d& vtD, ILZIVECTO
m_BlockSmoothTria[nB][nV].k } ;
GetVoxelBox( nCurVoxIJK[0], nCurVoxIJK[1], nCurVoxIJK[2], b3Vox) ;
// Se non c'è intersezione col voxel, passo al successivo.
if ( ! TestIntersLineBox( ptLocP, vtDirL, b3Vox.GetMin(), b3Vox.GetMax()))
if ( ! IntersLineBox( ptLocP, vtDirL, b3Vox.GetMin(), b3Vox.GetMax()))
continue ;
for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) {
Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
@@ -3281,7 +3374,7 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
if ( ! GetBlockBox( nBlockIJK, b3BlockBox))
return false ;
// Se c'è intersezione valuto tutti i voxel interni
if ( TestIntersPlaneBox( plPlaneLoc, b3BlockBox)) {
if ( TestIntersPlaneBox( b3BlockBox, plPlaneLoc)) {
// Ciclo sui voxel del blocco.
// Triangoli smooth
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
@@ -3289,7 +3382,7 @@ VolZmap::GetPlaneIntersection( const Plane3d& plPlane, ICURVEPOVECTOR& vpLoop) c
BBox3d b3Vox ;
GetVoxelBox( m_BlockSmoothTria[nB][nV].i, m_BlockSmoothTria[nB][nV].j, m_BlockSmoothTria[nB][nV].k, b3Vox) ;
// Se non c'è intersezione col voxel, passo al successivo.
if ( ! TestIntersPlaneBox( plPlaneLoc, b3Vox))
if ( ! TestIntersPlaneBox(b3Vox, plPlaneLoc))
continue ;
for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) {
Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
@@ -3393,5 +3486,5 @@ bool
VolZmap::TestIntersPlaneZmapBBox( const Plane3d& plPlane) const
{
BBox3d b3Zmap( ORIG, Point3d( m_nNx[0] * m_dStep, m_nNy[0] * m_dStep, m_dMaxZ[0])) ;
return TestIntersPlaneBox( plPlane, b3Zmap) ;
return TestIntersPlaneBox( b3Zmap, plPlane) ;
}
+2 -76
View File
@@ -220,7 +220,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
// Determino le intersezioni della retta con la regione
CRVCVECTOR IntersectionResults ;
Surf.GetCurveClassification( GridLine, EPS_SMALL, IntersectionResults) ;
Surf.GetCurveClassification( GridLine, IntersectionResults) ;
// Analizzo le parti in cui la retta è stata divisa
int nPart = int( IntersectionResults.size()) ;
@@ -327,7 +327,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
// Determino le intersezioni della retta con la regione
CRVCVECTOR IntersectionResults ;
Surf.GetCurveClassification( GridLine, EPS_SMALL, IntersectionResults) ;
Surf.GetCurveClassification( GridLine, IntersectionResults) ;
// Analizzo le parti
int nPart = int( IntersectionResults.size()) ;
@@ -665,77 +665,3 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
return bCompleted ;
}
//----------------------------------------------------------------------------
bool
VolZmap::CreateEmptyMap( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex)
{
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
if ( dStep < EPS_SMALL || dLengthX < EPS_SMALL || dLengthY < EPS_SMALL || dLengthZ < EPS_SMALL)
return false ;
// Il passo di discretizzazione non può essere inferiore a 100 * EPS_SMALL
m_dStep = max( dStep, 100 * EPS_SMALL) ;
// Aggiorno la dimensione della mappa 1 o 3
m_nMapNum = ( bTriDex ? 3 : 1) ;
// Disponendo i sistemi di riferimento in una successione, le coordinate x,y,z
// di uno si ottengono da una permutazione ciclica di quelle del precedente sistema.
// es: X(n) = Z(n-1), Y(n) = X(n-1), Z(n) = Y(n-1)
// Definisco il sistema di riferimento intrinseco
m_MapFrame.Set( ptO, X_AX, Y_AX, Z_AX) ;
// Definisco i vettori dei limiti su indici
m_nNx[0] = max( int( ( dLengthX + EPS_SMALL) / m_dStep + 0.5), 1) ;
m_nNy[0] = max( int( ( dLengthY + EPS_SMALL) / m_dStep + 0.5), 1) ;
// Numero di componenti connesse
m_nConnectedCompoCount = 1 ;
// Se tridexel
if ( bTriDex) {
m_nNx[1] = m_nNy[0] ;
m_nNy[1] = max( int( ( dLengthZ + EPS_SMALL) / m_dStep + 0.5), 1) ;
m_nNx[2] = m_nNy[1] ;
m_nNy[2] = m_nNx[0] ;
}
// altrimenti mono dexel
else {
m_nNx[1] = 0 ;
m_nNy[1] = 0 ;
m_nNx[2] = 0 ;
m_nNy[2] = 0 ;
}
// Definisco il numero di blocchi lungo x,y e z
if ( ! CalcBlockNum())
return false ;
// Creazione delle mappe
// Calcolo del numero di celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_nDim[i] = m_nNx[i] * m_nNy[i] ;
// Creazione delle celle per ogni mappa
for ( int i = 0 ; i < m_nMapNum ; ++ i)
m_Values[i].resize( m_nDim[i]) ;
// Definizione delle limitazioni iniziali in Z per ogni mappa
m_dMinZ[0] = 0 ;
m_dMaxZ[0] = dLengthZ ;
m_dMinZ[1] = 0 ;
m_dMaxZ[1] = ( bTriDex ? dLengthX : 0) ;
m_dMinZ[2] = 0 ;
m_dMaxZ[2] = ( bTriDex ? dLengthY : 0) ;
// Tipologia
m_nShape = GENERIC ;
// Aggiornamento dello stato
m_nStatus = OK ;
return true ;
}
+9 -10
View File
@@ -1,13 +1,13 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2021
// EgalTech 2015-2019
//----------------------------------------------------------------------------
// File : VolZmap.cpp Data : 13.09.21 Versione : 2.3i1
// File : VolZmap.cpp Data : 07.03.19 Versione : 2.1c2
// Contenuto : Implementazione della classe Volume Zmap (tre griglie)
//
//
//
// Modifiche : 22.01.15 DS Creazione modulo.
// 13.09.21 LM Correzione funzione che determina se voxel su frontiera di un blocco.
//
//
//----------------------------------------------------------------------------
@@ -18,7 +18,6 @@
#include "GeoConst.h"
#include "MC_Tables.h"
#include "PolygonPlane.h"
#include "IntersLineBox.h"
#include "/EgtDev/Include/EGkIntervals.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EGkChainCurves.h"
@@ -845,7 +844,7 @@ VolZmap::UpdateTripleMapGraphics( void) const
VecTriHold.resize( m_nNumBlock) ;
// Ciclo sui blocchi per eliminare le slice fra blocchi da aggiornare
for ( int t = 0 ; t < m_nNumBlock ; ++ t) {
for ( int t = 0 ; t < m_nNumBlock ; ++ t) {
for ( auto it = m_SliceXY[t].begin() ; it != m_SliceXY[t].end() ;) {
int nSlIJK[3] ;
if ( GetVoxIJKFromN( it->first, nSlIJK[0], nSlIJK[1], nSlIJK[2])) {
@@ -1084,7 +1083,7 @@ VolZmap::ExtMarchingCubes( int nBlock, VoxelContainer& vVox) const
// Flag di regolarità dei campi scalare e vettoriale
bool bReg = true ;
// Ciclo sui segmenti
for ( int EdgeIndex = 0 ; EdgeIndex < 12 ; ++ EdgeIndex) {
// Se il segmento non attraversa la superficie passo al successivo
@@ -3985,13 +3984,13 @@ VolZmap::IsAVoxelOnBoundary( const int nLimits[], const int nIJK[], int nDeltaIn
-- nDeltaIndex[0] ;
else if ( nIJK[0] == nLimits[1] - 1)
++ nDeltaIndex[0] ;
if ( nIJK[1] == nLimits[2])
if ( nIJK[0] == nLimits[0])
-- nDeltaIndex[1];
else if ( nIJK[1] == nLimits[3] - 1)
else if ( nIJK[0] == nLimits[1] - 1)
++ nDeltaIndex[1];
if ( nIJK[2] == nLimits[4])
if ( nIJK[0] == nLimits[0])
-- nDeltaIndex[2];
else if ( nIJK[2] == nLimits[5] - 1)
else if ( nIJK[0] == nLimits[1] - 1)
++ nDeltaIndex[2];
return ( nDeltaIndex[0] != 0 || nDeltaIndex[1] != 0 || nDeltaIndex[2] != 0) ;
}
+547 -4037
View File
File diff suppressed because it is too large Load Diff
+635
View File
@@ -0,0 +1,635 @@
/*! \file dpoint.hpp
\brief d-dimensional point class
A d-dimensional point class which is written carefully using templates. It allows for basic
operations on points in any dimension. Orientation tests for 2 and 3 dimensional points are
supported using <a href="http://www.cs.berkeley.edu/~jrs/">Jonathan's</a> code. This class
forms the building block of other classes like dplane, dsphere etc.
\author <a href="www.compgeom.com/~piyush">Piyush Kumar</a>
\bug No known bugs.
*/
#ifndef REVIVER_POINT_HPP
#define REVIVER_POINT_HPP
// changed mrkkrj --
//#include "assert.hpp"
#include "tpp_assert.hpp"
// END changed --
#include <iostream>
#include <valarray>
#include <stdio.h>
#include <limits>
//! The reviver namespace signifies the part of the code borrowed from reviver (dpoint.hpp).
namespace reviver {
// Forward Declaration of the main Point Class
// Eucledian d-dimensional point. The distance is L_2
template<typename NumType, unsigned D>
class dpoint;
///////////////////////////////////////////////////////
// Internal number type traits for dpoint
///////////////////////////////////////////////////////
template<typename T>
class InternalNumberType;
template<>
class InternalNumberType<float>{
public:
typedef double __INT;
};
template<>
class InternalNumberType<int>{
public:
typedef long long __INT;
};
template<>
class InternalNumberType<double>{
public:
typedef double __INT;
};
template<>
class InternalNumberType<long>{
public:
typedef long long __INT;
};
///////////////////////////////////////////////////////
// Origin of d-dimensional point
///////////////////////////////////////////////////////
template< typename NumType, unsigned D, unsigned I > struct origin
{
static inline void eval( dpoint<NumType,D>& p )
{
p[I] = 0.0;
origin< NumType, D, I-1 >::eval( p );
}
};
// Partial Template Specialization
template <typename NumType, unsigned D> struct origin<NumType, D, 0>
{
static inline void eval( dpoint<NumType,D>& p )
{
p[0] = 0.0;
}
};
//! A structure to compute squared distances between points
/*!
Uses unrolling of loops using templates.
*/
///////////////////////////////////////////////////////
// Squared Distance of d-dimensional point
///////////////////////////////////////////////////////
template< typename NumType, unsigned D, unsigned I > struct Distance
{
static inline double eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
{
double sum = ((double)p[I] - (double)q[I] ) *( (double)p[I] - (double)q[I] );
return sum + Distance< NumType, D, I-1 >::eval( p,q );
}
};
//! Partial Template Specialization for distance calculations
template <typename NumType, unsigned D> struct Distance<NumType, D, 0>
{
static inline double eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
{
return ((double) p[0] - (double)q[0] )*( (double)p[0] - (double)q[0] );
}
};
//! A structure to compute dot product between two points or associated vectors
/*!
Uses unrolling of loops using templates.
*/
///////////////////////////////////////////////////////
// Dot Product of two d-dimensional points
///////////////////////////////////////////////////////
template< typename __INT, typename NumType, unsigned D, unsigned I > struct DotProd
{
static inline __INT eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
{
__INT sum = ( ((__INT)p[I]) * ((__INT)q[I]) );
return sum + DotProd< __INT, NumType, D, I-1 >::eval( p,q );
}
};
//! Partial Template Specialization for dot product calculations
template < typename __INT, typename NumType, unsigned D> struct DotProd<__INT,NumType, D, 0>
{
static inline __INT eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
{
return ( ((__INT)p[0]) * ((__INT)q[0]) );
}
};
///////////////////////////////////////////////////////
// Equality of two d-dimensional points
///////////////////////////////////////////////////////
template< typename NumType, unsigned D, unsigned I > struct IsEqual
{
static inline bool eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
{
if( p[I] != q[I] ) return false;
else return IsEqual< NumType, D, I-1 >::eval( p,q );
}
};
// Partial Template Specialization
template <typename NumType, unsigned D> struct IsEqual<NumType, D, 0>
{
static inline NumType eval( const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
{
return (p[0] == q[0])?1:0;
}
};
//! Equate two d-dimensional points.
/*!
Uses unrolling of loops using templates.
A class used to implement operator= for points. This class also helps in automatic type
conversions of points (with explicit calls for conversion).
*/
template<
typename NumType1,
typename NumType2,
unsigned D,
unsigned I
> struct Equate
{
static inline void eval( dpoint<NumType1,D>& p,const dpoint<NumType2,D>& q )
{
p[I] = q[I];
Equate< NumType1, NumType2, D, I-1 >::eval( p,q );
}
};
//! Partial Template Specialization for Equate
template <
typename NumType1,
typename NumType2,
unsigned D
> struct Equate<NumType1,NumType2, D, 0>
{
static inline void eval( dpoint<NumType1,D>& p,const dpoint<NumType2,D>& q )
{
p[0] = q[0];
}
};
//! A structure to add two points
/*!
Uses unrolling of loops using templates.
*/
///////////////////////////////////////////////////////
// Add two d-dimensional points
///////////////////////////////////////////////////////
template< typename NumType, unsigned D, unsigned I > struct Add
{
static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
{
result[I] = p[I] + q[I];
Add< NumType, D, I-1 >::eval( result,p,q );
}
};
//! Partial Template Specialization for Add structure
template <typename NumType, unsigned D> struct Add<NumType, D, 0>
{
static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
{
result[0] = p[0] + q[0];
}
};
///////////////////////////////////////////////////////
// Subtract two d-dimensional points
///////////////////////////////////////////////////////
// Could actually be done using scalar multiplication and addition
// What about unsigned types?
template< typename NumType >
inline NumType Subtract_nums(const NumType& x, const NumType& y) {
if(!std::numeric_limits<NumType>::is_signed) {
std::cerr << "Exception: Can't subtract unsigned types."; exit(1);
}
return x - y;
}
//! Subtract two d-dimensional vectors
/*!
Caution: Do not use on unsigned types.
*/
template< typename NumType, unsigned D, unsigned I > struct Subtract
{
static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
{
result[I] = Subtract_nums(p[I] , q[I]);
Subtract< NumType, D, I-1 >::eval( result,p,q );
}
};
//! Partial Template Specialization for subtraction of points (associated vectors)
template <typename NumType, unsigned D> struct Subtract<NumType, D, 0>
{
static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, const dpoint<NumType,D>& q )
{
result[0] = Subtract_nums(p[0] , q[0]);
}
};
//! Mutiply scalar with d-dimensional point
/*!
Scalar mulipltication of d-dimensional point with a number using template unrolling.
*/
template< typename NumType, unsigned D, unsigned I > struct Multiply
{
static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, NumType k)
{
result[I] = p[I] * k;
Multiply< NumType, D, I-1 >::eval( result,p,k );
}
};
//! Partial Template Specialization for scalar multiplication
template <typename NumType, unsigned D> struct Multiply<NumType, D, 0>
{
static inline void eval( dpoint<NumType,D>& result, const dpoint<NumType,D>& p, NumType k )
{
result[0] = p[0] * k;
}
};
//! Main d dimensional Point Class
/*!
- NumType = Floating Point Type
- D = Dimension of Point
*/
template<typename NumType = double, unsigned D = 3>
class dpoint {
// Makes Swap operation fast
NumType x[D];
public:
typedef NumType NT;
typedef typename InternalNumberType<NumType>::__INT __INT;
// To be defined in a cpp file
// const MgcVector2 MgcVector2::ZERO(0,0);
// static const dpoint<NumType,D> Zero;
inline void move2origin(){ origin<NumType, D, D-1>::eval(*this); };
dpoint(){
Assert( (D >= 1), "Dimension < 1 not allowed" );
// move2origin();
};
//! 1 D Point
dpoint(NumType x0){ x[0] = x0; };
//! 2 D Point
dpoint(NumType x0,NumType x1){ x[0] = x0; x[1] = x1; };
//! 3 D Point
dpoint(NumType x0,NumType x1,NumType x2){ x[0] = x0; x[1] = x1; x[2] = x2; };
//! Array Initialization
dpoint(NumType ax[]){ for(int i =0; i < D; ++i) x[i] = ax[i]; };
//! Initialization from another point : Copy Constructor
dpoint(const dpoint<NumType,D>& p){ Equate<NumType,NumType,D,D-1>::eval((*this),p); };
//! Automatic type conversions of points.
//! Only allowed if the conversion is specified explicitly by the programmer.
template<class OtherNumType>
explicit dpoint(const dpoint<OtherNumType,D>& p){ Equate<NumType,OtherNumType,D,D-1>::eval((*this),p); };
// Destructor
~dpoint(){};
inline int dim() const { return D; };
inline double sqr_dist(const dpoint<NumType,D> q) const ;
inline double distance(const dpoint<NumType,D> q) const ;
inline __INT dotprod (const dpoint<NumType,D> q) const ;
inline __INT sqr_length(void) const;
inline void normalize (void);
inline NumType& operator[](int i);
inline NumType operator[](int i) const;
inline dpoint& operator= (const dpoint<NumType,D>& q);
template<typename NT, unsigned __DIM>
friend dpoint<NT,__DIM> operator- (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q);
template<typename NT, unsigned __DIM>
friend dpoint<NT,__DIM> operator+ (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q);
template<typename NT, unsigned __DIM>
friend bool operator== (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q);
template<typename NT, unsigned __DIM>
friend bool operator!= (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q);
// inline dpoint& operator= (const valarray<NumType>& v);
// inline operator valarray<NumType>() const;
template<typename __NT,unsigned __DIM>
friend void iswap(dpoint<__NT,__DIM>& p,dpoint<__NT,__DIM>& q);
};
template<typename NumType, unsigned D>
void dpoint<NumType,D>::normalize (void){
double len = sqrt(sqr_length());
if (len > 0.00001)
for(int i = 0; i < D; ++i){
x[i] /= len;
}
}
/*
template<typename NumType, unsigned D>
dpoint<NumType,D>::operator valarray<NumType>() const{
valarray<NumType> result((*this).x , D);
return result;
}
//Warning : Valarray should be of size D
//TODO: Unwind this for loop into a template system
template<typename NumType, unsigned D>
dpoint<NumType,D>&
dpoint<NumType,D>::operator= (const valarray<NumType>& v){
dpoint<NumType,D> result;
for(int i = 0; i < D; i++) (*this).x[i] = v[i];
return (*this);
}
*/
template<typename NT, unsigned __DIM>
dpoint<NT,__DIM>
operator+ (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q){
dpoint<NT,__DIM> result;
Add<NT,__DIM,__DIM-1>::eval(result,p,q);
return result;
}
template<typename NT, unsigned __DIM>
dpoint<NT,__DIM>
operator- (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q){
dpoint<NT,__DIM> result;
// cout << "Subtracting..." << p << " from " << q << " = ";
Subtract<NT,__DIM,__DIM-1>::eval(result,p,q);
// cout << result << endl;
return result;
}
template<typename NT, unsigned __DIM>
bool
operator== (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q){
return IsEqual<NT,__DIM,__DIM-1>::eval(p,q);
}
template<typename NT, unsigned __DIM>
bool
operator!= (const dpoint<NT,__DIM>& p, const dpoint<NT,__DIM>& q){
return !(IsEqual<NT,__DIM,__DIM-1>::eval(p,q));
}
template<typename NT, unsigned __DIM>
dpoint<NT,__DIM>
operator* (const dpoint<NT,__DIM>& p, const NT k){
dpoint<NT,__DIM> result;
Multiply<NT,__DIM,__DIM-1>::eval(result,p,k);
return result;
}
template<typename NT, unsigned __DIM>
dpoint<NT,__DIM>
operator/ (const dpoint<NT,__DIM>& p, const NT k){
Assert( (k != 0), "Hell division by zero man...\n");
dpoint<NT,__DIM> result;
Multiply<NT,__DIM,__DIM-1>::eval(result,p,((double)1.0)/k);
return result;
}
template < typename NumType, unsigned D >
dpoint<NumType,D>&
dpoint<NumType,D>::operator=(const dpoint<NumType,D> &q)
{
Assert((this != &q), "Error p = p");
Equate<NumType,NumType,D,D-1>::eval(*this,q);
return *this;
}
template < typename NumType, unsigned D >
NumType
dpoint<NumType,D>::operator[](int i) const
{ return x[i]; }
template < typename NumType, unsigned D >
NumType&
dpoint<NumType,D>::operator[](int i)
{
return x[i];
}
template<typename NumType, unsigned D>
double
dpoint<NumType,D>::sqr_dist (const dpoint<NumType,D> q) const {
return Distance<NumType,D,D-1>::eval(*this,q);
}
template<typename NumType, unsigned D>
double
dpoint<NumType,D>::distance (const dpoint<NumType,D> q) const {
return sqrt(static_cast<double>(Distance<NumType,D,D-1>::eval(*this,q)));
}
template<typename NumType, unsigned D>
typename dpoint<NumType,D>::__INT
dpoint<NumType,D>::dotprod (const dpoint<NumType,D> q) const {
return DotProd<__INT,NumType,D,D-1>::eval(*this,q);
}
template<typename NumType, unsigned D>
typename dpoint<NumType,D>::__INT
dpoint<NumType,D>::sqr_length (void) const {
#ifdef _DEBUG
if( DotProd<__INT,NumType,D,D-1>::eval(*this,*this) < 0) {
std::cerr << "Point that caused error: ";
std::cerr << *this << std::endl;
std::cerr << DotProd<__INT,NumType,D,D-1>::eval(*this,*this) << std::endl;
std::cerr << "Fatal: Hell!\n"; exit(1);
}
#endif
return DotProd<__INT,NumType,D,D-1>::eval(*this,*this);
}
template < class NumType, unsigned D >
std::ostream&
operator<<(std::ostream& os,const dpoint<NumType,D> &p)
{
os << "Point (d=";
os << D << ", (";
for (unsigned int i=0; i<D-1; ++i)
os << p[i] << ", ";
return os << p[D-1] << "))";
};
template < class NumType, unsigned D >
std::istream&
operator>>(std::istream& is,dpoint<NumType,D> &p)
{
for (int i=0; i<D; ++i)
if(!(is >> p[i])){
if(!is.eof()){
std::cerr << "Error Reading Point:"
<< is << std::endl;
exit(1);
}
}
return is;
};
/*
template<typename __NT,unsigned __DIM>
static inline void iswap(dpoint<__NT,__DIM>& p,dpoint<__NT,__DIM>& q){
__NT *y;
y = p.x;
p.x = q.x;
q.x = y;
}
*/
template < typename NumType, unsigned D >
dpoint<NumType, D> CrossProd(const dpoint<NumType, D>& vector1,
const dpoint<NumType, D>& vector2) {
Assert(D == 3, "Cross product only defined for 3d vectors");
dpoint<NumType, D> vector;
vector[0] = (vector1[1] * vector2[2]) - (vector2[1] * vector1[2]);
vector[1] = (vector2[0] * vector1[2]) - (vector1[0] * vector2[2]);
vector[2] = (vector1[0] * vector2[1]) - (vector2[0] * vector1[1]);
return vector;
}
template < typename __NT, unsigned __DIM >
int
orientation(const dpoint<__NT,__DIM> p[__DIM+1])
{
int _sign = + 1;
// To be implemented
std::cerr << "Not yet implemented\n";
exit(1);
return _sign;
}
template < typename __NT >
inline __NT
orientation(
const dpoint<__NT,2>& p,
const dpoint<__NT,2>& q,
const dpoint<__NT,2>& r
)
{
// 2D speaciliazation for orientation
std::cout << "FATAL";
exit(1);
return ((p[0]-r[0])*(q[1]-r[1]))-((q[0]-r[0])*(p[1]-r[1]));
}
extern "C" double orient2d(double *p, double *q, double *r);
template < >
inline double
orientation<double>(
const dpoint<double,2>& p,
const dpoint<double,2>& q,
const dpoint<double,2>& r
)
{
// 2D speaciliazation for orientation
double pp[2] = { p[0], p[1] };
double qq[2] = { q[0], q[1] };
double rr[2] = { r[0], r[1] };
return orient2d(pp,qq,rr);
}
template < >
inline float
orientation<float>(
const dpoint<float,2>& p,
const dpoint<float,2>& q,
const dpoint<float,2>& r
)
{
// 2D speaciliazation for orientation
double pp[2] = { p[0], p[1] };
double qq[2] = { q[0], q[1] };
double rr[2] = { r[0], r[1] };
return (float)orient2d(pp,qq,rr);
}
}; // Namespace Ends here
#endif
-823
View File
@@ -1,823 +0,0 @@
#pragma once
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <limits>
#include <memory>
#include <utility>
#include <vector>
namespace mapbox {
namespace util {
template <std::size_t I, typename T> struct nth {
inline static typename std::tuple_element<I, T>::type
get(const T& t) { return std::get<I>(t); };
};
}
namespace detail {
template <typename N = uint32_t>
class Earcut {
public:
std::vector<N> indices;
std::size_t vertices = 0;
template <typename Polygon>
void operator()(const Polygon& points);
private:
struct Node {
Node(N index, double x_, double y_) : i(index), x(x_), y(y_) {}
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
Node(Node&&) = delete;
Node& operator=(Node&&) = delete;
const N i;
const double x;
const double y;
// previous and next vertice nodes in a polygon ring
Node* prev = nullptr;
Node* next = nullptr;
// z-order curve value
int32_t z = 0;
// previous and next nodes in z-order
Node* prevZ = nullptr;
Node* nextZ = nullptr;
// indicates whether this is a steiner point
bool steiner = false;
};
template <typename Ring> Node* linkedList(const Ring& points, const bool clockwise);
Node* filterPoints(Node* start, Node* end = nullptr);
void earcutLinked(Node* ear, int pass = 0);
bool isEar(Node* ear);
bool isEarHashed(Node* ear);
Node* cureLocalIntersections(Node* start);
void splitEarcut(Node* start);
template <typename Polygon> Node* eliminateHoles(const Polygon& points, Node* outerNode);
Node* eliminateHole(Node* hole, Node* outerNode);
Node* findHoleBridge(Node* hole, Node* outerNode);
bool sectorContainsSector(const Node* m, const Node* p);
void indexCurve(Node* start);
Node* sortLinked(Node* list);
int32_t zOrder(const double x_, const double y_);
Node* getLeftmost(Node* start);
bool pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const;
bool isValidDiagonal(Node* a, Node* b);
double area(const Node* p, const Node* q, const Node* r) const;
bool equals(const Node* p1, const Node* p2);
bool intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2);
bool onSegment(const Node* p, const Node* q, const Node* r);
int sign(double val);
bool intersectsPolygon(const Node* a, const Node* b);
bool locallyInside(const Node* a, const Node* b);
bool middleInside(const Node* a, const Node* b);
Node* splitPolygon(Node* a, Node* b);
template <typename Point> Node* insertNode(std::size_t i, const Point& p, Node* last);
void removeNode(Node* p);
bool hashing;
double minX, maxX;
double minY, maxY;
double inv_size = 0;
template <typename T, typename Alloc = std::allocator<T>>
class ObjectPool {
public:
ObjectPool() { }
ObjectPool(std::size_t blockSize_) {
reset(blockSize_);
}
~ObjectPool() {
clear();
}
template <typename... Args>
T* construct(Args&&... args) {
if (currentIndex >= blockSize) {
currentBlock = alloc_traits::allocate(alloc, blockSize);
allocations.emplace_back(currentBlock);
currentIndex = 0;
}
T* object = &currentBlock[currentIndex++];
alloc_traits::construct(alloc, object, std::forward<Args>(args)...);
return object;
}
void reset(std::size_t newBlockSize) {
for (auto allocation : allocations) {
alloc_traits::deallocate(alloc, allocation, blockSize);
}
allocations.clear();
blockSize = std::max<std::size_t>(1, newBlockSize);
currentBlock = nullptr;
currentIndex = blockSize;
}
void clear() { reset(blockSize); }
private:
T* currentBlock = nullptr;
std::size_t currentIndex = 1;
std::size_t blockSize = 1;
std::vector<T*> allocations;
Alloc alloc;
typedef typename std::allocator_traits<Alloc> alloc_traits;
};
ObjectPool<Node> nodes;
};
template <typename N> template <typename Polygon>
void Earcut<N>::operator()(const Polygon& points) {
// reset
indices.clear();
vertices = 0;
if (points.empty()) return;
double x;
double y;
int threshold = 80;
std::size_t len = 0;
for (size_t i = 0; threshold >= 0 && i < points.size(); i++) {
threshold -= static_cast<int>(points[i].size());
len += points[i].size();
}
//estimate size of nodes and indices
nodes.reset(len * 3 / 2);
indices.reserve(len + points[0].size());
Node* outerNode = linkedList(points[0], true);
if (!outerNode || outerNode->prev == outerNode->next) return;
if (points.size() > 1) outerNode = eliminateHoles(points, outerNode);
// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox
hashing = threshold < 0;
if (hashing) {
Node* p = outerNode->next;
minX = maxX = outerNode->x;
minY = maxY = outerNode->y;
do {
x = p->x;
y = p->y;
minX = std::min<double>(minX, x);
minY = std::min<double>(minY, y);
maxX = std::max<double>(maxX, x);
maxY = std::max<double>(maxY, y);
p = p->next;
} while (p != outerNode);
// minX, minY and size are later used to transform coords into integers for z-order calculation
inv_size = std::max<double>(maxX - minX, maxY - minY);
inv_size = inv_size != .0 ? (1. / inv_size) : .0;
}
earcutLinked(outerNode);
nodes.clear();
}
// create a circular doubly linked list from polygon points in the specified winding order
template <typename N> template <typename Ring>
typename Earcut<N>::Node*
Earcut<N>::linkedList(const Ring& points, const bool clockwise) {
using Point = typename Ring::value_type;
double sum = 0;
const std::size_t len = points.size();
std::size_t i, j;
Node* last = nullptr;
// calculate original winding order of a polygon ring
for (i = 0, j = len > 0 ? len - 1 : 0; i < len; j = i++) {
const auto& p1 = points[i];
const auto& p2 = points[j];
const double p20 = util::nth<0, Point>::get(p2);
const double p10 = util::nth<0, Point>::get(p1);
const double p11 = util::nth<1, Point>::get(p1);
const double p21 = util::nth<1, Point>::get(p2);
sum += (p20 - p10) * (p11 + p21);
}
// link points into circular doubly-linked list in the specified winding order
if (clockwise == (sum > 0)) {
for (i = 0; i < len; i++) last = insertNode(vertices + i, points[i], last);
} else {
for (i = len; i-- > 0;) last = insertNode(vertices + i, points[i], last);
}
if (last && equals(last, last->next)) {
removeNode(last);
last = last->next;
}
vertices += len;
return last;
}
// eliminate colinear or duplicate points
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::filterPoints(Node* start, Node* end) {
if (!end) end = start;
Node* p = start;
bool again;
do {
again = false;
if (!p->steiner && (equals(p, p->next) || area(p->prev, p, p->next) == 0)) {
removeNode(p);
p = end = p->prev;
if (p == p->next) break;
again = true;
} else {
p = p->next;
}
} while (again || p != end);
return end;
}
// main ear slicing loop which triangulates a polygon (given as a linked list)
template <typename N>
void Earcut<N>::earcutLinked(Node* ear, int pass) {
if (!ear) return;
// interlink polygon nodes in z-order
if (!pass && hashing) indexCurve(ear);
Node* stop = ear;
Node* prev;
Node* next;
int iterations = 0;
// iterate through ears, slicing them one by one
while (ear->prev != ear->next) {
iterations++;
prev = ear->prev;
next = ear->next;
if (hashing ? isEarHashed(ear) : isEar(ear)) {
// cut off the triangle
indices.emplace_back(prev->i);
indices.emplace_back(ear->i);
indices.emplace_back(next->i);
removeNode(ear);
// skipping the next vertice leads to less sliver triangles
ear = next->next;
stop = next->next;
continue;
}
ear = next;
// if we looped through the whole remaining polygon and can't find any more ears
if (ear == stop) {
// try filtering points and slicing again
if (!pass) earcutLinked(filterPoints(ear), 1);
// if this didn't work, try curing all small self-intersections locally
else if (pass == 1) {
ear = cureLocalIntersections(filterPoints(ear));
earcutLinked(ear, 2);
// as a last resort, try splitting the remaining polygon into two
} else if (pass == 2) splitEarcut(ear);
break;
}
}
}
// check whether a polygon node forms a valid ear with adjacent nodes
template <typename N>
bool Earcut<N>::isEar(Node* ear) {
const Node* a = ear->prev;
const Node* b = ear;
const Node* c = ear->next;
if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
// now make sure we don't have other points inside the potential ear
Node* p = ear->next->next;
while (p != ear->prev) {
if (pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
area(p->prev, p, p->next) >= 0) return false;
p = p->next;
}
return true;
}
template <typename N>
bool Earcut<N>::isEarHashed(Node* ear) {
const Node* a = ear->prev;
const Node* b = ear;
const Node* c = ear->next;
if (area(a, b, c) >= 0) return false; // reflex, can't be an ear
// triangle bbox; min & max are calculated like this for speed
const double minTX = std::min<double>(a->x, std::min<double>(b->x, c->x));
const double minTY = std::min<double>(a->y, std::min<double>(b->y, c->y));
const double maxTX = std::max<double>(a->x, std::max<double>(b->x, c->x));
const double maxTY = std::max<double>(a->y, std::max<double>(b->y, c->y));
// z-order range for the current triangle bbox;
const int32_t minZ = zOrder(minTX, minTY);
const int32_t maxZ = zOrder(maxTX, maxTY);
// first look for points inside the triangle in increasing z-order
Node* p = ear->nextZ;
while (p && p->z <= maxZ) {
if (p != ear->prev && p != ear->next &&
pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
area(p->prev, p, p->next) >= 0) return false;
p = p->nextZ;
}
// then look for points in decreasing z-order
p = ear->prevZ;
while (p && p->z >= minZ) {
if (p != ear->prev && p != ear->next &&
pointInTriangle(a->x, a->y, b->x, b->y, c->x, c->y, p->x, p->y) &&
area(p->prev, p, p->next) >= 0) return false;
p = p->prevZ;
}
return true;
}
// go through all polygon nodes and cure small local self-intersections
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::cureLocalIntersections(Node* start) {
Node* p = start;
do {
Node* a = p->prev;
Node* b = p->next->next;
// a self-intersection where edge (v[i-1],v[i]) intersects (v[i+1],v[i+2])
if (!equals(a, b) && intersects(a, p, p->next, b) && locallyInside(a, b) && locallyInside(b, a)) {
indices.emplace_back(a->i);
indices.emplace_back(p->i);
indices.emplace_back(b->i);
// remove two nodes involved
removeNode(p);
removeNode(p->next);
p = start = b;
}
p = p->next;
} while (p != start);
return filterPoints(p);
}
// try splitting polygon into two and triangulate them independently
template <typename N>
void Earcut<N>::splitEarcut(Node* start) {
// look for a valid diagonal that divides the polygon into two
Node* a = start;
do {
Node* b = a->next->next;
while (b != a->prev) {
if (a->i != b->i && isValidDiagonal(a, b)) {
// split the polygon in two by the diagonal
Node* c = splitPolygon(a, b);
// filter colinear points around the cuts
a = filterPoints(a, a->next);
c = filterPoints(c, c->next);
// run earcut on each half
earcutLinked(a);
earcutLinked(c);
return;
}
b = b->next;
}
a = a->next;
} while (a != start);
}
// link every hole into the outer loop, producing a single-ring polygon without holes
template <typename N> template <typename Polygon>
typename Earcut<N>::Node*
Earcut<N>::eliminateHoles(const Polygon& points, Node* outerNode) {
const size_t len = points.size();
std::vector<Node*> queue;
for (size_t i = 1; i < len; i++) {
Node* list = linkedList(points[i], false);
if (list) {
if (list == list->next) list->steiner = true;
queue.push_back(getLeftmost(list));
}
}
std::sort(queue.begin(), queue.end(), [](const Node* a, const Node* b) {
return a->x < b->x;
});
// process holes from left to right
for (size_t i = 0; i < queue.size(); i++) {
outerNode = eliminateHole(queue[i], outerNode);
outerNode = filterPoints(outerNode, outerNode->next);
}
return outerNode;
}
// find a bridge between vertices that connects hole with an outer ring and and link it
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::eliminateHole(Node* hole, Node* outerNode) {
Node* bridge = findHoleBridge(hole, outerNode);
if (!bridge) {
return outerNode;
}
Node* bridgeReverse = splitPolygon(bridge, hole);
// filter collinear points around the cuts
Node* filteredBridge = filterPoints(bridge, bridge->next);
filterPoints(bridgeReverse, bridgeReverse->next);
// Check if input node was removed by the filtering
return outerNode == bridge ? filteredBridge : outerNode;
}
// David Eberly's algorithm for finding a bridge between hole and outer polygon
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::findHoleBridge(Node* hole, Node* outerNode) {
Node* p = outerNode;
double hx = hole->x;
double hy = hole->y;
double qx = -std::numeric_limits<double>::infinity();
Node* m = nullptr;
// find a segment intersected by a ray from the hole's leftmost Vertex to the left;
// segment's endpoint with lesser x will be potential connection Vertex
do {
if (hy <= p->y && hy >= p->next->y && p->next->y != p->y) {
double x = p->x + (hy - p->y) * (p->next->x - p->x) / (p->next->y - p->y);
if (x <= hx && x > qx) {
qx = x;
if (x == hx) {
if (hy == p->y) return p;
if (hy == p->next->y) return p->next;
}
m = p->x < p->next->x ? p : p->next;
}
}
p = p->next;
} while (p != outerNode);
if (!m) return 0;
if (hx == qx) return m; // hole touches outer segment; pick leftmost endpoint
// look for points inside the triangle of hole Vertex, segment intersection and endpoint;
// if there are no points found, we have a valid connection;
// otherwise choose the Vertex of the minimum angle with the ray as connection Vertex
const Node* stop = m;
double tanMin = std::numeric_limits<double>::infinity();
double tanCur = 0;
p = m;
double mx = m->x;
double my = m->y;
do {
if (hx >= p->x && p->x >= mx && hx != p->x &&
pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p->x, p->y)) {
tanCur = std::abs(hy - p->y) / (hx - p->x); // tangential
if (locallyInside(p, hole) &&
(tanCur < tanMin || (tanCur == tanMin && (p->x > m->x || sectorContainsSector(m, p))))) {
m = p;
tanMin = tanCur;
}
}
p = p->next;
} while (p != stop);
return m;
}
// whether sector in vertex m contains sector in vertex p in the same coordinates
template <typename N>
bool Earcut<N>::sectorContainsSector(const Node* m, const Node* p) {
return area(m->prev, m, p->prev) < 0 && area(p->next, m, m->next) < 0;
}
// interlink polygon nodes in z-order
template <typename N>
void Earcut<N>::indexCurve(Node* start) {
assert(start);
Node* p = start;
do {
p->z = p->z ? p->z : zOrder(p->x, p->y);
p->prevZ = p->prev;
p->nextZ = p->next;
p = p->next;
} while (p != start);
p->prevZ->nextZ = nullptr;
p->prevZ = nullptr;
sortLinked(p);
}
// Simon Tatham's linked list merge sort algorithm
// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::sortLinked(Node* list) {
assert(list);
Node* p;
Node* q;
Node* e;
Node* tail;
int i, numMerges, pSize, qSize;
int inSize = 1;
for (;;) {
p = list;
list = nullptr;
tail = nullptr;
numMerges = 0;
while (p) {
numMerges++;
q = p;
pSize = 0;
for (i = 0; i < inSize; i++) {
pSize++;
q = q->nextZ;
if (!q) break;
}
qSize = inSize;
while (pSize > 0 || (qSize > 0 && q)) {
if (pSize == 0) {
e = q;
q = q->nextZ;
qSize--;
} else if (qSize == 0 || !q) {
e = p;
p = p->nextZ;
pSize--;
} else if (p->z <= q->z) {
e = p;
p = p->nextZ;
pSize--;
} else {
e = q;
q = q->nextZ;
qSize--;
}
if (tail) tail->nextZ = e;
else list = e;
e->prevZ = tail;
tail = e;
}
p = q;
}
tail->nextZ = nullptr;
if (numMerges <= 1) return list;
inSize *= 2;
}
}
// z-order of a Vertex given coords and size of the data bounding box
template <typename N>
int32_t Earcut<N>::zOrder(const double x_, const double y_) {
// coords are transformed into non-negative 15-bit integer range
int32_t x = static_cast<int32_t>(32767.0 * (x_ - minX) * inv_size);
int32_t y = static_cast<int32_t>(32767.0 * (y_ - minY) * inv_size);
x = (x | (x << 8)) & 0x00FF00FF;
x = (x | (x << 4)) & 0x0F0F0F0F;
x = (x | (x << 2)) & 0x33333333;
x = (x | (x << 1)) & 0x55555555;
y = (y | (y << 8)) & 0x00FF00FF;
y = (y | (y << 4)) & 0x0F0F0F0F;
y = (y | (y << 2)) & 0x33333333;
y = (y | (y << 1)) & 0x55555555;
return x | (y << 1);
}
// find the leftmost node of a polygon ring
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::getLeftmost(Node* start) {
Node* p = start;
Node* leftmost = start;
do {
if (p->x < leftmost->x || (p->x == leftmost->x && p->y < leftmost->y))
leftmost = p;
p = p->next;
} while (p != start);
return leftmost;
}
// check if a point lies within a convex triangle
template <typename N>
bool Earcut<N>::pointInTriangle(double ax, double ay, double bx, double by, double cx, double cy, double px, double py) const {
return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&
(ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&
(bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;
}
// check if a diagonal between two polygon nodes is valid (lies in polygon interior)
template <typename N>
bool Earcut<N>::isValidDiagonal(Node* a, Node* b) {
return a->next->i != b->i && a->prev->i != b->i && !intersectsPolygon(a, b) && // dones't intersect other edges
((locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
(area(a->prev, a, b->prev) != 0.0 || area(a, b->prev, b) != 0.0)) || // does not create opposite-facing sectors
(equals(a, b) && area(a->prev, a, a->next) > 0 && area(b->prev, b, b->next) > 0)); // special zero-length case
}
// signed area of a triangle
template <typename N>
double Earcut<N>::area(const Node* p, const Node* q, const Node* r) const {
return (q->y - p->y) * (r->x - q->x) - (q->x - p->x) * (r->y - q->y);
}
// check if two points are equal
template <typename N>
bool Earcut<N>::equals(const Node* p1, const Node* p2) {
return p1->x == p2->x && p1->y == p2->y;
}
// check if two segments intersect
template <typename N>
bool Earcut<N>::intersects(const Node* p1, const Node* q1, const Node* p2, const Node* q2) {
int o1 = sign(area(p1, q1, p2));
int o2 = sign(area(p1, q1, q2));
int o3 = sign(area(p2, q2, p1));
int o4 = sign(area(p2, q2, q1));
if (o1 != o2 && o3 != o4) return true; // general case
if (o1 == 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1
if (o2 == 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1
if (o3 == 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2
if (o4 == 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2
return false;
}
// for collinear points p, q, r, check if point q lies on segment pr
template <typename N>
bool Earcut<N>::onSegment(const Node* p, const Node* q, const Node* r) {
return q->x <= std::max<double>(p->x, r->x) &&
q->x >= std::min<double>(p->x, r->x) &&
q->y <= std::max<double>(p->y, r->y) &&
q->y >= std::min<double>(p->y, r->y);
}
template <typename N>
int Earcut<N>::sign(double val) {
return (0.0 < val) - (val < 0.0);
}
// check if a polygon diagonal intersects any polygon segments
template <typename N>
bool Earcut<N>::intersectsPolygon(const Node* a, const Node* b) {
const Node* p = a;
do {
if (p->i != a->i && p->next->i != a->i && p->i != b->i && p->next->i != b->i &&
intersects(p, p->next, a, b)) return true;
p = p->next;
} while (p != a);
return false;
}
// check if a polygon diagonal is locally inside the polygon
template <typename N>
bool Earcut<N>::locallyInside(const Node* a, const Node* b) {
return area(a->prev, a, a->next) < 0 ?
area(a, b, a->next) >= 0 && area(a, a->prev, b) >= 0 :
area(a, b, a->prev) < 0 || area(a, a->next, b) < 0;
}
// check if the middle Vertex of a polygon diagonal is inside the polygon
template <typename N>
bool Earcut<N>::middleInside(const Node* a, const Node* b) {
const Node* p = a;
bool inside = false;
double px = (a->x + b->x) / 2;
double py = (a->y + b->y) / 2;
do {
if (((p->y > py) != (p->next->y > py)) && p->next->y != p->y &&
(px < (p->next->x - p->x) * (py - p->y) / (p->next->y - p->y) + p->x))
inside = !inside;
p = p->next;
} while (p != a);
return inside;
}
// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits
// polygon into two; if one belongs to the outer ring and another to a hole, it merges it into a
// single ring
template <typename N>
typename Earcut<N>::Node*
Earcut<N>::splitPolygon(Node* a, Node* b) {
Node* a2 = nodes.construct(a->i, a->x, a->y);
Node* b2 = nodes.construct(b->i, b->x, b->y);
Node* an = a->next;
Node* bp = b->prev;
a->next = b;
b->prev = a;
a2->next = an;
an->prev = a2;
b2->next = a2;
a2->prev = b2;
bp->next = b2;
b2->prev = bp;
return b2;
}
// create a node and util::optionally link it with previous one (in a circular doubly linked list)
template <typename N> template <typename Point>
typename Earcut<N>::Node*
Earcut<N>::insertNode(std::size_t i, const Point& pt, Node* last) {
Node* p = nodes.construct(static_cast<N>(i), util::nth<0, Point>::get(pt), util::nth<1, Point>::get(pt));
if (!last) {
p->prev = p;
p->next = p;
} else {
assert(last);
p->next = last->next;
p->prev = last;
last->next->prev = p;
last->next = p;
}
return p;
}
template <typename N>
void Earcut<N>::removeNode(Node* p) {
p->next->prev = p->prev;
p->prev->next = p->next;
if (p->prevZ) p->prevZ->nextZ = p->nextZ;
if (p->nextZ) p->nextZ->prevZ = p->prevZ;
}
}
template <typename N = uint32_t, typename Polygon>
std::vector<N> earcut(const Polygon& poly) {
mapbox::detail::Earcut<N> earcut;
earcut(poly);
return std::move(earcut.indices);
}
}
+43
View File
@@ -0,0 +1,43 @@
/*! \file assert.cpp
\brief Implements a better 'Assert'
*/
#include "stdafx.h"
#include <iostream>
#include <stdlib.h>
#if _WINDOWS
#include <cassert>
#endif
namespace tpp {
/*! \def MyAssertFunction
\brief Function used by 'Assert' function in _DEBUG mode.
Details.
*/
bool MyAssertFunction( bool b, const char* desc, int line, const char* file){
// changed mrkkrj --
#if _WINDOWS
(void)desc;
(void)line;
(void)file;
assert(b); // use integration with Visual Studio!
(void)b;
return true;
#else
// Original:
if (b) return true;
std::cerr << "\n\nAssertion Failure\n";
std::cerr << "Description : " << desc << std::endl;
std::cerr << "Filename : " << file << std::endl;
std::cerr << "Line No : " << line << std::endl;
exit(1);
#endif
}
} // end of namespace
+29
View File
@@ -0,0 +1,29 @@
/*! \file assert.hpp
\brief Implements a better 'Assert'.
Used in the reviver::dpoint inplementation.
*/
namespace tpp {
#ifndef REVIVER_ASSERT_HPP
#define REVIVER_ASSERT_HPP
/*! \def MyAssertFunction
\brief Function used by 'Assert' function in _DEBUG mode.
*/
extern bool MyAssertFunction( bool b, const char* desc, int line, const char* file);
#if defined( _DEBUG )
// changed mrkkrj --
//#define Assert( exp, description ) MyAssertFunction( (int)(exp), description, __LINE__, __FILE__ )
#define Assert( exp, description ) tpp::MyAssertFunction( (int)(exp), description, __LINE__, __FILE__ )
// END changed --
#else
#define Assert( exp, description )
#endif
#endif
}
+1454
View File
File diff suppressed because it is too large Load Diff
+719
View File
@@ -0,0 +1,719 @@
/*! \file tpp_interface.hpp
\brief The main Delaunay C++ class of the Triangle++ wrapper.
Use this class to produce Delaunay triangulations.
The following description pertains to the original version, the current version
was ported to VisualStudio. Thus it doesn't need Python scripts, and is supposed
to be used *as it is* in your program!
*/
/*! \mainpage Triangle++
\section intro Introduction
<table border="0">
<tr><td>
If you do not know, what a Delaunay triangulation is, you can read more about it
<a href="http://www.compgeom.com/~piyush/teach/5930/slides/lecture8.ppt">here</a> and
<a href="http://en.wikipedia.org/wiki/Delaunay_triangulation">here</a>.
This C++ library module is just a wrapper class on the
<a href="http://www.cs.berkeley.edu/~jrs/">Triangle</a>
package of <a href="http://www.cs.berkeley.edu/~jrs/">Jonathan</a>.
Many times I have had to use triangle in C++ code bases of mine and have been forced to use C.
At last I thought I would put a wrapper on his cool C code and it seems that this is what I got.
The design is not perfect and the code was written in a day, but it does compile and run on the
machines I tried (cygwin/redhat). The C++ wrapper will certainly slow access down if you want to
mess with the triangulation but the basic delaunay triangulation should be as fast as triangle.
Look at the tpp_interface.hpp file for getting started on what this wrapper can do for you. Also
have a look at main.cpp which shows an example of using this class. The class is thread-safe.
<p>
<b>Requirements</b> : Python, make and C++ compilers.
Supported C/C++ Compilers: g++ / icpc (Intel C++).
Also needed is doxygen for generating documentation.
</p>
<p>
<b>Compilation</b> : Just type 'make'</p>
<p>
<b>Testing</b> : Goto the bin directory, and type './test ../data/input.dat' (after compilation of course).
</p>
</td>
<td><img src="http://upload.wikimedia.org/wikipedia/en/9/92/Delaunay_triangulation.png" alt="Delaunay Triangulation Example"></td>
</tr>
</table>
\section Downloads
You can download the latest version of the source code from <a href="triangle++.tar.gz">here</a>.
\section authors Authors
<ul>
<li><a href="http://compgeom.com/~piyush">Piyush Kumar</a></li>
<li><a href="http://www.ib-krajewski.de">Marek Krajewski</a></li>
<li>Hopefully more to come... (please feel free to extend this wrapper)</li>
</ul>
\section changelog Change Log
17/04/20: mrkkrj added support Voronoi tesselation <br>
22/01/20: mrkkrj added support for custom constraints (angle and area) <br>
17/09/18: mrkkrj ported to 64-bit (preliminary, not thorougly tested!) <br>
11/07/11: mrkkrj - bugfix in Triangle's divandconqdelauney() <br>
10/15/11: mrkkrj - added support for the "quality triangulation" option, added some debug support<br>
08/24/11: mrkkrj - Ported to VisualStudio, added comp. operators, reformatted and added some comments<br>
10/21/06: Replaced vertexsort with C++ sort.<br>
10/25/06: Wrapped in tpp namespace for usage with other libraries with similar names.
Added some more documentation/small changes. Used doxygen 1.5.0 and dot. Tested compilation with
icc 9.0/9.1, gcc-4.1/3.4.6. <br>
11/03/06: Fixed the compilation system. <br>
\todo
<ol>
<li> Intel Compiler Warnings with -Wall </li>
<ul>
<li> remove the compiler warnings for icpc 9.0/9.1</li>
</ul>
<li> Implement vertexmedian() in C++. </li>
<li> Implement the flip operator as a member function of Delaunay. </li>
</ol>
*/
//-----------------------------------------------------------
#ifndef TRPP_INTERFACE
#define TRPP_INTERFACE
// changed mrkkrj --
//#include <dpoint.hpp>
#include "dpoint.hpp"
// END changed --
#include <vector>
#include <string>
//! The main namespace in which the Triangle++ project lives
namespace tpp {
// (mrkkrj)
enum DebugOutputLevel {
None,
Info, // most useful; it gives information on algorithmic progress and much more detailed statistics
Vertex, // gives vertex-by-vertex details, and prints so much that Triangle runs much more slowly
Debug // gives information only a debugger could love
};
//! The main Delaunay Class that wraps around Triangle.
/*!
This is a C++ wrapper of the Triangle package by JRS.
This class currently uses the dpoint class written by me (the point class is a d-dimensional point
class reviver::dpoint (but for this application it only uses the d=2 case).
Additionally, the inner helper C++ class Triwrap groups the original Triangle's C functions.
\author Piyush Kumar, mrkkrj
\note (mrkkrj) For for backgroud info on the Triangle's implementation see "Triangle:
Engineering a 2D Quality Mesh Generator and Delaunay Triangulator" by JP Shewchuk:
www.cs.cmu.edu/~quake-papers/triangle.ps
*/
class Delaunay {
public:
//! Point Typedef
/*! Warning: If you want to use your own point class, you might have to
work hard...
- mrkkrj: true!!! - spare your time, use an adapter class.
*/
typedef reviver::dpoint <double, 2> Point;
//! The main constructor.
/*!
Takes a vector of 2 dimensional points where each of the coordinates is
expressed as double.
*/
Delaunay(const std::vector<Point>& points);
//! The main destructor.
/*!
Does memory cleanup mostly.
*/
~Delaunay();
//! Delaunay Triangulate the input points (Quality)
/*!
This function calls Triangle.h to Delaunay-triangulate points given as input to the
constructor of this class. Here a Quality triangualtion will be created.
\param quality enforce minimal angle (default: 20°) and, minimal area (only if explicitely set)
*/
void Triangulate(bool quality = false, DebugOutputLevel = None);
//! Delaunay Triangulate the input points (Conforming)
/*!
This function calls Triangle.h to Delaunay-triangulate points given as input to the
constructor of this class. Here a Conforming triangualtion will be created.
*/
void TriangulateConf(bool quality = false, DebugOutputLevel = None);
//! Voronoi-tesselate the input points (added mrkkrj)
/*!
This function calls triangle to create a Voronoi diagram with points given as input
to the constructor of this class.
Note that a Voronoi diagram can be only created if the underlying triangulation is convex
and doesn't have holes!
\param useConformingDelaunay use conforming Delaunay triangulation as base for the Voronoi diagram
*/
void Tesselate(bool useConformingDelaunay = false, DebugOutputLevel traceLvl = None);
//! Set a quality constraint for the triangulation
/*!
\param angle min. resulting angle, if angle <= 0, the constraint will be removed.
*/
void setMinAngle(float angle) {
m_minAngle = angle;
}
//! Set a quality constraint for the triangulation
/*!
\param area max. triangle area, if area <= 0, the constraint will be removed.
*/
void setMaxArea(float area) {
m_maxArea = area;
}
//! Set the segments to constrain the triangulation
/*!
Takes a vector of 2 dimensional points where each consecutive pair of points describes a single segment.
Both endpoints of every segment are vertices of the input vector, and a segment may intersect other segments
and vertices only at its endpoints.
\return true if the input is valid, false otherwise
*/
bool setSegmentConstraint(const std::vector<Point>& segments);
//! Set the segments to constrain the triangulation
/*!
Same as above, but usign indexes of the input points!
\return true if the input is valid, false otherwise
*/
bool setSegmentConstraint(const std::vector<int>& segmentPointIndexes);
//! Set the holes to constrain the triangulation
/*!
Takes a vector of 2 dimensional points where each consecutive pair of points describes a single edge of a hole.
\return true if the input is valid, false otherwise
*/
bool setHolesConstraint(const std::vector<Point>& holes);
//! Are the quality constrainst sane?
/*!
\possible true if is highly probable for triangualtion to succeed
\return true if triangualtion is guaranteed to succeed
*/
bool checkConstraints(bool& possible) const;
//! Are the quality constrainst sane, take two
/*!
\relaxed report highly probable as correct too, as error otherwise
\return true if triangualtion is guaranteed to succeed, or at least higly probable to
*/
bool checkConstraintsOpt(bool relaxed) const;
//! Get minAngle intervals
/*!
\guaranteed up to this value triangualtion is guaranteed to succeed
\possible up to this value it is highly probable for triangualtion to succeed
*/
static void getMinAngleBoundaries(float& guaranteed, float& possible);
//! Set a user test function for the triangulation
/*!
OPEN TODO::: (use the -u switch!!!!)
*/
void setUserConstraint(bool (*f)()) {};
//! Output a geomview .off file containing the delaunay triangulation
/*!
\param fname output file name.
*/
void writeoff(std::string& fname);
//! Number of edges in the triangulation
/*!
\return Number of Edges
Remember to call Triangulate before using this function.
*/
int nedges() const;
//! Number of triangles in the triangulation
/*!
\return Number of Triangles
Remember to call Triangulate before using this function.
*/
int ntriangles() const;
//! Number of vertices in the triangulation
/*!
\return Number of Vertices
Remember to call Triangulate before using this function.
*/
int nvertices() const;
//! Number of vertices on the convex hull.
/*!
\return Number of vertices on the convex hull.
Remember to call Triangulate before using this function.
*/
int hull_size() const;
//! Number of Voronoi points in the tesselation
/*!
\return Number of Points
Remember to call Tesselate before using this function.
*/
int nvpoints() const;
//! Number of Voronoi edges in the tesselation
/*!
\return Number of Edges
Remember to call Tesselate before using this function.
*/
int nvedges() const;
///////////////////////////////
//
// Vertex Iterator
//
///////////////////////////////
//! The vertex iterator for the Delaunay class
class vIterator {
private:
vIterator(Delaunay* tiangulator); //! To set container
Delaunay* MyDelaunay; //! Which container do I point
void* vloop; //! Triangles Internal data.
public:
vIterator operator++();
vIterator() :vloop(nullptr) {};
Point& operator*() const;
~vIterator();
friend class Delaunay;
friend bool operator==(vIterator const&, vIterator const&);
friend bool operator!=(vIterator const&, vIterator const&);
};
//! Vertex iterator begin function
vIterator vbegin() { return vIterator(this); };
//! Vertex iterator end function
vIterator vend();
//! Given an iterator, find its index in the input vector of points.
int vertexId(vIterator const& vit) const;
//! Given an index, return the actual double Point
const Point& point_at_vertex_id(int i) { return m_PList[i]; };
//! Return the Point additionally created in quality mesh generation ("q" option)
Point added_point_at_vertex_id(int i);
friend class vIterator;
///////////////////////////////
//
// Face Iterator
//
///////////////////////////////
//! The face iterator for the Delaunay class
class fIterator {
private:
struct tdata {
double*** tri;
int orient;
};
typedef struct tdata poface;
fIterator(Delaunay* tiangulator); //! To set container
Delaunay* MyDelaunay; //! Which container do I point
//void *floop; //! Triangles Internal data.
poface floop;
public:
void operator++();
fIterator() { floop.tri = nullptr; };
~fIterator();
friend class Delaunay;
friend bool operator==(fIterator const&, fIterator const&);
friend bool operator!=(fIterator const&, fIterator const&);
friend bool operator<(fIterator const&, fIterator const&); // added mrkkrj
};
//! Face iterator begin function
fIterator fbegin() { return fIterator(this); };
//! Face iterator end function
fIterator fend();
int faceId(fIterator const&);
//! Access the origin (Org) vertex of a face.
/*!
\param fit Face interator.
\param point if specified: the cordinates of the vertex
\return Index of the vertex in m_pList,
or -1 if quality option was used and a new vertex was created!
A triangle abc has origin (org) a,destination (dest) b, and apex (apex)
c. These vertices occur in counterclockwise order about the triangle.
Remember to call Triangulate before using this function. Do not use it on a null iterator.
*/
int Org(fIterator const& fit, Point* point = 0);
//! Access the destination (Dest) vertex of a face.
/*!
\param fit Face interator.
\param point if specified: the cordinates of the vertex
\return Index of the vertex in m_pList,
or -1 if quality option was used and a new vertex was created!
A triangle abc has origin (org) a,destination (dest) b, and apex (apex)
c. These vertices occur in counterclockwise order about the triangle.
Remember to call Triangulate before using this function. Do not use it on a null iterator.
*/
int Dest(fIterator const& fit, Point* point = 0);
//! Access the apex (Apex) vertex of a face.
/*!
\param fit Face interator.
\param point if specified: the cordinates of the vertex
\return Index of the vertex in m_pList,
or -1 if quality option was used and a new vertex was created!
A triangle abc has origin (org) a,destination (dest) b, and apex (apex)
c. These vertices occur in counterclockwise order about the triangle.
Remember to call Triangulate before using this function. Do not use it on a null iterator.
*/
int Apex(fIterator const& fit, Point* point = 0);
//! Access the triangle adjoining edge i
/*!
\param fit Face Iterator
\param i edge number
\return The vertex on the opposite face, or -1 (see Org() above)
A triangle abc has origin (org) a,destination (dest) b, and apex (apex)
c. These vertices occur in counterclockwise order about the triangle.
<ul>
<li>sym(abc, 0) -> ba*</li>
<li>sym(abc, 1) -> cb*</li>
<li>sym(abc, 2) -> ac*</li>
</ul>
* is the farthest vertex on the adjoining triangle whose index
is returned. A -1 is returned if the edge is part of the convex hull.
Remember to call Triangulate before using this function.
Do not use it on a null iterator.
*/
int Sym(fIterator const& fit, char i);
//! Access the triangle opposite to current edge of the face
/*!
\param fit Face iterator
\return The iterator of the opposite face
A triangle abc has origin (org) a,destination (dest) b, and apex (apex)
c. These vertices occur in counterclockwise order about the triangle.
The iterator
to the triangle is returned. The iterator is empty if the edge
is on the convex hull.
Remember to call Triangulate before using this function.
Do not use it on a null iterator.
*/
fIterator Sym(fIterator const& fit);
//! Is the iterator empty?
/*!
\param fit Face interator.
\return true if the iterator is empty
*/
inline bool empty(fIterator const& fit)
{
return fit.floop.tri == nullptr;
};
//! Is the iterator pointing to the dummy triangle?
/*!
\param fit Face interator.
\return true if the iterator is of the dummy triangle.
*/
bool isdummy(fIterator const& fit);
//! Find the next edge (counterclockwise) of a triangle.
/*!
\param fit face iterator
\return The face iterator corresponding to the next counterclockwise edge of a triangle
Lnext(abc) -> bca.
Remember to call Triangulate before using this function.
Do not use it on a null iterator.
*/
fIterator Lnext(fIterator const& fit);
//! Find the previous edge (clockwise) of a triangle.
/*!
\param fit face iterator
\return The face iterator corresponding to the previous clockwise edge of a triangle
Lprev(abc) -> cab.
Remember to call Triangulate before using this function.
Do not use it on a null iterator.
*/
fIterator Lprev(fIterator const& fit);
//! Find the next edge (counterclockwise) of a triangle with the same origin
/*!
\param fit face iterator
\return The face iterator corresponding to the next edge counterclockwise with the same origin.
Onext(abc) -> ac*.
Remember to call Triangulate before using this function.
Do not use it on a null iterator.
*/
fIterator Onext(fIterator const& fit);
//! Find the next edge clockwise with the same origin.
/*!
\param fit face iterator
\return The face iterator corresponding to the next edge clockwise with the same origin.
Onext(abc) -> a*b.
Remember to call Triangulate before using this function.
Do not use it on a null iterator.
*/
fIterator Oprev(fIterator const& fit);
// TODO List: (for face iterators)
/* dnext: Find the next edge counterclockwise with the same destination. */
/* dnext(abc) -> *ba */
/* */
/* dprev: Find the next edge clockwise with the same destination. */
/* dprev(abc) -> cb* */
/* */
/* rnext: Find the next edge (counterclockwise) of the adjacent triangle. */
/* rnext(abc) -> *a* */
/* */
/* rprev: Find the previous edge (clockwise) of the adjacent triangle. */
/* rprev(abc) -> b** */
//! Calculate incident triangles around a vertex.
/*!
\param vertexid The vertex for which you want incident triangles.
\param ivv Returns triangles around a vertex in counterclockwise order.
Note that behaviour is undefined if vertexid is greater than
number of vertices - 1. Remember to call Triangulate before using this function.
All triangles returned have Org(triangle) = vertexid.
All triangles returned are in counterclockwise order.
*/
void trianglesAroundVertex(int vertexid, std::vector<int>& ivv);
//! Calculate the area of a face.
/*!
\param fit Face interator.
\return area of the face associated with the iterator.
*/
double area(fIterator const& fit);
//! Point locate a vertex v
/*!
\param vertexid vertex id
\return a face iterator whose origin is v.
*/
fIterator locate(int vertexid); // OPEN:: doesn't seem to be working!
///////////////////////////////
//
// Voronoi Points Iterator
// (added mrkkrj)
//
///////////////////////////////
//! The Voronoi points iterator for the Delaunay class
class vvIterator {
public:
vvIterator();
vvIterator operator++();
Point& operator*() const;
void advance(int steps);
private:
vvIterator(Delaunay* tiangulator); //! To set container
Delaunay* m_delaunay; //! Which container do I point to
void* vvloop; //! Triangle's Internal data.
int vvindex;
int vvcount;
friend class Delaunay;
friend bool operator==(vvIterator const&, vvIterator const&);
friend bool operator!=(vvIterator const&, vvIterator const&);
};
//! Voronoi Points iterator begin function
vvIterator vvbegin() { return vvIterator(this); };
//! Voronoi Points iterator end function
vvIterator vvend();
///////////////////////////////
//
// Voronoi Edges Iterator
// (added mrkkrj)
//
///////////////////////////////
//! The Voronoi edges iterator for the Delaunay class
class veIterator {
public:
veIterator();
veIterator operator++();
int startPointId() const;
int endPointId(Point& normvec) const;
private:
veIterator(Delaunay* tiangulator); //! To set container
Delaunay* m_delaunay; //! Which container do I point to
void* veloop; //! Triangle's Internal data.
int veindex;
int vecount;
friend class Delaunay;
friend bool operator==(veIterator const&, veIterator const&);
friend bool operator!=(veIterator const&, veIterator const&);
};
//! Voronoi Points iterator begin function
veIterator vebegin() { return veIterator(this); };
//! Voronoi Points iterator end function
veIterator veend();
//! Access the origin (Org) vertex of an edge. (added mrkkrj)
/*!
\param eit Voronoi Edge iterator.
\return The start point of the Voronoi edge,
Remember to call Tesselate before using this function. Do not use it on a null iterator.
*/
const Point& Org(veIterator const& eit);
//! Access the destination (Dest) vertex of an edge. (added mrkkrj)
/*!
\param eit Voronoi Edge iterator.
\param finiteEdge true for finite edges, false for inifinte rays.
\return The end point of the Voronoi edge, for infinite rays the normal vector of the ray
Remember to call Tesselate before using this function. Do not use it on a null iterator.
*/
Point Dest(veIterator const& eit, bool& finiteEdge);
//--------------------------------------
// added mrkkrj - helper for Points
// OPEN:: compiler cannot instantiate less<> with operator<() for Point, why?!
//--------------------------------------
struct OrderPoints
{
bool operator() (const Point& lhs, const Point& rhs) const {
// first sort on x, then on y coordinates
if (lhs[0] < rhs[0]) {
return true;
}
if (lhs[0] == rhs[0] && lhs[1] < rhs[1]) {
return true;
}
return false;
}
};
//////////////////////////////////////////////////////////////////////////////////////////////
std::vector< Delaunay::Point> MyVertexTraverse( ) ;
std::vector< int> Delaunay::MyTriangleTraverse( ) ;
//////////////////////////////////////////////////////////////////////////////////////////////
private:
void Triangulate(std::string& triswitches);
// added mrkkrj - helper functions for face iterator access methods
// HACK:: double* as not to export internal impl.
void SetPoint(Point& point, double* vertexptr);
int GetVertexIndex(fIterator const& fit, double* vertexptr);
int GetFirstIndexNumber() const;
// added mrkkrj
std::string formatFloatConstraint(float f) const;
void setDebugLevelOption(std::string& options, DebugOutputLevel traceLvl);
void freeTriangleDataStructs();
friend class fIterator;
private:
std::vector<Point> m_PList; /*! Stores the input point list. */
void* m_in; /*! Used for intput to triangle */
void* m_triangleWrap; /*! Triangle impl. is wrapped in this pointer. */
void* m_pmesh; /*! pointer to triangle mesh */
void* m_pbehavior;
bool m_Triangulated;
// added mrkkrj:
void* m_vorout; /*! pointer to Voronoi output */
// added mrkkrj: quality constraints
float m_minAngle;
float m_maxArea;
// added mrkkrj: segment constraints
std::vector<int> m_SList;
// added mrkkrj: holes
std::vector<Point> m_HList;
}; // Class Delaunay
} // namespace tpp ends.
#endif
+300
View File
@@ -0,0 +1,300 @@
/*! \file triangle.h
\brief Original Triangle package's include file.
Exports triangulateio structure for use in tpp_impl.hpp. You should not
use struct triangulateio in your application if you are using Triangle++
wrapper!
*/
/*****************************************************************************/
/* */
/* (triangle.h) */
/* */
/* Include file for programs that call Triangle. */
/* */
/* Accompanies Triangle Version 1.6 */
/* July 28, 2005 */
/* */
/* Copyright 1996, 2005 */
/* Jonathan Richard Shewchuk */
/* 2360 Woolsey #H */
/* Berkeley, California 94705-1927 */
/* jrs@cs.berkeley.edu */
/* */
/*****************************************************************************/
/*****************************************************************************/
/* */
/* How to call Triangle from another program */
/* */
/* */
/* If you haven't read Triangle's instructions (run "triangle -h" to read */
/* them), you won't understand what follows. */
/* */
/* Triangle must be compiled into an object file (triangle.o) with the */
/* TRILIBRARY symbol defined (generally by using the -DTRILIBRARY compiler */
/* switch). The makefile included with Triangle will do this for you if */
/* you run "make trilibrary". The resulting object file can be called via */
/* the procedure triangulate(). */
/* */
/* If the size of the object file is important to you, you may wish to */
/* generate a reduced version of triangle.o. The REDUCED symbol gets rid */
/* of all features that are primarily of research interest. Specifically, */
/* the -DREDUCED switch eliminates Triangle's -i, -F, -s, and -C switches. */
/* The CDT_ONLY symbol gets rid of all meshing algorithms above and beyond */
/* constrained Delaunay triangulation. Specifically, the -DCDT_ONLY switch */
/* eliminates Triangle's -r, -q, -a, -u, -D, -Y, -S, and -s switches. */
/* */
/* IMPORTANT: These definitions (TRILIBRARY, REDUCED, CDT_ONLY) must be */
/* made in the makefile or in triangle.c itself. Putting these definitions */
/* in this file (triangle.h) will not create the desired effect. */
/* */
/* */
/* The calling convention for triangulate() follows. */
/* */
/* void triangulate(triswitches, in, out, vorout) */
/* char *triswitches; */
/* struct triangulateio *in; */
/* struct triangulateio *out; */
/* struct triangulateio *vorout; */
/* */
/* `triswitches' is a string containing the command line switches you wish */
/* to invoke. No initial dash is required. Some suggestions: */
/* */
/* - You'll probably find it convenient to use the `z' switch so that */
/* points (and other items) are numbered from zero. This simplifies */
/* indexing, because the first item of any type always starts at index */
/* [0] of the corresponding array, whether that item's number is zero or */
/* one. */
/* - You'll probably want to use the `Q' (quiet) switch in your final code, */
/* but you can take advantage of Triangle's printed output (including the */
/* `V' switch) while debugging. */
/* - If you are not using the `q', `a', `u', `D', `j', or `s' switches, */
/* then the output points will be identical to the input points, except */
/* possibly for the boundary markers. If you don't need the boundary */
/* markers, you should use the `N' (no nodes output) switch to save */
/* memory. (If you do need boundary markers, but need to save memory, a */
/* good nasty trick is to set out->pointlist equal to in->pointlist */
/* before calling triangulate(), so that Triangle overwrites the input */
/* points with identical copies.) */
/* - The `I' (no iteration numbers) and `g' (.off file output) switches */
/* have no effect when Triangle is compiled with TRILIBRARY defined. */
/* */
/* `in', `out', and `vorout' are descriptions of the input, the output, */
/* and the Voronoi output. If the `v' (Voronoi output) switch is not used, */
/* `vorout' may be NULL. `in' and `out' may never be NULL. */
/* */
/* Certain fields of the input and output structures must be initialized, */
/* as described below. */
/* */
/*****************************************************************************/
/*****************************************************************************/
/* */
/* The `triangulateio' structure. */
/* */
/* Used to pass data into and out of the triangulate() procedure. */
/* */
/* */
/* Arrays are used to store points, triangles, markers, and so forth. In */
/* all cases, the first item in any array is stored starting at index [0]. */
/* However, that item is item number `1' unless the `z' switch is used, in */
/* which case it is item number `0'. Hence, you may find it easier to */
/* index points (and triangles in the neighbor list) if you use the `z' */
/* switch. Unless, of course, you're calling Triangle from a Fortran */
/* program. */
/* */
/* Description of fields (except the `numberof' fields, which are obvious): */
/* */
/* `pointlist': An array of point coordinates. The first point's x */
/* coordinate is at index [0] and its y coordinate at index [1], followed */
/* by the coordinates of the remaining points. Each point occupies two */
/* REALs. */
/* `pointattributelist': An array of point attributes. Each point's */
/* attributes occupy `numberofpointattributes' REALs. */
/* `pointmarkerlist': An array of point markers; one int per point. */
/* */
/* `trianglelist': An array of triangle corners. The first triangle's */
/* first corner is at index [0], followed by its other two corners in */
/* counterclockwise order, followed by any other nodes if the triangle */
/* represents a nonlinear element. Each triangle occupies */
/* `numberofcorners' ints. */
/* `triangleattributelist': An array of triangle attributes. Each */
/* triangle's attributes occupy `numberoftriangleattributes' REALs. */
/* `trianglearealist': An array of triangle area constraints; one REAL per */
/* triangle. Input only. */
/* `neighborlist': An array of triangle neighbors; three ints per */
/* triangle. Output only. */
/* */
/* `segmentlist': An array of segment endpoints. The first segment's */
/* endpoints are at indices [0] and [1], followed by the remaining */
/* segments. Two ints per segment. */
/* `segmentmarkerlist': An array of segment markers; one int per segment. */
/* */
/* `holelist': An array of holes. The first hole's x and y coordinates */
/* are at indices [0] and [1], followed by the remaining holes. Two */
/* REALs per hole. Input only, although the pointer is copied to the */
/* output structure for your convenience. */
/* */
/* `regionlist': An array of regional attributes and area constraints. */
/* The first constraint's x and y coordinates are at indices [0] and [1], */
/* followed by the regional attribute at index [2], followed by the */
/* maximum area at index [3], followed by the remaining area constraints. */
/* Four REALs per area constraint. Note that each regional attribute is */
/* used only if you select the `A' switch, and each area constraint is */
/* used only if you select the `a' switch (with no number following), but */
/* omitting one of these switches does not change the memory layout. */
/* Input only, although the pointer is copied to the output structure for */
/* your convenience. */
/* */
/* `edgelist': An array of edge endpoints. The first edge's endpoints are */
/* at indices [0] and [1], followed by the remaining edges. Two ints per */
/* edge. Output only. */
/* `edgemarkerlist': An array of edge markers; one int per edge. Output */
/* only. */
/* `normlist': An array of normal vectors, used for infinite rays in */
/* Voronoi diagrams. The first normal vector's x and y magnitudes are */
/* at indices [0] and [1], followed by the remaining vectors. For each */
/* finite edge in a Voronoi diagram, the normal vector written is the */
/* zero vector. Two REALs per edge. Output only. */
/* */
/* */
/* Any input fields that Triangle will examine must be initialized. */
/* Furthermore, for each output array that Triangle will write to, you */
/* must either provide space by setting the appropriate pointer to point */
/* to the space you want the data written to, or you must initialize the */
/* pointer to NULL, which tells Triangle to allocate space for the results. */
/* The latter option is preferable, because Triangle always knows exactly */
/* how much space to allocate. The former option is provided mainly for */
/* people who need to call Triangle from Fortran code, though it also makes */
/* possible some nasty space-saving tricks, like writing the output to the */
/* same arrays as the input. */
/* */
/* Triangle will not free() any input or output arrays, including those it */
/* allocates itself; that's up to you. You should free arrays allocated by */
/* Triangle by calling the trifree() procedure defined below. (By default, */
/* trifree() just calls the standard free() library procedure, but */
/* applications that call triangulate() may replace trimalloc() and */
/* trifree() in triangle.c to use specialized memory allocators.) */
/* */
/* Here's a guide to help you decide which fields you must initialize */
/* before you call triangulate(). */
/* */
/* `in': */
/* */
/* - `pointlist' must always point to a list of points; `numberofpoints' */
/* and `numberofpointattributes' must be properly set. */
/* `pointmarkerlist' must either be set to NULL (in which case all */
/* markers default to zero), or must point to a list of markers. If */
/* `numberofpointattributes' is not zero, `pointattributelist' must */
/* point to a list of point attributes. */
/* - If the `r' switch is used, `trianglelist' must point to a list of */
/* triangles, and `numberoftriangles', `numberofcorners', and */
/* `numberoftriangleattributes' must be properly set. If */
/* `numberoftriangleattributes' is not zero, `triangleattributelist' */
/* must point to a list of triangle attributes. If the `a' switch is */
/* used (with no number following), `trianglearealist' must point to a */
/* list of triangle area constraints. `neighborlist' may be ignored. */
/* - If the `p' switch is used, `segmentlist' must point to a list of */
/* segments, `numberofsegments' must be properly set, and */
/* `segmentmarkerlist' must either be set to NULL (in which case all */
/* markers default to zero), or must point to a list of markers. */
/* - If the `p' switch is used without the `r' switch, then */
/* `numberofholes' and `numberofregions' must be properly set. If */
/* `numberofholes' is not zero, `holelist' must point to a list of */
/* holes. If `numberofregions' is not zero, `regionlist' must point to */
/* a list of region constraints. */
/* - If the `p' switch is used, `holelist', `numberofholes', */
/* `regionlist', and `numberofregions' is copied to `out'. (You can */
/* nonetheless get away with not initializing them if the `r' switch is */
/* used.) */
/* - `edgelist', `edgemarkerlist', `normlist', and `numberofedges' may be */
/* ignored. */
/* */
/* `out': */
/* */
/* - `pointlist' must be initialized (NULL or pointing to memory) unless */
/* the `N' switch is used. `pointmarkerlist' must be initialized */
/* unless the `N' or `B' switch is used. If `N' is not used and */
/* `in->numberofpointattributes' is not zero, `pointattributelist' must */
/* be initialized. */
/* - `trianglelist' must be initialized unless the `E' switch is used. */
/* `neighborlist' must be initialized if the `n' switch is used. If */
/* the `E' switch is not used and (`in->numberofelementattributes' is */
/* not zero or the `A' switch is used), `elementattributelist' must be */
/* initialized. `trianglearealist' may be ignored. */
/* - `segmentlist' must be initialized if the `p' or `c' switch is used, */
/* and the `P' switch is not used. `segmentmarkerlist' must also be */
/* initialized under these circumstances unless the `B' switch is used. */
/* - `edgelist' must be initialized if the `e' switch is used. */
/* `edgemarkerlist' must be initialized if the `e' switch is used and */
/* the `B' switch is not. */
/* - `holelist', `regionlist', `normlist', and all scalars may be ignored.*/
/* */
/* `vorout' (only needed if `v' switch is used): */
/* */
/* - `pointlist' must be initialized. If `in->numberofpointattributes' */
/* is not zero, `pointattributelist' must be initialized. */
/* `pointmarkerlist' may be ignored. */
/* - `edgelist' and `normlist' must both be initialized. */
/* `edgemarkerlist' may be ignored. */
/* - Everything else may be ignored. */
/* */
/* After a call to triangulate(), the valid fields of `out' and `vorout' */
/* will depend, in an obvious way, on the choice of switches used. Note */
/* that when the `p' switch is used, the pointers `holelist' and */
/* `regionlist' are copied from `in' to `out', but no new space is */
/* allocated; be careful that you don't free() the same array twice. On */
/* the other hand, Triangle will never copy the `pointlist' pointer (or any */
/* others); new space is allocated for `out->pointlist', or if the `N' */
/* switch is used, `out->pointlist' remains uninitialized. */
/* */
/* All of the meaningful `numberof' fields will be properly set; for */
/* instance, `numberofedges' will represent the number of edges in the */
/* triangulation whether or not the edges were written. If segments are */
/* not used, `numberofsegments' will indicate the number of boundary edges. */
/* */
/*****************************************************************************/
struct triangulateio {
REAL *pointlist; /* In / out */
REAL *pointattributelist; /* In / out */
int *pointmarkerlist; /* In / out */
int numberofpoints; /* In / out */
int numberofpointattributes; /* In / out */
int *trianglelist; /* In / out */
REAL *triangleattributelist; /* In / out */
REAL *trianglearealist; /* In only */
int *neighborlist; /* Out only */
int numberoftriangles; /* In / out */
int numberofcorners; /* In / out */
int numberoftriangleattributes; /* In / out */
int *segmentlist; /* In / out */
int *segmentmarkerlist; /* In / out */
int numberofsegments; /* In / out */
REAL *holelist; /* In / pointer to array copied out */
int numberofholes; /* In / copied out */
REAL *regionlist; /* In / pointer to array copied out */
int numberofregions; /* In / copied out */
int *edgelist; /* Out only */
int *edgemarkerlist; /* Not used with Voronoi diagram; out only */
REAL *normlist; /* Used only with Voronoi diagram; out only */
int numberofedges; /* Out only */
};
#ifdef ANSI_DECLARATORS
void triangulate(char *, struct triangulateio *, struct triangulateio *,
struct triangulateio *);
void trifree(VOID *memptr);
#else /* not ANSI_DECLARATORS */
void triangulate();
void trifree();
#endif /* not ANSI_DECLARATORS */
+16198
View File
File diff suppressed because it is too large Load Diff