Fishnet 2.0.1
Framework for Graph-Based Analysis of GIS Vector Data
Loading...
Searching...
No Matches
OGRMultiPolygonAdapter.hpp
Go to the documentation of this file.
1#pragma once
2#include <numeric>
8#include "OGRAdapterBase.hpp"
10
11namespace fishnet::geometry{
12
19class OGRMultiPolygonAdapter: public OGRAdapterBase<OGRMultiPolygon>{
20private:
22
23 static OGRUniquePtr<OGRMultiPolygon> emptyMultiPolygon() {
24 return OGRUniquePtr<OGRMultiPolygon>(static_cast<OGRMultiPolygon*>(OGRGeometryFactory::createGeometry(wkbMultiPolygon)));
25 }
26
34 void canonicalize() noexcept {
35 auto normalized = OGRUniquePtr<OGRGeometry>(geomPtr->Normalize());
36 if(normalized && wkbFlatten(normalized->getGeometryType()) == wkbMultiPolygon){
37 geomPtr.reset(normalized.release()->toMultiPolygon());
38 }
39 }
40
41 OGRPolygon * polygonAt(int index) const {
42 return static_cast<OGRPolygon*>(geomPtr->getGeometryRef(index));
43 }
44
53 auto borrowedPolygons() const -> fishnet::util::forward_range_of<OGRPolygonAdapter> auto {
54 return std::ranges::views::iota(0, geomPtr->getNumGeometries())
55 | std::ranges::views::transform([this](int i){
56 return OGRPolygonAdapter::borrowed(polygonAt(i));
57 });
58 }
59
64 bool isAddable(const OGRPolygonAdapter & polygon) const {
65 for(const auto & present : borrowedPolygons()){
66 if(present == polygon)
67 return false;
68 if(present.crosses(polygon))
69 return false;
70 if(present.contains(polygon) || polygon.contains(present))
71 return false;
72 }
73 return true;
74 }
75
76 friend class OGRGeometryAdapter;
77
82 OGRUniquePtr<OGRGeometry> releaseGeometry() && noexcept {
83 auto deleter = geomPtr.get_deleter();
84 return OGRUniquePtr<OGRGeometry>(geomPtr.release(), deleter);
85 }
86public:
87 using numeric_type = double;
89 static constexpr GeometryType type = GeometryType::MULTIPOLYGON;
90
91 OGRMultiPolygonAdapter(OGRUniquePtr<OGRMultiPolygon> && multiPolygonPtr):Base(std::move(multiPolygonPtr)) {
92 geomPtr->closeRings();
93 canonicalize();
94 }
95
96 OGRMultiPolygonAdapter(IMultiPolygon auto const & multiPolygon):Base(emptyMultiPolygon()){
97 for(const auto & polygon : multiPolygon.getPolygons()){
98 OGRPolygonAdapter adapted {polygon};
99 geomPtr->addGeometry(adapted.raw());
100 }
101 canonicalize();
102 }
103
110 OGRMultiPolygonAdapter(const PolygonRange auto & polygons, bool checked = false):Base(emptyMultiPolygon()){
111 for(const auto & polygon : polygons){
112 OGRPolygonAdapter adapted {polygon};
113 // every polygon is canonical on its own, so only the order of the members is left to
114 // canonicalise, once, after all of them have been added
115 if(checked || isAddable(adapted))
116 geomPtr->addGeometry(adapted.raw());
117 }
118 canonicalize();
119 }
120
121 size_t size() const noexcept {
122 return static_cast<size_t>(geomPtr->getNumGeometries());
123 }
124
133 auto getPolygons() const & -> fishnet::util::forward_range_of<OGRPolygonAdapter> auto {
134 return std::ranges::views::iota(0, geomPtr->getNumGeometries())
135 | std::ranges::views::transform([this](int i){
136 return OGRPolygonAdapter::fromCanonicalPolygon(*polygonAt(i));
137 });
138 }
139
141 std::vector<OGRPolygonAdapter> getPolygons() const && {
142 return fishnet::util::toVector(this->getPolygons());
143 }
144
150 bool addPolygon(const OGRPolygonAdapter & polygon) noexcept {
151 if(not isAddable(polygon))
152 return false;
153 if(geomPtr->addGeometry(polygon.raw()) != OGRERR_NONE)
154 return false;
155 canonicalize();
156 return true;
157 }
158
159 bool removePolygon(const OGRPolygonAdapter & polygon) noexcept {
160 for(int i = 0; i < geomPtr->getNumGeometries(); ++i){
161 if(polygonAt(i)->Equals(polygon.raw())){
162 if(geomPtr->removeGeometry(i) != OGRERR_NONE)
163 return false;
164 canonicalize();
165 return true;
166 }
167 }
168 return false;
169 }
170
176 std::vector<Polygon<double>> polygons;
177 polygons.reserve(this->size());
178 for(const auto & polygon : borrowedPolygons()){
179 polygons.push_back(polygon.toNative());
180 }
181 return MultiPolygon<Polygon<double>>(polygons, true);
182 }
183
184 double area() const {
185 return geomPtr->get_Area();
186 }
187
192 Vec2DReal accumulatedWeightedCentroid {0.0,0.0};
193 double totalArea = this->area();
194 for(const auto & polygon : borrowedPolygons()){
195 accumulatedWeightedCentroid = accumulatedWeightedCentroid + polygon.centroid() * (polygon.area() / totalArea);
196 }
197 return accumulatedWeightedCentroid;
198 }
199
201 OGREnvelope boundingBox;
202 geomPtr->getEnvelope(&boundingBox);
203 return Rectangle<double>(boundingBox.MinX, boundingBox.MaxY, boundingBox.MaxX, boundingBox.MinY);
204 }
205
206 bool isInside(const IPoint auto & point) const {
207 OGRPoint ogrPoint(point.getX(), point.getY());
208 return geomPtr->Contains(&ogrPoint);
209 }
210
211 bool isOnBoundary(const IPoint auto & point) const {
212 OGRPoint ogrPoint(point.getX(), point.getY());
213 return geomPtr->Touches(&ogrPoint);
214 }
215
216 bool isOutside(const IPoint auto & point) const {
217 OGRPoint ogrPoint(point.getX(), point.getY());
218 return geomPtr->Disjoint(&ogrPoint);
219 }
220
221 bool contains(const IPoint auto & point) const {
222 OGRPoint ogrPoint(point.getX(), point.getY());
223 return not geomPtr->Disjoint(&ogrPoint);
224 }
225
226 bool contains(const ISegment auto & segment) const {
227 // a segment is contained if it is contained in one of the polygons, being spread over
228 // multiple polygons of the multi-polygon does not count
229 return std::ranges::any_of(borrowedPolygons(),[&segment](const auto & polygon){return polygon.contains(segment);});
230 }
231
232 bool contains(const IPolygon auto & query) const {
233 return std::ranges::any_of(borrowedPolygons(),[&query](const auto & polygon){return polygon.contains(query);});
234 }
235
236 bool containsInHole(const IPolygon auto & query) const {
237 return std::ranges::any_of(borrowedPolygons(),[&query](const auto & polygon){return polygon.containsInHole(query);});
238 }
239
240 bool intersects(const LinearGeometry auto & linearFeature) const {
241 return std::ranges::any_of(borrowedPolygons(),[&linearFeature](const auto & polygon){return polygon.intersects(linearFeature);});
242 }
243
244 std::unordered_set<Vec2DReal> intersections(const LinearGeometry auto & linearFeature) const {
245 std::unordered_set<Vec2DReal> intersectionSet;
246 for(const auto & polygon : borrowedPolygons()){
247 for(const auto & point : polygon.intersections(linearFeature)){
248 intersectionSet.insert(point);
249 }
250 }
251 return intersectionSet;
252 }
253
254 bool crosses(const IPolygon auto & query) const {
255 return std::ranges::any_of(borrowedPolygons(),[&query](const auto & polygon){return polygon.crosses(query);});
256 }
257
258 bool touches(const IPolygon auto & query) const {
259 return not contains(query) && not crosses(query)
260 && std::ranges::any_of(borrowedPolygons(),[&query](const auto & polygon){return polygon.touches(query);});
261 }
262
263 double distance(const IPolygon auto & query) const {
264 return std::ranges::min(borrowedPolygons() | std::views::transform([&query](const auto & polygon){return polygon.distance(query);}));
265 }
266
267 double distance(const IMultiPolygon auto & other) const {
268 return std::ranges::min(other.getPolygons() | std::views::transform([this](const auto & otherPolygon){return this->distance(otherPolygon);}));
269 }
270
277 double distance(const OGRMultiPolygonAdapter & other) const {
278 return geomPtr->Distance(other.geomPtr.get());
279 }
280};
281static_assert(IMultiPolygon<OGRMultiPolygonAdapter>);
282static_assert(Shape<OGRMultiPolygonAdapter>);
283}
Implementation of a Multi-Polygon.
Definition MultiPolygon.hpp:20
Base class for OGR geometry adapters, which owns an OGR geometry.
Definition OGRAdapterBase.hpp:83
T * raw() const noexcept
Definition OGRAdapterBase.hpp:115
OGRUniquePtr< OGRMultiPolygon > geomPtr
Definition OGRAdapterBase.hpp:85
Adapter for an OGRGeometry of statically unknown type, as handed out by a data source.
Definition OGRGeometryAdapter.hpp:83
IMultiPolygon implementation backed by an OGRMultiPolygon.
Definition OGRMultiPolygonAdapter.hpp:19
bool addPolygon(const OGRPolygonAdapter &polygon) noexcept
Add a polygon to the multi-polygon.
Definition OGRMultiPolygonAdapter.hpp:150
bool isOutside(const IPoint auto &point) const
Definition OGRMultiPolygonAdapter.hpp:216
MultiPolygon< Polygon< double > > toNative() const
Copy the multi-polygon out into a fishnet MultiPolygon, which precomputes its segments.
Definition OGRMultiPolygonAdapter.hpp:175
Vec2DReal centroid() const
Centroid of the multi-polygon, i.e. the centroids of its polygons weighted by area.
Definition OGRMultiPolygonAdapter.hpp:191
OGRMultiPolygonAdapter(OGRUniquePtr< OGRMultiPolygon > &&multiPolygonPtr)
Definition OGRMultiPolygonAdapter.hpp:91
size_t size() const noexcept
Definition OGRMultiPolygonAdapter.hpp:121
bool isInside(const IPoint auto &point) const
Definition OGRMultiPolygonAdapter.hpp:206
OGRMultiPolygonAdapter(IMultiPolygon auto const &multiPolygon)
Definition OGRMultiPolygonAdapter.hpp:96
std::unordered_set< Vec2DReal > intersections(const LinearGeometry auto &linearFeature) const
Definition OGRMultiPolygonAdapter.hpp:244
double numeric_type
Definition OGRMultiPolygonAdapter.hpp:87
OGRMultiPolygonAdapter(const PolygonRange auto &polygons, bool checked=false)
Construct a multi-polygon from a range of polygons.
Definition OGRMultiPolygonAdapter.hpp:110
bool isOnBoundary(const IPoint auto &point) const
Definition OGRMultiPolygonAdapter.hpp:211
double area() const
Definition OGRMultiPolygonAdapter.hpp:184
double distance(const IPolygon auto &query) const
Definition OGRMultiPolygonAdapter.hpp:263
std::vector< OGRPolygonAdapter > getPolygons() const &&
Definition OGRMultiPolygonAdapter.hpp:141
double distance(const OGRMultiPolygonAdapter &other) const
Distance between two OGR backed multi-polygons.
Definition OGRMultiPolygonAdapter.hpp:277
bool contains(const ISegment auto &segment) const
Definition OGRMultiPolygonAdapter.hpp:226
bool contains(const IPolygon auto &query) const
Definition OGRMultiPolygonAdapter.hpp:232
bool containsInHole(const IPolygon auto &query) const
Definition OGRMultiPolygonAdapter.hpp:236
double distance(const IMultiPolygon auto &other) const
Definition OGRMultiPolygonAdapter.hpp:267
static constexpr GeometryType type
Definition OGRMultiPolygonAdapter.hpp:89
bool touches(const IPolygon auto &query) const
Definition OGRMultiPolygonAdapter.hpp:258
auto getPolygons() const &-> fishnet::util::forward_range_of< OGRPolygonAdapter > auto
Definition OGRMultiPolygonAdapter.hpp:133
bool removePolygon(const OGRPolygonAdapter &polygon) noexcept
Definition OGRMultiPolygonAdapter.hpp:159
bool crosses(const IPolygon auto &query) const
Definition OGRMultiPolygonAdapter.hpp:254
bool contains(const IPoint auto &point) const
Definition OGRMultiPolygonAdapter.hpp:221
bool intersects(const LinearGeometry auto &linearFeature) const
Definition OGRMultiPolygonAdapter.hpp:240
Rectangle< double > aaBB() const
Definition OGRMultiPolygonAdapter.hpp:200
IPolygon implementation backed by an OGRPolygon.
Definition OGRPolygonAdapter.hpp:22
Vec2DReal centroid() const
Area weighted centroid of the polygon, obtained by decomposition into its rings.
Definition OGRPolygonAdapter.hpp:136
bool contains(const IPoint auto &point) const
Definition OGRPolygonalAdapter.hpp:178
double distance(const IPolygon auto &other) const
Distance between the two polygons.
Definition OGRPolygonAdapter.hpp:209
Polygon< double > toNative() const
Copy the polygon out into a fishnet Polygon, which precomputes its segments.
Definition OGRPolygonAdapter.hpp:120
bool crosses(const IPolygon auto &other) const
Definition OGRPolygonAdapter.hpp:177
bool intersects(const LinearGeometry auto &linearFeature) const
Definition OGRPolygonAdapter.hpp:158
std::unordered_set< Vec2DReal > intersections(const LinearGeometry auto &linearFeature) const
Definition OGRPolygonAdapter.hpp:164
bool touches(const IPolygon auto &other) const
Definition OGRPolygonAdapter.hpp:188
bool containsInHole(const IPoint auto &point) const
Definition OGRPolygonAdapter.hpp:149
double area() const
Area enclosed by the boundary, reduced by the area of the holes.
Definition OGRPolygonalAdapter.hpp:147
Implementation of a rectangle Stores top,right,bottom and left point of the rectangle.
Definition Rectangle.hpp:15
Implementation of a two-dimensional vector.
Definition Vec2D.hpp:16
Interface for a multi-polygon A multi-polygon is a collection of polygons.
Definition IMultiPolygon.hpp:93
Interface for a point.
Definition IPoint.hpp:92
Interface for a polygon A polygon is a two-dimensional shape defined by a boundary and zero or more h...
Definition IPolygon.hpp:98
Interface for a segment A segment is formed between two points p and q, containing only the points on...
Definition ISegment.hpp:105
Definition IGeometry.hpp:13
Definition IPolygon.hpp:134
Definition CollectionConcepts.hpp:27
Definition BoundingBoxWrapper.hpp:5
std::unique_ptr< T, __impl::OGRGeometryDeleter > OGRUniquePtr
Definition OGRAdapterBase.hpp:48
GeometryType
Definition GeometryBase.hpp:6
constexpr auto toVector(R &&range)
Definition CollectionConcepts.hpp:64
Definition BFSClustering.hpp:5
STL namespace.