Skip to content

Commit c1e2f2f

Browse files
committed
CoverageSimplify: add progress callback and add GEOSCoverageSimplifyVWWithProgress_r()
1 parent cd8275e commit c1e2f2f

13 files changed

Lines changed: 290 additions & 44 deletions

File tree

capi/geos_c.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,5 +2061,15 @@ extern "C" {
20612061
return GEOSCoverageSimplifyVW_r(handle, input, tolerance, preserveBoundary);
20622062
}
20632063

2064+
Geometry*
2065+
GEOSCoverageSimplifyVWWithProgress(const Geometry* input, double tolerance,
2066+
int preserveBoundary,
2067+
GEOSProgressCallback_r progressFunc,
2068+
void* progressUserData)
2069+
{
2070+
return GEOSCoverageSimplifyVWWithProgress_r(
2071+
handle, input, tolerance, preserveBoundary, progressFunc, progressUserData);
2072+
}
2073+
20642074

20652075
} /* extern "C" */

capi/geos_c.h.in

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,23 @@ typedef void (*GEOSMessageHandler)(GEOS_PRINTF_FORMAT const char *fmt, ...)
117117
*/
118118
typedef void (*GEOSMessageHandler_r)(const char *message, void *userdata);
119119

120+
121+
/**
122+
* A GEOS progression and cancel function.
123+
*
124+
* Such function takes a progression ratio, and an optional
125+
* message, and returns true if computation must continue, or false if it
126+
* must be interrupted.
127+
*
128+
* \param progressRatio Progression ratio (between 0 and 1)
129+
* \param message Information message (can be NULL)
130+
* \param userdata the user data pointer that was passed to GEOS together with
131+
* this callback.
132+
* \return TRUE if processing must continue, or FALSE to interrupt it.
133+
*/
134+
typedef int (*GEOSProgressCallback_r)(double progressRatio, const char* message, void* userdata);
135+
136+
120137
/*
121138
* When we're included by geos_c.cpp, these types are #defined to the
122139
* C++ definitions via preprocessor. We don't touch them to allow the
@@ -886,6 +903,16 @@ GEOSCoverageSimplifyVW_r(
886903
double tolerance,
887904
int preserveBoundary);
888905

906+
/** \see GEOSCoverageSimplifyVWWithProgress */
907+
extern GEOSGeometry GEOS_DLL *
908+
GEOSCoverageSimplifyVWWithProgress_r(
909+
GEOSContextHandle_t extHandle,
910+
const GEOSGeometry* input,
911+
double tolerance,
912+
int preserveBoundary,
913+
GEOSProgressCallback_r progressFunc,
914+
void* progressUserData);
915+
889916
/** \see GEOSCoverageCleanParams_create */
890917
extern GEOSCoverageCleanParams GEOS_DLL *
891918
GEOSCoverageCleanParams_create_r(
@@ -4321,6 +4348,40 @@ extern GEOSGeometry GEOS_DLL * GEOSCoverageSimplifyVW(
43214348
double tolerance,
43224349
int preserveBoundary);
43234350

4351+
/**
4352+
* Operates on a coverage (represented as a list of polygonal geometry
4353+
* with exactly matching edge geometry) to apply a Visvalingam–Whyatt
4354+
* simplification to the edges, reducing complexity in proportion with
4355+
* the provided tolerance, while retaining a valid coverage (no edges
4356+
* will cross or touch after the simplification).
4357+
* Geometries never disappear, but they may be simplified down to just
4358+
* a triangle. Also, some invalid geoms (such as Polygons which have too
4359+
* few non-repeated points) will be returned unchanged.
4360+
* If the input dataset is not a valid coverage due to overlaps,
4361+
* it will still be simplified, but invalid topology such as crossing
4362+
* edges will still be invalid.
4363+
*
4364+
* \param input The polygonal coverage to access,
4365+
* stored in a geometry collection. All members must be POLYGON
4366+
* or MULTIPOLYGON.
4367+
* \param tolerance A tolerance parameter in linear units.
4368+
* \param preserveBoundary Use 1 to preserve the outside edges
4369+
* of the coverage without simplification,
4370+
* 0 to allow them to be simplified.
4371+
* \param progressFunc Progress callback (or null)
4372+
* \param progressUserData User data passed to progress callback (can be null)
4373+
* \return A collection containing the simplified geometries, or null
4374+
* on error.
4375+
*
4376+
* \since 3.14
4377+
*/
4378+
extern GEOSGeometry GEOS_DLL * GEOSCoverageSimplifyVWWithProgress(
4379+
const GEOSGeometry* input,
4380+
double tolerance,
4381+
int preserveBoundary,
4382+
GEOSProgressCallback_r progressFunc,
4383+
void* progressUserData);
4384+
43244385
/**
43254386
* Create a default GEOSCoverageCleanParams object for controlling
43264387
* the way invalid polygon interactions are repaird by \ref GEOSCoverageCleanWithParams.
@@ -5328,7 +5389,7 @@ extern char GEOS_DLL GEOSIntersects(const GEOSGeometry* g1, const GEOSGeometry*
53285389
extern char GEOS_DLL GEOSCrosses(const GEOSGeometry* g1, const GEOSGeometry* g2);
53295390

53305391
/**
5331-
* Tests if geometry g1 is completely within g2,
5392+
* Tests if geometry g1 is completely within g2,
53325393
* but not wholly contained in the boundary of g2.
53335394
* \param g1 Input geometry
53345395
* \param g2 Input geometry

capi/geos_ts_c.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
#include <geos/util/Interrupt.h>
115115
#include <geos/util/UniqueCoordinateArrayFilter.h>
116116
#include <geos/util/Machine.h>
117+
#include <geos/util/Progress.h>
117118
#include <geos/version.h>
118119

119120
// This should go away
@@ -4522,6 +4523,25 @@ extern "C" {
45224523
double tolerance,
45234524
int preserveBoundary)
45244525
{
4526+
return GEOSCoverageSimplifyVWWithProgress_r(extHandle, input, tolerance,
4527+
preserveBoundary,
4528+
nullptr, nullptr);
4529+
}
4530+
4531+
Geometry*
4532+
GEOSCoverageSimplifyVWWithProgress_r(GEOSContextHandle_t extHandle,
4533+
const Geometry* input,
4534+
double tolerance,
4535+
int preserveBoundary,
4536+
GEOSProgressCallback_r progressFunc,
4537+
void* progressUserData)
4538+
{
4539+
geos::util::ProgressFunction progressFunction =
4540+
[progressFunc, progressUserData](double progress, const char* message)
4541+
{
4542+
return progressFunc(progress, message, progressUserData);
4543+
};
4544+
45254545
using geos::coverage::CoverageSimplifier;
45264546

45274547
return execute(extHandle, [&]() -> Geometry* {
@@ -4536,10 +4556,10 @@ extern "C" {
45364556
CoverageSimplifier cov(coverage);
45374557
std::vector<std::unique_ptr<Geometry>> simple;
45384558
if (preserveBoundary == 1) {
4539-
simple = cov.simplifyInner(tolerance);
4559+
simple = cov.simplifyInner(tolerance, progressFunc ? &progressFunction : nullptr);
45404560
}
45414561
else if (preserveBoundary == 0) {
4542-
simple = cov.simplify(tolerance);
4562+
simple = cov.simplify(tolerance, progressFunc ? &progressFunction : nullptr);
45434563
}
45444564
else return nullptr;
45454565

include/geos/coverage/CoverageSimplifier.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <vector>
2020
#include <memory>
2121
#include <geos/export.h>
22+
#include <geos/util/Progress.h>
2223

2324

2425
namespace geos {
@@ -87,15 +88,18 @@ class GEOS_DLL CoverageSimplifier {
8788
*
8889
* @param coverage a set of polygonal geometries forming a coverage
8990
* @param tolerance the simplification tolerance
91+
* @param progressFunction Progress function, or nullptr.
9092
* @return the simplified polygons
9193
*/
9294
static std::vector<std::unique_ptr<Geometry>> simplify(
9395
std::vector<const Geometry*>& coverage,
94-
double tolerance);
96+
double tolerance,
97+
geos::util::ProgressFunction* progressFunction);
9598

