Libosmium  2.1.0
Fast and flexible C++ library for working with OpenStreetMap data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
factory.hpp
Go to the documentation of this file.
1 #ifndef OSMIUM_GEOM_FACTORY_HPP
2 #define OSMIUM_GEOM_FACTORY_HPP
3 
4 /*
5 
6 This file is part of Osmium (http://osmcode.org/libosmium).
7 
8 Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
9 
10 Boost Software License - Version 1.0 - August 17th, 2003
11 
12 Permission is hereby granted, free of charge, to any person or organization
13 obtaining a copy of the software and accompanying documentation covered by
14 this license (the "Software") to use, reproduce, display, distribute,
15 execute, and transmit the Software, and to prepare derivative works of the
16 Software, and to permit third-parties to whom the Software is furnished to
17 do so, all subject to the following:
18 
19 The copyright notices in the Software and this entire statement, including
20 the above license grant, this restriction and the following disclaimer,
21 must be included in all copies of the Software, in whole or in part, and
22 all derivative works of the Software, unless such copies or derivative
23 works are solely in the form of machine-executable object code generated by
24 a source language processor.
25 
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32 DEALINGS IN THE SOFTWARE.
33 
34 */
35 
36 #include <cstddef>
37 #include <stdexcept>
38 #include <string>
39 #include <utility>
40 
43 #include <osmium/memory/item.hpp>
44 #include <osmium/osm/area.hpp>
45 #include <osmium/osm/item_type.hpp>
46 #include <osmium/osm/location.hpp>
47 #include <osmium/osm/node.hpp>
48 #include <osmium/osm/node_ref.hpp>
49 #include <osmium/osm/way.hpp>
50 
51 namespace osmium {
52 
57  struct geometry_error : public std::runtime_error {
58 
59  geometry_error(const std::string& what) :
60  std::runtime_error(what) {
61  }
62 
63  geometry_error(const char* what) :
64  std::runtime_error(what) {
65  }
66 
67  }; // struct geometry_error
68 
72  namespace geom {
73 
77  enum class use_nodes : bool {
78  unique = true,
79  all = false
80  }; // enum class use_nodes
81 
86  enum class direction : bool {
87  backward = true,
88  forward = false
89  }; // enum class direction
90 
96 
97  public:
98 
100  return Coordinates{location.lon(), location.lat()};
101  }
102 
103  int epsg() const noexcept {
104  return 4326;
105  }
106 
107  std::string proj_string() const {
108  return "+proj=longlat +datum=WGS84 +no_defs";
109  }
110 
111  }; // class IdentityProjection
112 
116  template <class TGeomImpl, class TProjection = IdentityProjection>
118 
122  void add_points(const osmium::OuterRing& nodes) {
123  osmium::Location last_location;
124  for (const osmium::NodeRef& node_ref : nodes) {
125  if (last_location != node_ref.location()) {
126  last_location = node_ref.location();
127  m_impl.multipolygon_add_location(m_projection(last_location));
128  }
129  }
130  }
131 
132  TProjection m_projection;
133  TGeomImpl m_impl;
134 
135  public:
136 
140  template <class... TArgs>
142  m_projection(),
143  m_impl(std::forward<TArgs>(args)...) {
144  }
145 
150  template <class... TArgs>
151  GeometryFactory<TGeomImpl, TProjection>(TProjection&& projection, TArgs&&... args) :
152  m_projection(std::move(projection)),
153  m_impl(std::forward<TArgs>(args)...) {
154  }
155 
156  typedef typename TGeomImpl::point_type point_type;
157  typedef typename TGeomImpl::linestring_type linestring_type;
158  typedef typename TGeomImpl::polygon_type polygon_type;
159  typedef typename TGeomImpl::multipolygon_type multipolygon_type;
160  typedef typename TGeomImpl::ring_type ring_type;
161 
162  int epsg() const {
163  return m_projection.epsg();
164  }
165 
166  std::string proj_string() const {
167  return m_projection.proj_string();
168  }
169 
170  /* Point */
171 
172  point_type create_point(const osmium::Location location) const {
173  return m_impl.make_point(m_projection(location));
174  }
175 
176  point_type create_point(const osmium::Node& node) {
177  return create_point(node.location());
178  }
179 
180  point_type create_point(const osmium::NodeRef& node_ref) {
181  return create_point(node_ref.location());
182  }
183 
184  /* LineString */
185 
187  m_impl.linestring_start();
188  }
189 
190  template <class TIter>
191  size_t fill_linestring(TIter it, TIter end) {
192  size_t num_points = 0;
193  for (; it != end; ++it, ++num_points) {
194  m_impl.linestring_add_location(m_projection(it->location()));
195  }
196  return num_points;
197  }
198 
199  template <class TIter>
200  size_t fill_linestring_unique(TIter it, TIter end) {
201  size_t num_points = 0;
202  osmium::Location last_location;
203  for (; it != end; ++it) {
204  if (last_location != it->location()) {
205  last_location = it->location();
206  m_impl.linestring_add_location(m_projection(last_location));
207  ++num_points;
208  }
209  }
210  return num_points;
211  }
212 
213  linestring_type linestring_finish(size_t num_points) {
214  return m_impl.linestring_finish(num_points);
215  }
216 
219  size_t num_points = 0;
220 
221  if (un == use_nodes::unique) {
222  osmium::Location last_location;
223  switch (dir) {
224  case direction::forward:
225  num_points = fill_linestring_unique(wnl.cbegin(), wnl.cend());
226  break;
227  case direction::backward:
228  num_points = fill_linestring_unique(wnl.crbegin(), wnl.crend());
229  break;
230  }
231  } else {
232  switch (dir) {
233  case direction::forward:
234  num_points = fill_linestring(wnl.cbegin(), wnl.cend());
235  break;
236  case direction::backward:
237  num_points = fill_linestring(wnl.crbegin(), wnl.crend());
238  break;
239  }
240  }
241 
242  if (num_points < 2) {
243  throw osmium::geometry_error("not enough points for linestring");
244  }
245 
246  return linestring_finish(num_points);
247  }
248 
250  return create_linestring(way.nodes(), un, dir);
251  }
252 
253  /* Polygon */
254 
255  void polygon_start() {
256  m_impl.polygon_start();
257  }
258 
259  template <class TIter>
260  size_t fill_polygon(TIter it, TIter end) {
261  size_t num_points = 0;
262  for (; it != end; ++it, ++num_points) {
263  m_impl.polygon_add_location(m_projection(it->location()));
264  }
265  return num_points;
266  }
267 
268  template <class TIter>
269  size_t fill_polygon_unique(TIter it, TIter end) {
270  size_t num_points = 0;
271  osmium::Location last_location;
272  for (; it != end; ++it) {
273  if (last_location != it->location()) {
274  last_location = it->location();
275  m_impl.polygon_add_location(m_projection(last_location));
276  ++num_points;
277  }
278  }
279  return num_points;
280  }
281 
282  polygon_type polygon_finish(size_t num_points) {
283  return m_impl.polygon_finish(num_points);
284  }
285 
286  /* MultiPolygon */
287 
288  multipolygon_type create_multipolygon(const osmium::Area& area) {
289  size_t num_polygons = 0;
290  size_t num_rings = 0;
291  m_impl.multipolygon_start();
292 
293  for (auto it = area.cbegin(); it != area.cend(); ++it) {
294  const osmium::OuterRing& ring = static_cast<const osmium::OuterRing&>(*it);
295  if (it->type() == osmium::item_type::outer_ring) {
296  if (num_polygons > 0) {
297  m_impl.multipolygon_polygon_finish();
298  }
299  m_impl.multipolygon_polygon_start();
300  m_impl.multipolygon_outer_ring_start();
301  add_points(ring);
302  m_impl.multipolygon_outer_ring_finish();
303  ++num_rings;
304  ++num_polygons;
305  } else if (it->type() == osmium::item_type::inner_ring) {
306  m_impl.multipolygon_inner_ring_start();
307  add_points(ring);
308  m_impl.multipolygon_inner_ring_finish();
309  ++num_rings;
310  }
311  }
312 
313  // if there are no rings, this area is invalid
314  if (num_rings == 0) {
315  throw osmium::geometry_error("invalid area");
316  }
317 
318  m_impl.multipolygon_polygon_finish();
319  return m_impl.multipolygon_finish();
320  }
321 
322  }; // class GeometryFactory
323 
324  } // namespace geom
325 
326 } // namespace osmium
327 
328 #endif // OSMIUM_GEOM_FACTORY_HPP
WayNodeList & nodes()
Definition: way.hpp:75
const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
Definition: node_ref_list.hpp:151
point_type create_point(const osmium::NodeRef &node_ref)
Definition: factory.hpp:180
linestring_type linestring_finish(size_t num_points)
Definition: factory.hpp:213
Definition: factory.hpp:117
const_reverse_iterator crbegin() const noexcept
Returns a reverse_iterator to the beginning.
Definition: node_ref_list.hpp:171
size_t fill_polygon_unique(TIter it, TIter end)
Definition: factory.hpp:269
Linestring has reverse direction.
point_type create_point(const osmium::Location location) const
Definition: factory.hpp:172
const_iterator cend() const
Definition: object.hpp:345
Definition: area.hpp:113
Definition: reader_iterator.hpp:39
geometry_error(const std::string &what)
Definition: factory.hpp:59
const_iterator cbegin() const
Definition: object.hpp:341
Definition: way.hpp:65
TGeomImpl::ring_type ring_type
Definition: factory.hpp:160
const_iterator cend() const noexcept
Returns an iterator to the end.
Definition: node_ref_list.hpp:156
geometry_error(const char *what)
Definition: factory.hpp:63
int epsg() const noexcept
Definition: factory.hpp:103
Linestring has same direction as way.
double lat() const
Definition: location.hpp:205
void add_points(const osmium::OuterRing &nodes)
Definition: factory.hpp:122
TGeomImpl::point_type point_type
Definition: factory.hpp:156
Definition: way.hpp:52
Namespace for everything in the Osmium library.
Definition: assembler.hpp:55
TGeomImpl m_impl
Definition: factory.hpp:133
linestring_type create_linestring(const osmium::WayNodeList &wnl, use_nodes un=use_nodes::unique, direction dir=direction::forward)
Definition: factory.hpp:217
TProjection m_projection
Definition: factory.hpp:132
void polygon_start()
Definition: factory.hpp:255
Definition: coordinates.hpp:47
size_t fill_linestring_unique(TIter it, TIter end)
Definition: factory.hpp:200
int epsg() const
Definition: factory.hpp:162
osmium::io::InputIterator< osmium::io::Reader > end(osmium::io::Reader &)
Definition: reader_iterator.hpp:45
Remove consecutive nodes with same location.
std::string proj_string() const
Definition: factory.hpp:107
void linestring_start()
Definition: factory.hpp:186
Definition: area.hpp:56
std::string proj_string() const
Definition: factory.hpp:166
TGeomImpl::multipolygon_type multipolygon_type
Definition: factory.hpp:159
Definition: location.hpp:79
osmium::Location & location() noexcept
Definition: node_ref.hpp:73
multipolygon_type create_multipolygon(const osmium::Area &area)
Definition: factory.hpp:288
size_t fill_linestring(TIter it, TIter end)
Definition: factory.hpp:191
polygon_type polygon_finish(size_t num_points)
Definition: factory.hpp:282
direction
Definition: factory.hpp:86
Definition: factory.hpp:57
TGeomImpl::polygon_type polygon_type
Definition: factory.hpp:158
double lon() const
Definition: location.hpp:186
TGeomImpl::linestring_type linestring_type
Definition: factory.hpp:157
size_t fill_polygon(TIter it, TIter end)
Definition: factory.hpp:260
osmium::Location location() const noexcept
Definition: node.hpp:61
Definition: node.hpp:47
point_type create_point(const osmium::Node &node)
Definition: factory.hpp:176
use_nodes
Definition: factory.hpp:77
Definition: node_ref.hpp:50
const_reverse_iterator crend() const noexcept
Returns a reverse_iterator to the end.
Definition: node_ref_list.hpp:176
linestring_type create_linestring(const osmium::Way &way, use_nodes un=use_nodes::unique, direction dir=direction::forward)
Definition: factory.hpp:249
Coordinates operator()(osmium::Location location) const
Definition: factory.hpp:99
Definition: factory.hpp:95