Libosmium  2.7.2
Fast and flexible C++ library for working with OpenStreetMap data
wkb.hpp
Go to the documentation of this file.
1 #ifndef OSMIUM_GEOM_WKB_HPP
2 #define OSMIUM_GEOM_WKB_HPP
3 
4 /*
5 
6 This file is part of Osmium (http://osmcode.org/libosmium).
7 
8 Copyright 2013-2016 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 <cstdint>
38 #include <string>
39 
41 #include <osmium/geom/factory.hpp>
42 #include <osmium/util/cast.hpp>
43 #include <osmium/util/endian.hpp>
44 
45 namespace osmium {
46 
47  namespace geom {
48 
49  enum class wkb_type : bool {
50  wkb = false,
51  ewkb = true
52  }; // enum class wkb_type
53 
54  enum class out_type : bool {
55  binary = false,
56  hex = true
57  }; // enum class out_type
58 
59  namespace detail {
60 
61  template <typename T>
62  inline void str_push(std::string& str, T data) {
63  size_t size = str.size();
64  str.resize(size + sizeof(T));
65  std::copy_n(reinterpret_cast<char*>(&data), sizeof(T), &str[size]);
66  }
67 
68  inline std::string convert_to_hex(const std::string& str) {
69  static const char* lookup_hex = "0123456789ABCDEF";
70  std::string out;
71 
72  for (char c : str) {
73  out += lookup_hex[(c >> 4) & 0xf];
74  out += lookup_hex[c & 0xf];
75  }
76 
77  return out;
78  }
79 
80  class WKBFactoryImpl {
81 
83  static constexpr uint32_t srid = 4326;
84 
92  enum wkbGeometryType : uint32_t {
93  wkbPoint = 1,
94  wkbLineString = 2,
95  wkbPolygon = 3,
96  wkbMultiPoint = 4,
97  wkbMultiLineString = 5,
98  wkbMultiPolygon = 6,
99  wkbGeometryCollection = 7,
100 
101  // SRID-presence flag (EWKB)
102  wkbSRID = 0x20000000
103  }; // enum wkbGeometryType
104 
108  enum class wkb_byte_order_type : uint8_t {
109  XDR = 0, // Big Endian
110  NDR = 1 // Little Endian
111  }; // enum class wkb_byte_order_type
112 
113  std::string m_data;
114  uint32_t m_points {0};
115  wkb_type m_wkb_type;
116  out_type m_out_type;
117 
118  size_t m_linestring_size_offset = 0;
119  size_t m_polygons = 0;
120  size_t m_rings = 0;
121  size_t m_multipolygon_size_offset = 0;
122  size_t m_polygon_size_offset = 0;
123  size_t m_ring_size_offset = 0;
124 
125  size_t header(std::string& str, wkbGeometryType type, bool add_length) const {
126 #if __BYTE_ORDER == __LITTLE_ENDIAN
127  str_push(str, wkb_byte_order_type::NDR);
128 #else
129  str_push(str, wkb_byte_order_type::XDR);
130 #endif
131  if (m_wkb_type == wkb_type::ewkb) {
132  str_push(str, type | wkbSRID);
133  str_push(str, srid);
134  } else {
135  str_push(str, type);
136  }
137  size_t offset = str.size();
138  if (add_length) {
139  str_push(str, static_cast<uint32_t>(0));
140  }
141  return offset;
142  }
143 
144  void set_size(const size_t offset, const size_t size) {
145  uint32_t s = static_cast_with_assert<uint32_t>(size);
146  std::copy_n(reinterpret_cast<char*>(&s), sizeof(uint32_t), &m_data[offset]);
147  }
148 
149  public:
150 
151  using point_type = std::string;
152  using linestring_type = std::string;
153  using polygon_type = std::string;
154  using multipolygon_type = std::string;
155  using ring_type = std::string;
156 
157  explicit WKBFactoryImpl(wkb_type wtype = wkb_type::wkb, out_type otype = out_type::binary) :
158  m_wkb_type(wtype),
159  m_out_type(otype) {
160  }
161 
162  /* Point */
163 
164  point_type make_point(const osmium::geom::Coordinates& xy) const {
165  std::string data;
166  header(data, wkbPoint, false);
167  str_push(data, xy.x);
168  str_push(data, xy.y);
169 
170  if (m_out_type == out_type::hex) {
171  return convert_to_hex(data);
172  } else {
173  return data;
174  }
175  }
176 
177  /* LineString */
178 
179  void linestring_start() {
180  m_data.clear();
181  m_linestring_size_offset = header(m_data, wkbLineString, true);
182  }
183 
184  void linestring_add_location(const osmium::geom::Coordinates& xy) {
185  str_push(m_data, xy.x);
186  str_push(m_data, xy.y);
187  }
188 
189  linestring_type linestring_finish(size_t num_points) {
190  set_size(m_linestring_size_offset, num_points);
191  std::string data;
192 
193  using std::swap;
194  swap(data, m_data);
195 
196  if (m_out_type == out_type::hex) {
197  return convert_to_hex(data);
198  } else {
199  return data;
200  }
201  }
202 
203  /* MultiPolygon */
204 
205  void multipolygon_start() {
206  m_data.clear();
207  m_polygons = 0;
208  m_multipolygon_size_offset = header(m_data, wkbMultiPolygon, true);
209  }
210 
211  void multipolygon_polygon_start() {
212  ++m_polygons;
213  m_rings = 0;
214  m_polygon_size_offset = header(m_data, wkbPolygon, true);
215  }
216 
217  void multipolygon_polygon_finish() {
218  set_size(m_polygon_size_offset, m_rings);
219  }
220 
221  void multipolygon_outer_ring_start() {
222  ++m_rings;
223  m_points = 0;
224  m_ring_size_offset = m_data.size();
225  str_push(m_data, static_cast<uint32_t>(0));
226  }
227 
228  void multipolygon_outer_ring_finish() {
229  set_size(m_ring_size_offset, m_points);
230  }
231 
232  void multipolygon_inner_ring_start() {
233  ++m_rings;
234  m_points = 0;
235  m_ring_size_offset = m_data.size();
236  str_push(m_data, static_cast<uint32_t>(0));
237  }
238 
239  void multipolygon_inner_ring_finish() {
240  set_size(m_ring_size_offset, m_points);
241  }
242 
243  void multipolygon_add_location(const osmium::geom::Coordinates& xy) {
244  str_push(m_data, xy.x);
245  str_push(m_data, xy.y);
246  ++m_points;
247  }
248 
249  multipolygon_type multipolygon_finish() {
250  set_size(m_multipolygon_size_offset, m_polygons);
251  std::string data;
252 
253  using std::swap;
254  swap(data, m_data);
255 
256  if (m_out_type == out_type::hex) {
257  return convert_to_hex(data);
258  } else {
259  return data;
260  }
261  }
262 
263  }; // class WKBFactoryImpl
264 
265  } // namespace detail
266 
267  template <typename TProjection = IdentityProjection>
269 
270  } // namespace geom
271 
272 } // namespace osmium
273 
274 #endif // OSMIUM_GEOM_WKB_HPP
double y
Definition: coordinates.hpp:49
Definition: factory.hpp:146
type
Definition: entity_bits.hpp:63
void swap(Buffer &lhs, Buffer &rhs)
Definition: buffer.hpp:731
Namespace for everything in the Osmium library.
Definition: assembler.hpp:66
Definition: attr.hpp:298
Definition: coordinates.hpp:46
wkb_type
Definition: wkb.hpp:49
out_type
Definition: wkb.hpp:54
double x
Definition: coordinates.hpp:48