Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 29138a8a0b | |||
| 99b503a637 | |||
| acad826499 | |||
| 2f4d75b958 | |||
| 7e2bf848a9 | |||
| 4f62467320 | |||
| 78d4d79cbf | |||
| 1c8ee6a332 | |||
| e4b5e4c0a9 | |||
| 6f60e2d711 | |||
| 20a9efaebb | |||
| fd9a6a9847 | |||
| c773b8829e | |||
| 8710115634 | |||
| 4056be90d9 | |||
| 77640f3a6f | |||
| 9b11212d07 | |||
| 2ea8812f52 | |||
| e2ae42a045 | |||
| 41d76f0c3f | |||
| d2b77833fd | |||
| 9ac1a56535 | |||
| 9aca1f1e25 | |||
| e3c10e9bd3 | |||
| e84a34917a | |||
| 009328b31b | |||
| ca83aaa249 | |||
| 6cdfdf6db8 | |||
| 6628b1ee24 | |||
| 2d70d27d85 | |||
| 63d62fcc92 | |||
| b4303d0e0d | |||
| 9369447886 | |||
| dca713b240 | |||
| aa82c82ddc | |||
| 8a6dbf044e | |||
| 76d009ddbe | |||
| 6deff01b6e | |||
| e79bb117d2 | |||
| 2ea4b59b9b | |||
| 6e9465247f | |||
| 1d1fb41212 |
+2
-2
@@ -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
@@ -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
@@ -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 ;
|
||||
|
||||
Binary file not shown.
@@ -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" />
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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) ;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) ;
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+33
-61
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
@@ -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 ;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 ;
|
||||
|
||||
@@ -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
@@ -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
@@ -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 ;
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
-635
@@ -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
@@ -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 = ¤tBlock[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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user