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> 84 # define THROW std::throw_with_nested 89 struct geos_geometry_error :
public geometry_error {
91 explicit geos_geometry_error(
const char* message) :
92 geometry_error(
std::string{
"geometry creation failed in GEOS library: "} + message) {
102 class GEOSFactoryImpl {
104 std::unique_ptr<const geos::geom::PrecisionModel> m_precision_model;
105 std::unique_ptr<geos::geom::GeometryFactory> m_our_geos_factory;
106 geos::geom::GeometryFactory* m_geos_factory;
108 std::unique_ptr<geos::geom::CoordinateSequence> m_coordinate_sequence;
109 std::vector<std::unique_ptr<geos::geom::LinearRing>> m_rings;
110 std::vector<std::unique_ptr<geos::geom::Polygon>> m_polygons;
114 using point_type = std::unique_ptr<geos::geom::Point>;
115 using linestring_type = std::unique_ptr<geos::geom::LineString>;
116 using polygon_type = std::unique_ptr<geos::geom::Polygon>;
117 using multipolygon_type = std::unique_ptr<geos::geom::MultiPolygon>;
118 using ring_type = std::unique_ptr<geos::geom::LinearRing>;
120 explicit GEOSFactoryImpl(
int , geos::geom::GeometryFactory& geos_factory) :
121 m_precision_model(nullptr),
122 m_our_geos_factory(nullptr),
123 m_geos_factory(&geos_factory) {
131 m_precision_model(new geos::geom::PrecisionModel),
132 m_our_geos_factory(new geos::geom::GeometryFactory{m_precision_model.get(), srid}),
133 m_geos_factory(m_our_geos_factory.get()) {
136 explicit GEOSFactoryImpl(
int srid) :
137 m_precision_model(new geos::geom::PrecisionModel),
138 m_our_geos_factory(new geos::geom::GeometryFactory{m_precision_model.get(), srid}),
139 m_geos_factory(m_our_geos_factory.get()) {
146 return point_type{m_geos_factory->createPoint(geos::geom::Coordinate{xy.
x, xy.
y})};
147 }
catch (
const geos::util::GEOSException& e) {
148 THROW(osmium::geos_geometry_error(e.what()));
154 void linestring_start() {
156 m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<std::size_t>(0), 2));
157 }
catch (
const geos::util::GEOSException& e) {
158 THROW(osmium::geos_geometry_error(e.what()));
164 m_coordinate_sequence->add(geos::geom::Coordinate{xy.
x, xy.
y});
165 }
catch (
const geos::util::GEOSException& e) {
166 THROW(osmium::geos_geometry_error(e.what()));
170 linestring_type linestring_finish(std::size_t ) {
172 return linestring_type{m_geos_factory->createLineString(m_coordinate_sequence.release())};
173 }
catch (
const geos::util::GEOSException& e) {
174 THROW(osmium::geos_geometry_error(e.what()));
180 void multipolygon_start() {
184 void multipolygon_polygon_start() {
188 void multipolygon_polygon_finish() {
190 assert(!m_rings.empty());
191 auto inner_rings =
new std::vector<geos::geom::Geometry*>;
192 std::transform(std::next(m_rings.begin(), 1), m_rings.end(), std::back_inserter(*inner_rings), [](std::unique_ptr<geos::geom::LinearRing>& r) {
195 m_polygons.emplace_back(m_geos_factory->createPolygon(m_rings[0].release(), inner_rings));
197 }
catch (
const geos::util::GEOSException& e) {
198 THROW(osmium::geos_geometry_error(e.what()));
202 void multipolygon_outer_ring_start() {
204 m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<std::size_t>(0), 2));
205 }
catch (
const geos::util::GEOSException& e) {
206 THROW(osmium::geos_geometry_error(e.what()));
210 void multipolygon_outer_ring_finish() {
212 m_rings.emplace_back(m_geos_factory->createLinearRing(m_coordinate_sequence.release()));
213 }
catch (
const geos::util::GEOSException& e) {
214 THROW(osmium::geos_geometry_error(e.what()));
218 void multipolygon_inner_ring_start() {
220 m_coordinate_sequence.reset(m_geos_factory->getCoordinateSequenceFactory()->create(static_cast<std::size_t>(0), 2));
221 }
catch (
const geos::util::GEOSException& e) {
222 THROW(osmium::geos_geometry_error(e.what()));
226 void multipolygon_inner_ring_finish() {
228 m_rings.emplace_back(m_geos_factory->createLinearRing(m_coordinate_sequence.release()));
229 }
catch (
const geos::util::GEOSException& e) {
230 THROW(osmium::geos_geometry_error(e.what()));
236 m_coordinate_sequence->add(geos::geom::Coordinate{xy.
x, xy.
y});
237 }
catch (
const geos::util::GEOSException& e) {
238 THROW(osmium::geos_geometry_error(e.what()));
242 multipolygon_type multipolygon_finish() {
244 auto polygons =
new std::vector<geos::geom::Geometry*>;
245 std::transform(m_polygons.begin(), m_polygons.end(), std::back_inserter(*polygons), [](std::unique_ptr<geos::geom::Polygon>& p) {
249 return multipolygon_type{m_geos_factory->createMultiPolygon(polygons)};
250 }
catch (
const geos::util::GEOSException& e) {
251 THROW(osmium::geos_geometry_error(e.what()));
260 template <
typename TProjection = IdentityProjection>
261 using GEOSFactory = GeometryFactory<osmium::geom::detail::GEOSFactoryImpl, TProjection>;
271 #endif // OSMIUM_GEOM_GEOS_HPP double y
Definition: coordinates.hpp:51
#define OSMIUM_DEPRECATED
Definition: compatibility.hpp:51
Definition: location.hpp:551
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
Definition: coordinates.hpp:48
OSMIUM_DEPRECATED Coordinates transform(const CRS &src, const CRS &dest, Coordinates c)
Definition: projection.hpp:126
double x
Definition: coordinates.hpp:50