Fishnet 2.0.1
Framework for Graph-Based Analysis of GIS Vector Data
Loading...
Searching...
No Matches
OGRPolygonAdapter.hpp
Go to the documentation of this file.
1#pragma once
2#include <vector>
5#include <fishnet/Polygon.hpp>
8#include "OGRRingAdapter.hpp"
9
10namespace fishnet::geometry{
11
23private:
25 :OGRPolygonalAdapter(std::move(polygonPtr), canonical) {}
26
35 static OGRPolygonAdapter fromCanonicalPolygon(const OGRPolygon & polygon) {
36 return OGRPolygonAdapter(OGRUniquePtr<OGRPolygon>(polygon.clone()), Canonical{});
37 }
38
46 static OGRPolygonAdapter borrowed(OGRPolygon * polygon) {
47 return OGRPolygonAdapter(__impl::borrow(polygon), Canonical{});
48 }
49
54 OGRRingAdapter borrowedBoundary() const {
55 return OGRRingAdapter::borrowed(geomPtr->getExteriorRing());
56 }
57
64 auto borrowedHoles() const -> fishnet::util::forward_range_of<OGRRingAdapter> auto {
65 return std::ranges::views::iota(0, geomPtr->getNumInteriorRings())
66 | std::ranges::views::transform([this](int i){
67 return OGRRingAdapter::borrowed(geomPtr->getInteriorRing(i));
68 });
69 }
70
72 friend class OGRGeometryAdapter;
73
78 OGRUniquePtr<OGRGeometry> releaseGeometry() && noexcept {
79 auto deleter = geomPtr.get_deleter();
80 return OGRUniquePtr<OGRGeometry>(geomPtr.release(), deleter);
81 }
82
83public:
85 using numeric_type = double;
86 static constexpr GeometryType type = GeometryType::POLYGON;
87
89
91
96 return OGRRingAdapter::fromCanonicalRing(*exteriorRing());
97 }
98
103 std::vector<OGRRingAdapter> getHoles() const {
104 std::vector<OGRRingAdapter> holes;
105 holes.reserve(static_cast<size_t>(geomPtr->getNumInteriorRings()));
106 for(int i = 0; i < geomPtr->getNumInteriorRings(); ++i){
107 holes.emplace_back(OGRRingAdapter::fromCanonicalHole(*geomPtr->getInteriorRing(i)));
108 }
109 return holes;
110 }
111
112 bool isSimple() const {
113 return geomPtr->getNumInteriorRings() == 0;
114 }
115
121 std::vector<Ring<double>> holes;
122 holes.reserve(static_cast<size_t>(geomPtr->getNumInteriorRings()));
123 for(const auto & hole : getHoles()){
124 holes.push_back(hole.toNative());
125 }
126 return Polygon<double>(getBoundary().toNative(), holes, true);
127 }
128
137 auto boundary = borrowedBoundary();
138 auto accumulatedArea = boundary.area();
139 for(const auto & hole : borrowedHoles()){
140 accumulatedArea -= hole.area();
141 }
142 auto accumulatedCentroid = boundary.centroid() * (boundary.area() / accumulatedArea);
143 for(const auto & hole : borrowedHoles()){
144 accumulatedCentroid = accumulatedCentroid + hole.centroid() * (-hole.area() / accumulatedArea);
145 }
146 return accumulatedCentroid;
147 }
148
149 bool containsInHole(const IPoint auto & point) const {
150 return std::ranges::any_of(borrowedHoles(), [&point](const auto & hole){return hole.contains(point);});
151 }
152
153 bool containsInHole(const IPolygon auto & other) const {
154 auto otherBoundary = other.getBoundary();
155 return std::ranges::any_of(borrowedHoles(), [&otherBoundary](const auto & hole){return hole.contains(otherBoundary);});
156 }
157
158 bool intersects(const LinearGeometry auto & linearFeature) const {
159 if(borrowedBoundary().intersects(linearFeature))
160 return true;
161 return std::ranges::any_of(borrowedHoles(), [&linearFeature](const auto & hole){return hole.intersects(linearFeature);});
162 }
163
164 std::unordered_set<Vec2DReal> intersections(const LinearGeometry auto & linearFeature) const {
165 std::unordered_set<Vec2DReal> intersectionSet;
166 for(const auto & point : borrowedBoundary().intersections(linearFeature)){
167 intersectionSet.insert(point);
168 }
169 for(const auto & hole : borrowedHoles()){
170 for(const auto & point : hole.intersections(linearFeature)){
171 intersectionSet.insert(point);
172 }
173 }
174 return intersectionSet;
175 }
176
177 bool crosses(const IPolygon auto & other) const {
178 if(not this->aaBB().overlap(other.aaBB()))
179 return false; // polygons whose bounding boxes are apart cannot share a single point
180 if(containsInHole(other))
181 return false;
182 auto otherBoundary = other.getBoundary();
183 if(borrowedBoundary().crosses(otherBoundary))
184 return true;
185 return std::ranges::any_of(borrowedHoles(), [&otherBoundary](const auto & hole){return hole.crosses(otherBoundary);});
186 }
187
188 bool touches(const IPolygon auto & other) const {
189 if(not this->aaBB().overlap(other.aaBB()))
190 return false; // polygons whose bounding boxes are apart cannot touch
191 if(this->crosses(other))
192 return false;
193 auto otherBoundary = other.getBoundary();
194 if(borrowedBoundary().touches(otherBoundary))
195 return true;
196 return std::ranges::any_of(borrowedHoles(), [&otherBoundary](const auto & hole){
197 // a hole fully contains the other polygon and touches it at least at one point
198 return hole.contains(otherBoundary) && std::ranges::any_of(otherBoundary.getPoints(),[&hole](const auto & p){
199 return hole.isOnBoundary(p);
200 });
201 });
202 }
203
209 double distance(const IPolygon auto & other) const {
210 // polygons whose bounding boxes are apart can neither contain nor touch each other, so
211 // the gap between their boundaries is all there is left to compute
212 if(this->aaBB().overlap(other.aaBB())){
213 if(this->contains(other))
214 return 0;
215 if(this->touches(other))
216 return 0;
217 }
218 auto otherBoundary = other.getBoundary();
219 for(const auto & hole : borrowedHoles()){
220 if(hole.contains(otherBoundary)){
221 return shapeDistance(hole, otherBoundary);
222 }
223 }
224 return borrowedBoundary().distance(otherBoundary);
225 }
226
234 double distance(const OGRPolygonAdapter & other) const {
235 return geomPtr->Distance(other.geomPtr.get());
236 }
237};
238static_assert(IPolygon<OGRPolygonAdapter>);
239static_assert(Shape<OGRPolygonAdapter>);
240}
OGRUniquePtr< OGRPolygon > 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
IPolygon implementation backed by an OGRPolygon.
Definition OGRPolygonAdapter.hpp:22
bool isSimple() const
Definition OGRPolygonAdapter.hpp:112
OGRRingAdapter getBoundary() const
Definition OGRPolygonAdapter.hpp:95
OGRPolygonAdapter(IPolygon auto const &polygon)
Definition OGRPolygonAdapter.hpp:90
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
OGRPolygonAdapter(OGRUniquePtr< OGRPolygon > &&polygonPtr)
Definition OGRPolygonAdapter.hpp:88
static constexpr GeometryType type
Definition OGRPolygonAdapter.hpp:86
Polygon< double > toNative() const
Copy the polygon out into a fishnet Polygon, which precomputes its segments.
Definition OGRPolygonAdapter.hpp:120
double numeric_type
Definition OGRPolygonAdapter.hpp:85
bool crosses(const IPolygon auto &other) const
Definition OGRPolygonAdapter.hpp:177
double distance(const OGRPolygonAdapter &other) const
Distance between two OGR backed polygons.
Definition OGRPolygonAdapter.hpp:234
bool intersects(const LinearGeometry auto &linearFeature) const
Definition OGRPolygonAdapter.hpp:158
bool containsInHole(const IPolygon auto &other) const
Definition OGRPolygonAdapter.hpp:153
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
std::vector< OGRRingAdapter > getHoles() const
Definition OGRPolygonAdapter.hpp:103
Common base of the OGR backed adapters which enclose an area.
Definition OGRPolygonalAdapter.hpp:24
const OGRLinearRing * exteriorRing() const noexcept
Definition OGRPolygonalAdapter.hpp:116
bool contains(const IPoint auto &point) const
Definition OGRPolygonalAdapter.hpp:178
static OGRUniquePtr< OGRPolygon > toOGRPolygon(const IRing auto &ring)
Copy an arbitrary IRing into an OGRPolygon, ready to be used with GEOS.
Definition OGRPolygonalAdapter.hpp:44
Rectangle< double > aaBB() const
Definition OGRPolygonalAdapter.hpp:151
IRing implementation backed by an OGRPolygon holding nothing but an exterior ring.
Definition OGRRingAdapter.hpp:30
double distance(const IRing auto &other) const
Definition OGRRingAdapter.hpp:232
std::unordered_set< Vec2DReal > intersections(const LinearGeometry auto &linearFeature) const
Definition OGRRingAdapter.hpp:205
Polygon implementation A Polygon consist of a boundary (IRing) and zero or more holes (IRing)
Definition Polygon.hpp:14
Implementation of a two-dimensional vector.
Definition Vec2D.hpp:16
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
Definition IGeometry.hpp:13
Definition CollectionConcepts.hpp:27
Definition BoundingBoxWrapper.hpp:5
std::unique_ptr< T, __impl::OGRGeometryDeleter > OGRUniquePtr
Definition OGRAdapterBase.hpp:48
GeometryType
Definition GeometryBase.hpp:6
static fishnet::math::DEFAULT_FLOATING_POINT shapeDistance(Shape auto const &lhs, Shape auto const &rhs, util::BiFunction< Vec2DReal, Vec2DReal, fishnet::math::DEFAULT_FLOATING_POINT > auto const &distanceFunction) noexcept
Compute the distance between two shapes, with custom distance function.
Definition PolygonDistance.hpp:465
STL namespace.
Tag for a polygon which is known to be in canonical form already.
Definition OGRPolygonalAdapter.hpp:125