9699
static std::vector<std::unique_ptr<Geometry>> simplify(
97100
const std::vector<std::unique_ptr<Geometry>>& coverage,
98-
double tolerance);
101+
double tolerance,
102+
geos::util::ProgressFunction* progressFunction);
99103

100104
/**
101105
* Simplifies the inner boundaries of a set of polygonal geometries forming a coverage,
@@ -104,35 +108,40 @@ class GEOS_DLL CoverageSimplifier {
104108
*
105109
* @param coverage a set of polygonal geometries forming a coverage
106110
* @param tolerance the simplification tolerance
111+
* @param progressFunction Progress function, or nullptr.
107112
* @return the simplified polygons
108113
*/
109114
static std::vector<std::unique_ptr<Geometry>> simplifyInner(
110115
std::vector<const Geometry*>& coverage,
111-
double tolerance);
116+
double tolerance,
117+
geos::util::ProgressFunction* progressFunction);
112118

113119
static std::vector<std::unique_ptr<Geometry>> simplifyInner(
114120
const std::vector<std::unique_ptr<Geometry>>& coverage,
115-
double tolerance);
121+
double tolerance,
122+
geos::util::ProgressFunction* progressFunction);
116123

117124
/**
118125
* Computes the simplified coverage, preserving the coverage topology.
119126
*
120127
* @param tolerance the simplification tolerance
128+
* @param progressFunction Progress function, or nullptr.
121129
* @return the simplified polygons
122130
*/
123131
std::vector<std::unique_ptr<Geometry>> simplify(
124-
double tolerance);
132+
double tolerance, geos::util::ProgressFunction* progressFunction);
125133

126134
/**
127135
* Computes the inner-boundary simplified coverage,
128136
* preserving the coverage topology,
129137
* and leaving outer boundary edges unchanged.
130138
*
131139
* @param tolerance the simplification tolerance
140+
* @param progressFunction Progress function, or nullptr.
132141
* @return the simplified polygons
133142
*/
134143
std::vector<std::unique_ptr<Geometry>> simplifyInner(
135-
double tolerance);
144+
double tolerance, geos::util::ProgressFunction* progressFunction);
136145

