Fishnet 2.0.1
Framework for Graph-Based Analysis of GIS Vector Data
Loading...
Searching...
No Matches
OGRGeometryAdapter.hpp
Go to the documentation of this file.
1#pragma once
2#include <fishnet/Option.hpp>
3#include <fishnet/Vec2D.hpp>
4#include "OGRAdapterBase.hpp"
5#include "OGRRingAdapter.hpp"
8
9namespace fishnet::geometry{
10
11class OGRGeometryAdapter;
12
25template<typename G>
27 std::same_as<G, Vec2DReal>
28 || std::same_as<G, OGRRingAdapter>
29 || std::same_as<G, OGRPolygonAdapter>
30 || std::same_as<G, OGRMultiPolygonAdapter>
31 || std::same_as<G, OGRGeometryAdapter>;
32
41template<typename G>
43
44namespace __impl{
45 // overload set used only in an unevaluated context (@see NarrowTarget below) to compute which
46 // concrete adapter narrowTo() should produce for a given G: itself for one of the adapters (or
47 // Vec2DReal), otherwise whichever adapter models the same kind of shape as G
48 template<OGRLayerGeometry G>
49 G narrowTargetOf();
50
51 template<typename G> requires (not OGRLayerGeometry<G>) && IRing<G>
52 OGRRingAdapter narrowTargetOf();
53
54 template<typename G> requires (not OGRLayerGeometry<G>) && IPolygon<G>
55 OGRPolygonAdapter narrowTargetOf();
56
57 template<typename G> requires (not OGRLayerGeometry<G>) && IMultiPolygon<G>
58 OGRMultiPolygonAdapter narrowTargetOf();
59}
60
68template<typename G>
69using NarrowTarget = decltype(__impl::narrowTargetOf<G>());
70
83class OGRGeometryAdapter: public OGRAdapterBase<OGRGeometry>{
84private:
86public:
87 using numeric_type = double;
88
89 OGRGeometryAdapter(OGRUniquePtr<OGRGeometry> && geometryPtr):Base(std::move(geometryPtr)) {}
90
91 OGRGeometryAdapter(const OGRRingAdapter & ring):Base(OGRUniquePtr<OGRGeometry>(ring.raw()->getExteriorRing()->clone())) {}
92
93 OGRGeometryAdapter(const OGRPolygonAdapter & polygon):Base(OGRUniquePtr<OGRGeometry>(polygon.raw()->clone())) {}
94
95 OGRGeometryAdapter(const OGRMultiPolygonAdapter & multiPolygon):Base(OGRUniquePtr<OGRGeometry>(multiPolygon.raw()->clone())) {}
96
101 OGRGeometryAdapter(OGRRingAdapter && ring):Base(std::move(ring).releaseGeometry()) {}
102
103 OGRGeometryAdapter(OGRPolygonAdapter && polygon):Base(std::move(polygon).releaseGeometry()) {}
104
105 OGRGeometryAdapter(OGRMultiPolygonAdapter && multiPolygon):Base(std::move(multiPolygon).releaseGeometry()) {}
106
115
117
119
125 GeometryType geometryType() const noexcept {
126 return GeometryTypeWKBAdapter::fromWKB(wkbFlatten(geomPtr->getGeometryType()));
127 }
128
129 bool isEmpty() const noexcept {
130 return geomPtr->IsEmpty();
131 }
132
139 bool isRing() const noexcept {
140 auto wkbType = wkbFlatten(geomPtr->getGeometryType());
141 return (wkbType == wkbLineString || wkbType == wkbLinearRing)
142 && not isEmpty() && geomPtr->toLineString()->getNumPoints() >= 3;
143 }
144
145 bool isPolygon() const noexcept {
146 return wkbFlatten(geomPtr->getGeometryType()) == wkbPolygon && not isEmpty();
147 }
148
149 bool isMultiPolygon() const noexcept {
150 return wkbFlatten(geomPtr->getGeometryType()) == wkbMultiPolygon && not isEmpty();
151 }
152
153 bool isPoint() const noexcept {
154 return wkbFlatten(geomPtr->getGeometryType()) == wkbPoint && not isEmpty();
155 }
156
164 if(not isPoint())
165 return {};
166 const auto * point = geomPtr->toPoint();
167 return Vec2DReal(point->getX(), point->getY());
168 }
169
175 if(not isRing())
176 return {};
177 const auto * lineString = geomPtr->toLineString();
178 auto ring = OGRUniquePtr<OGRLinearRing>(static_cast<OGRLinearRing*>(OGRGeometryFactory::createGeometry(wkbLinearRing)));
179 for(int i = 0; i < lineString->getNumPoints(); ++i){
180 ring->addPoint(lineString->getX(i), lineString->getY(i));
181 }
182 return OGRRingAdapter(std::move(ring));
183 }
184
190 if(not isPolygon())
191 return {};
192 return OGRPolygonAdapter(OGRUniquePtr<OGRPolygon>(geomPtr->toPolygon()->clone()));
193 }
194
204 if(not isPolygon())
205 return {};
206 auto deleter = geomPtr.get_deleter(); // whoever owns the geometry keeps owning it
207 auto * released = geomPtr.release();
208 return OGRPolygonAdapter(OGRUniquePtr<OGRPolygon>(released->toPolygon(), deleter));
209 }
210
216 if(not isMultiPolygon())
217 return {};
218 return OGRMultiPolygonAdapter(OGRUniquePtr<OGRMultiPolygon>(geomPtr->toMultiPolygon()->clone()));
219 }
220
226 if(not isMultiPolygon())
227 return {};
228 auto deleter = geomPtr.get_deleter();
229 auto * released = geomPtr.release();
230 return OGRMultiPolygonAdapter(OGRUniquePtr<OGRMultiPolygon>(released->toMultiPolygon(), deleter));
231 }
232
233
239 template<typename G> requires OGRLayerGeometry<G> || Shape<G>
241 using Target = NarrowTarget<G>;
242 // a point is read out by value and a ring is rebuilt from the points either way, so neither
243 // gains anything from copying the whole geometry first
244 if constexpr (std::same_as<Target, Vec2DReal>)
245 return toPoint();
246 else if constexpr (std::same_as<Target, OGRRingAdapter>)
247 return toRing();
248 else
249 return OGRGeometryAdapter(*this).narrowTo<G>();
250 }
251
252
266 template<typename G> requires OGRLayerGeometry<G> || Shape<G>
268 using Target = NarrowTarget<G>;
269 if constexpr (std::same_as<Target, OGRGeometryAdapter>){
270 return std::move(*this); // a layer which takes anything has nothing to narrow
271 } else if constexpr (std::same_as<Target, Vec2DReal>){
272 return toPoint();
273 } else if constexpr (std::same_as<Target, OGRRingAdapter>){
274 return toRing();
275 } else if constexpr (std::same_as<Target, OGRPolygonAdapter>){
276 if(auto polygon = std::move(*this).toPolygon())
277 return polygon;
278 auto multiPolygon = std::move(*this).toMultiPolygon();
279 if(not multiPolygon || multiPolygon.value().size() != 1)
280 return {};
281 auto polygons = multiPolygon.value().getPolygons();
282 return *std::ranges::begin(polygons);
283 } else if constexpr (std::same_as<Target, OGRMultiPolygonAdapter>){
284 if(auto multiPolygon = std::move(*this).toMultiPolygon())
285 return multiPolygon;
286 auto polygon = std::move(*this).toPolygon();
287 if(not polygon)
288 return {};
289 std::vector<OGRPolygonAdapter> parts;
290 parts.push_back(std::move(polygon.value()));
291 return OGRMultiPolygonAdapter(parts, true);
292 } else {
293 static_assert(false, "narrowTo has no case for this geometry: a type was added to "
294 "OGRLayerGeometry without saying how an OGR geometry is narrowed to it");
295 }
296 }
297};
298
299static_assert(OGRWritableGeometry<OGRPolygonAdapter>);
300static_assert(OGRWritableGeometry<OGRGeometryAdapter>);
301static_assert(OGRLayerGeometry<Vec2DReal>);
302static_assert(OGRLayerGeometry<OGRRingAdapter>);
303static_assert(OGRLayerGeometry<OGRPolygonAdapter>);
304static_assert(OGRLayerGeometry<OGRMultiPolygonAdapter>);
305static_assert(OGRLayerGeometry<OGRGeometryAdapter>);
306}
Definition Option.hpp:13
static geometry::GeometryType fromWKB(OGRwkbGeometryType type)
Definition OGRAdapterBase.hpp:148
Base class for OGR geometry adapters, which owns an OGR geometry.
Definition OGRAdapterBase.hpp:83
OGRGeometry * raw() const noexcept
Definition OGRAdapterBase.hpp:115
OGRUniquePtr< OGRGeometry > geomPtr
Definition OGRAdapterBase.hpp:85
Adapter for an OGRGeometry of statically unknown type, as handed out by a data source.
Definition OGRGeometryAdapter.hpp:83
double numeric_type
Definition OGRGeometryAdapter.hpp:87
bool isPolygon() const noexcept
Definition OGRGeometryAdapter.hpp:145
OGRGeometryAdapter(OGRRingAdapter &&ring)
Adopt a ring, polygon or multi-polygon which is no longer needed, without cloning it.
Definition OGRGeometryAdapter.hpp:101
OGRGeometryAdapter(const OGRRingAdapter &ring)
Definition OGRGeometryAdapter.hpp:91
bool isRing() const noexcept
Whether the wrapped geometry can be viewed as a ring.
Definition OGRGeometryAdapter.hpp:139
GeometryType geometryType() const noexcept
Geometry type of the wrapped geometry.
Definition OGRGeometryAdapter.hpp:125
Option< OGRPolygonAdapter > toPolygon() &&
Hand the wrapped polygon over to an OGRPolygonAdapter, without copying it.
Definition OGRGeometryAdapter.hpp:203
Option< NarrowTarget< G > > narrowTo() &&
Narrow to G, coercing between polygon and multi-polygon where the shape is the same.
Definition OGRGeometryAdapter.hpp:267
OGRGeometryAdapter(const IRing auto &ring)
Build from any ring, polygon or multi-polygon which is not already one of the OGR adapters above,...
Definition OGRGeometryAdapter.hpp:114
Option< OGRPolygonAdapter > toPolygon() const &
Convert to an OGRPolygonAdapter.
Definition OGRGeometryAdapter.hpp:189
Option< OGRRingAdapter > toRing() const
Convert to an OGRRingAdapter.
Definition OGRGeometryAdapter.hpp:174
Option< OGRMultiPolygonAdapter > toMultiPolygon() &&
Hand the wrapped multi-polygon over to an OGRMultiPolygonAdapter, without copying it.
Definition OGRGeometryAdapter.hpp:225
OGRGeometryAdapter(OGRPolygonAdapter &&polygon)
Definition OGRGeometryAdapter.hpp:103
OGRGeometryAdapter(const IPolygon auto &polygon)
Definition OGRGeometryAdapter.hpp:116
bool isMultiPolygon() const noexcept
Definition OGRGeometryAdapter.hpp:149
bool isPoint() const noexcept
Definition OGRGeometryAdapter.hpp:153
Option< Vec2DReal > toPoint() const
Read the wrapped point out into a Vec2DReal.
Definition OGRGeometryAdapter.hpp:163
OGRGeometryAdapter(const OGRPolygonAdapter &polygon)
Definition OGRGeometryAdapter.hpp:93
Option< NarrowTarget< G > > narrowTo() const &
Narrow to G, leaving this adapter intact.
Definition OGRGeometryAdapter.hpp:240
OGRGeometryAdapter(const IMultiPolygon auto &multiPolygon)
Definition OGRGeometryAdapter.hpp:118
OGRGeometryAdapter(OGRUniquePtr< OGRGeometry > &&geometryPtr)
Definition OGRGeometryAdapter.hpp:89
OGRGeometryAdapter(const OGRMultiPolygonAdapter &multiPolygon)
Definition OGRGeometryAdapter.hpp:95
Option< OGRMultiPolygonAdapter > toMultiPolygon() const &
Convert to an OGRMultiPolygonAdapter.
Definition OGRGeometryAdapter.hpp:215
bool isEmpty() const noexcept
Definition OGRGeometryAdapter.hpp:129
OGRGeometryAdapter(OGRMultiPolygonAdapter &&multiPolygon)
Definition OGRGeometryAdapter.hpp:105
IMultiPolygon implementation backed by an OGRMultiPolygon.
Definition OGRMultiPolygonAdapter.hpp:19
IPolygon implementation backed by an OGRPolygon.
Definition OGRPolygonAdapter.hpp:22
IRing implementation backed by an OGRPolygon holding nothing but an exterior ring.
Definition OGRRingAdapter.hpp:30
A geometry which carries its type at runtime instead of statically.
Definition IGeometry.hpp:41
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 ring A ring is a closed loop of segments, forming a boundary of a shape.
Definition IRing.hpp:143
A geometry an OGR layer can be read into and written from.
Definition OGRGeometryAdapter.hpp:26
A geometry which can be written to an OGR data source.
Definition OGRGeometryAdapter.hpp:42
A geometry enclosing an area: a ring, a polygon or a multi-polygon.
Definition IGeometry.hpp:23
Definition BoundingBoxWrapper.hpp:5
std::unique_ptr< T, __impl::OGRGeometryDeleter > OGRUniquePtr
Definition OGRAdapterBase.hpp:48
decltype(__impl::narrowTargetOf< G >()) NarrowTarget
What narrowTo<G>() produces: G itself for one of the OGRLayerGeometry types, otherwise whichever OGR ...
Definition OGRGeometryAdapter.hpp:69
GeometryType
Definition GeometryBase.hpp:6
Vec2D< fishnet::math::DEFAULT_FLOATING_POINT > Vec2DReal
Definition Vec2D.hpp:220
STL namespace.