Compare commits

..

42 Commits

Author SHA1 Message Date
LorenzoM 29138a8a0b Tolti commenti inutili e sistemata interfaccia 2022-01-21 12:50:34 +01:00
LorenzoM 99b503a637 Migliorie vm additivo 2022-01-20 13:09:53 +01:00
LorenzoM acad826499 CorrettiErrori/LineeDiTest 2022-01-18 18:09:21 +01:00
LorenzoM 2f4d75b958 Correzioni/UtensileSferico/NB:CiSonoLineePerTest 2022-01-18 13:07:48 +01:00
LorenzoM 7e2bf848a9 Correzione errori vm 2022-01-14 18:05:04 +01:00
LorenzoM 4f62467320 Corretti errori vm additivo 2022-01-14 17:54:51 +01:00
LorenzoM 78d4d79cbf Aggiunto utensile additivo generico 2022-01-14 13:19:06 +01:00
LorenzoM 1c8ee6a332 Correzione errori vm additivo 2022-01-13 17:55:39 +01:00
LorenzoM e4b5e4c0a9 Correzioni vmill 2022-01-12 17:26:54 +01:00
LorenzoM 6f60e2d711 Correzione errori vmill additivo 2022-01-11 16:51:54 +01:00
LorenzoM 20a9efaebb Modifiche vm additivo 2022-01-10 18:27:41 +01:00
LorenzoM fd9a6a9847 Merge commit '8710115634c9be74c0a8ead37b0bb32144f84b96' into TempForVmill 2022-01-10 10:17:58 +01:00
LorenzoM c773b8829e Correzione errori 2022-01-10 10:00:38 +01:00
DarioS 8710115634 EgtGeomKernel :
- inserita opzione in compilazioni 64bit per evitare Warning su verifica riferimenti non nulli.
2022-01-09 15:49:58 +01:00
DarioS 4056be90d9 EgtGeomKernel 2.4a3 :
- modifiche a IntersLineBox e IntersPlaneBox
- adattamenti conseguenti.
2022-01-09 15:17:00 +01:00
DarioS 77640f3a6f EgtGeomKernel :
- migliorie a RemoveTJunctions di SurfTriMesh.
2022-01-07 17:13:16 +01:00
DarioS 9b11212d07 EgtGeomKernel 2.4a2 :
- in TriMesh eliminata ResetFaceting e UpdateFaceting ora cerca di ricostruire facce con indice come le eventuali precedenti
- in Trimesh SimplifyFacets cerca di conservare l'identificativo di faccia nei nuovi triangoli
- in Trimesh aggiunta funzione Repair e migliorata SimplifyFacets
- in Trimesh al termine di CutWithOtherSurf si cerca di regolarizzare il risultato.
2022-01-07 10:00:19 +01:00
LorenzoM 2ea8812f52 Recuperato da branch LorenzoM file VolZmap + tool 2022-01-05 18:29:08 +01:00
LorenzoM e2ae42a045 prova 2022-01-05 17:46:51 +01:00
DarioS 41d76f0c3f EgtGeomKernel 2.4a1 :
- migliorie alle booleane delle superfici trimesh.
2022-01-04 08:03:15 +01:00
DarioS d2b77833fd EgtGeomKernel 2.3l3 :
- altre modifiche per triangolazioni.
2021-12-23 15:44:49 +01:00
LorenzoM 9ac1a56535 Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2021-12-23 09:23:38 +01:00
LorenzoM 9aca1f1e25 Migliorie trimesh 2021-12-23 09:22:25 +01:00
DarioS e3c10e9bd3 EgtGeomKernel 2.3l2 :
- aggiunta triangolazione mediante earcut di mapbox
- piccola modifica a calcoli preliminari per triangolazione standard.
2021-12-18 22:50:02 +01:00
LorenzoM e84a34917a Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel 2021-12-07 10:04:33 +01:00
LorenzoM 009328b31b Migliorie operazioni booleane e intersezione triangoli 2021-12-07 09:43:59 +01:00
DarioS ca83aaa249 EgtGeomKernel 2.3l1 :
- in IntersTriaTria aggiunto riconoscimento triangoli coincidenti
- in IntersTriaTria aggiunta distinzione tra intersezione sovrapposta equiversa e controversa.
2021-12-06 16:47:36 +01:00
DarioS 6cdfdf6db8 EgtGeomKernel 2.3k6 :
- dopo tagli e tagli generalizzati lunghezza minima per SimplfyFacets portata da 500 a 5000 per evitare problemi di adiacenza non trovata tra facce.
2021-11-25 14:47:03 +01:00
DarioS 6628b1ee24 EgtGeomKernel 2.3k5 :
- correzione in RemoveTriangle di TriMesh (controllo validità indice vertice).
2021-11-22 22:56:13 +01:00
DarioS 2d70d27d85 EgtGeomKernel 2.3k4 :
- piccole modifiche estetiche e cambio versione.
2021-11-14 12:32:28 +01:00
LorenzoM 63d62fcc92 Gestione tagli piccoli 2021-11-10 15:39:33 +01:00
LorenzoM b4303d0e0d Gestione dei triangoli giacenti sui rettangoli 2021-11-09 10:53:32 +01:00
DarioS 9369447886 EgtGeomKernel :
- altre migliorie a GeneralizedCut di SurfTriMesh.
2021-11-07 17:17:54 +01:00
DarioS dca713b240 EgtGeomKernel 2.3k3 :
- modifiche per GeneralizedCut di SurfTriMesh
- Cut e GeneralizedCut di SurfTriMesh spostati in nuovo sorgente SurfTriMeshCuts.cpp.
2021-11-07 12:57:53 +01:00
DarioS aa82c82ddc EgtGeomKernel 2.3k2 :
- corretta SurfTriMesh::SimplifyFacets.
2021-11-04 10:03:35 +01:00
DarioS 8a6dbf044e EgtGeomKernel :
- piccole modifiche in Cut e GeneralizedCut per eseguire il più possibile SimplfyFacet.
2021-11-03 13:30:26 +01:00
DarioS 76d009ddbe EgtGeomKernel 2.3k1 :
- corretto offset di segmenti di retta singoli con estrusione
- modifiche per calcolo taglio superfici TriMesh
- modifiche a funzione SimplifyFacets di superfici TriMesh.
2021-11-02 08:19:11 +01:00
LorenzoM 6deff01b6e Modifiche generalized cut 2021-10-29 17:17:51 +02:00
LorenzoM e79bb117d2 Pulizia codice simplify facet 2021-10-27 17:53:12 +02:00
LorenzoM 2ea4b59b9b Aggiunta funzione FimplifyFacets in TriMesh 2021-10-26 18:11:58 +02:00
DarioS 6e9465247f EgtGeomKernel 2.3j1 :
- diemnticato un file.
2021-10-24 18:00:00 +02:00
DarioS 1d1fb41212 EgtGeomKernel 2.3j :
- modifiche a SurfTriMesh::Cut (più semplice abilitare calcolo con facce invece di triangoli)
- ora CurveClassification (di Regioni e Curve) ricevono anche il parametro dMinLen.
2021-10-24 17:57:53 +02:00
47 changed files with 4338 additions and 23680 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 ;
+4 -3
View File
@@ -30,6 +30,7 @@
#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>
@@ -1321,8 +1322,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 a 10 * Epsilon
if ( ! ApproxWithLines( 10 * EPS_SMALL, dAngTolDeg, APL_SPECIAL, PL))
// prima approssimazione lineare alla tolleranza minima del programma
if ( ! ApproxWithLines( 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) ;
@@ -3134,7 +3135,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, ccClass))
if ( ! pSfrCut->GetCurveClassification( *pOutLoop, EPS_SMALL, ccClass))
return false ;
// determino gli intervalli di curva da conservare
Intervals inOk ;
+10 -11
View File
@@ -23,33 +23,30 @@
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 ;
vApproxMin.reserve( 4) ;
vApproxMin.clear() ;
double dUIni, dUFin ;
Point3d ptIni, ptFin ;
double dMinDist, dSqMinDist ;
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 ;
@@ -66,8 +63,10 @@ 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.
+6 -7
View File
@@ -151,6 +151,7 @@ copy $(TargetPath) \EgtProg\DllD32</Command>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -243,6 +244,7 @@ copy $(TargetPath) \EgtProg\Dll32</Command>
<WholeProgramOptimization>false</WholeProgramOptimization>
<DebugInformationFormat>None</DebugInformationFormat>
<LanguageStandard>stdcpp17</LanguageStandard>
<AdditionalOptions>-Wno-tautological-undefined-compare</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -392,10 +394,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" />
@@ -559,7 +561,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClInclude Include="DistPointCrvComposite.h" />
<ClInclude Include="DistPointLine.h" />
<ClInclude Include="DllMain.h" />
<ClInclude Include="dpoint.hpp" />
<ClInclude Include="earcut.hpp" />
<ClInclude Include="ExtDimension.h" />
<ClInclude Include="ExtText.h" />
<ClInclude Include="FontAux.h" />
@@ -588,6 +590,7 @@ 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" />
@@ -607,10 +610,6 @@ 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" />
+6 -15
View File
@@ -453,11 +453,11 @@
<ClCompile Include="CDeRectPrismoidTria.cpp">
<Filter>File di origine\GeoCollision</Filter>
</ClCompile>
<ClCompile Include="tpp_assert.cpp">
<Filter>File di origine</Filter>
<ClCompile Include="SurfTriMeshUtilities.cpp">
<Filter>File di origine\Geo</Filter>
</ClCompile>
<ClCompile Include="tpp_impl.cpp">
<Filter>File di origine</Filter>
<ClCompile Include="SurfTriMeshCuts.cpp">
<Filter>File di origine\Geo</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
@@ -1082,19 +1082,10 @@
<ClInclude Include="CDeRectPrismoidTria.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="dpoint.hpp">
<ClInclude Include="earcut.hpp">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="tpp_assert.hpp">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="tpp_interface.hpp">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="triangle.h">
<Filter>File di intestazione</Filter>
</ClInclude>
<ClInclude Include="triangle_impl.hpp">
<ClInclude Include="IntersLineBox.h">
<Filter>File di intestazione</Filter>
</ClInclude>
</ItemGroup>
+2 -443
View File
@@ -2775,448 +2775,7 @@ GdbExecutor::ExecuteVolZmap( const string& sCmd2, const STRVECTOR& vsParams)
//else if ( sCmd2 == "EDGES") {
// return ExecuteVolZmapEdges( vsParams) ;
//}
///////////////////////////if ( sCmd2 == "ELLCYL") {
/////////////////////////// // Parametri: nParentId, nLineId1, nLineId2, ptLine, vtLine, ptCirc, vtAx, dRad, vtSweptVec, nInOut, ptPP1, vtPV1, ptPP2, vtPV2, ptPP3, vtPV3
/////////////////////////// if (vsParams.size() != 16)
/////////////////////////// return false;
/////////////////////////// // recupero il riferimento in cui è immerso
/////////////////////////// Frame3d frRef;
/////////////////////////// if (!m_pGDB->GetGroupGlobFrame(GetIdParam(vsParams[0]), frRef))
/////////////////////////// return false;
/////////////////////////// // recupero punto iniziale retta
/////////////////////////// Point3d ptLine;
/////////////////////////// if (!GetPointParam(vsParams[3], frRef, ptLine))
/////////////////////////// return false;
/////////////////////////// // recupero vettore retta
/////////////////////////// Vector3d vtLine;
/////////////////////////// if (!GetVectorParam(vsParams[4], frRef, vtLine))
/////////////////////////// return false;
/////////////////////////// vtLine.Normalize();
/////////////////////////// // recupero centro circonferenza
/////////////////////////// Point3d ptCirc;
/////////////////////////// if (!GetPointParam(vsParams[5], frRef, ptCirc))
/////////////////////////// return false;
/////////////////////////// // recupero vettore asse circonferenza
/////////////////////////// Vector3d vtAx;
/////////////////////////// if (!GetVectorParam(vsParams[6], frRef, vtAx))
/////////////////////////// return false;
/////////////////////////// vtAx.Normalize();
/////////////////////////// // recupero raggio della circonferenza
/////////////////////////// double dRad;
/////////////////////////// if (!FromString(vsParams[7], dRad))
/////////////////////////// return false;
/////////////////////////// // recupero vettore di traslazione
/////////////////////////// Vector3d vtSweptVec;
/////////////////////////// if (!GetVectorParam(vsParams[8], frRef, vtSweptVec))
/////////////////////////// return false;
/////////////////////////// // intero per recupero flag bInOut
/////////////////////////// int nInOut;
/////////////////////////// if (!FromString(vsParams[9], nInOut))
/////////////////////////// return false;
/////////////////////////// bool bInOut = nInOut == 0 ? false : true;
/////////////////////////// // recupero punto piano 1
/////////////////////////// Point3d ptPP1;
/////////////////////////// if (!GetPointParam(vsParams[10], frRef, ptPP1))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 1
/////////////////////////// Vector3d vtPV1;
/////////////////////////// if (!GetVectorParam(vsParams[11], frRef, vtPV1))
/////////////////////////// return false;
/////////////////////////// vtPV1.Normalize();
/////////////////////////// // recupero punto piano 2
/////////////////////////// Point3d ptPP2;
/////////////////////////// if (!GetPointParam(vsParams[12], frRef, ptPP2))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 2
/////////////////////////// Vector3d vtPV2;
/////////////////////////// if (!GetVectorParam(vsParams[13], frRef, vtPV2))
/////////////////////////// return false;
/////////////////////////// vtPV2.Normalize();
/////////////////////////// // recupero punto piano 3
/////////////////////////// Point3d ptPP3;
/////////////////////////// if (!GetPointParam(vsParams[14], frRef, ptPP3))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 3
/////////////////////////// Vector3d vtPV3;
/////////////////////////// if (!GetVectorParam(vsParams[15], frRef, vtPV3))
/////////////////////////// return false;
/////////////////////////// vtPV3.Normalize();
/////////////////////////// // definisco i piani
/////////////////////////// Plane3d plPlane1;
/////////////////////////// plPlane1.Set(ptPP1, vtPV1);
/////////////////////////// Plane3d plPlane2;
/////////////////////////// plPlane2.Set(ptPP2, vtPV2);
/////////////////////////// Plane3d plPlane3;
/////////////////////////// plPlane3.Set(ptPP3, vtPV3);
/////////////////////////// vector<Plane3d> vPlanesVec;
/////////////////////////// /*vPlanesVec.emplace_back( plPlane1) ;
/////////////////////////// vPlanesVec.emplace_back( plPlane2) ;
/////////////////////////// vPlanesVec.emplace_back( plPlane3) ;*/
/////////////////////////// // Intersezione
/////////////////////////// VolZmap MyVol;
/////////////////////////// Point3d ptInt1;
/////////////////////////// Vector3d vtN1;
/////////////////////////// Point3d ptInt2;
/////////////////////////// Vector3d vtN2;
/////////////////////////// int nSol = MyVol.IntersLineCircSweptSurfCuttedByPlanes(ptLine, vtLine, ptCirc, vtAx, dRad, vtSweptVec, bInOut, vPlanesVec,
/////////////////////////// ptInt1, vtN1, ptInt2, vtN2);
/////////////////////////// if (nSol == 1) {
/////////////////////////// PtrOwner<CurveLine> pLine(CreateBasicCurveLine());
/////////////////////////// pLine->Set(ptInt1, ptInt1 + vtN1);
/////////////////////////// // inserisco nel DB
/////////////////////////// return AddGeoObj(vsParams[1], vsParams[0], Release(pLine));
/////////////////////////// }
/////////////////////////// else if (nSol == 2) {
/////////////////////////// PtrOwner<CurveLine> pLine1(CreateBasicCurveLine());
/////////////////////////// pLine1->Set(ptInt1, ptInt1 + vtN1);
/////////////////////////// PtrOwner<CurveLine> pLine2(CreateBasicCurveLine());
/////////////////////////// pLine2->Set(ptInt2, ptInt2 + vtN2);
/////////////////////////// // inserisco nel DB
/////////////////////////// return AddGeoObj(vsParams[1], vsParams[0], Release(pLine1)) &&
/////////////////////////// AddGeoObj(vsParams[2], vsParams[0], Release(pLine2));
/////////////////////////// }
///////////////////////////}
///////////////////////////else if (sCmd2 == "STDCYL") {
/////////////////////////// // Parametri : nParentId, nLineId1, nLineId2, ptLineP, vtLineDir, ptBaseCen, vtAx, dRad, dH, nInOut, ptPP1, vtPV1, ptPP2, vtPV2, ptPP3, vtPV3
/////////////////////////// if (vsParams.size() != 16)
/////////////////////////// return false;
/////////////////////////// // recupero il riferimento in cui è immerso
/////////////////////////// Frame3d frRef;
/////////////////////////// if (!m_pGDB->GetGroupGlobFrame(GetIdParam(vsParams[0]), frRef))
/////////////////////////// return false;
/////////////////////////// // recupero punto iniziale retta
/////////////////////////// Point3d ptLineP;
/////////////////////////// if (!GetPointParam(vsParams[3], frRef, ptLineP))
/////////////////////////// return false;
/////////////////////////// // recupero vettore retta
/////////////////////////// Vector3d vtLineDir;
/////////////////////////// if (!GetVectorParam(vsParams[4], frRef, vtLineDir))
/////////////////////////// return false;
/////////////////////////// vtLineDir.Normalize();
/////////////////////////// // recupero centro circonferenza
/////////////////////////// Point3d ptBaseCen;
/////////////////////////// if (!GetPointParam(vsParams[5], frRef, ptBaseCen))
/////////////////////////// return false;
/////////////////////////// // recupero vettore asse circonferenza
/////////////////////////// Vector3d vtAx;
/////////////////////////// if (!GetVectorParam(vsParams[6], frRef, vtAx))
/////////////////////////// return false;
/////////////////////////// vtAx.Normalize();
/////////////////////////// // recupero raggio della circonferenza
/////////////////////////// double dRad;
/////////////////////////// if (!FromString(vsParams[7], dRad))
/////////////////////////// return false;
/////////////////////////// // recupero raggio della circonferenza
/////////////////////////// double dH;
/////////////////////////// if (!FromString(vsParams[8], dH))
/////////////////////////// return false;
/////////////////////////// // intero per recupero flag bInOut
/////////////////////////// int nInOut;
/////////////////////////// if (!FromString(vsParams[9], nInOut))
/////////////////////////// return false;
/////////////////////////// bool bInOut = nInOut == 0 ? false : true;
/////////////////////////// // recupero punto piano 1
/////////////////////////// Point3d ptPP1;
/////////////////////////// if (!GetPointParam(vsParams[10], frRef, ptPP1))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 1
/////////////////////////// Vector3d vtPV1;
/////////////////////////// if (!GetVectorParam(vsParams[11], frRef, vtPV1))
/////////////////////////// return false;
/////////////////////////// vtPV1.Normalize();
/////////////////////////// // recupero punto piano 2
/////////////////////////// Point3d ptPP2;
/////////////////////////// if (!GetPointParam(vsParams[12], frRef, ptPP2))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 2
/////////////////////////// Vector3d vtPV2;
/////////////////////////// if (!GetVectorParam(vsParams[13], frRef, vtPV2))
/////////////////////////// return false;
/////////////////////////// vtPV2.Normalize();
/////////////////////////// // recupero punto piano 3
/////////////////////////// Point3d ptPP3;
/////////////////////////// if (!GetPointParam(vsParams[14], frRef, ptPP3))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 3
/////////////////////////// Vector3d vtPV3;
/////////////////////////// if (!GetVectorParam(vsParams[15], frRef, vtPV3))
/////////////////////////// return false;
/////////////////////////// vtPV3.Normalize();
/////////////////////////// // definisco i piani
/////////////////////////// Plane3d plPlane1;
/////////////////////////// plPlane1.Set(ptPP1, vtPV1);
/////////////////////////// Plane3d plPlane2;
/////////////////////////// plPlane2.Set(ptPP2, vtPV2);
/////////////////////////// Plane3d plPlane3;
/////////////////////////// plPlane3.Set(ptPP3, vtPV3);
/////////////////////////// vector<Plane3d> vPlanesVec;
/////////////////////////// /*vPlanesVec.emplace_back( plPlane1) ;
/////////////////////////// vPlanesVec.emplace_back( plPlane2) ;
/////////////////////////// vPlanesVec.emplace_back( plPlane3) ;*/
/////////////////////////// // Intersezione
/////////////////////////// VolZmap MyVol;
/////////////////////////// Point3d ptInt1;
/////////////////////////// Vector3d vtN1;
/////////////////////////// Point3d ptInt2;
/////////////////////////// Vector3d vtN2;
/////////////////////////// int nSol = MyVol.IntersLineCylinderCuttedByPlanes(ptLineP, vtLineDir, ptBaseCen, vtAx, dRad, dH, bInOut, vPlanesVec, ptInt1, vtN1, ptInt2, vtN2);
/////////////////////////// if (nSol == 1) {
/////////////////////////// PtrOwner<CurveLine> pLine(CreateBasicCurveLine());
/////////////////////////// pLine->Set(ptInt1, ptInt1 + vtN1);
/////////////////////////// // inserisco nel DB
/////////////////////////// return AddGeoObj(vsParams[1], vsParams[0], Release(pLine));
/////////////////////////// }
/////////////////////////// else if (nSol == 2) {
/////////////////////////// PtrOwner<CurveLine> pLine1(CreateBasicCurveLine());
/////////////////////////// pLine1->Set(ptInt1, ptInt1 + vtN1);
/////////////////////////// PtrOwner<CurveLine> pLine2(CreateBasicCurveLine());
/////////////////////////// pLine2->Set(ptInt2, ptInt2 + vtN2);
/////////////////////////// // inserisco nel DB
/////////////////////////// return AddGeoObj(vsParams[1], vsParams[0], Release(pLine1)) &&
/////////////////////////// AddGeoObj(vsParams[2], vsParams[0], Release(pLine2));
/////////////////////////// }
///////////////////////////}
///////////////////////////else if ( sCmd2 == "PLANE") {
/////////////////////////// // Parametri : nParentId, nLineId, ptLineP, vtLineDir, ptParOrig, vtSeg1, vtSeg2, nExtNorm
/////////////////////////// if (vsParams.size() != 8)
/////////////////////////// return false;
/////////////////////////// // recupero il riferimento in cui è immerso
/////////////////////////// Frame3d frRef;
/////////////////////////// if (!m_pGDB->GetGroupGlobFrame(GetIdParam(vsParams[0]), frRef))
/////////////////////////// return false;
/////////////////////////// // recupero punto iniziale retta
/////////////////////////// Point3d ptLineP;
/////////////////////////// if (!GetPointParam(vsParams[2], frRef, ptLineP))
/////////////////////////// return false;
/////////////////////////// // recupero vettore retta
/////////////////////////// Vector3d vtLineDir;
/////////////////////////// if (!GetVectorParam(vsParams[3], frRef, vtLineDir))
/////////////////////////// return false;
/////////////////////////// vtLineDir.Normalize();
/////////////////////////// // recupero origine parallelogramma
/////////////////////////// Point3d ptParOrig;
/////////////////////////// if (!GetPointParam(vsParams[4], frRef, ptParOrig))
/////////////////////////// return false;
/////////////////////////// // recupero vettore segmento 1
/////////////////////////// Vector3d vtSeg1;
/////////////////////////// if (!GetVectorParam(vsParams[5], frRef, vtSeg1))
/////////////////////////// return false;
/////////////////////////// // recupero vettore segmento 2
/////////////////////////// Vector3d vtSeg2;
/////////////////////////// if (!GetVectorParam(vsParams[6], frRef, vtSeg2))
/////////////////////////// return false;
/////////////////////////// // intero per recupero flag nExtNorm
/////////////////////////// int nExtNorm;
/////////////////////////// if (!FromString(vsParams[7], nExtNorm))
/////////////////////////// return false;
/////////////////////////// bool bExtNorm = nExtNorm == 0 ? false : true;
/////////////////////////// // Intersezione
/////////////////////////// VolZmap MyVol;
/////////////////////////// Point3d ptInt;
/////////////////////////// Vector3d vtN;
/////////////////////////// int nSol = MyVol.IntersLineParallelogram( ptLineP, vtLineDir, ptParOrig, vtSeg1, vtSeg2, bExtNorm, ptInt, vtN) ;
/////////////////////////// if (nSol == 1) {
/////////////////////////// PtrOwner<CurveLine> pLine(CreateBasicCurveLine());
/////////////////////////// pLine->Set(ptInt, ptInt + vtN);
/////////////////////////// // inserisco nel DB
/////////////////////////// return AddGeoObj(vsParams[1], vsParams[0], Release(pLine));
/////////////////////////// }
///////////////////////////}
///////////////////////////else if (sCmd2 == "CONE") {
/////////////////////////// // Parametri : nParentId, nLineId1, nLineId2, ptLineP, vtLineDir, ptVert, vtAx, dRad, dH, nInOut, ptPP1, vtPV1, ptPP2, vtPV2, ptPP3, vtPV3
/////////////////////////// if (vsParams.size() != 16)
/////////////////////////// return false;
/////////////////////////// // recupero il riferimento in cui è immerso
/////////////////////////// Frame3d frRef;
/////////////////////////// if (!m_pGDB->GetGroupGlobFrame(GetIdParam(vsParams[0]), frRef))
/////////////////////////// return false;
/////////////////////////// // recupero punto iniziale retta
/////////////////////////// Point3d ptLineP;
/////////////////////////// if (!GetPointParam(vsParams[3], frRef, ptLineP))
/////////////////////////// return false;
/////////////////////////// // recupero vettore retta
/////////////////////////// Vector3d vtLineDir;
/////////////////////////// if (!GetVectorParam(vsParams[4], frRef, vtLineDir))
/////////////////////////// return false;
/////////////////////////// vtLineDir.Normalize();
/////////////////////////// // recupero vertice cono
/////////////////////////// Point3d ptVert;
/////////////////////////// if (!GetPointParam(vsParams[5], frRef, ptVert))
/////////////////////////// return false;
/////////////////////////// // recupero vettore asse cono
/////////////////////////// Vector3d vtAx;
/////////////////////////// if (!GetVectorParam(vsParams[6], frRef, vtAx))
/////////////////////////// return false;
/////////////////////////// vtAx.Normalize();
/////////////////////////// // recupero raggio della base del cono
/////////////////////////// double dRad;
/////////////////////////// if (!FromString(vsParams[7], dRad))
/////////////////////////// return false;
/////////////////////////// // recupero altezza del cono
/////////////////////////// double dH;
/////////////////////////// if (!FromString(vsParams[8], dH))
/////////////////////////// return false;
/////////////////////////// // intero per recupero flag nExtNorm
/////////////////////////// int nInOut;
/////////////////////////// if (!FromString(vsParams[9], nInOut))
/////////////////////////// return false;
/////////////////////////// bool bInOut = nInOut == 0 ? false : true;
/////////////////////////// // recupero punto piano 1
/////////////////////////// Point3d ptPP1;
/////////////////////////// if (!GetPointParam(vsParams[10], frRef, ptPP1))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 1
/////////////////////////// Vector3d vtPV1;
/////////////////////////// if (!GetVectorParam(vsParams[11], frRef, vtPV1))
/////////////////////////// return false;
/////////////////////////// vtPV1.Normalize();
/////////////////////////// // recupero punto piano 2
/////////////////////////// Point3d ptPP2;
/////////////////////////// if (!GetPointParam(vsParams[12], frRef, ptPP2))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 2
/////////////////////////// Vector3d vtPV2;
/////////////////////////// if (!GetVectorParam(vsParams[13], frRef, vtPV2))
/////////////////////////// return false;
/////////////////////////// vtPV2.Normalize();
/////////////////////////// // recupero punto piano 3
/////////////////////////// Point3d ptPP3;
/////////////////////////// if (!GetPointParam(vsParams[14], frRef, ptPP3))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 3
/////////////////////////// Vector3d vtPV3;
/////////////////////////// if (!GetVectorParam(vsParams[15], frRef, vtPV3))
/////////////////////////// return false;
/////////////////////////// vtPV3.Normalize();
/////////////////////////// // definisco i piani
/////////////////////////// Plane3d plPlane1;
/////////////////////////// plPlane1.Set(ptPP1, vtPV1);
/////////////////////////// Plane3d plPlane2;
/////////////////////////// plPlane2.Set(ptPP2, vtPV2);
/////////////////////////// Plane3d plPlane3;
/////////////////////////// plPlane3.Set(ptPP3, vtPV3);
/////////////////////////// vector<Plane3d> vPlanesVec;
/////////////////////////// /*vPlanesVec.emplace_back( plPlane1) ;
/////////////////////////// vPlanesVec.emplace_back( plPlane2) ;
/////////////////////////// vPlanesVec.emplace_back( plPlane3) ;*/
/////////////////////////// // Intersezione
/////////////////////////// VolZmap MyVol;
/////////////////////////// Point3d ptInt1;
/////////////////////////// Vector3d vtN1;
/////////////////////////// Point3d ptInt2;
/////////////////////////// Vector3d vtN2;
/////////////////////////// int nSol = MyVol.IntersLineConeCuttedByPlanes( ptLineP, vtLineDir, ptVert, vtAx, dRad, dH, bInOut, vPlanesVec, ptInt1, vtN1, ptInt2, vtN2);
/////////////////////////// if (nSol == 1) {
/////////////////////////// PtrOwner<CurveLine> pLine(CreateBasicCurveLine());
/////////////////////////// pLine->Set(ptInt1, ptInt1 + vtN1);
/////////////////////////// // inserisco nel DB
/////////////////////////// return AddGeoObj(vsParams[1], vsParams[0], Release(pLine));
/////////////////////////// }
/////////////////////////// else if (nSol == 2) {
/////////////////////////// PtrOwner<CurveLine> pLine1(CreateBasicCurveLine());
/////////////////////////// pLine1->Set(ptInt1, ptInt1 + vtN1);
/////////////////////////// PtrOwner<CurveLine> pLine2(CreateBasicCurveLine());
/////////////////////////// pLine2->Set(ptInt2, ptInt2 + vtN2);
/////////////////////////// // inserisco nel DB
/////////////////////////// return AddGeoObj(vsParams[1], vsParams[0], Release(pLine1)) &&
/////////////////////////// AddGeoObj(vsParams[2], vsParams[0], Release(pLine2));
/////////////////////////// }
///////////////////////////}
///////////////////////////else if (sCmd2 == "SPHERE") {
/////////////////////////// // Parametri: nParentId, nLineId1, nLineId2, ptLineP, vtLineD, ptCen, dRad, nInOut, ptPP1, vtPV1, ptPP2, vtPV2, ptPP3, vtPV3
/////////////////////////// if (vsParams.size() != 14)
/////////////////////////// return false;
/////////////////////////// // recupero il riferimento in cui è immerso
/////////////////////////// Frame3d frRef;
/////////////////////////// if (!m_pGDB->GetGroupGlobFrame(GetIdParam(vsParams[0]), frRef))
/////////////////////////// return false;
/////////////////////////// // recupero punto iniziale retta
/////////////////////////// Point3d ptLineP;
/////////////////////////// if (!GetPointParam(vsParams[3], frRef, ptLineP))
/////////////////////////// return false;
/////////////////////////// // recupero vettore retta
/////////////////////////// Vector3d vtLineD;
/////////////////////////// if (!GetVectorParam(vsParams[4], frRef, vtLineD))
/////////////////////////// return false;
/////////////////////////// vtLineD.Normalize();
/////////////////////////// // recupero centro sfera
/////////////////////////// Point3d ptCen;
/////////////////////////// if (!GetPointParam(vsParams[5], frRef, ptCen))
/////////////////////////// return false;
/////////////////////////// // recupero raggio della sfera
/////////////////////////// double dRad;
/////////////////////////// if (!FromString(vsParams[6], dRad))
/////////////////////////// return false;
/////////////////////////// // intero per recupero flag nExtNorm
/////////////////////////// int nInOut;
/////////////////////////// if (!FromString(vsParams[7], nInOut))
/////////////////////////// return false;
/////////////////////////// bool bInOut = nInOut == 0 ? false : true;
/////////////////////////// // recupero punto piano 1
/////////////////////////// Point3d ptPP1;
/////////////////////////// if (!GetPointParam(vsParams[8], frRef, ptPP1))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 1
/////////////////////////// Vector3d vtPV1;
/////////////////////////// if (!GetVectorParam(vsParams[9], frRef, vtPV1))
/////////////////////////// return false;
/////////////////////////// vtPV1.Normalize();
/////////////////////////// // recupero punto piano 2
/////////////////////////// Point3d ptPP2;
/////////////////////////// if (!GetPointParam(vsParams[10], frRef, ptPP2))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 2
/////////////////////////// Vector3d vtPV2;
/////////////////////////// if (!GetVectorParam(vsParams[11], frRef, vtPV2))
/////////////////////////// return false;
/////////////////////////// vtPV2.Normalize();
/////////////////////////// // recupero punto piano 3
/////////////////////////// Point3d ptPP3;
/////////////////////////// if (!GetPointParam(vsParams[12], frRef, ptPP3))
/////////////////////////// return false;
/////////////////////////// // recupero vettore piano 3
/////////////////////////// Vector3d vtPV3;
/////////////////////////// if (!GetVectorParam(vsParams[13], frRef, vtPV3))
/////////////////////////// return false;
/////////////////////////// vtPV3.Normalize();
/////////////////////////// // definisco i piani
/////////////////////////// Plane3d plPlane1;
/////////////////////////// plPlane1.Set(ptPP1, vtPV1);
/////////////////////////// Plane3d plPlane2;
/////////////////////////// plPlane2.Set(ptPP2, vtPV2);
/////////////////////////// Plane3d plPlane3;
/////////////////////////// plPlane3.Set(ptPP3, vtPV3);
/////////////////////////// vector<Plane3d> vPlanesVec;
/////////////////////////// /*vPlanesVec.emplace_back( plPlane1) ;
/////////////////////////// vPlanesVec.emplace_back( plPlane2) ;
/////////////////////////// vPlanesVec.emplace_back( plPlane3) ;*/
/////////////////////////// // Intersezione
/////////////////////////// VolZmap MyVol;
/////////////////////////// Point3d ptInt1;
/////////////////////////// Vector3d vtN1;
/////////////////////////// Point3d ptInt2;
/////////////////////////// Vector3d vtN2;
/////////////////////////// int nSol = MyVol.IntersLineSphereCuttedByPlanes(ptLineP, vtLineD, ptCen, dRad, bInOut, vPlanesVec, ptInt1, vtN1, ptInt2, vtN2);
/////////////////////////// if (nSol == 1) {
/////////////////////////// PtrOwner<CurveLine> pLine(CreateBasicCurveLine());
/////////////////////////// pLine->Set(ptInt1, ptInt1 + vtN1);
/////////////////////////// // inserisco nel DB
/////////////////////////// return AddGeoObj(vsParams[1], vsParams[0], Release(pLine));
/////////////////////////// }
/////////////////////////// else if (nSol == 2) {
/////////////////////////// PtrOwner<CurveLine> pLine1(CreateBasicCurveLine());
/////////////////////////// pLine1->Set(ptInt1, ptInt1 + vtN1);
/////////////////////////// PtrOwner<CurveLine> pLine2(CreateBasicCurveLine());
/////////////////////////// pLine2->Set(ptInt2, ptInt2 + vtN2);
/////////////////////////// // inserisco nel DB
/////////////////////////// return AddGeoObj(vsParams[1], vsParams[0], Release(pLine1)) &&
/////////////////////////// AddGeoObj(vsParams[2], vsParams[0], Release(pLine2));
/////////////////////////// }
///////////////////////////}
///////////////////////////else
/////////////////////////// return false ;
///////////////////////////return true ;
return true;
return false ;
}
/*
//----------------------------------------------------------------------------
@@ -8088,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, ccClass))
if ( ! intCC.GetCurveClassification( 0, EPS_SMALL, ccClass))
return false ;
// recupero gli indici dei gruppi destinazione e i loro riferimenti
const int N_GRP = 4 ;
+1 -1
View File
@@ -49,7 +49,7 @@ const double BEZARC_ANG_CEN_MAX = 90 ;
//----------------- Costanti per superfici TriMesh ---------------------------
// tolleranza lineare standard
const double STM_STD_LIN_TOL = EPS_SMALL/*0.1*/ ;
const double STM_STD_LIN_TOL = 0.1 ;
// angolo limite per definire un edge che è contorno di poligono
const double STM_STD_BOUNDARY_ANG = 0.1 ;
// angolo limite per mediare le normali in un vertice
-1
View File
@@ -684,7 +684,6 @@ 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) ;
+10 -8
View File
@@ -391,7 +391,7 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d
//----------------------------------------------------------------------------
bool
IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
IntersCurveCurve::GetCurveClassification( int nCrv, double dLenMin, CRVCVECTOR& ccClass)
{
// pulisco vettore classificazioni
ccClass.clear() ;
@@ -407,7 +407,7 @@ IntersCurveCurve::GetCurveClassification( int nCrv, CRVCVECTOR& ccClass)
return false ;
// se esiste almeno una intersezione
if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[0], m_Info, ccClass) ;
return CalcCurveClassification( m_pCurve[0], m_Info, dLenMin, 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, CRVCVECTOR& ccClass)
SwapInfoAB( InfoTmp, 1) ;
// se esiste almeno una intersezione
if ( m_nIntersCount >= 1)
return CalcCurveClassification( m_pCurve[1], InfoTmp, ccClass) ;
return CalcCurveClassification( m_pCurve[1], InfoTmp, dLenMin, 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, CRVCVECTOR& ccClass)
IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTOR& Info, double dLenMin, CRVCVECTOR& ccClass)
{
// numero intersezioni
int nNumInters = int( Info.size()) ;
@@ -471,6 +471,8 @@ 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()) ;
@@ -527,7 +529,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 > EPS_SMALL) {
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
// verifico che la definizione sul tratto sia omogenea e valida
int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ;
if ( ( nLastTy != ICCT_NULL && nPrevTy != nLastTy) ||
@@ -562,7 +564,7 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
}
}
// eventuale tratto finale rimasto
if ( dCurrPar < dEndPar - EPS_PARAM && dEndLen - dCurrLen > EPS_SMALL) {
if ( dCurrPar < dEndPar - EPS_PARAM && dEndLen - dCurrLen > dLenMin) {
// verifico che la definizione sul tratto sia valida
if ( nLastTy == ICCT_NULL || nLastTy == ICCT_ON)
return false ;
@@ -673,7 +675,7 @@ IntersCurveCurve::GetRegionCurveClassification( void)
{
// classifico la prima curva rispetto alla seconda
CRVCVECTOR ccClass ;
if ( ! GetCurveClassification( 0, ccClass))
if ( ! GetCurveClassification( 0, EPS_SMALL, ccClass))
return CCREGC_NULL ;
// derivo la classificazione delle curve come regioni
bool bIn = false ;
@@ -710,7 +712,7 @@ IntersCurveCurve::GetRegionCurveClassification( void)
if ( bOnP)
return CCREGC_IN2 ;
CRVCVECTOR ccClass2 ;
if ( ! GetCurveClassification( 1, ccClass2) || ccClass2.empty())
if ( ! GetCurveClassification( 1, EPS_SMALL, ccClass2) || ccClass2.empty())
return CCREGC_NULL ;
if ( ccClass2[0].nClass == CRVC_OUT)
return CCREGC_OUT ;
+127 -108
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2020-2020
// EgalTech 2020-2022
//----------------------------------------------------------------------------
// File : IntersLineBox.cpp Data : 07.05.20 Versione : 2.2e1
// File : IntersLineBox.cpp Data : 08.01.22 Versione : 2.4a3
// Contenuto : Implementazione della intersezione linea/box.
//
//
@@ -13,13 +13,77 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "SurfTriMesh.h"
#include "IntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
#include "/EgtDev/Include/EgtNumUtils.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)
@@ -38,114 +102,69 @@ bool
IntersLineBox( const Point3d& ptL, const Vector3d& vtL, double dLen, const BBox3d& b3Box, INTDBLVECTOR& vInters, bool bFinite)
{
// Recupero i dati del Box
Point3d ptMin ;
double dDimX, dDimY, dDimZ ;
if ( ! b3Box.GetMinDim( ptMin, dDimX, dDimY, dDimZ))
Point3d ptMin, ptMax ;
if ( ! b3Box.GetMinMax( ptMin, ptMax))
return false ;
// 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 ;
// 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) ;
}
// 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 ;
else {
if ( dU > - EPS_SMALL && dU < dLen + EPS_SMALL)
vInters.emplace_back( ILBT_TOUCH, Clamp( dU, 0., dLen)) ;
}
}
// 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 ;
}
// 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 ;
}
}
// passo alla successiva
++ j ;
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) ;
}
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)) ;
}
}
return true ;
}
// 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
@@ -0,0 +1,34 @@
//----------------------------------------------------------------------------
// 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) ;
}
+3 -56
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2017-2018
// EgalTech 2017-2022
//----------------------------------------------------------------------------
// File : IntersLineSurfStd.cpp Data : 03.12.18 Versione : 1.9l1
// File : IntersLineSurfStd.cpp Data : 08.01.22 Versione : 2.4a3
// Contenuto : Implementazione delle funzioni di intersezione
// componente lineare e superficie standard.
//
@@ -13,6 +13,7 @@
#include "stdafx.h"
#include "IntersLineSurfStd.h"
#include "IntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkFrame3d.h"
#include "/EgtDev/Include/ENkPolynomialRoots.h"
@@ -21,60 +22,6 @@
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,11 +34,6 @@
// 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,
+3 -4
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2015-2019
// EgalTech 2015-2022
//----------------------------------------------------------------------------
// File : IntersLineSurfTm.cpp Data : 09.03.15 Versione : 2.1b6
// File : IntersLineSurfTm.cpp Data : 08.01.22 Versione : 2.4a3
// Contenuto : Implementazione della intersezione linea/superficie trimesh.
//
//
@@ -14,8 +14,7 @@
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "ProjPlane.h"
#include "IntersLineSurfStd.h"
#include "/EgtDev/Include/EGkSurfTriMesh.h"
#include "IntersLineBox.h"
#include "/EgtDev/Include/EGkIntersLineTria.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
+34 -6
View File
@@ -1,8 +1,8 @@
//----------------------------------------------------------------------------
// EgalTech 2020-2020
//----------------------------------------------------------------------------
// File : IntersLineBox.cpp Data : 07.05.20 Versione : 2.2e1
// Contenuto : Implementazione della intersezione linea/box.
// File : IntersPlaneBox.cpp Data : 07.05.20 Versione : 2.2e1
// Contenuto : Implementazione della intersezione piano/box.
//
//
//
@@ -20,19 +20,47 @@
using namespace std ;
//----------------------------------------------------------------------------
// Box e piano devono essere nello stesso riferimento. Il box deve essere axis aligned.
bool
IntersPlaneBox( const Point3d& ptOn, const Vector3d& vtN, const BBox3d& b3Box,
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,
PNTVECTOR& vPnt, BIPNTVECTOR& vBpt, TRIA3DVECTOR& vTria)
{
// Creo il piano
Plane3d plPlane ;
if ( ! plPlane.Set( ptOn, vtN))
// Verifico il piano
if ( ! plPlane.IsValid())
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) {
else if ( nRes == ITTT_OVERLAPS || nRes == ITTT_COUNTER_OVERLAPS) {
for ( const auto& Tria : vIttTria) {
// verifico se triangolo già inserito
bool bFound = false ;
+34 -5
View File
@@ -83,8 +83,37 @@ 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))
return IntersCoplanarTriaTria( trTria1, trTria2, vTria) ;
( 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 ;
}
// limito la linea di intersezione con il primo triangolo
Point3d ptSt1, ptEn1 ;
@@ -112,7 +141,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() ;
@@ -122,7 +151,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() ;
@@ -205,7 +234,7 @@ int
FindTriaTriaIntersType( const Triangle3d& trTria1, const Triangle3d& trTria2, const Point3d& ptLineSt, const Vector3d& vtLineDir,
double dStU1, double dEnU1, double dStU2, double dEnU2, int nRes1, int nRes2, double& dIntStU, double& dIntEnU)
{
// Controllo su validità input
// Controllo su validit input
if ( ! ( trTria1.IsValid() && trTria2.IsValid() && vtLineDir.IsNormalized()))
return ITTT_NO ;
// Casi
+14 -3
View File
@@ -68,9 +68,20 @@ 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, false, 10 * EPS_SMALL))
if ( pCrv == nullptr || ! pCrv->IsFlat( plPlane, bIsLine, 10 * EPS_SMALL))
return false ;
// recupero o assegno estrusione
Vector3d vtExtr ;
@@ -449,7 +460,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
inOk.Set( dStart, dEnd) ;
IntersCurveCurve ccInt( *pCrv, *pCircS) ;
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, ccPart))
if ( ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccPart))
return false ;
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
@@ -498,7 +509,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
inOk.Set( dStart, dEnd) ;
IntersCurveCurve ccInt( *pCrv, *pCircE) ;
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, ccPart))
if ( ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccPart))
return false ;
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
+201 -311
View File
@@ -19,11 +19,10 @@
#include "PolygonPlane.h"
#include "PointsPCA.h"
#include "GeoConst.h"
#include "/EgtDev/Include/EGkPolygon3d.h"
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGnStringUtils.h"
#include "/EgtDev/Include/EGtNumUtils.h"
#include "/EgtDev/Include/EgtNumUtils.h"
using namespace std ;
@@ -55,7 +54,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
{
// se da aggiungere in coda
if ( bEndOrStart) {
// se il punto uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
// se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.back().first)) {
++ m_nRejected ;
return true ;
@@ -70,7 +69,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart)
}
// altrimenti si aggiunge in testa
else {
// se il punto uguale al primo (ignoro parametro), non lo inserisco ma ok
// se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok
if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.front().first)) {
++ m_nRejected ;
return true ;
@@ -94,7 +93,7 @@ PolyLine::Close( void)
// ci devono essere almeno 2 punti
if ( m_lUPoints.size() < 2)
return false ;
// verifico non sia gi chiuso
// verifico non sia già chiuso
if ( AreSamePointApprox( m_lUPoints.front().first, m_lUPoints.back().first))
return false ;
// aggiungo un punto uguale al primo in coda
@@ -229,7 +228,7 @@ PolyLine::ToLoc( const Frame3d& frRef)
bool
PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
{
// se i due riferimenti coincidono, non devo fare alcunch
// se i due riferimenti coincidono, non devo fare alcunché
if ( AreSameFrame( frOri, frDest))
return true ;
// ciclo sui punti
@@ -244,7 +243,7 @@ PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
bool
PolyLine::Join( PolyLine& PL, double dOffsetPar)
{
// se l'altra polilinea non contiene alcunch, esco con ok
// se l'altra polilinea non contiene alcunchè, esco con ok
if ( PL.m_lUPoints.size() == 0)
return true ;
// verifico che l'ultimo punto di questa polilinea coincida con il primo dell'altra
@@ -396,7 +395,7 @@ PolyLine::GetPrevUPoint( double* pdPar, Point3d* pptP, bool bNotFirst) const
bool
PolyLine::GetCurrUPoint( double* pdPar, Point3d* pptP) const
{
// verifico validit punto corrente
// verifico validità punto corrente
if ( m_iter == m_lUPoints.end())
return false ;
@@ -437,7 +436,7 @@ PolyLine::GetFirstULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d*
bool
PolyLine::GetNextULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* pptFin) const
{
// parametro e punto iniziali ( il precedente finale)
// parametro e punto iniziali (è il precedente finale)
if ( m_iter == m_lUPoints.end())
return false ;
if ( pdIni != nullptr)
@@ -518,19 +517,19 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co
PointsPCA ptsPCA ;
for ( bool bFound = GetFirstLine( ptP1, ptP2) ; bFound ; bFound = GetNextLine( ptP1, ptP2))
ptsPCA.AddPoint( Media( ptP1, ptP2), Dist( ptP1, ptP2)) ;
// recupero il rango, ovvero la dimensionalit dell'insieme di punti
// recupero il rango, ovvero la dimensionalità dell'insieme di punti
nRank = ptsPCA.GetRank() ;
// se dimensione nulla, o non ci sono punti o sono tutti praticamente coincidenti
if ( nRank == 0)
return ptsPCA.GetCenter( ptCen) ;
// se dimensione 1, allora i punti sono distribuiti su una linea
if ( nRank == 1) {
// assegno il centro e la direzione della linea (il verso indifferente)
// assegno il centro e la direzione della linea (il verso è indifferente)
ptsPCA.GetCenter( ptCen) ;
ptsPCA.GetPrincipalComponent( 0, vtDir) ;
return true ;
}
// altrimenti dimensione 2 o 3, allora determinato un piano principale, verifico se tutti i punti vi giacciono
// altrimenti dimensione 2 o 3, allora è determinato un piano principale, verifico se tutti i punti vi giacciono
// Center and normal vector
ptsPCA.GetCenter( ptCen) ;
Vector3d vtX, vtY ;
@@ -538,9 +537,9 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co
ptsPCA.GetPrincipalComponent( 1, vtY) ;
vtDir = vtX ^ vtY ;
if ( ! vtDir.Normalize()) {
// riduco la dimensionalit a lineare
// riduco la dimensionalità a lineare
nRank = 1 ;
// assegno il centro e la direzione della linea (il verso indifferente)
// assegno il centro e la direzione della linea (il verso è indifferente)
ptsPCA.GetCenter( ptCen) ;
vtDir = vtX ;
return true ;
@@ -569,12 +568,12 @@ PolyLine::IsFlat( Plane3d& plPlane, double dToler) const
plPlane.Reset() ;
return false ;
}
// recupero dati sulla planarit della polilinea
// recupero dati sulla planarità della polilinea
int nRank ;
Point3d ptCen ;
Vector3d vtDir ;
bool bFlat = IsFlat( nRank, ptCen, vtDir, dToler) ;
// imposto il piano a seconda della dimensionalit
// imposto il piano a seconda della dimensionalità
switch ( nRank) {
case 0 : // punto
plPlane.Set( ptCen, Z_AX) ;
@@ -645,7 +644,7 @@ PolyLine::GetAreaXY( double& dArea) const
// verifico sia chiusa
if ( ! IsClosed())
return false ;
// calcolo l'area considerando solo XY ( la Z di Newell)
// calcolo l'area considerando solo XY (è la Z di Newell)
dArea = 0 ;
Point3d ptIni, ptFin ;
for ( bool bFound = GetFirstLine( ptIni, ptFin) ; bFound ; bFound = GetNextLine( ptIni, ptFin)) {
@@ -779,10 +778,10 @@ PolyLine::RemoveAlignedPoints( double dToler)
}
// se curva chiusa con almeno 4 punti, devo analizzare il terzetto attorno alla chiusura
if ( IsClosed() && m_lUPoints.size() >= 4) {
// precP e currP sono gi corretti
// precP e currP sono già corretti
// il primo punto ripete l'ultimo (geometricamente coincide con currP)
auto firstP = m_lUPoints.begin() ;
// questo il vero successivo
// questo è il vero successivo
nextP = next( firstP) ;
// distanza del punto corrente dal segmento che unisce gli adiacenti
DistPointLine dPL( currP->first, precP->first, nextP->first) ;
@@ -831,12 +830,11 @@ PolyLine::MyChangeStart( int nPos)
// solo per polilinee chiuse
if ( ! IsClosed())
return false ;
// cancello ultimo punto ( coincide con primo)
// cancello l'ultimo punto ( coincide con il primo)
m_lUPoints.pop_back() ;
// 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
// 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
m_lUPoints.push_back( m_lUPoints.front()) ;
return true ;
@@ -938,7 +936,7 @@ PolyLine::MyApproxOnSide( const Vector3d& vtN, bool bLeftSide, double dToler)
}
}
}
// non stato eliminato alcunch
// non è stato eliminato alcunché
// ripristino la tolleranza corrente
dCurrToler = dToler ;
// avanzo il terzetto di uno step
@@ -979,7 +977,7 @@ PolyLine::MakeConvex( const Vector3d& vtN, bool bLeftSide)
bool
PolyLine::MyMakeConvex( const Vector3d& vtN, bool bLeftSide)
{
// ciclo i controlli finch non ci sono rimozioni
// ciclo i controlli finchè non ci sono rimozioni
bool bRemoved = true ;
while ( bRemoved) {
bRemoved = false ;
@@ -1007,7 +1005,7 @@ PolyLine::MyMakeConvex( const Vector3d& vtN, bool bLeftSide)
bRemoved = true ;
continue ;
}
// non stato eliminato alcunch : avanzo il terzetto di uno step
// non è stato eliminato alcunché : avanzo il terzetto di uno step
precP = currP ;
currP = nextP ;
++ nextP ;
@@ -1034,7 +1032,7 @@ PolyLine::Invert( bool bInvertU)
m_lUPoints.reverse() ;
// se richiesto, inverto anche il parametro U
if ( bInvertU) {
// recupero il primo valore di U che il vecchio finale ed il riferimento di inversione
// recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione
double dUfin = m_lUPoints.front().second ;
// ciclo su tutti gli elementi
for ( auto& UPoint : m_lUPoints) {
@@ -1249,7 +1247,7 @@ PolyLine::GetMinAreaRectangleXY( Point3d& ptCen, Vector3d& vtAx, double& dLen, d
bool
PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
{
// se vuota non faccio alcunch
// se vuota non faccio alcunché
if ( m_lUPoints.size() == 0)
return false ;
@@ -1300,327 +1298,219 @@ PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut)
}
//----------------------------------------------------------------------------
bool
PolyLine::ChangePolyLineStart( const Point3d& ptNewStart, double dTol)
{
// Rinomino la lista di punti della PolyLine.
PNTULIST& LoopList = 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 ;
}
//----------------------------------------------------------------------------
// nSegNum 0-based
bool
PolyLine::PointPositionOnPolyLine( const Point3d& ptPoint, int& nSegNum, double& dParOnSeg, double dTol) const
DistPointPolyLine( const Point3d& ptP, const PolyLine& plPoly, double& dDist)
{
// Rinomino la lista di punti della PolyLine.
const PNTULIST& LoopList = 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 ;
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDist) {
nSegNum = nS ;
dMinSqDist = dSqDist ;
itMinDistSt = itSt ;
itMinDistEn = itEn ;
}
// 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 ;
}
// 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
PolyLine::IsPointInsidePolyLine( const Point3d& ptP) const
IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler)
{
// Se la PolyLine non chiusa, il punto non pu essere interno.
if ( ! IsClosed())
// 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 ;
// Lista dei punti
const PNTULIST& List = GetUPointList() ;
// Ciclo sui segmenti della PolyLine per cercarne il tratto pi vicino al punto.
double dMinSqDist = DBL_MAX ;
// 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 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) ;
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) ;
double dSqDist ;
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDist) {
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
dDistCalc.GetMinDistPoint( ptMinDist) ;
itMinDistSt = itSt ;
itMinDistEnd = itEnd ;
}
}
// 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( *this) ;
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 ;
}
// 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() ;
}
// 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( *this) ;
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 ;
}
// 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() ;
}
// Punto di minima distanza interno al segmeno
// altrimenti minima distanza con l'interno
else {
Vector3d vtP = ptP - itMinDistSt->first ;
Vector3d vtTan = itMinDistEn->first - itMinDistSt->first ;
vtTan.Normalize() ;
Polygon3d AuxPolygon ;
AuxPolygon.FromPolyLine( *this) ;
Vector3d vtPolyNorm = AuxPolygon.GetVersN() ;
Vector3d vtOut = vtTan ^ vtPolyNorm ;
vtP -= ( vtP * vtTan) * vtTan ;
if ( vtP * vtOut < - EPS_SMALL)
return true ;
vtTang = itMinDistEnd->first - prev( itMinDistEnd)->first ;
}
return false ;
// Determino la posizione del punto
Vector3d vtDiff = ptP - ptMinDist ;
Vector3d vtOut = vtTang ^ plPlane.GetVersN() ;
vtOut.Normalize() ;
return ( vtDiff * vtOut < -dToler) ;
}
//----------------------------------------------------------------------------
bool
PolyLine::DistPointPolyLine( const Point3d& ptP, double& dPointPolyLineDist) const
GetPointParamOnPolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler, double& dPar)
{
if ( GetPointNbr() == 0)
// La polilinea deve contenere almeno due punti
if ( plPoly.GetPointNbr() < 2)
return false ;
dPointPolyLineDist = DBL_MAX ;
Point3d ptSt, ptEn ;
bool bContinue = GetFirstPoint( ptSt) && GetNextPoint( ptEn) ;
while ( bContinue) {
double dPoinLineDist ;
DistPointLine PointLineDistCalc( ptP, ptSt, ptEn) ;
PointLineDistCalc.GetDist( dPoinLineDist) ;
if ( dPoinLineDist < dPointPolyLineDist)
dPointPolyLineDist = dPoinLineDist ;
ptSt = ptEn ;
bContinue = GetNextPoint( ptEn) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
PolyLine::SplitPolyLineAtPoint( const Point3d& ptPoint, PolyLine& Loop1, PolyLine& Loop2, double dTol) const
{
// Rinomino la lista di punti della PolyLine.
const PNTULIST& LoopList = 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) ;
// 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 ;
dDistCalc.GetSqDist( dSqDist) ;
if ( dSqDist < dMinSqDist) {
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
itMinDistSt = itSt ;
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
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) ;
double dSqDist ;
if ( dDistCalc.GetSqDist( dSqDist) && dSqDist < dMinSqDist) {
dMinSqDist = dSqDist ;
itMinDistEnd = itEnd ;
}
}
// Se il punto non sta sul loop, lo segnalo.
if ( dMinSqDist > dTol * dTol)
// Se il punto non sta sulla polilinea, non ha senso cambiare l'inizio
if ( dMinSqDist > dToler * dToler)
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.
bool bPointOnEnd = false ;
auto itStop = itMinDistSt ;
auto itNext = itMinDistSt ;
++ itNext ;
if ( AreSamePointApprox( ptPoint, itStop->first))
;
else if ( AreSamePointApprox( ptPoint, itNext->first))
itStop = itNext ;
else {
bPointOnEnd = true ;
itStop = itNext ;
}
// 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( ptPoint, 0) ;
if ( bPointOnEnd) {
LoopList2.emplace_back( ptPoint, 0) ;
}
for ( auto it = itStop ; it != LoopList.end() ; ++ it) {
LoopList2.emplace_back( it->first, it->second) ;
}
// 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 ;
}
//----------------------------------------------------------------------------
bool
PolyLine::AddPolyLineToPolyLine( PolyLine& PolyToAdd, double dTol)
SplitPolyLineAtPoint( const PolyLine& plPoly, const Point3d& ptP, double dToler, PolyLine& plPoly1, PolyLine& plPoly2)
{
// Se la PolyLine a cui devo aggiungere l'altra chiusa, non posso aggiungere nulla.
if ( IsClosed())
// La polilinea deve contenere almeno due punti
if ( plPoly.GetPointNbr() < 2)
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 ;
GetLastPoint( ptLast) ;
auto it = PolyToAddList.begin() ;
if ( 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) {
AddUPoint( 0., it->first) ;
// 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 ;
}
}
// 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 ;
}
+8 -8
View File
@@ -165,7 +165,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
for ( auto i : m_vExtInd) {
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, ccClass) ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_OUT) {
bOk = false ;
break ;
@@ -178,7 +178,7 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv)
continue ;
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
if ( ccInt.GetCrossOrOverlapIntersCount() == 0 &&
ccInt.GetCurveClassification( 0, ccClass) &&
ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) &&
! ccClass.empty() && ccClass[0].nClass == CRVC_OUT) {
bOk = true ;
break ;
@@ -298,7 +298,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[m_vExtInd[i]]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 0, ccClass) ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
@@ -309,7 +309,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
IntersCurveCurve ccInt2( *pMyCrv, *m_vpLoop[k]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 0, ccClass2) ||
! ccInt2.GetCurveClassification( 0, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
@@ -1150,7 +1150,7 @@ SurfFlatRegion::CloneChunk( int nChunk) const
//----------------------------------------------------------------------------
bool
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const
SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
{
// la curva deve già essere nel riferimento intrinseco della regione
// verifico lo stato
@@ -1179,7 +1179,7 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass
IntersCurveCurve ccInt( Crv, *pLoop) ;
// classificazione
CRVCVECTOR ccPart ;
if ( ! ccInt.GetCurveClassification( 0, ccPart))
if ( ! ccInt.GetCurveClassification( 0, dLenMin, ccPart))
return false ;
for ( auto& ccOne : ccPart) {
switch ( ccOne.nClass) {
@@ -1272,7 +1272,7 @@ SurfFlatRegion::MyGetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass
//----------------------------------------------------------------------------
bool
SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass) const
SurfFlatRegion::GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const
{
// verifico lo stato
if ( m_nStatus != OK || m_vpLoop.empty())
@@ -1293,7 +1293,7 @@ SurfFlatRegion::GetCurveClassification( const ICurve& Crv, CRVCVECTOR& ccClass)
pCrvLoc = pCopyCrv ;
}
// esecuzione classificazione nel riferimento intrinseco
return MyGetCurveClassification( *pCrvLoc, ccClass) ;
return MyGetCurveClassification( *pCrvLoc, dLenMin, ccClass) ;
}
//----------------------------------------------------------------------------
+2 -2
View File
@@ -92,7 +92,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, CRVCVECTOR& ccClass) const override ;
bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ;
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
public : // IGeoObjRW
@@ -131,7 +131,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, CRVCVECTOR& ccClass) const ;
bool MyGetCurveClassification( const ICurve& Crv, double dLenMin, 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) ;
+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, ccClass))
if ( ! Other.MyGetCurveClassification( *pLoop, EPS_SMALL, 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, ccClass) ||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// lo inserisco
+94 -464
View File
File diff suppressed because it is too large Load Diff
+33 -61
View File
@@ -18,7 +18,6 @@
#include "GeoObjRW.h"
#include "/EgtDev/Include/EGkSurfTriMesh.h"
#include "/EgtDev/Include/EGkHashGrids3d.h"
#include "/EgtDev/Include/EGkPointGrid3d.h"
#include <deque>
#include <set>
@@ -95,34 +94,15 @@ typedef std::unordered_map< int, Chain> CHAINMAP ;
typedef std::unordered_map< int, TRIA3DVECTOR> TRIA3DVECTORMAP ;
//----------------------------------------------------------------------------
// 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
//----------------------------------------------------------------------------
// Struttura intersezione linea-faccia
struct LineFacetClass {
Point3d ptSt, ptEn ;
int nTypeA, nTypeB ;
LineFacetClass() {
LineFacetClass( void) {
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 ;
@@ -132,32 +112,27 @@ struct LineFacetClass {
typedef std::vector<LineFacetClass> LineFacetClassVector ;
//----------------------------------------------------------------------------
enum FacetPlaneIntersType { FPI_ERROR = 0, FPI_CUT = 1, FPI_INN = 2, FPI_OUT = 3, FPI_ON = 4 } ;
enum FacetPlaneIntersType { FPI_ERROR = 0, FPI_CUT = 1, FPI_IN = 2, FPI_OUT = 3, FPI_ON = 4 } ;
//----------------------------------------------------------------------------
enum LineClassificationWithExtPolygon { LCP_ERROR = 0, LCP_INN = 1, LCP_OUT = 2, LCP_OVERLAP = 3 } ;
//----------------------------------------------------------------------------
// Definizione strutture e contenitori
// Contatti interno-interno
// 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 ;
@@ -169,7 +144,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 ;
@@ -231,7 +206,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
bool Init( int nNumVert, int nNumTria, int nNumFacet = 0) override ;
void SetLinearTolerance( double dLinTol) override
{ m_dLinTol = EPS_SMALL/*std::max( dLinTol, EPS_SMALL)*/ ; } ///////////////////////////////////////////////////////////////
{ m_dLinTol = std::max( dLinTol, EPS_SMALL) ; }
void SetBoundaryAngle( double dBoundaryAngDeg) override
{ m_dBoundaryAng = std::max( dBoundaryAngDeg, EPS_ANG_SMALL) ;
m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ;
@@ -310,6 +285,7 @@ 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 ;
@@ -375,9 +351,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 ;
@@ -385,17 +361,17 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ;
void ResetHashGrids3d( void) const ;
bool VerifyHashGrids3d( void) const ;
void ResetPointGrid3d( void) const ;
bool VerifyPointGrid3d( 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 IntersFacetPlane( const SurfFlatRegion& Region, const PolyLine& ExtLoop, const Plane3d& plCutPlane,
LineFacetClassVector& IntersLinePart) ;
int IntersFacetPlane( const POLYLINEVECTOR& vFacetLoopsVec, const Plane3d& plCutPlane,
LineFacetClassVector& IntersLinePart) ;
int VerifyLoopPlane( const PolyLine& ExtLoop, const Plane3d& plCutPlane) ;
int IntersFacetPlane( const SurfFlatRegion& Region, const Plane3d& plCutPlane,
LineFacetClassVector& IntersLinePart) ;
bool IntersFacetFacet( const SurfFlatRegion& RegionA, const PolyLine& ExtLoopA,
const SurfFlatRegion& RegionB, const PolyLine& ExtLoopB,
LineFacetClassVector& IntersLinePart) ;
@@ -416,6 +392,11 @@ 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
@@ -425,29 +406,20 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
double m_dCosBndAng ; // coseno dell'angolo limite per considerare un lato un contorno
double m_dSmoothAng ; // angolo limite per mediare le normali (in gradi)
double m_dCosSmAng ; // coseno dell'angolo limite per mediare le normali
bool m_bOriented ; // la superficie orientata consistentemente in tutte le sue parti
bool m_bOriented ; // la superficie è orientata consistentemente in tutte le sue parti
bool m_bClosed ; // la superficie racchiude un volume
bool m_bFaceted ; // flag di validit della sfaccettatura
bool m_bFaceted ; // flag di validità della sfaccettatura
VERTVECTOR m_vVert ; // vettore dei vertici
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[2] ; // vettore proprietà temporanee
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
mutable BBox3d m_b3HGrd3d ; // Box3d collegato a Hash Grid 3d
mutable PointGrid3d* m_pPGrd3d ; // Point Grid 3d nel suo riferimento
mutable BBox3d m_b3HGrd3d ; // Box3d collegato a Hash Grid 3d
} ;
//----------------------------------------------------------------------------
//static bool ChangePolyLineStart( const Point3d& ptNewStart, PolyLine& Loop) ;
//// nSegNum 0-based
//static bool PointPositionOnPolyLine( const Point3d& ptPoint, /*const*/ PolyLine& Loop, int& nSegNum, double& dParOnSeg) ;
//static bool IsPointInsidePolyLine( const Point3d& ptP, /*const*/ PolyLine& plPoly) ;
//static bool SplitPolyLineAtPoint( const Point3d& ptPoint, /*const*/ PolyLine& Loop, PolyLine& Loop1, PolyLine& Loop2) ;
//static bool AddPolyLineToPolyLine(PolyLine& Poly, PolyLine& PolyToAdd) ;
//-----------------------------------------------------------------------------
inline SurfTriMesh* CreateBasicSurfTriMesh( void)
{ return ( static_cast<SurfTriMesh*>( CreateGeoObj( SRF_TRIMESH))) ; }
+493 -1916
View File
File diff suppressed because it is too large Load Diff
+874
View File
@@ -0,0 +1,874 @@
//----------------------------------------------------------------------------
// 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 ;
}
+64 -41
View File
@@ -22,15 +22,6 @@
using namespace std ;
//----------------------------------------------------------------------------
bool
SurfTriMesh::ResetFaceting( void)
{
m_bFaceted = false ;
m_vFacet.clear() ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::VerifyFaceting( void) const
@@ -44,14 +35,36 @@ 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 ;
// ricostruisco le sfaccettature
bool bOk = true ;
// indice faccia corrente
int nFacet = -1 ;
// ricostruisco le sfaccettature come definite in precedenza (dove possibile)
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
for ( int i = 0 ; i < int( m_vTria.size()) ; ++ i) {
// salto triangoli cancellati o già assegnati
if ( m_vTria[i].nIdVert[0] == SVT_DEL ||
@@ -60,32 +73,9 @@ SurfTriMesh::UpdateFaceting( void)
// assegno indice di faccia al triangolo
m_vTria[i].nIdFacet = ++ nFacet ;
m_vFacet.push_back( i) ;
// 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) ;
}
}
}
// aggiorno faccia
if ( ! UpdateOneFace( nFacet, i))
bOk = false ;
}
// se ci sono stati problemi, salvo nel log
@@ -97,6 +87,40 @@ 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)
@@ -114,7 +138,7 @@ SurfTriMesh::UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane,
}
if ( nV == SVT_NULL)
return false ;
double dTol = max( min( m_dLinTol, 20 * EPS_SMALL), /*2 **/ EPS_SMALL) ; ////////////////////////////////////////////////////
double dTol = max( min( m_dLinTol, 20 * EPS_SMALL), 2 * EPS_SMALL) ;
if ( ! PointInPlaneEpsilon( m_vVert[m_vTria[nT].nIdVert[nV]].ptP, plPlane, dTol))
return true ;
// il triangolo fa parte della faccia
@@ -413,7 +437,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
Plane3d plPlane ;
double dArea ;
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea, /*100 **/ EPS_SMALL))
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea, 100 * EPS_SMALL))
return false ;
// se loop esterno
if ( vtN * plPlane.GetVersN() > 0) {
@@ -712,10 +736,9 @@ SurfTriMesh::RemoveFacet( int nF)
if ( ! DoCompacting())
return false ;
// dichiaro necessità ricalcolo della grafica e di hashgrids3d e pointgrid3d
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
m_OGrMgr.Reset() ;
ResetHashGrids3d() ;
ResetPointGrid3d() ;
return true ;
}
+604
View File
@@ -0,0 +1,604 @@
//----------------------------------------------------------------------------
// 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 ;
}
+16 -20
View File
@@ -29,8 +29,7 @@ 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_bAllPartCut( true)*/
m_dTipRadius( 0), m_dRefRadius( 0), m_dCutterHeight( 0), m_dMrtChsWidth( 0), m_dMrtChsThickness( 0)
{
}
@@ -74,10 +73,6 @@ Tool::SetTolerances( double dLinTol, double dAngTolDeg)
bool
Tool::SetStdTool( const string& sToolName, double dH, double dR, double dCornR, double dCutterH, int nToolNum)
{
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////// Per test additivi //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//return SetAdditiveTool( sToolName, dH, dR, dCornR, nToolNum) ;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Impostazioni generali
m_sName = sToolName ;
m_nCurrentNum = nToolNum ;
@@ -680,7 +675,6 @@ Tool::SetAdditiveTool( const std::string& sToolName, double dH, double dR, doubl
if ( dH < EPS_SMALL || dR < EPS_SMALL || dRC < - EPS_SMALL)
return false ;
m_nType = ADDITIVE ;
m_dHeight = dH ;
m_dRadius = dR ;
m_dRCorner = dRC ;
@@ -689,13 +683,15 @@ Tool::SetAdditiveTool( const std::string& sToolName, double dH, double dR, doubl
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 < 0)
if ( dCylRad < EPS_SMALL)
return false ;
// Profilo
m_Outline.AddPoint( Point3d( 0, 0, 0)) ;
@@ -708,22 +704,19 @@ Tool::SetAdditiveTool( const std::string& sToolName, double dH, double dR, doubl
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 < EPS_SMALL)
if ( m_dRadius - m_dRCorner < 0)
return false ;
// Raggio corner nullo
if ( m_dRadius < EPS_SMALL) {
// Profilo
m_Outline.AddPoint( Point3d( 0, 0, 0)) ;
m_Outline.AddLine( Point3d( m_dRadius, 0, 0)) ;
m_Outline.SetCurveTempProp( 0, 1, 1) ;
m_Outline.AddLine( Point3d( m_dRadius, - m_dHeight, 0)) ;
m_Outline.SetCurveTempProp( 1, 1, 1) ;
m_Outline.AddLine( Point3d( 0, - m_dHeight, 0)) ;
m_Outline.SetCurveTempProp( 2, 1, 1) ;
// Utensile sferico
else if ( m_dRadius - m_dRCorner < EPS_SMALL)
;
// Raggio corner nullo: cilindro
else if ( m_dRCorner < EPS_SMALL) {
;
}
else {
// Profilo
@@ -732,6 +725,7 @@ Tool::SetAdditiveTool( const std::string& sToolName, double dH, double dR, doubl
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) ;
@@ -741,8 +735,10 @@ Tool::SetAdditiveTool( const std::string& sToolName, double dH, double dR, doubl
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) ;
}
}
return SetGenTool( sToolName, &m_Outline, nToolNum) ;
m_nType = ADDITIVE ;
return bToolDefined ;
}
+1 -2
View File
@@ -63,7 +63,7 @@ class Tool
const VCT3DVECTOR& GetArcNormalVec( void) const
{ return m_vArcNormals ; }
bool GetCuttingFlag() const
{ /*return m_bAllPartCut ;*/ return ( m_nType == GEN ? m_ArcLineApprox.GetTempProp( 1) == 1 : true ) ; }
{ return ( m_nType == GEN ? m_ArcLineApprox.GetTempProp( 1) == 1 : true ) ; }
public :
enum ToolType { UNDEF = 0, // Utensile indefinito
@@ -81,7 +81,6 @@ class Tool
private :
bool m_bApproxWithLines ;
//bool m_bAllPartCut ;
double m_dLinTol ;
double m_dAngTolDeg ;
std::string m_sName ;
+202 -250
View File
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------
// EgalTech 2014-2014
// EgalTech 2014-2021
//----------------------------------------------------------------------------
// File : Triangulate.cpp Data : 23.06.14 Versione : 1.5f6
// File : Triangulate.cpp Data : 18.12.21 Versione : 2.3l
// Contenuto : Implementazione della classe Triangulate.
//
//
@@ -12,63 +12,54 @@
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
//#include "stdafx.h"
//#include "DllMain.h"
//#include "Triangulate.h"
//#include "ProjPlane.h"
//#include "/EgtDev/Include/EGkPolyLine.h"
//#include "/EgtDev/Include/EGkPlane3d.h"
//#include "/EgtDev/Include/EGkStringUtils3d.h"
//#include <algorithm>
#include "stdafx.h"
#include "DllMain.h"
#include "Triangulate.h"
#include "ProjPlane.h"
#include "CurveComposite.h"
#include "CurveLine.h"
#include "/EgtDev/Include/EGkIntersCurves.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "earcut.hpp"
#include "/EgtDev/Include/EGkPolyLine.h"
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "tpp_interface.hpp"
#include <algorithm>
using namespace std ;
using namespace tpp ;
//----------------------------------------------------------------------------
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, TrgType trgType)
Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// pulisco i vettori di ritorno
vPt.clear() ;
vTr.clear() ;
// 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 ;
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
vPt.clear() ;
vPt.reserve( PL.GetPointNbr() - 1) ;
// salto il primo punto (coincide con l'ultimo)
Point3d ptP ;
@@ -80,18 +71,12 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr, TrgType t
// 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, vPol, vTr) &&
! MakeByEC3( vPt, vPol, vTr)) {
if ( ! MakeByEC2( vPt, vTr) &&
! MakeByEC3( vPt, vTr)) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC23(1)")
return false ;
return MakeByEC_HPP( PL, bCCW, vPt, vTr) ;
}
// se era CW, devo invertire il senso dei triangoli
@@ -103,13 +88,12 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr, TrgType t
//----------------------------------------------------------------------------
// In : POLYLINEVECTOR : vector of polylines, the first outer, the others inner
// trgType : triangulation type
// Out : PNTVECTOR (Point3d Vector) : points of the polyline
// INTVECTOR (int Vector) : 3*T indices of above points for T triangles
//----------------------------------------------------------------------------
bool
Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, TrgType trgType)
{
Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// pulisco i vettori di ritorno
vPt.clear() ;
vTr.clear() ;
@@ -117,7 +101,7 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, Tr
if ( &vPL == nullptr || vPL.empty())
return false ;
// se una sola polilinea mi riconduco al caso precedente
if ( vPL.size() == 1 && trgType == TRG_STANDARD)
if ( vPL.size() == 1)
return Make( vPL[0], vPt, vTr) ;
// verifico che la polilinea esterna sia chiusa e piana e calcolo il piano medio del poligono
double dArea ;
@@ -138,30 +122,11 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, Tr
return false ;
}
// 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 ;
// forzo esecuzione triangolazione con earcut.hpp
if ( FORCE_EARCUT_HPP) {
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
}
// ear clipping
// se non CCW inverto tutte le polilinee
if ( ! bCCW) {
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
@@ -169,8 +134,7 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, Tr
}
// calcolo ordine decrescente su Xmax o Ymax o Zmax secondo m_nPlane per le curve interne
INTVECTOR vOrd ;
if ( ! SortInternalLoops( vPL, vOrd))
return false ;
bool bOk = SortInternalLoops( vPL, vOrd) ;
// 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 ;
@@ -183,22 +147,27 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, Tr
// 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)
if ( ! GetPntVectorFromPolyline( vPL[0], false, vPt))
return false ;
bOk = bOk && GetPntVectorFromPolyline( vPL[0], false, vPt) ;
// ciclo sui percorsi interni ordinati secondo Xmax decrescente
PNTVECTOR vPi ;
vPi.reserve( nMax) ;
for ( int i = 1 ; i < int( vPL.size()) ; ++ i) {
for ( int i = 1 ; bOk && i < int( vPL.size()) ; ++ i) {
// riordino il percorso per avere punto iniziale con Xmax
if ( ! GetPntVectorFromPolyline( vPL[vOrd[i]], true, vPi))
return false ;
if ( ! GetPntVectorFromPolyline( vPL[vOrd[i]], true, vPi)) {
bOk = false ;
break ;
}
// cerco un punto del percorso esterno visibile dal punto iniziale del precedente interno
int nI ;
if ( ! GetOuterPntToJoin( vPt, vPi[0], nI))
return false ;
if ( ! GetOuterPntToJoin( vPt, vPi[0], nI)) {
bOk = false ;
break ;
}
// riordino percorso esterno per avere questo punto all'inizio
if ( ! ChangeStartPntVector( nI, vPt))
return false ;
if ( ! ChangeStartPntVector( nI, vPt)) {
bOk = false ;
break ;
}
// ripeto punto iniziale
vPt.push_back( vPt[0]) ;
// accodo percorso interno
@@ -214,20 +183,14 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, Tr
for ( int i = 0 ; i < int( vPL.size()) ; ++i)
const_cast<PolyLine&>(vPL[i]).Invert( true) ;
}
// 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) ;
if ( ! bOk)
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
// eseguo la triangolazione
if ( ! MakeByEC2( vPt, vPol, vTr) &&
! MakeByEC3( vPt, vPol, vTr)) {
if ( ! MakeByEC2( vPt, vTr) &&
! MakeByEC3( vPt, vTr)) {
LOG_ERROR( GetEGkLogger(), "Error in MakeByEC23(N)")
return false ;
return MakeByEC_HPP( vPL, bCCW, vPt, vTr) ;
}
// se era CW, devo invertire il senso dei triangoli
@@ -238,168 +201,112 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, Tr
}
//----------------------------------------------------------------------------
// Delaunay Triangulation ( Triangle library)
// Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0])
// Ear Clipping algorithm from mapbox
//----------------------------------------------------------------------------
bool
Triangulate::MakeByDelaunay( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr, bool bConforming, bool bQuality)
bool
Triangulate::MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr)
{
Plane3d plPlane ;
double dArea;
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
// 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)))
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) ;
}
// 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 = 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( vDelaunayVert.size() - 1) ;
vDelaunayConstr.push_back( 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 ( ! vMyPL[i].IsPointInsidePolyLine( pt)) {
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 ;
}
}
// 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 ;
}
}
// 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)
// 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 ;
// 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) ;
}
// triangoli
vTr = trGenerator.MyTriangleTraverse() ;
if ( ! bCCW)
reverse( vTr.begin(), vTr.end()) ;
return true ;
}
//----------------------------------------------------------------------------
bool
Triangulate::PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
const INTVECTOR& vPrev, const INTVECTOR& vNext)
Triangulate::MakeByEC_HPP( const POLYLINEVECTOR& vPL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// 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 ;
// 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)))
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 ;
}
}
}
m_vVert.reserve( n / 5) ;
// 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)")
return false ;
}
if ( ! bCCW)
reverse( vTr.begin(), vTr.end()) ;
return true ;
}
@@ -408,16 +315,22 @@ Triangulate::PrepareGrid( const PNTVECTOR& vPt, const INTVECTOR& vPol,
// Ear Clipping algorithm
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
Triangulate::MakeByEC( const PNTVECTOR& vPt, INTVECTOR& vTr)
{
// Clear triangle vector
vTr.clear() ;
// At least 3 points
int n = int( vPol.size()) ;
int n = int( vPt.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)) ;
@@ -456,7 +369,7 @@ Triangulate::MakeByEC( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& v
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] ;
@@ -480,16 +393,22 @@ Triangulate::MakeByEC( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& v
// Ear Clipping algorithm enhanced, choose smaller diagonal
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr)
{
// Clear triangle vector
vTr.clear() ;
// At least 3 points
int n = int( vPol.size()) ;
int n = int( vPt.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)) ;
@@ -576,7 +495,7 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
// 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] ;
@@ -601,16 +520,22 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
// AR = ( Lmax * Lmax) / ( 2 * Area) = SqLenMax / L1 * L2
//----------------------------------------------------------------------------
bool
Triangulate::MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& vTr)
Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr)
{
// Clear triangle vector
vTr.clear() ;
// At least 3 points
int n = int( vPol.size()) ;
int n = int( vPt.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)) ;
@@ -689,7 +614,7 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
// 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] ;
@@ -708,6 +633,36 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR&
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,
@@ -717,10 +672,7 @@ Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
bool bIsEar = true ;
// An ear must be convex (here counterclockwise)
if ( TriangleIsCCW( vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]]) &&
! Collinear( vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]]) /*&&
! AreSamePoint( vPt[vPol[vPrev[i]]], vPt[vPol[i]]) &&
! AreSamePoint( vPt[vPol[i]], vPt[vPol[vNext[i]]]) &&
! AreSamePoint( vPt[vPol[vNext[i]]], vPt[vPol[vPrev[i]]])*/ ) {
! Collinear( vPt[vPol[vPrev[i]]], vPt[vPol[i]], vPt[vPol[vNext[i]]])) {
// Loop over all vertices not part of the tentative ear
BBox3d b3Tria ;
b3Tria.Add( vPt[vPol[vPrev[i]]]) ;
@@ -756,7 +708,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 ;
}
@@ -986,7 +938,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) {
@@ -1082,14 +1034,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] ;
@@ -1105,7 +1057,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
@@ -1141,7 +1093,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) &&
@@ -1156,10 +1108,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
+7 -15
View File
@@ -16,27 +16,21 @@
#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
} ;
//----------------------------------------------------------------------------
class Triangulate
{
public :
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) ;
bool Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
bool Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
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 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) ;
@@ -58,5 +52,3 @@ class Triangulate
PointGrid3d m_VertGrid ;
INTVECTOR m_vVert ;
} ;
+12 -2
View File
@@ -35,7 +35,7 @@ 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_Tool( true)*/
m_nDexVoxRatio( 1), m_nNumBlock( 0), m_nConnectedCompoCount( 0), m_nCurrTool( - 1)
{
for ( int i = 0 ; i < N_MAPS ; ++ i) {
m_nNx[i] = 0 ;
@@ -47,7 +47,6 @@ VolZmap::VolZmap(void)
}
m_nTempProp[0] = 0 ;
m_nTempProp[1] = 0 ;
//m_Tool.SetTolerances( LIN_TOL_STD, ANG_TOL_APPROX_DEG) ;
}
//----------------------------------------------------------------------------
@@ -2033,6 +2032,15 @@ VolZmap::SetChiselTool( const string& sToolName, double dH, double dW, double dT
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)
@@ -2075,6 +2083,8 @@ VolZmap::ResetAllTools( void)
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 ;
+10 -6
View File
@@ -91,6 +91,7 @@ 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
@@ -338,13 +339,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW
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/*, double dHei, double dRad, double dCornerRad*/) ;
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,
@@ -355,7 +359,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) const ;
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting = true) const ;
bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen,
bool bTapLow, bool bTapUp,
@@ -365,7 +369,7 @@ 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) const ;
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting = true) 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 ;
+25 -118
View File
@@ -16,10 +16,12 @@
#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"
@@ -30,103 +32,6 @@
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
@@ -2376,7 +2281,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) const
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting) const
{
// Porto la linea nel riferimento del cilindro
Point3d ptP = ptLineSt ; ptP.ToLoc( CylFrame) ;
@@ -2386,14 +2291,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 EpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
double dEpsRad = ( bSubtracting ? ( vtV.IsZeroXY() ? - EPS_SMALL : 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 * EpsRad) {
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
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 * EpsRad) {
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
nBasInt += 2 ;
vtN2 = - Z_AX ;
}
@@ -2776,7 +2681,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) const
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2, bool bSubtracting) const
{
// Controllo sulle dimensioni lineari affinché sia valido il poliedro
if ( dLenX <= EPS_SMALL || dLenY <= EPS_SMALL || dLenZ <= EPS_SMALL)
@@ -2800,17 +2705,19 @@ VolZmap::IntersLineMyPolyhedron( const Point3d& ptLineSt, const Vector3d& vtLine
// Controlli affinché non vengano tagliati dexel a filo
// con il passaggio dell'utensile:
// 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 ;
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 ;
}
// Punti notevoli
Point3d ptI1 = ptP + ( ( ptFacet135.y - ptP.y) / vtV.y) * vtV ;
@@ -3188,7 +3095,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 ( IntersLineBox( ptLocP, vtDirL, b3BlockBox.GetMin(), b3BlockBox.GetMax())) {
if ( TestIntersLineBox( ptLocP, vtDirL, b3BlockBox.GetMin(), b3BlockBox.GetMax())) {
// Ciclo sui voxel del blocco.
// Triangoli smooth
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
@@ -3199,7 +3106,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 ( ! IntersLineBox( ptLocP, vtDirL, b3Vox.GetMin(), b3Vox.GetMax()))
if ( ! TestIntersLineBox( 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] ;
@@ -3374,7 +3281,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( b3BlockBox, plPlaneLoc)) {
if ( TestIntersPlaneBox( plPlaneLoc, b3BlockBox)) {
// Ciclo sui voxel del blocco.
// Triangoli smooth
for ( int nV = 0 ; nV < int( m_BlockSmoothTria[nB].size()) ; ++ nV) {
@@ -3382,7 +3289,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(b3Vox, plPlaneLoc))
if ( ! TestIntersPlaneBox( plPlaneLoc, b3Vox))
continue ;
for ( int nT = 0 ; nT < int( m_BlockSmoothTria[nB][nV].vTria.size()) ; ++ nT) {
Triangle3d trTria = m_BlockSmoothTria[nB][nV].vTria[nT] ;
@@ -3486,5 +3393,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( b3Zmap, plPlane) ;
return TestIntersPlaneBox( plPlane, b3Zmap) ;
}
+3 -7
View File
@@ -28,10 +28,6 @@ using namespace std ;
bool
VolZmap::Create( const Point3d& ptO, double dLengthX, double dLengthY, double dLengthZ, double dStep, bool bTriDex)
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////// Per test additivi //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//return CreateEmptyMap( ptO, dLengthX, dLengthY, dLengthZ, dStep, 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 ;
@@ -224,7 +220,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
// Determino le intersezioni della retta con la regione
CRVCVECTOR IntersectionResults ;
Surf.GetCurveClassification( GridLine, IntersectionResults) ;
Surf.GetCurveClassification( GridLine, EPS_SMALL, IntersectionResults) ;
// Analizzo le parti in cui la retta è stata divisa
int nPart = int( IntersectionResults.size()) ;
@@ -331,7 +327,7 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
// Determino le intersezioni della retta con la regione
CRVCVECTOR IntersectionResults ;
Surf.GetCurveClassification( GridLine, IntersectionResults) ;
Surf.GetCurveClassification( GridLine, EPS_SMALL, IntersectionResults) ;
// Analizzo le parti
int nPart = int( IntersectionResults.size()) ;
@@ -736,7 +732,7 @@ VolZmap::CreateEmptyMap( const Point3d& ptO, double dLengthX, double dLengthY, d
m_dMaxZ[2] = ( bTriDex ? dLengthY : 0) ;
// Tipologia
m_nShape = BOX ;
m_nShape = GENERIC ;
// Aggiornamento dello stato
m_nStatus = OK ;
+1
View File
@@ -18,6 +18,7 @@
#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"
+572 -399
View File
File diff suppressed because it is too large Load Diff
-635
View File
@@ -1,635 +0,0 @@
/*! \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
@@ -0,0 +1,823 @@
#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
@@ -1,43 +0,0 @@
/*! \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
@@ -1,29 +0,0 @@
/*! \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
@@ -1,719 +0,0 @@
/*! \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
@@ -1,300 +0,0 @@
/*! \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 */
-16197
View File
File diff suppressed because it is too large Load Diff