137146

138147
private:
@@ -145,7 +154,8 @@ class GEOS_DLL CoverageSimplifier {
145154
void simplifyEdges(
146155
std::vector<CoverageEdge*> edges,
147156
const MultiLineString* constraints,
148-
double tolerance);
157+
double tolerance,
158+
geos::util::ProgressFunction* progressFunction);
149159

150160
void setCoordinates(
151161
std::vector<CoverageEdge*>& edges,

include/geos/coverage/TPVWSimplifier.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <geos/simplify/LinkedLine.h>
2222
#include <geos/coverage/Corner.h>
2323
#include <geos/export.h>
24+
#include <geos/util/Progress.h>
2425

2526

2627
namespace geos {
@@ -164,11 +165,13 @@ class GEOS_DLL TPVWSimplifier
164165
*
165166
* @param lines the lines to simplify
166167
* @param distanceTolerance the simplification tolerance
168+
* @param progressFunction Progress function, or nullptr.
167169
* @return the simplified lines
168170
*/
169171
static std::unique_ptr<MultiLineString> simplify(
170172
const MultiLineString* lines,
171-
double distanceTolerance);
173+
double distanceTolerance,
174+
geos::util::ProgressFunction* progressFunction);
172175

173176
/**
174177
* Simplifies a set of lines, preserving the topology of the lines between
@@ -181,13 +184,15 @@ class GEOS_DLL TPVWSimplifier
181184
* @param freeRings flags indicating which ring edges do not have node endpoints
182185
* @param constraintLines the linear constraints
183186
* @param distanceTolerance the simplification tolerance
187+
* @param progressFunction Progress function, or nullptr.
184188
* @return the simplified lines
185189
*/
186190
static std::unique_ptr<MultiLineString> simplify(
187191
const MultiLineString* lines,
188192
std::vector<bool>& freeRings,
189193
const MultiLineString* constraintLines,
190-
double distanceTolerance);
194+
double distanceTolerance,
195+
geos::util::ProgressFunction* progressFunction);
191196

192197
// Constructor
193198
TPVWSimplifier(const MultiLineString* lines,
@@ -209,7 +214,7 @@ class GEOS_DLL TPVWSimplifier
209214

210215
void setConstraints(const MultiLineString* constraints);
211216

212-
std::unique_ptr<MultiLineString> simplify();
217+
std::unique_ptr<MultiLineString> simplify(geos::util::ProgressFunction* progressFunction);
213218

214219
std::vector<Edge> createEdges(
215220
const MultiLineString* lines,

include/geos/util/Progress.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**********************************************************************
2+
*
3+
* GEOS - Geometry Engine Open Source
4+
* http://geos.osgeo.org
5+
*
6+
* Copyright (C) 2025 Even Rouault <even.rouault@spatialys.com>
7+
*
8+
* This is free software; you can redistribute and/or modify it under
9+
* the terms of the GNU Lesser General Public Licence as published
10+
* by the Free Software Foundation.
11+
* See the COPYING file for more information.
12+
*
13+
**********************************************************************/
14+
15+
#pragma once
16+
17+
#include <functional>
18+
19+
#include <geos/export.h>
20+
21+
namespace geos {
22+
namespace util { // geos::util
23+
24+
/** Signature of a progression and cancel function.
25+
*
26+
* Such function takes a progression ratio (between 0 and 1), and an optional
27+
* message, and returns true if computation must continue, or false if it
28+
* must be interrupted.
29+
*/
30+
typedef std::function<bool(double, const char*)> ProgressFunction;
31+
32+
/** Do progress function related processing for an iteration loop of iterCount iterations.
33+
*
34+
* This function will invoke (*progressFunction) every notificationInterval
35+
*iteration.
36+
*
37+
* This function will return, or throw a geos::util::InterruptedException.
38+
*
39+
* A typical use is:
40+
* \code
41+
* const size_t notificationInterval = std::max<size_t>(1, iterCount / 100);
42+
* for (size_t i = 0, iNotify = 0; i < iterCount; ++i) {
43+
* // do something useful
44+
* if (progressFunction) {
45+
* geos::util::ProgressFunctionIteration(*progressFunction, i, iterCount, iNotify, notificationInterval);
46+
* }
47+
* }
48+
* if (progressFunction) {
49+
* (*progressFunction)(1.0, nullptr);
50+
* }
51+
* \endcode
52+
*
53+
* @param progressFunction Progress function
54+
* @param i Current index of loop iteration.
55+
* @param iterCount Total number of loop iteration.
56+
* @param iNotify Notification counter, updated by this function. Must be set by the caller (before the loop) to 0.
57+
* @param notificationInterval Notification interval (e.g. iterCount / 100).
58+
*/
59+
void ProgressFunctionIteration(ProgressFunction& progressFunction, size_t i, size_t iterCount, size_t& iNotify, size_t notificationInterval);
60+
61+
} // namespace geos::util
62+
} // namespace geos
63+

0 commit comments

Comments
 (0)