Loading...
Searching...
No Matches
factory.hpp
Go to the documentation of this file.
#ifndef OSMIUM_GEOM_FACTORY_HPP
#define OSMIUM_GEOM_FACTORY_HPP
/*
This file is part of Osmium (https://osmcode.org/libosmium).
Copyright 2013-2025 Jochen Topf <jochen@topf.org> and others (see README).
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <osmium/geom/coordinates.hpp>
#include <osmium/memory/collection.hpp>
#include <osmium/memory/item.hpp>
#include <osmium/osm/area.hpp>
#include <osmium/osm/item_type.hpp>
#include <osmium/osm/location.hpp>
#include <osmium/osm/node.hpp>
#include <osmium/osm/node_ref.hpp>
#include <osmium/osm/node_ref_list.hpp>
#include <osmium/osm/types.hpp>
#include <osmium/osm/way.hpp>
#include <osmium/util/compatibility.hpp>
#include <cstddef>
#include <stdexcept>
#include <string>
#include <utility>
namespace osmium {
class OSMIUM_EXPORT geometry_error : public std::runtime_error {
std::string m_message;
osmium::object_id_type m_id;
public:
explicit geometry_error(const std::string& message, const char* object_type = "", osmium::object_id_type id = 0) :
std::runtime_error(message),
m_message(message),
m_id(id) {
if (m_id != 0) {
m_message += " (";
m_message += object_type;
m_message += "_id=";
m_message += std::to_string(m_id);
m_message += ")";
}
}
void set_id(const char* object_type, osmium::object_id_type id) {
if (m_id == 0 && id != 0) {
m_message += " (";
m_message += object_type;
m_message += "_id=";
m_message += std::to_string(id);
m_message += ")";
}
m_id = id;
}
osmium::object_id_type id() const noexcept {
return m_id;
}
const char* what() const noexcept override {
return m_message.c_str();
}
}; // class geometry_error
namespace geom {
enum class use_nodes : bool {
unique = true,
all = false
}; // enum class use_nodes
enum class direction : bool {
backward = true,
forward = false
}; // enum class direction
class IdentityProjection {
public:
Coordinates operator()(osmium::Location location) const {
return Coordinates{location.lon(), location.lat()};
}
static int epsg() noexcept {
return 4326;
}
static std::string proj_string() noexcept {
return "+proj=longlat +datum=WGS84 +no_defs";
}
}; // class IdentityProjection
template <typename TGeomImpl, typename TProjection = IdentityProjection>
class GeometryFactory {
void add_points(const osmium::NodeRefList& nodes) {
osmium::Location last_location;
for (const osmium::NodeRef& node_ref : nodes) {
if (last_location != node_ref.location()) {
last_location = node_ref.location();
m_impl.multipolygon_add_location(m_projection(last_location));
}
}
}
TProjection m_projection;
TGeomImpl m_impl;
public:
GeometryFactory() :
m_projection(),
m_impl(m_projection.epsg()) {
}
template <typename... TArgs>
explicit GeometryFactory(TArgs&&... args) :
m_projection(),
m_impl(m_projection.epsg(), std::forward<TArgs>(args)...) {
}
template <typename... TArgs>
explicit GeometryFactory(TProjection&& projection, TArgs&&... args) :
m_projection(std::move(projection)),
m_impl(m_projection.epsg(), std::forward<TArgs>(args)...) {
}
using projection_type = TProjection;
using point_type = typename TGeomImpl::point_type;
using linestring_type = typename TGeomImpl::linestring_type;
using polygon_type = typename TGeomImpl::polygon_type;
using multipolygon_type = typename TGeomImpl::multipolygon_type;
using ring_type = typename TGeomImpl::ring_type;
int epsg() const noexcept {
return m_projection.epsg();
}
std::string proj_string() const {
return m_projection.proj_string();
}
/* Point */
point_type create_point(const osmium::Location& location) const {
return m_impl.make_point(m_projection(location));
}
point_type create_point(const osmium::Node& node) {
try {
return create_point(node.location());
} catch (osmium::geometry_error& e) {
e.set_id("node", node.id());
throw;
}
}
point_type create_point(const osmium::NodeRef& node_ref) {
try {
return create_point(node_ref.location());
} catch (osmium::geometry_error& e) {
e.set_id("node", node_ref.ref());
throw;
}
}
/* LineString */
void linestring_start() {
m_impl.linestring_start();
}
template <typename TIter>
size_t fill_linestring(TIter it, TIter end) {
size_t num_points = 0;
for (; it != end; ++it, ++num_points) {
m_impl.linestring_add_location(m_projection(it->location()));
}
return num_points;
}
template <typename TIter>
size_t fill_linestring_unique(TIter it, TIter end) {
size_t num_points = 0;
osmium::Location last_location;
for (; it != end; ++it) {
if (last_location != it->location()) {
last_location = it->location();
m_impl.linestring_add_location(m_projection(last_location));
++num_points;
}
}
return num_points;
}
linestring_type linestring_finish(size_t num_points) {
return m_impl.linestring_finish(num_points);
}
linestring_type create_linestring(const osmium::WayNodeList& wnl, use_nodes un = use_nodes::unique, direction dir = direction::forward) {
linestring_start();
size_t num_points = 0;
if (un == use_nodes::unique) {
switch (dir) {
case direction::forward:
num_points = fill_linestring_unique(wnl.cbegin(), wnl.cend());
break;
case direction::backward:
num_points = fill_linestring_unique(wnl.crbegin(), wnl.crend());
break;
}
} else {
switch (dir) {
case direction::forward:
num_points = fill_linestring(wnl.cbegin(), wnl.cend());
break;
case direction::backward:
num_points = fill_linestring(wnl.crbegin(), wnl.crend());
break;
}
}
if (num_points < 2) {
throw osmium::geometry_error{"need at least two points for linestring"};
}
return linestring_finish(num_points);
}
linestring_type create_linestring(const osmium::Way& way, use_nodes un = use_nodes::unique, direction dir = direction::forward) {
try {
return create_linestring(way.nodes(), un, dir);
} catch (osmium::geometry_error& e) {
e.set_id("way", way.id());
throw;
}
}
/* Polygon */
void polygon_start() {
m_impl.polygon_start();
}
template <typename TIter>
size_t fill_polygon(TIter it, TIter end) {
size_t num_points = 0;
for (; it != end; ++it, ++num_points) {
m_impl.polygon_add_location(m_projection(it->location()));
}
return num_points;
}
template <typename TIter>
size_t fill_polygon_unique(TIter it, TIter end) {
size_t num_points = 0;
osmium::Location last_location;
for (; it != end; ++it) {
if (last_location != it->location()) {
last_location = it->location();
m_impl.polygon_add_location(m_projection(last_location));
++num_points;
}
}
return num_points;
}
polygon_type polygon_finish(size_t num_points) {
return m_impl.polygon_finish(num_points);
}
polygon_type create_polygon(const osmium::WayNodeList& wnl, use_nodes un = use_nodes::unique, direction dir = direction::forward) {
polygon_start();
size_t num_points = 0;
if (un == use_nodes::unique) {
switch (dir) {
case direction::forward:
num_points = fill_polygon_unique(wnl.cbegin(), wnl.cend());
break;
case direction::backward:
num_points = fill_polygon_unique(wnl.crbegin(), wnl.crend());
break;
}
} else {
switch (dir) {
case direction::forward:
num_points = fill_polygon(wnl.cbegin(), wnl.cend());
break;
case direction::backward:
num_points = fill_polygon(wnl.crbegin(), wnl.crend());
break;
}
}
if (num_points < 4) {
throw osmium::geometry_error{"need at least four points for polygon"};
}
return polygon_finish(num_points);
}
polygon_type create_polygon(const osmium::Way& way, use_nodes un = use_nodes::unique, direction dir = direction::forward) {
try {
return create_polygon(way.nodes(), un, dir);
} catch (osmium::geometry_error& e) {
e.set_id("way", way.id());
throw;
}
}
/* MultiPolygon */
multipolygon_type create_multipolygon(const osmium::Area& area) {
try {
size_t num_polygons = 0;
size_t num_rings = 0;
m_impl.multipolygon_start();
for (const auto& item : area) {
if (item.type() == osmium::item_type::outer_ring) {
const auto& ring = static_cast<const osmium::OuterRing&>(item);
if (num_polygons > 0) {
m_impl.multipolygon_polygon_finish();
}
m_impl.multipolygon_polygon_start();
m_impl.multipolygon_outer_ring_start();
add_points(ring);
m_impl.multipolygon_outer_ring_finish();
++num_rings;
++num_polygons;
} else if (item.type() == osmium::item_type::inner_ring) {
const auto& ring = static_cast<const osmium::InnerRing&>(item);
m_impl.multipolygon_inner_ring_start();
add_points(ring);
m_impl.multipolygon_inner_ring_finish();
++num_rings;
}
}
// if there are no rings, this area is invalid
if (num_rings == 0) {
throw osmium::geometry_error{"invalid area"};
}
m_impl.multipolygon_polygon_finish();
return m_impl.multipolygon_finish();
} catch (osmium::geometry_error& e) {
e.set_id("area", area.id());
throw;
}
}
}; // class GeometryFactory
} // namespace geom
} // namespace osmium
#endif // OSMIUM_GEOM_FACTORY_HPP
area.hpp
osmium::Area
Definition area.hpp:125
osmium::InnerRing
Definition area.hpp:80
osmium::Location
Definition location.hpp:271
osmium::Location::lon
double lon() const
Definition location.hpp:400
osmium::Location::lat
double lat() const
Definition location.hpp:419
osmium::NodeRefList
Definition node_ref_list.hpp:52
osmium::NodeRefList::cbegin
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
Definition node_ref_list.hpp:209
osmium::NodeRefList::cend
const_iterator cend() const noexcept
Returns an iterator to the end.
Definition node_ref_list.hpp:214
osmium::NodeRefList::crend
const_reverse_iterator crend() const noexcept
Returns a reverse_iterator to the end.
Definition node_ref_list.hpp:234
osmium::NodeRefList::crbegin
const_reverse_iterator crbegin() const noexcept
Returns a reverse_iterator to the beginning.
Definition node_ref_list.hpp:229
osmium::NodeRef
Definition node_ref.hpp:50
osmium::NodeRef::ref
constexpr osmium::object_id_type ref() const noexcept
Definition node_ref.hpp:71
osmium::NodeRef::location
osmium::Location & location() noexcept
Definition node_ref.hpp:85
osmium::Node
Definition node.hpp:48
osmium::OuterRing
Definition area.hpp:60
osmium::WayNodeList
Definition way.hpp:55
osmium::Way
Definition way.hpp:72
osmium::geom::GeometryFactory
Definition factory.hpp:149
osmium::geom::GeometryFactory::create_multipolygon
multipolygon_type create_multipolygon(const osmium::Area &area)
Definition factory.hpp:381
osmium::geom::GeometryFactory::multipolygon_type
typename TGeomImpl::multipolygon_type multipolygon_type
Definition factory.hpp:198
osmium::geom::GeometryFactory::linestring_start
void linestring_start()
Definition factory.hpp:235
osmium::geom::GeometryFactory::fill_polygon
size_t fill_polygon(TIter it, TIter end)
Definition factory.hpp:313
osmium::geom::GeometryFactory::point_type
typename TGeomImpl::point_type point_type
Definition factory.hpp:195
osmium::geom::GeometryFactory::create_point
point_type create_point(const osmium::Node &node)
Definition factory.hpp:215
osmium::geom::GeometryFactory::m_impl
TGeomImpl m_impl
Definition factory.hpp:165
osmium::geom::GeometryFactory::GeometryFactory
GeometryFactory()
Definition factory.hpp:169
osmium::geom::GeometryFactory::fill_linestring
size_t fill_linestring(TIter it, TIter end)
Definition factory.hpp:240
osmium::geom::GeometryFactory::polygon_start
void polygon_start()
Definition factory.hpp:308
osmium::geom::GeometryFactory::fill_polygon_unique
size_t fill_polygon_unique(TIter it, TIter end)
Definition factory.hpp:322
osmium::geom::GeometryFactory::create_linestring
linestring_type create_linestring(const osmium::Way &way, use_nodes un=use_nodes::unique, direction dir=direction::forward)
Definition factory.hpp:297
osmium::geom::GeometryFactory::create_polygon
polygon_type create_polygon(const osmium::WayNodeList &wnl, use_nodes un=use_nodes::unique, direction dir=direction::forward)
Definition factory.hpp:339
osmium::geom::GeometryFactory::polygon_type
typename TGeomImpl::polygon_type polygon_type
Definition factory.hpp:197
osmium::geom::GeometryFactory::epsg
int epsg() const noexcept
Definition factory.hpp:201
osmium::geom::GeometryFactory::create_point
point_type create_point(const osmium::NodeRef &node_ref)
Definition factory.hpp:224
osmium::geom::GeometryFactory::projection_type
TProjection projection_type
Definition factory.hpp:193
osmium::geom::GeometryFactory::m_projection
TProjection m_projection
Definition factory.hpp:164
osmium::geom::GeometryFactory::GeometryFactory
GeometryFactory(TArgs &&... args)
Definition factory.hpp:178
osmium::geom::GeometryFactory::create_point
point_type create_point(const osmium::Location &location) const
Definition factory.hpp:211
osmium::geom::GeometryFactory::GeometryFactory
GeometryFactory(TProjection &&projection, TArgs &&... args)
Definition factory.hpp:188
osmium::geom::GeometryFactory::create_polygon
polygon_type create_polygon(const osmium::Way &way, use_nodes un=use_nodes::unique, direction dir=direction::forward)
Definition factory.hpp:370
osmium::geom::GeometryFactory::fill_linestring_unique
size_t fill_linestring_unique(TIter it, TIter end)
Definition factory.hpp:249
osmium::geom::GeometryFactory::create_linestring
linestring_type create_linestring(const osmium::WayNodeList &wnl, use_nodes un=use_nodes::unique, direction dir=direction::forward)
Definition factory.hpp:266
osmium::geom::GeometryFactory::linestring_finish
linestring_type linestring_finish(size_t num_points)
Definition factory.hpp:262
osmium::geom::GeometryFactory::linestring_type
typename TGeomImpl::linestring_type linestring_type
Definition factory.hpp:196
osmium::geom::GeometryFactory::proj_string
std::string proj_string() const
Definition factory.hpp:205
osmium::geom::GeometryFactory::polygon_finish
polygon_type polygon_finish(size_t num_points)
Definition factory.hpp:335
osmium::geom::GeometryFactory::ring_type
typename TGeomImpl::ring_type ring_type
Definition factory.hpp:199
osmium::geom::GeometryFactory::add_points
void add_points(const osmium::NodeRefList &nodes)
Definition factory.hpp:154
osmium::geom::IdentityProjection
Definition factory.hpp:127
osmium::geom::IdentityProjection::proj_string
static std::string proj_string() noexcept
Definition factory.hpp:139
osmium::geom::IdentityProjection::operator()
Coordinates operator()(osmium::Location location) const
Definition factory.hpp:131
osmium::geom::IdentityProjection::epsg
static int epsg() noexcept
Definition factory.hpp:135
osmium::geometry_error
Definition factory.hpp:60
osmium::geometry_error::set_id
void set_id(const char *object_type, osmium::object_id_type id)
Definition factory.hpp:80
osmium::geometry_error::what
const char * what() const noexcept override
Definition factory.hpp:95
osmium::geometry_error::id
osmium::object_id_type id() const noexcept
Definition factory.hpp:91
osmium::geometry_error::m_message
std::string m_message
Definition factory.hpp:62
osmium::geometry_error::m_id
osmium::object_id_type m_id
Definition factory.hpp:63
osmium::geometry_error::geometry_error
geometry_error(const std::string &message, const char *object_type="", osmium::object_id_type id=0)
Definition factory.hpp:67
collection.hpp
compatibility.hpp
OSMIUM_EXPORT
#define OSMIUM_EXPORT
Definition compatibility.hpp:45
coordinates.hpp
item.hpp
item_type.hpp
location.hpp
osmium::geom::use_nodes
use_nodes
Definition factory.hpp:109
osmium::geom::use_nodes::unique
@ unique
Remove consecutive nodes with same location.
osmium::geom::use_nodes::all
@ all
Use all nodes.
osmium::geom::direction
direction
Definition factory.hpp:118
osmium::geom::direction::backward
@ backward
Linestring has reverse direction.
osmium::geom::direction::forward
@ forward
Linestring has same direction as way.
osmium
Namespace for everything in the Osmium library.
Definition assembler.hpp:53
osmium::object_id_type
int64_t object_id_type
Type for OSM object (node, way, or relation) IDs.
Definition types.hpp:45
osmium::item_type::node
@ node
osmium::item_type::way
@ way
osmium::item_type::outer_ring
@ outer_ring
osmium::item_type::inner_ring
@ inner_ring
std
Definition location.hpp:555
node.hpp
node_ref.hpp
node_ref_list.hpp
osmium::geom::Coordinates
Definition coordinates.hpp:48
types.hpp
way.hpp