GEOS 3.15.0dev
CoveragePolygonValidator.h
1/**********************************************************************
2 *
3 * GEOS - Geometry Engine Open Source
4 * http://geos.osgeo.org
5 *
6 * Copyright (C) 2022 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/noding/BasicSegmentString.h>
18#include <geos/geom/LineSegment.h>
19#include <geos/algorithm/locate/IndexedPointInAreaLocator.h>
20#include <geos/coverage/CoveragePolygon.h>
21#include <geos/coverage/CoverageRing.h>
22
23#include <unordered_map>
24#include <map>
25
26// Forward declarations
27namespace geos {
28namespace geom {
29class Coordinate;
30class Envelope;
31class Geometry;
32class GeometryFactory;
33}
34}
35
36
37namespace geos { // geos
38namespace coverage { // geos::coverage
39
40
102
103private:
104
114 class CoverageRingSegment : public LineSegment
115 {
116 public:
117
118 // Members
119 CoverageRing* ringForward;
120 std::size_t indexForward;
121 CoverageRing* ringOpp;
122 std::size_t indexOpp;
123
124 CoverageRingSegment(
125 const Coordinate& p_p0, const Coordinate& p_p1,
126 CoverageRing* p_ring, std::size_t p_index)
127 : LineSegment(p_p0, p_p1)
128 , ringForward(nullptr)
129 , indexForward(0)
130 , ringOpp(nullptr)
131 , indexOpp(0)
132 {
133 if (p_p1.compareTo(p_p0) < 0) {
134 reverse();
135 ringOpp = p_ring;
136 indexOpp = p_index;
137 }
138 else {
139 ringForward = p_ring;
140 indexForward = p_index;
141 }
142 };
143
144 void match(const CoverageRingSegment* seg) {
145 bool isInvalid = checkInvalid(seg);
146 if (isInvalid) {
147 return;
148 }
149 //-- record the match
150 if (ringForward == nullptr) {
151 ringForward = seg->ringForward;
152 indexForward = seg->indexForward;
153 }
154 else {
155 ringOpp = seg->ringOpp;
156 indexOpp = seg->indexOpp;
157 }
158 //-- mark ring segments as matched
159 ringForward->markMatched(indexForward);
160 ringOpp->markMatched(indexOpp);
161 }
162
163 bool checkInvalid(const CoverageRingSegment* seg) const {
164 if (ringForward != nullptr && seg->ringForward != nullptr) {
165 ringForward->markInvalid(indexForward);
166 seg->ringForward->markInvalid(seg->indexForward);
167 return true;
168 }
169 if (ringOpp != nullptr && seg->ringOpp != nullptr) {
170 ringOpp->markInvalid(indexOpp);
171 seg->ringOpp->markInvalid(seg->indexOpp);
172 return true;
173 }
174 return false;
175 }
176
177 struct CoverageRingSegHash {
178 std::size_t
179 operator() (CoverageRingSegment const* s) const {
180 std::size_t h = std::hash<double>{}(s->p0.x);
181 h ^= (std::hash<double>{}(s->p0.y) << 1);
182 h ^= (std::hash<double>{}(s->p1.x) << 1);
183 return h ^ (std::hash<double>{}(s->p1.y) << 1);
184 }
185 };
186
187 struct CoverageRingSegEq {
188 bool
189 operator() (CoverageRingSegment const* lhs, CoverageRingSegment const* rhs) const {
190 return lhs->p0.x == rhs->p0.x
191 && lhs->p0.y == rhs->p0.y
192 && lhs->p1.x == rhs->p1.x
193 && lhs->p1.y == rhs->p1.y;
194 }
195 };
196
197 };
198
199 // Members
200 const Geometry* targetGeom;
201 std::vector<const Geometry*> adjGeoms;
202 //std::vector<const Polygon*> m_adjPolygons;
203 const GeometryFactory* geomFactory;
204 double gapWidth = 0.0;
205 std::vector<std::unique_ptr<CoveragePolygon>> m_adjCovPolygons;
206 std::deque<CoverageRing> coverageRingStore;
207 std::deque<CoverageRingSegment> coverageRingSegmentStore;
208
209 typedef std::unordered_map<CoverageRingSegment*, CoverageRingSegment*, CoverageRingSegment::CoverageRingSegHash, CoverageRingSegment::CoverageRingSegEq> CoverageRingSegmentMap;
210
211 // Declare type as noncopyable
213 CoveragePolygonValidator& operator=(const CoveragePolygonValidator& rhs) = delete;
214
215public:
216
225 static std::unique_ptr<Geometry> validate(
226 const Geometry* targetPolygon,
227 std::vector<const Geometry*>& adjPolygons);
228
242 static std::unique_ptr<Geometry> validate(
243 const Geometry* targetPolygon,
244 std::vector<const Geometry*>& adjPolygons,
245 double gapWidth);
246
258 const Geometry* targetPolygon,
259 std::vector<const Geometry*>& adjPolygons);
260
266 void setGapWidth(double p_gapWidth);
267
274 std::unique_ptr<Geometry> validate();
275
276private:
277
278 static std::vector<std::unique_ptr<CoveragePolygon>>
279 toCoveragePolygons(const std::vector<const Polygon*> polygons);
280 static std::vector<const Polygon*> extractPolygons(std::vector<const Geometry*>& geoms);
281
282 /* private */
283 std::unique_ptr<Geometry> createEmptyResult();
284
302 void markMatchedSegments(
303 std::vector<CoverageRing*>& targetRings,
304 std::vector<CoverageRing*>& adjRings,
305 const Envelope& targetEnv);
306
316 void markMatchedSegments(
317 std::vector<CoverageRing*>& rings,
318 const Envelope& envLimit,
319 CoverageRingSegmentMap& segmentMap);
320
321 CoverageRingSegment* createCoverageRingSegment(
322 CoverageRing* ring, std::size_t index);
323
333 void markInvalidInteractingSegments(
334 std::vector<CoverageRing*>& targetRings,
335 std::vector<CoverageRing*>& adjRings,
336 double distanceTolerance);
337
345 void markInvalidInteriorSegments(
346 std::vector<CoverageRing*>& targetRings,
347 std::vector<std::unique_ptr<CoveragePolygon>>& adjCovPolygons);
348
349 void markInvalidInteriorSection(
350 CoverageRing& ring,
351 std::size_t iStart,
352 std::size_t iEnd,
353 std::vector<std::unique_ptr<CoveragePolygon>>& adjCovPolygons );
354
355 void markInvalidInteriorSegment(
356 CoverageRing& ring, std::size_t i, CoveragePolygon* adjPoly);
357
358 void checkTargetRings(
359 std::vector<CoverageRing*>& targetRings,
360 std::vector<CoverageRing*>& adjRngs,
361 const Envelope& targetEnv);
362
363 std::unique_ptr<Geometry> createInvalidLines(std::vector<CoverageRing*>& rings);
364
365 std::vector<CoverageRing*> createRings(const Geometry* geom);
366
367 std::vector<CoverageRing*> createRings(std::vector<const Polygon*>& polygons);
368
369 void createRings(const Polygon* poly, std::vector<CoverageRing*>& rings);
370
371 void addRing(
372 const LinearRing* ring,
373 bool isShell,
374 std::vector<CoverageRing*>& rings);
375
376 CoverageRing* createRing(const LinearRing* ring, bool isShell);
377
378
379
380};
381
382} // namespace geos::coverage
383} // namespace geos
Determines the location of Coordinates relative to an areal geometry, using indexing for efficiency.
Definition IndexedPointInAreaLocator.h:54
Definition CoveragePolygonValidator.h:92
std::unique_ptr< Geometry > validate()
static std::unique_ptr< Geometry > validate(const Geometry *targetPolygon, std::vector< const Geometry * > &adjPolygons)
CoveragePolygonValidator(const Geometry *targetPolygon, std::vector< const Geometry * > &adjPolygons)
static std::unique_ptr< Geometry > validate(const Geometry *targetPolygon, std::vector< const Geometry * > &adjPolygons, double gapWidth)
The internal representation of a list of coordinates inside a Geometry.
Definition CoordinateSequence.h:56
Coordinate is the lightweight class used to store coordinates.
Definition Coordinate.h:217
An Envelope defines a rectangulare region of the 2D coordinate plane.
Definition Envelope.h:59
Supplies a set of utility methods for building Geometry objects from CoordinateSequence or other Geom...
Definition GeometryFactory.h:71
Basic implementation of Geometry, constructed and destructed by GeometryFactory.
Definition Geometry.h:196
Definition LineSegment.h:61
Models an OGC SFS LinearRing. A LinearRing is a LineString which is both closed and simple.
Definition LinearRing.h:54
Represents a linear polygon, which may include holes.
Definition Polygon.h:61
Basic namespace for all GEOS functionalities.
Definition geos.h:38