GEOS  3.13.0dev
RingHull.h
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/Coordinate.h>
18 #include <geos/simplify/LinkedRing.h>
19 #include <geos/index/VertexSequencePackedRtree.h>
20 
21 #include <queue>
22 
23 namespace geos {
24 namespace geom {
25 class Envelope;
26 class LinearRing;
27 class LineString;
28 class Polygon;
29 }
30 namespace simplify {
31 class RingHullIndex;
32 }
33 }
34 
35 
42 
43 
44 namespace geos {
45 namespace simplify { // geos::simplify
46 
47 
48 class RingHull
49 {
50 
51 public:
52 
53  /*
54  * Creates a new instance.
55  *
56  * @param p_ring the ring vertices to process
57  * @param p_isOuter whether the hull is outer or inner
58  */
59  RingHull(const LinearRing* p_ring, bool p_isOuter);
60 
61  void setMinVertexNum(std::size_t minVertexNum);
62 
63  void setMaxAreaDelta(double maxAreaDelta);
64 
65  const Envelope* getEnvelope() const;
66 
67  std::unique_ptr<LinearRing> getHull(RingHullIndex& hullIndex);
68 
69  static bool isConvex(const LinkedRing& vertexRing, std::size_t index);
70 
71  static double area(const LinkedRing& vertexRing, std::size_t index);
72 
73  void compute(RingHullIndex& hullIndex);
74 
75  std::unique_ptr<Polygon> toGeometry() const;
76 
77 
78 private:
79 
80 
81  class Corner
82  {
83 
84  private:
85 
86  std::size_t index;
87  std::size_t prev;
88  std::size_t next;
89  double area;
90 
91  public:
92 
93  Corner(std::size_t p_idx, std::size_t p_prev, std::size_t p_next, double p_area)
94  : index(p_idx)
95  , prev(p_prev)
96  , next(p_next)
97  , area(p_area)
98  {};
99 
100  inline int compareTo(const Corner& rhs) const {
101  if (area == rhs.getArea()) {
102  if (index == rhs.getIndex())
103  return 0;
104  else return index < rhs.getIndex() ? -1 : 1;
105  }
106  else return area < rhs.getArea() ? -1 : 1;
107  }
108 
109  inline bool operator< (const Corner& rhs) const {
110  return compareTo(rhs) < 0;
111  };
112 
113  inline bool operator> (const Corner& rhs) const {
114  return compareTo(rhs) > 0;
115  };
116 
117  inline bool operator==(const Corner& rhs) const {
118  return compareTo(rhs) == 0;
119  };
120 
121  bool isVertex(std::size_t p_index) const;
122  std::size_t getIndex() const;
123  double getArea() const;
124  void envelope(const LinkedRing& ring, Envelope& env) const;
125  bool intersects(const Coordinate& v, const LinkedRing& ring) const;
126  bool isRemoved(const LinkedRing& ring) const;
127  std::unique_ptr<LineString> toLineString(const LinkedRing& ring);
128 
129  struct Greater {
130  inline bool operator()(const Corner & a, const Corner & b) const {
131  return a > b;
132  }
133  };
134 
135  using PriorityQueue = std::priority_queue<Corner, std::vector<Corner>, Corner::Greater>;
136 
137  }; // class Corner
138 
139 
140 
141  const LinearRing* inputRing;
142  double targetVertexNum = -1.0;
143  double targetAreaDelta = -1.0;
144 
150  std::unique_ptr<CoordinateSequence> vertex;
151  std::unique_ptr<LinkedRing> vertexRing;
152  double areaDelta = 0;
153 
159  std::unique_ptr<VertexSequencePackedRtree> vertexIndex;
160 
161  Corner::PriorityQueue cornerQueue;
162 
163 
164  void init(CoordinateSequence& ring, bool isOuter);
165  void addCorner(std::size_t i, Corner::PriorityQueue& cornerQueue);
166  bool isAtTarget(const Corner& corner);
167 
177  void removeCorner(const Corner& corner, Corner::PriorityQueue& cornerQueue);
178  bool isRemovable(const Corner& corner, const RingHullIndex& hullIndex) const;
179 
189  bool hasIntersectingVertex(
190  const Corner& corner,
191  const Envelope& cornerEnv,
192  const RingHull* hull) const;
193 
194  const Coordinate& getCoordinate(std::size_t index) const;
195 
196  void query(
197  const Envelope& cornerEnv,
198  std::vector<std::size_t>& result) const;
199 
200  void queryHull(const Envelope& queryEnv, std::vector<Coordinate>& pts);
201 
202 
203 
204 
205 }; // RingHull
206 
207 
208 } // geos::simplify
209 } // geos
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:216
An Envelope defines a rectangulare region of the 2D coordinate plane.
Definition: Envelope.h:58
Definition: LineString.h:65
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
Definition: VertexSequencePackedRtree.h:54
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25