1 #ifndef OSMIUM_GEOM_GEOS_HPP
2 #define OSMIUM_GEOM_GEOS_HPP
36 #include <geos/version.h>
37 #if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && (GEOS_VERSION_MAJOR < 3 || (GEOS_VERSION_MAJOR == 3 && GEOS_VERSION_MINOR <= 5))
39 #define OSMIUM_WITH_GEOS
59 #include <geos/geom/Coordinate.h>
60 #include <geos/geom/CoordinateSequence.h>
61 #include <geos/geom/CoordinateSequenceFactory.h>
62 #include <geos/geom/GeometryFactory.h>
63 #include <geos/geom/LinearRing.h>
64 #include <geos/geom/MultiPolygon.h>
65 #include <geos/geom/Point.h>
66 #include <geos/geom/Polygon.h>
67 #include <geos/geom/PrecisionModel.h>
68 #include <geos/util/GEOSException.h>
82 struct geos_geometry_error :
public geometry_error {
84 explicit geos_geometry_error(
const char* message) :
85 geometry_error(
std::string{
"geometry creation failed in GEOS library: "} + message) {
95 class GEOSFactoryImpl {
97 std::unique_ptr<const geos::geom::PrecisionModel> m_precision_model;
98 std::unique_ptr<geos::geom::GeometryFactory> m_our_geos_factory;
99 geos::geom::GeometryFactory* m_geos_factory;
101 std::unique_ptr<geos::geom::CoordinateSequence> m_coordinate_sequence;
102 std::vector<std::unique_ptr<geos::geom::LinearRing>> m_rings;
103 std::vector<std::unique_ptr<geos::geom::Polygon>> m_polygons;
107 using point_type = std::unique_ptr<geos::geom::Point>;
108 using linestring_type = std::unique_ptr<geos::geom::LineString>;
109 using polygon_type = std::unique_ptr<geos::geom::Polygon>;
110 using multipolygon_type = std::unique_ptr<geos::geom::MultiPolygon>;
111 using ring_type = std::unique_ptr<geos::geom::LinearRing>;
113 explicit GEOSFactoryImpl(
int , geos::geom::GeometryFactory& geos_factory) :
114 m_precision_model(nullptr),
115 m_our_geos_factory(nullptr),
116 m_geos_factory(&geos_factory) {
124 m_precision_model(new geos::geom::PrecisionModel),
125 m_our_geos_factory(new geos::geom::GeometryFactory{m_precision_model.get(), srid}),
126 m_geos_factory(m_our_geos_factory.get()) {
129 explicit GEOSFactoryImpl(
int srid) :
130 m_precision_model(new geos::geom::PrecisionModel),
131 m_our_geos_factory(new geos::geom::GeometryFactory{m_precision_model.get(), srid}),
132 m_geos_factory(m_our_geos_factory.get()) {
139 return point_type{m_geos_factory->createPoint(geos::geom::Coordinate{xy.
x, xy.
y})};
140 }
catch (
const geos::util::GEOSException& e) {
141 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
147 void linestring_start() {
149 m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(
static_cast<std::size_t
>(0), 2));
150 }
catch (
const geos::util::GEOSException& e) {
151 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
157 m_coordinate_sequence->add(geos::geom::Coordinate{xy.
x, xy.
y});
158 }
catch (
const geos::util::GEOSException& e) {
159 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
163 linestring_type linestring_finish(std::size_t ) {
165 return linestring_type{m_geos_factory->createLineString(m_coordinate_sequence.release())};
166 }
catch (
const geos::util::GEOSException& e) {
167 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
173 void multipolygon_start() {
177 void multipolygon_polygon_start() {
181 void multipolygon_polygon_finish() {
183 assert(!m_rings.empty());
184 auto inner_rings =
new std::vector<geos::geom::Geometry*>;
185 std::transform(std::next(m_rings.begin(), 1), m_rings.end(), std::back_inserter(*inner_rings), [](std::unique_ptr<geos::geom::LinearRing>& r) {
188 m_polygons.emplace_back(m_geos_factory->createPolygon(m_rings[0].release(), inner_rings));
190 }
catch (
const geos::util::GEOSException& e) {
191 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
195 void multipolygon_outer_ring_start() {
197 m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(
static_cast<std::size_t
>(0), 2));
198 }
catch (
const geos::util::GEOSException& e) {
199 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
203 void multipolygon_outer_ring_finish() {
205 m_rings.emplace_back(m_geos_factory->createLinearRing(m_coordinate_sequence.release()));
206 }
catch (
const geos::util::GEOSException& e) {
207 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
211 void multipolygon_inner_ring_start() {
213 m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(
static_cast<std::size_t
>(0), 2));
214 }
catch (
const geos::util::GEOSException& e) {
215 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
219 void multipolygon_inner_ring_finish() {
221 m_rings.emplace_back(m_geos_factory->createLinearRing(m_coordinate_sequence.release()));
222 }
catch (
const geos::util::GEOSException& e) {
223 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
229 m_coordinate_sequence->add(geos::geom::Coordinate{xy.
x, xy.
y});
230 }
catch (
const geos::util::GEOSException& e) {
231 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
235 multipolygon_type multipolygon_finish() {
237 auto polygons =
new std::vector<geos::geom::Geometry*>;
238 std::transform(m_polygons.begin(), m_polygons.end(), std::back_inserter(*polygons), [](std::unique_ptr<geos::geom::Polygon>& p) {
242 return multipolygon_type{m_geos_factory->createMultiPolygon(polygons)};
243 }
catch (
const geos::util::GEOSException& e) {
244 std::throw_with_nested(osmium::geos_geometry_error(e.what()));
253 template <
typename TProjection = IdentityProjection>
254 using GEOSFactory = GeometryFactory<osmium::geom::detail::GEOSFactoryImpl, TProjection>;
#define OSMIUM_DEPRECATED
Definition: compatibility.hpp:51
OSMIUM_DEPRECATED Coordinates transform(const CRS &src, const CRS &dest, Coordinates c)
Definition: projection.hpp:125
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
Definition: location.hpp:555
Definition: coordinates.hpp:48
double y
Definition: coordinates.hpp:51
double x
Definition: coordinates.hpp:50