/src/geos/include/geos/simplify/PolygonHullSimplifier.h
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (C) 2021 Paul Ramsey <pramsey@cleverelephant.ca> |
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 <geos/geom/Geometry.h> |
18 | | #include <geos/util/IllegalArgumentException.h> |
19 | | #include <geos/simplify/RingHull.h> |
20 | | |
21 | | |
22 | | namespace geos { |
23 | | namespace geom { |
24 | | class GeometryFactory; |
25 | | class LinearRing; |
26 | | class MultiPolygon; |
27 | | class Polygon; |
28 | | } |
29 | | namespace algorithm { |
30 | | namespace hull { |
31 | | class RingHullIndex; |
32 | | } |
33 | | } |
34 | | } |
35 | | |
36 | | namespace geos { |
37 | | namespace simplify { // geos::simplify |
38 | | |
39 | | /** |
40 | | * Computes topology-preserving simplified hulls of polygonal geometry. |
41 | | * Both outer and inner hulls can be computed. |
42 | | * Outer hulls contain the input geometry and are larger in area. |
43 | | * Inner hulls are contained by the input geometry and are smaller in area. |
44 | | * In both the hull vertices are a subset of the input vertices. |
45 | | * The hull construction attempts to minimize the area difference |
46 | | * with the input geometry. |
47 | | * Hulls are generally concave if the input is. |
48 | | * Computed hulls are topology-preserving: |
49 | | * they do not contain any self-intersections or overlaps, |
50 | | * so the result polygonal geometry is valid. |
51 | | * |
52 | | * Polygons with holes and MultiPolygons are supported. |
53 | | * The result has the same geometric type and structure as the input. |
54 | | * |
55 | | * The number of vertices in the computed hull is determined by a target parameter. |
56 | | * Two parameters are supported: |
57 | | * |
58 | | * * Vertex Number fraction: the fraction of the input vertices retained in the result. |
59 | | * Value 1 produces the original geometry. |
60 | | * Smaller values produce less concave results. |
61 | | * For outer hulls, value 0 produces the convex hull (with triangles for any holes). |
62 | | * For inner hulls, value 0 produces a triangle (if no holes are present). |
63 | | * |
64 | | * * Area Delta ratio: the ratio of the change in area to the input area. |
65 | | * Value 0 produces the original geometry. |
66 | | * Larger values produce less concave results. |
67 | | * |
68 | | * The algorithm ensures that the result does not cause the target parameter |
69 | | * to be exceeded. This allows computing outer or inner hulls |
70 | | * with a small area delta ratio as an effective way of removing |
71 | | * narrow gores and spikes. |
72 | | * |
73 | | * @author Martin Davis |
74 | | * |
75 | | */ |
76 | | class GEOS_DLL PolygonHullSimplifier |
77 | | { |
78 | | using Envelope = geos::geom::Envelope; |
79 | | using Geometry = geos::geom::Geometry; |
80 | | using GeometryFactory = geos::geom::GeometryFactory; |
81 | | using LinearRing = geos::geom::LinearRing; |
82 | | using MultiPolygon = geos::geom::MultiPolygon; |
83 | | using Polygon = geos::geom::Polygon; |
84 | | |
85 | | public: |
86 | | |
87 | | /** |
88 | | * Creates a new instance |
89 | | * to compute a simplified hull of a polygonal geometry. |
90 | | * An outer or inner hull is computed |
91 | | * depending on the value of "isOuter". |
92 | | * |
93 | | * @param geom the polygonal geometry to process |
94 | | * @param bOuter indicates whether to compute an outer or inner hull |
95 | | */ |
96 | | PolygonHullSimplifier(const Geometry* geom, bool bOuter) |
97 | 0 | : inputGeom(geom) |
98 | 0 | , geomFactory(geom->getFactory()) |
99 | 0 | , isOuter(bOuter) |
100 | 0 | , vertexNumFraction(-1.0) |
101 | 0 | , areaDeltaRatio(-1.0) |
102 | 0 | { |
103 | 0 | if (!geom->isPolygonal()) { |
104 | 0 | throw util::IllegalArgumentException("Input geometry must be polygonal"); |
105 | 0 | } |
106 | 0 | }; |
107 | | |
108 | | /** |
109 | | * Computes a topology-preserving simplified hull of a polygonal geometry, |
110 | | * with hull shape determined by a target parameter |
111 | | * specifying the fraction of the input vertices retained in the result. |
112 | | * Larger values compute less concave results. |
113 | | * A value of 1 produces the convex hull; a value of 0 produces the original geometry. |
114 | | * Either outer or inner hulls can be computed. |
115 | | * |
116 | | * @param geom the polygonal geometry to process |
117 | | * @param isOuter indicates whether to compute an outer or inner hull |
118 | | * @param vertexNumFraction the target fraction of number of input vertices in result |
119 | | * @return the hull geometry |
120 | | */ |
121 | | static std::unique_ptr<Geometry> hull( |
122 | | const Geometry* geom, |
123 | | bool isOuter, |
124 | | double vertexNumFraction); |
125 | | |
126 | | /** |
127 | | * Computes a topology-preserving simplified hull of a polygonal geometry, |
128 | | * with hull shape determined by a target parameter |
129 | | * specifying the ratio of maximum difference in area to original area. |
130 | | * Larger values compute less concave results. |
131 | | * A value of 0 produces the original geometry. |
132 | | * Either outer or inner hulls can be computed.. |
133 | | * |
134 | | * @param geom the polygonal geometry to process |
135 | | * @param isOuter indicates whether to compute an outer or inner hull |
136 | | * @param areaDeltaRatio the target ratio of area difference to original area |
137 | | * @return the hull geometry |
138 | | */ |
139 | | static std::unique_ptr<Geometry> hullByAreaDelta( |
140 | | const Geometry* geom, |
141 | | bool isOuter, |
142 | | double areaDeltaRatio); |
143 | | |
144 | | |
145 | | /** |
146 | | * Sets the target fraction of input vertices |
147 | | * which are retained in the result. |
148 | | * The value should be in the range [0,1]. |
149 | | * |
150 | | * @param p_vertexNumFraction a fraction of the number of input vertices |
151 | | */ |
152 | | void setVertexNumFraction(double p_vertexNumFraction); |
153 | | /** |
154 | | * Sets the target maximum ratio of the change in area of the result to the input area. |
155 | | * The value must be 0 or greater. |
156 | | * |
157 | | * @param p_areaDeltaRatio a ratio of the change in area of the result |
158 | | */ |
159 | | void setAreaDeltaRatio(double p_areaDeltaRatio); |
160 | | |
161 | | /** |
162 | | * Gets the result polygonal hull geometry. |
163 | | * |
164 | | * @return the polygonal geometry for the hull |
165 | | */ |
166 | | std::unique_ptr<Geometry> getResult(); |
167 | | |
168 | | |
169 | | |
170 | | private: |
171 | | |
172 | | // Members |
173 | | const Geometry* inputGeom; |
174 | | const GeometryFactory* geomFactory; |
175 | | bool isOuter; |
176 | | double vertexNumFraction; |
177 | | double areaDeltaRatio; |
178 | | // Allocate the RingHull* in here so they are cleaned |
179 | | // up with PolygonHullSimplifier |
180 | | std::vector<std::unique_ptr<RingHull>> ringStore; |
181 | | |
182 | | /** |
183 | | * Computes hulls for MultiPolygon elements for |
184 | | * the cases where hulls might overlap. |
185 | | * |
186 | | * @param multiPoly the MultiPolygon to process |
187 | | * @return the hull geometry |
188 | | */ |
189 | | std::unique_ptr<Geometry> computeMultiPolygonAll(const MultiPolygon* multiPoly); |
190 | | std::unique_ptr<Geometry> computeMultiPolygonEach(const MultiPolygon* multiPoly); |
191 | | std::unique_ptr<Polygon> computePolygon(const Polygon* poly); |
192 | | |
193 | | /** |
194 | | * Create all ring hulls for the rings of a polygon, |
195 | | * so that all are in the hull index if required. |
196 | | * |
197 | | * @param poly the polygon being processed |
198 | | * @param hullIndex the hull index if present, or null |
199 | | * @return the list of ring hulls |
200 | | */ |
201 | | std::vector<RingHull*> initPolygon(const Polygon* poly, |
202 | | RingHullIndex& hullIndex); |
203 | | |
204 | | double ringArea(const Polygon* poly) const; |
205 | | |
206 | | RingHull* createRingHull( |
207 | | const LinearRing* ring, |
208 | | bool isOuter, |
209 | | double areaTotal, |
210 | | RingHullIndex& hullIndex); |
211 | | |
212 | | std::unique_ptr<Polygon> polygonHull( |
213 | | const Polygon* poly, |
214 | | std::vector<RingHull*>& ringHulls, |
215 | | RingHullIndex& hullIndex) const; |
216 | | |
217 | | /** |
218 | | * Disable copy construction and assignment. Needed to make this |
219 | | * class compile under MSVC. (See https://stackoverflow.com/q/29565299) |
220 | | */ |
221 | | PolygonHullSimplifier(const PolygonHullSimplifier&) = delete; |
222 | | PolygonHullSimplifier& operator=(const PolygonHullSimplifier&) = delete; |
223 | | |
224 | | }; // PolygonHullSimplifier |
225 | | |
226 | | |
227 | | } // geos::simplify |
228 | | } // geos |
229 | | |