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 (http://osmcode.org/libosmium).
Copyright 2013-2016 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 <cstddef>
#include <stdexcept>
#include <string>
#include <utility>
#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/way.hpp>
namespace osmium {
class 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();
}
}; // struct 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()};
}
int epsg() const noexcept {
return 4326;
}
std::string proj_string() const {
return "+proj=longlat +datum=WGS84 +no_defs";
}
}; // class IdentityProjection
template <typename TGeomImpl, typename TProjection = IdentityProjection>
class GeometryFactory {
void add_points(const osmium::OuterRing& 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:
template <typename... TArgs>
explicit GeometryFactory<TGeomImpl, TProjection>(TArgs&&... args) :
m_projection(),
m_impl(std::forward<TArgs>(args)...) {
}
template <typename... TArgs>
explicit GeometryFactory<TGeomImpl, TProjection>(TProjection&& projection, TArgs&&... args) :
m_projection(std::move(projection)),
m_impl(std::forward<TArgs>(args)...) {
}
typedef TProjection projection_type;
typedef typename TGeomImpl::point_type point_type;
typedef typename TGeomImpl::linestring_type linestring_type;
typedef typename TGeomImpl::polygon_type polygon_type;
typedef typename TGeomImpl::multipolygon_type multipolygon_type;
typedef typename TGeomImpl::ring_type ring_type;
int epsg() const {
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) {
osmium::Location last_location;
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) {
osmium::Location last_location;
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 (auto it = area.cbegin(); it != area.cend(); ++it) {
const osmium::OuterRing& ring = static_cast<const osmium::OuterRing&>(*it);
if (it->type() == osmium::item_type::outer_ring) {
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 (it->type() == osmium::item_type::inner_ring) {
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("area contains no rings");
}
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
osmium::Way::nodes
WayNodeList & nodes()
Definition: way.hpp:75
osmium::item_type::way
collection.hpp
osmium::NodeRefList::cbegin
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
Definition: node_ref_list.hpp:154
osmium::geom::GeometryFactory::create_point
point_type create_point(const osmium::NodeRef &node_ref)
Definition: factory.hpp:215
coordinates.hpp
osmium::geom::GeometryFactory::linestring_finish
linestring_type linestring_finish(size_t num_points)
Definition: factory.hpp:253
osmium::geom::GeometryFactory
Definition: factory.hpp:146
osmium::item_type::outer_ring
location.hpp
osmium::item_type::inner_ring
osmium::geometry_error::what
const char * what() const noexceptoverride
Definition: factory.hpp:92
osmium::NodeRefList::crbegin
const_reverse_iterator crbegin() const noexcept
Returns a reverse_iterator to the beginning.
Definition: node_ref_list.hpp:174
osmium::geom::GeometryFactory::fill_polygon_unique
size_t fill_polygon_unique(TIter it, TIter end)
Definition: factory.hpp:314
osmium::geom::direction::backward
Linestring has reverse direction.
osmium::OSMObject::cend
const_iterator cend() const
Definition: object.hpp:346
osmium::Area
Definition: area.hpp:113
std
Definition: reader_iterator.hpp:39
node_ref.hpp
osmium::item_type::area
osmium::OSMObject::cbegin
const_iterator cbegin() const
Definition: object.hpp:342
osmium::Way
Definition: way.hpp:65
osmium::geom::GeometryFactory::ring_type
TGeomImpl::ring_type ring_type
Definition: factory.hpp:190
item_type.hpp
osmium::NodeRefList::cend
const_iterator cend() const noexcept
Returns an iterator to the end.
Definition: node_ref_list.hpp:159
osmium::item_type::node
osmium::geom::IdentityProjection::epsg
int epsg() const noexcept
Definition: factory.hpp:132
osmium::geom::direction::forward
Linestring has same direction as way.
osmium::geometry_error
Definition: factory.hpp:57
osmium::Location::lat
double lat() const
Definition: location.hpp:205
osmium::geom::GeometryFactory::add_points
void add_points(const osmium::OuterRing &nodes)
Definition: factory.hpp:151
osmium::geom::GeometryFactory::point_type
TGeomImpl::point_type point_type
Definition: factory.hpp:186
osmium::NodeRef::ref
constexpr osmium::object_id_type ref() const noexcept
Definition: node_ref.hpp:65
way.hpp
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:363
osmium::WayNodeList
Definition: way.hpp:52
osmium::object_id_type
int64_t object_id_type
Type for OSM object (node, way, or relation) IDs.
Definition: types.hpp:45
osmium
Namespace for everything in the Osmium library.
Definition: assembler.hpp:59
osmium::geom::GeometryFactory::m_impl
TGeomImpl m_impl
Definition: factory.hpp:162
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:257
osmium::geom::GeometryFactory::m_projection
TProjection m_projection
Definition: factory.hpp:161
osmium::geom::GeometryFactory::polygon_start
void polygon_start()
Definition: factory.hpp:300
osmium::geom::Coordinates
Definition: coordinates.hpp:46
area.hpp
osmium::geom::GeometryFactory::create_point
point_type create_point(const osmium::Location &location) const
Definition: factory.hpp:202
osmium::geom::GeometryFactory::fill_linestring_unique
size_t fill_linestring_unique(TIter it, TIter end)
Definition: factory.hpp:240
osmium::geom::GeometryFactory::epsg
int epsg() const
Definition: factory.hpp:192
std::end
osmium::io::InputIterator< osmium::io::Reader > end(osmium::io::Reader &)
Definition: reader_iterator.hpp:45
osmium::geom::use_nodes::unique
Remove consecutive nodes with same location.
osmium::geom::IdentityProjection::proj_string
std::string proj_string() const
Definition: factory.hpp:136
osmium::geom::GeometryFactory::linestring_start
void linestring_start()
Definition: factory.hpp:226
osmium::OuterRing
Definition: area.hpp:56
osmium::geom::GeometryFactory::proj_string
std::string proj_string() const
Definition: factory.hpp:196
osmium::geometry_error::m_id
osmium::object_id_type m_id
Definition: factory.hpp:60
osmium::geom::GeometryFactory::multipolygon_type
TGeomImpl::multipolygon_type multipolygon_type
Definition: factory.hpp:189
osmium::Location
Definition: location.hpp:79
osmium::NodeRef::location
osmium::Location & location() noexcept
Definition: node_ref.hpp:79
osmium::geom::GeometryFactory::create_multipolygon
multipolygon_type create_multipolygon(const osmium::Area &area)
Definition: factory.hpp:374
osmium::geom::GeometryFactory::fill_linestring
size_t fill_linestring(TIter it, TIter end)
Definition: factory.hpp:231
osmium::geom::GeometryFactory::polygon_finish
polygon_type polygon_finish(size_t num_points)
Definition: factory.hpp:327
osmium::geom::direction
direction
Definition: factory.hpp:115
osmium::OSMObject::id
object_id_type id() const noexcept
Get ID of this object.
Definition: object.hpp:110
osmium::geom::GeometryFactory::polygon_type
TGeomImpl::polygon_type polygon_type
Definition: factory.hpp:188
osmium::Location::lon
double lon() const
Definition: location.hpp:186
osmium::geom::GeometryFactory::linestring_type
TGeomImpl::linestring_type linestring_type
Definition: factory.hpp:187
item.hpp
osmium::geom::GeometryFactory::fill_polygon
size_t fill_polygon(TIter it, TIter end)
Definition: factory.hpp:305
osmium::Node::location
osmium::Location location() const noexcept
Definition: node.hpp:61
osmium::geom::GeometryFactory::projection_type
TProjection projection_type
Definition: factory.hpp:185
osmium::geometry_error::id
osmium::object_id_type id() const noexcept
Definition: factory.hpp:88
osmium::Node
Definition: node.hpp:47
node.hpp
osmium::geom::GeometryFactory::create_point
point_type create_point(const osmium::Node &node)
Definition: factory.hpp:206
osmium::geom::use_nodes
use_nodes
Definition: factory.hpp:106
osmium::geometry_error::geometry_error
geometry_error(const std::string &message, const char *object_type="", osmium::object_id_type id=0)
Definition: factory.hpp:64
osmium::geometry_error::m_message
std::string m_message
Definition: factory.hpp:59
osmium::NodeRef
Definition: node_ref.hpp:50
osmium::NodeRefList::crend
const_reverse_iterator crend() const noexcept
Returns a reverse_iterator to the end.
Definition: node_ref_list.hpp:179
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:289
osmium::geom::IdentityProjection::operator()
Coordinates operator()(osmium::Location location) const
Definition: factory.hpp:128
osmium::geometry_error::set_id
void set_id(const char *object_type, osmium::object_id_type id)
Definition: factory.hpp:77
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:331
osmium::geom::IdentityProjection
Definition: factory.hpp:124