Skip to content

Commit e4b8c7b

Browse files
committed
TPVWSimplifier::simplify(): finer grain progress report
1 parent 6cde4b2 commit e4b8c7b

File tree

11 files changed

+236
-40
lines changed

11 files changed

+236
-40
lines changed

include/geos/coverage/CoverageBoundarySegmentFinder.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <geos/geom/Coordinate.h>
2121
#include <geos/geom/LineSegment.h>
2222
#include <geos/export.h>
23+
#include <geos/util/Progress.h>
2324

2425
namespace geos {
2526
namespace geom {
@@ -57,7 +58,8 @@ class CoverageBoundarySegmentFinder : public geos::geom::CoordinateSequenceFilte
5758

5859

5960
static LineSegment::UnorderedSet
60-
findBoundarySegments(const std::vector<const Geometry*>& geoms);
61+
findBoundarySegments(const std::vector<const Geometry*>& geoms,
62+
geos::util::ProgressFunction* progressFunction);
6163

6264
static bool isBoundarySegment(
6365
const LineSegment::UnorderedSet& boundarySegs,

include/geos/coverage/CoverageEdge.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <geos/geom/CoordinateSequence.h>
2121
#include <geos/geom/LineSegment.h>
2222
#include <geos/util.h>
23+
#include <geos/util/Progress.h>
2324

2425
// Forward declarations
2526
namespace geos {
@@ -116,7 +117,8 @@ class GEOS_DLL CoverageEdge {
116117

117118
static std::unique_ptr<MultiLineString> createLines(
118119
const std::vector<CoverageEdge*>& edges,
119-
const GeometryFactory* geomFactory);
120+
const GeometryFactory* geomFactory,
121+
geos::util::ProgressFunction* progressFunction);
120122

121123
std::unique_ptr<LineString> toLineString(
122124
const GeometryFactory* geomFactory);

include/geos/coverage/CoverageRingEdges.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <geos/geom/Coordinate.h>
1919
#include <geos/geom/LineSegment.h>
2020
#include <geos/coverage/CoverageEdge.h> // to materialize CoverageEdge
21+
#include <geos/util/Progress.h>
2122

2223
#include <set>
2324
#include <map>
@@ -72,10 +73,11 @@ class GEOS_DLL CoverageRingEdges {
7273

7374
public:
7475

75-
CoverageRingEdges(const std::vector<const Geometry*>& coverage)
76+
CoverageRingEdges(const std::vector<const Geometry*>& coverage,
77+
geos::util::ProgressFunction* progressFunction)
7678
: m_coverage(coverage)
7779
{
78-
build();
80+
build(progressFunction);
7981
};
8082

8183

@@ -96,14 +98,15 @@ class GEOS_DLL CoverageRingEdges {
9698
/**
9799
* Recreates the polygon coverage from the current edge values.
98100
*
101+
* @param progressFunction Progress function or null
99102
* @return an array of polygonal geometries representing the coverage
100103
*/
101-
std::vector<std::unique_ptr<Geometry>> buildCoverage() const;
104+
std::vector<std::unique_ptr<Geometry>> buildCoverage(geos::util::ProgressFunction* progressFunction) const;
102105

103106

104107
private:
105108

106-
void build();
109+
void build(geos::util::ProgressFunction* progressFunction);
107110

108111
void addRingEdges(
109112
const LinearRing* ring,
@@ -140,10 +143,12 @@ class GEOS_DLL CoverageRingEdges {
140143
const CoordinateSequence& ring);
141144

142145
Coordinate::UnorderedSet findMultiRingNodes(
143-
const std::vector<const Geometry*>& coverage);
146+
const std::vector<const Geometry*>& coverage,
147+
geos::util::ProgressFunction* progressFunction);
144148

145149
Coordinate::UnorderedSet findBoundaryNodes(
146-
LineSegment::UnorderedSet& lineSegments);
150+
LineSegment::UnorderedSet& lineSegments,
151+
geos::util::ProgressFunction* progressFunction);
147152

148153
std::unique_ptr<Geometry> buildPolygonal(
149154
const Geometry* geom) const;

include/geos/coverage/VertexRingCounter.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <geos/geom/CoordinateSequenceFilter.h>
2020
#include <geos/geom/Coordinate.h>
2121
#include <geos/export.h>
22+
#include <geos/util/Progress.h>
2223

2324
namespace geos {
2425
namespace geom {
@@ -54,7 +55,8 @@ class VertexRingCounter : public geos::geom::CoordinateSequenceFilter
5455

5556
static void count(
5657
const std::vector<const Geometry*>& geoms,
57-
std::map<Coordinate, std::size_t>& counts);
58+
std::map<Coordinate, std::size_t>& counts,
59+
geos::util::ProgressFunction* progressFunction);
5860

5961
private:
6062

src/coverage/CoverageBoundarySegmentFinder.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,22 @@ namespace coverage { // geos.coverage
2828
// public static
2929
LineSegment::UnorderedSet
3030
CoverageBoundarySegmentFinder::findBoundarySegments(
31-
const std::vector<const Geometry*>& geoms)
31+
const std::vector<const Geometry*>& geoms,
32+
geos::util::ProgressFunction* progressFunction)
3233
{
3334
LineSegment::UnorderedSet segs;
3435
CoverageBoundarySegmentFinder finder(segs);
35-
for (const Geometry* geom : geoms) {
36+
const size_t iterCount = geoms.size();
37+
const size_t notificationInterval = std::max<size_t>(1, iterCount / 100);
38+
for (size_t i = 0, iNotify = 0; i < iterCount; ++i) {
39+
const Geometry* geom = geoms[i];
3640
geom->apply_ro(finder);
41+
if (progressFunction) {
42+
geos::util::ProgressFunctionIteration(*progressFunction, i, iterCount, iNotify, notificationInterval);
43+
}
44+
}
45+
if (progressFunction) {
46+
(*progressFunction)(1.0, nullptr);
3747
}
3848
return segs;
3949
}

src/coverage/CoverageEdge.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,23 @@ CoverageEdge::createEdge(const CoordinateSequence& ring,
5555
std::unique_ptr<MultiLineString>
5656
CoverageEdge::createLines(
5757
const std::vector<CoverageEdge*>& edges,
58-
const GeometryFactory* geomFactory)
58+
const GeometryFactory* geomFactory,
59+
geos::util::ProgressFunction* progressFunction)
5960
{
6061
std::vector<std::unique_ptr<LineString>> lines;
61-
for (const CoverageEdge* edge : edges) {
62+
const size_t iterCount = edges.size();
63+
const size_t notificationInterval = std::max<size_t>(1, iterCount / 100);
64+
for (size_t i = 0, iNotify = 0; i < iterCount; ++i) {
65+
const CoverageEdge* edge = edges[i];
6266
auto cs = edge->getCoordinates()->clone();
6367
auto ls = geomFactory->createLineString(std::move(cs));
6468
lines.push_back(std::move(ls));
69+
if (progressFunction) {
70+
geos::util::ProgressFunctionIteration(*progressFunction, i, iterCount, iNotify, notificationInterval);
71+
}
72+
}
73+
if (progressFunction) {
74+
(*progressFunction)(1.0, nullptr);
6575
}
6676
return geomFactory->createMultiLineString(std::move(lines));
6777
}

src/coverage/CoverageRingEdges.cpp

Lines changed: 115 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,47 @@ CoverageRingEdges::selectEdges(std::size_t ringCount) const
6161

6262
/* private */
6363
void
64-
CoverageRingEdges::build()
64+
CoverageRingEdges::build(geos::util::ProgressFunction* progressFunction)
6565
{
66-
Coordinate::UnorderedSet nodes = findMultiRingNodes(m_coverage);
67-
LineSegment::UnorderedSet boundarySegs = CoverageBoundarySegmentFinder::findBoundarySegments(m_coverage);
68-
Coordinate::UnorderedSet boundaryNodes = findBoundaryNodes(boundarySegs);
66+
constexpr double RATIO_FIRST_PASS = 0.1;
67+
constexpr double RATIO_SECOND_PASS = 0.2;
68+
constexpr double RATIO_THIRD_PASS = 0.9;
69+
constexpr double RATIO_FOURTH_PASS = 1.0;
70+
geos::util::ProgressFunction subProgress;
71+
if (progressFunction)
72+
{
73+
subProgress = geos::util::CreateScaledProgressFunction(
74+
0, RATIO_FIRST_PASS, *progressFunction);
75+
}
76+
Coordinate::UnorderedSet nodes = findMultiRingNodes(m_coverage, progressFunction ? &subProgress : nullptr);
77+
78+
if (progressFunction)
79+
{
80+
subProgress = geos::util::CreateScaledProgressFunction(
81+
RATIO_FIRST_PASS, RATIO_SECOND_PASS, *progressFunction);
82+
}
83+
LineSegment::UnorderedSet boundarySegs = CoverageBoundarySegmentFinder::findBoundarySegments(
84+
m_coverage, progressFunction ? &subProgress : nullptr);
85+
86+
if (progressFunction)
87+
{
88+
subProgress = geos::util::CreateScaledProgressFunction(
89+
RATIO_SECOND_PASS, RATIO_THIRD_PASS, *progressFunction);
90+
}
91+
Coordinate::UnorderedSet boundaryNodes = findBoundaryNodes(
92+
boundarySegs, progressFunction ? &subProgress : nullptr);
6993
nodes.insert(boundaryNodes.begin(), boundaryNodes.end());
7094

95+
if (progressFunction)
96+
{
97+
subProgress = geos::util::CreateScaledProgressFunction(
98+
RATIO_THIRD_PASS, RATIO_FOURTH_PASS, *progressFunction);
99+
}
71100
std::map<LineSegment, CoverageEdge*> uniqueEdgeMap;
72-
for (const Geometry* geom : m_coverage) {
101+
const size_t iterCount = m_coverage.size();
102+
const size_t notificationInterval = std::max<size_t>(1, iterCount / 100);
103+
for (size_t i = 0, iNotify = 0; i < iterCount; ++i) {
104+
const Geometry* geom = m_coverage[i];
73105
for (std::size_t ipoly = 0; ipoly < geom->getNumGeometries(); ipoly++) {
74106
util::ensureNoCurvedComponents(geom->getGeometryN(ipoly));
75107

@@ -91,6 +123,13 @@ CoverageRingEdges::build()
91123
addRingEdges(hole, nodes, boundarySegs, uniqueEdgeMap);
92124
}
93125
}
126+
127+
if (progressFunction) {
128+
geos::util::ProgressFunctionIteration(subProgress, i, iterCount, iNotify, notificationInterval);
129+
}
130+
}
131+
if (progressFunction) {
132+
(*progressFunction)(1.0, nullptr);
94133
}
95134
}
96135

@@ -254,54 +293,117 @@ CoverageRingEdges::next(std::size_t index, const CoordinateSequence& ring)
254293

255294
/* private */
256295
Coordinate::UnorderedSet
257-
CoverageRingEdges::findMultiRingNodes(const std::vector<const Geometry*>& coverage)
296+
CoverageRingEdges::findMultiRingNodes(const std::vector<const Geometry*>& coverage,
297+
geos::util::ProgressFunction* progressFunction)
258298
{
259299
std::map<Coordinate, std::size_t> vertexRingCount;
260-
VertexRingCounter::count(coverage, vertexRingCount);
300+
geos::util::ProgressFunction subProgress;
301+
if (progressFunction)
302+
{
303+
subProgress = geos::util::CreateScaledProgressFunction(
304+
0, 0.5, *progressFunction);
305+
}
306+
307+
VertexRingCounter::count(coverage, vertexRingCount, progressFunction ? &subProgress : nullptr);
261308
Coordinate::UnorderedSet nodes;
262309
// for (Coordinate v : vertexCount.keySet()) {
263310
// if (vertexCount.get(v) > 2) {
264311
// nodes.add(v);
265312
// }
266313
// }
314+
const size_t iterCount = vertexRingCount.size();
315+
const size_t notificationInterval = std::max<size_t>(1, iterCount / 100);
316+
size_t i = 0, iNotify = 0;
317+
if (progressFunction)
318+
{
319+
subProgress = geos::util::CreateScaledProgressFunction(
320+
0.5, 1.0, *progressFunction);
321+
}
267322
for (const auto &mapPair : vertexRingCount) {
268323
const Coordinate& v = mapPair.first;
269324
std::size_t count = mapPair.second;
270325
if (count > 2)
271326
nodes.insert(v);
327+
if (progressFunction) {
328+
geos::util::ProgressFunctionIteration(subProgress, i, iterCount, iNotify, notificationInterval);
329+
}
330+
++i;
331+
}
332+
if (progressFunction) {
333+
(*progressFunction)(1.0, nullptr);
272334
}
273335
return nodes;
274336
}
275337

276338

277339
/* private */
278340
Coordinate::UnorderedSet
279-
CoverageRingEdges::findBoundaryNodes(LineSegment::UnorderedSet& boundarySegments)
341+
CoverageRingEdges::findBoundaryNodes(LineSegment::UnorderedSet& boundarySegments,
342+
geos::util::ProgressFunction* progressFunction)
280343
{
281344
std::unordered_map<Coordinate, std::size_t, Coordinate::HashCode> counter;
282-
for (const LineSegment& seg : boundarySegments) {
283-
counter[seg.p0] += 1;
284-
counter[seg.p1] += 1;
345+
geos::util::ProgressFunction subProgress;
346+
if (progressFunction)
347+
{
348+
subProgress = geos::util::CreateScaledProgressFunction(
349+
0, 0.5, *progressFunction);
350+
}
351+
{
352+
const size_t iterCount = boundarySegments.size();
353+
const size_t notificationInterval = std::max<size_t>(1, iterCount / 100);
354+
size_t i = 0, iNotify = 0;
355+
for (const LineSegment& seg : boundarySegments) {
356+
counter[seg.p0] += 1;
357+
counter[seg.p1] += 1;
358+
if (progressFunction) {
359+
geos::util::ProgressFunctionIteration(subProgress, i, iterCount, iNotify, notificationInterval);
360+
}
361+
++i;
362+
}
285363
}
286364

365+
if (progressFunction)
366+
{
367+
subProgress = geos::util::CreateScaledProgressFunction(
368+
0.5, 1.0, *progressFunction);
369+
}
287370
Coordinate::UnorderedSet nodes;
371+
const size_t iterCount = counter.size();
372+
const size_t notificationInterval = std::max<size_t>(1, iterCount / 100);
373+
size_t i = 0, iNotify = 0;
288374
for (const auto& c : counter) {
289375
const Coordinate& v = c.first;
290376
std::size_t count = c.second;
291377
if (count > 2)
292378
nodes.insert(v);
379+
if (progressFunction) {
380+
geos::util::ProgressFunctionIteration(subProgress, i, iterCount, iNotify, notificationInterval);
381+
}
382+
++i;
383+
}
384+
if (progressFunction) {
385+
(*progressFunction)(1.0, nullptr);
293386
}
294387
return nodes;
295388
}
296389

297390

298391
/* public */
299392
std::vector<std::unique_ptr<Geometry>>
300-
CoverageRingEdges::buildCoverage() const
393+
CoverageRingEdges::buildCoverage(geos::util::ProgressFunction* progressFunction) const
301394
{
302395
std::vector<std::unique_ptr<Geometry>> result;
303-
for (const Geometry* geom : m_coverage) {
396+
const size_t iterCount = m_coverage.size();
397+
const size_t notificationInterval = std::max<size_t>(1, iterCount / 100);
398+
for (size_t i = 0, iNotify = 0; i < iterCount; ++i) {
399+
const Geometry* geom = m_coverage[i];
304400
result.push_back(buildPolygonal(geom));
401+
if (progressFunction) {
402+
geos::util::ProgressFunctionIteration(*progressFunction, i, iterCount, iNotify, notificationInterval);
403+
}
404+
}
405+
if (progressFunction) {
406+
(*progressFunction)(1.0, nullptr);
305407
}
306408
return result;
307409
}

0 commit comments

Comments
 (0)