GEOS  3.13.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/CoverageRing.h>
21 
22 #include <unordered_map>
23 #include <map>
24 
25 // Forward declarations
26 namespace geos {
27 namespace geom {
28 class Coordinate;
29 class Envelope;
30 class Geometry;
31 class GeometryFactory;
32 }
33 }
34 
41 
42 namespace geos { // geos
43 namespace coverage { // geos::coverage
44 
45 
97 class GEOS_DLL CoveragePolygonValidator {
98 
99 private:
100 
110  class CoverageRingSegment : public LineSegment
111  {
112  public:
113 
114  // Members
115  CoverageRing* ringForward;
116  std::size_t indexForward;
117  CoverageRing* ringOpp;
118  std::size_t indexOpp;
119 
120  CoverageRingSegment(
121  const Coordinate& p_p0, const Coordinate& p_p1,
122  CoverageRing* p_ring, std::size_t p_index)
123  : LineSegment(p_p0, p_p1)
124  , ringForward(nullptr)
125  , indexForward(0)
126  , ringOpp(nullptr)
127  , indexOpp(0)
128  {
129  if (p_p1.compareTo(p_p0) < 0) {
130  reverse();
131  ringOpp = p_ring;
132  indexOpp = p_index;
133  }
134  else {
135  ringForward = p_ring;
136  indexForward = p_index;
137  }
138  };
139 
140  void match(const CoverageRingSegment* seg) {
141  bool isInvalid = checkInvalid(seg);
142  if (isInvalid) {
143  return;
144  }
145  //-- record the match
146  if (ringForward == nullptr) {
147  ringForward = seg->ringForward;
148  indexForward = seg->indexForward;
149  }
150  else {
151  ringOpp = seg->ringOpp;
152  indexOpp = seg->indexOpp;
153  }
154  //-- mark ring segments as matched
155  ringForward->markMatched(indexForward);
156  ringOpp->markMatched(indexOpp);
157  }
158 
159  bool checkInvalid(const CoverageRingSegment* seg) const {
160  if (ringForward != nullptr && seg->ringForward != nullptr) {
161  ringForward->markInvalid(indexForward);
162  seg->ringForward->markInvalid(seg->indexForward);
163  return true;
164  }
165  if (ringOpp != nullptr && seg->ringOpp != nullptr) {
166  ringOpp->markInvalid(indexOpp);
167  seg->ringOpp->markInvalid(seg->indexOpp);
168  return true;
169  }
170  return false;
171  }
172 
173  struct CoverageRingSegHash {
174  std::size_t
175  operator() (CoverageRingSegment const* s) const {
176  std::size_t h = std::hash<double>{}(s->p0.x);
177  h ^= (std::hash<double>{}(s->p0.y) << 1);
178  h ^= (std::hash<double>{}(s->p1.x) << 1);
179  return h ^ (std::hash<double>{}(s->p1.y) << 1);
180  }
181  };
182 
183  struct CoverageRingSegEq {
184  bool
185  operator() (CoverageRingSegment const* lhs, CoverageRingSegment const* rhs) const {
186  return lhs->p0.x == rhs->p0.x
187  && lhs->p0.y == rhs->p0.y
188  && lhs->p1.x == rhs->p1.x
189  && lhs->p1.y == rhs->p1.y;
190  }
191  };
192 
193  };
194 
195  // Members
196  const Geometry* targetGeom;
197  std::vector<const Geometry*> adjGeoms;
198  std::vector<const Polygon*> m_adjPolygons;
199  const GeometryFactory* geomFactory;
200  double gapWidth = 0.0;
201  std::map<std::size_t, std::unique_ptr<IndexedPointInAreaLocator>> adjPolygonLocators;
202  // std::vector<std::unique_ptr<CoverageRing>> coverageRingStore;
203  std::deque<CoverageRing> coverageRingStore;
204  std::vector<std::unique_ptr<CoordinateSequence>> localCoordinateSequences;
205  std::deque<CoverageRingSegment> coverageRingSegmentStore;
206 
207  typedef std::unordered_map<CoverageRingSegment*, CoverageRingSegment*, CoverageRingSegment::CoverageRingSegHash, CoverageRingSegment::CoverageRingSegEq> CoverageRingSegmentMap;
208 
209  // Declare type as noncopyable
210  CoveragePolygonValidator(const CoveragePolygonValidator& other) = delete;
211  CoveragePolygonValidator& operator=(const CoveragePolygonValidator& rhs) = delete;
212 
213 public:
214 
223  static std::unique_ptr<Geometry> validate(
224  const Geometry* targetPolygon,
225  std::vector<const Geometry*>& adjPolygons);
226 
240  static std::unique_ptr<Geometry> validate(
241  const Geometry* targetPolygon,
242  std::vector<const Geometry*>& adjPolygons,
243  double gapWidth);
244 
256  const Geometry* targetPolygon,
257  std::vector<const Geometry*>& adjPolygons);
258 
264  void setGapWidth(double p_gapWidth);
265 
272  std::unique_ptr<Geometry> validate();
273 
274 private:
275 
276  static std::vector<const Polygon*> extractPolygons(std::vector<const Geometry*>& geoms);
277 
278  /* private */
279  std::unique_ptr<Geometry> createEmptyResult();
280 
298  void markMatchedSegments(
299  std::vector<CoverageRing*>& targetRings,
300  std::vector<CoverageRing*>& adjRings,
301  const Envelope& targetEnv);
302 
312  void markMatchedSegments(
313  std::vector<CoverageRing*>& rings,
314  const Envelope& envLimit,
315  CoverageRingSegmentMap& segmentMap);
316 
317  CoverageRingSegment* createCoverageRingSegment(
318  CoverageRing* ring, std::size_t index);
319 
329  void markInvalidInteractingSegments(
330  std::vector<CoverageRing*>& targetRings,
331  std::vector<CoverageRing*>& adjRings,
332  double distanceTolerance);
333 
341  void markInvalidInteriorSegments(
342  std::vector<CoverageRing*>& targetRings,
343  std::vector<const Polygon*>& adjPolygons);
344 
345  void checkTargetRings(
346  std::vector<CoverageRing*>& targetRings,
347  std::vector<CoverageRing*>& adjRngs,
348  const Envelope& targetEnv);
349 
358  bool isInteriorVertex(const Coordinate& p,
359  std::vector<const Polygon*>& adjPolygons);
360 
361 
362  bool polygonContainsPoint(std::size_t index,
363  const Polygon* poly, const Coordinate& pt);
364 
365  IndexedPointInAreaLocator* getLocator(std::size_t index, const Polygon* poly);
366 
367  std::unique_ptr<Geometry> createInvalidLines(std::vector<CoverageRing*>& rings);
368 
369  std::vector<CoverageRing*> createRings(const Geometry* geom);
370 
371  std::vector<CoverageRing*> createRings(std::vector<const Polygon*>& polygons);
372 
373  void createRings(const Polygon* poly, std::vector<CoverageRing*>& rings);
374 
375  void addRing(
376  const LinearRing* ring,
377  bool isShell,
378  std::vector<CoverageRing*>& rings);
379 
380  CoverageRing* createRing(const LinearRing* ring, bool isShell);
381 
382 
383 
384 };
385 
386 } // namespace geos::coverage
387 } // namespace geos
Determines the location of Coordinates relative to an areal geometry, using indexing for efficiency.
Definition: IndexedPointInAreaLocator.h:54
Definition: CoveragePolygonValidator.h:97
std::unique_ptr< Geometry > validate()
static std::unique_ptr< Geometry > validate(const Geometry *targetPolygon, std::vector< const Geometry * > &adjPolygons, double gapWidth)
static std::unique_ptr< Geometry > validate(const Geometry *targetPolygon, std::vector< const Geometry * > &adjPolygons)
CoveragePolygonValidator(const Geometry *targetPolygon, std::vector< const Geometry * > &adjPolygons)
Coordinate is the lightweight class used to store coordinates.
Definition: Coordinate.h:216
An Envelope defines a rectangulare region of the 2D coordinate plane.
Definition: Envelope.h:58
Supplies a set of utility methods for building Geometry objects from CoordinateSequence or other Geom...
Definition: GeometryFactory.h:65
Basic implementation of Geometry, constructed and destructed by GeometryFactory.
Definition: Geometry.h:186
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:60
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25