A Rust library for reading the OpenStreetMap PBF file format (*.osm.pbf).

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. //! Iterate over the dense nodes in a `PrimitiveGroup`
  2. use block::str_from_stringtable;
  3. use error::Result;
  4. use proto::osmformat;
  5. use std;
  6. //TODO Add getter functions for id, version, uid, ...
  7. /// An OpenStreetMap node element from a compressed array of dense nodes (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Node)).
  8. #[derive(Clone, Debug)]
  9. pub struct DenseNode<'a> {
  10. block: &'a osmformat::PrimitiveBlock,
  11. /// The node id. It should be unique between nodes and might be negative to indicate
  12. /// that the element has not yet been uploaded to a server.
  13. pub id: i64,
  14. /// The version of this element.
  15. pub version: i32,
  16. timestamp: i64,
  17. /// The changeset id.
  18. pub changeset: i64,
  19. /// The user id.
  20. pub uid: i32,
  21. user_sid: i32,
  22. lat: i64,
  23. lon: i64,
  24. keys_vals_indices: &'a [i32],
  25. }
  26. impl<'a> DenseNode<'a> {
  27. /// Returns the user name.
  28. pub fn user(&self) -> Result<&'a str> {
  29. str_from_stringtable(self.block, self.user_sid as usize)
  30. }
  31. /// Returns the latitude coordinate in degrees.
  32. pub fn lat(&self) -> f64 {
  33. 1e-9 * self.nano_lat() as f64
  34. }
  35. /// Returns the latitude coordinate in nanodegrees (10⁻⁹).
  36. pub fn nano_lat(&self) -> i64 {
  37. self.block.get_lat_offset() + i64::from(self.block.get_granularity()) * self.lat
  38. }
  39. /// Returns the latitude coordinate in decimicrodegrees (10⁻⁷).
  40. pub fn decimicro_lat(&self) -> i32 {
  41. (self.nano_lat() / 100) as i32
  42. }
  43. /// Returns the longitude coordinate in degrees.
  44. pub fn lon(&self) -> f64 {
  45. 1e-9 * self.nano_lon() as f64
  46. }
  47. /// Returns the longitude in nanodegrees (10⁻⁹).
  48. pub fn nano_lon(&self) -> i64 {
  49. self.block.get_lon_offset() + i64::from(self.block.get_granularity()) * self.lon
  50. }
  51. /// Returns the longitude coordinate in decimicrodegrees (10⁻⁷).
  52. pub fn decimicro_lon(&self) -> i32 {
  53. (self.nano_lon() / 100) as i32
  54. }
  55. /// Returns the time stamp in milliseconds since the epoch.
  56. pub fn milli_timestamp(&self) -> i64 {
  57. self.timestamp * i64::from(self.block.get_date_granularity())
  58. }
  59. /// Returns an iterator over the tags of this node (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
  60. pub fn tags(&self) -> DenseTagIter<'a> {
  61. DenseTagIter {
  62. block: self.block,
  63. keys_vals_indices: self.keys_vals_indices.iter(),
  64. }
  65. }
  66. /// Returns an iterator over the tags of this node
  67. /// (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
  68. /// A tag is represented as a pair of indices (key and value) to the stringtable of the current
  69. /// `PrimitiveBlock`.
  70. pub fn raw_tags(&self) -> DenseRawTagIter<'a> {
  71. DenseRawTagIter {
  72. keys_vals_indices: self.keys_vals_indices.iter(),
  73. }
  74. }
  75. }
  76. /// An iterator over dense nodes. It decodes the delta encoded values.
  77. #[derive(Clone, Debug)]
  78. pub struct DenseNodeIter<'a> {
  79. block: &'a osmformat::PrimitiveBlock,
  80. dids: std::slice::Iter<'a, i64>, // deltas
  81. cid: i64, // current id
  82. versions: std::slice::Iter<'a, i32>,
  83. dtimestamps: std::slice::Iter<'a, i64>, // deltas
  84. ctimestamp: i64,
  85. dchangesets: std::slice::Iter<'a, i64>, // deltas
  86. cchangeset: i64,
  87. duids: std::slice::Iter<'a, i32>, // deltas
  88. cuid: i32,
  89. duser_sids: std::slice::Iter<'a, i32>, // deltas
  90. cuser_sid: i32,
  91. dlats: std::slice::Iter<'a, i64>, // deltas
  92. clat: i64,
  93. dlons: std::slice::Iter<'a, i64>, // deltas
  94. clon: i64,
  95. keys_vals_slice: &'a [i32],
  96. keys_vals_index: usize,
  97. }
  98. impl<'a> DenseNodeIter<'a> {
  99. pub(crate) fn new(
  100. block: &'a osmformat::PrimitiveBlock,
  101. osmdense: &'a osmformat::DenseNodes,
  102. ) -> DenseNodeIter<'a> {
  103. let info = osmdense.get_denseinfo();
  104. DenseNodeIter {
  105. block,
  106. dids: osmdense.get_id().iter(),
  107. cid: 0,
  108. versions: info.get_version().iter(),
  109. dtimestamps: info.get_timestamp().iter(),
  110. ctimestamp: 0,
  111. dchangesets: info.get_changeset().iter(),
  112. cchangeset: 0,
  113. duids: info.get_uid().iter(),
  114. cuid: 0,
  115. duser_sids: info.get_user_sid().iter(),
  116. cuser_sid: 0,
  117. dlats: osmdense.get_lat().iter(),
  118. clat: 0,
  119. dlons: osmdense.get_lon().iter(),
  120. clon: 0,
  121. keys_vals_slice: osmdense.get_keys_vals(),
  122. keys_vals_index: 0,
  123. }
  124. }
  125. pub(crate) fn empty(block: &'a osmformat::PrimitiveBlock) -> DenseNodeIter<'a> {
  126. DenseNodeIter {
  127. block,
  128. dids: [].iter(),
  129. cid: 0,
  130. versions: [].iter(),
  131. dtimestamps: [].iter(),
  132. ctimestamp: 0,
  133. dchangesets: [].iter(),
  134. cchangeset: 0,
  135. duids: [].iter(),
  136. cuid: 0,
  137. duser_sids: [].iter(),
  138. cuser_sid: 0,
  139. dlats: [].iter(),
  140. clat: 0,
  141. dlons: [].iter(),
  142. clon: 0,
  143. keys_vals_slice: &[],
  144. keys_vals_index: 0,
  145. }
  146. }
  147. }
  148. impl<'a> Iterator for DenseNodeIter<'a> {
  149. type Item = DenseNode<'a>;
  150. fn next(&mut self) -> Option<Self::Item> {
  151. match (
  152. self.dids.next(),
  153. self.versions.next(),
  154. self.dtimestamps.next(),
  155. self.dchangesets.next(),
  156. self.duids.next(),
  157. self.duser_sids.next(),
  158. self.dlats.next(),
  159. self.dlons.next(),
  160. ) {
  161. (
  162. Some(did),
  163. Some(version),
  164. Some(dtimestamp),
  165. Some(dchangeset),
  166. Some(duid),
  167. Some(duser_sid),
  168. Some(dlat),
  169. Some(dlon),
  170. ) => {
  171. self.cid += *did;
  172. self.ctimestamp += *dtimestamp;
  173. self.cchangeset += *dchangeset;
  174. self.cuid += *duid;
  175. self.cuser_sid += *duser_sid;
  176. self.clat += *dlat;
  177. self.clon += *dlon;
  178. let start_index = self.keys_vals_index;
  179. let mut end_index = start_index;
  180. for chunk in self.keys_vals_slice[self.keys_vals_index..].chunks(2) {
  181. if chunk[0] != 0 && chunk.len() == 2 {
  182. end_index += 2;
  183. self.keys_vals_index += 2;
  184. } else {
  185. self.keys_vals_index += 1;
  186. break;
  187. }
  188. }
  189. Some(DenseNode {
  190. block: self.block,
  191. id: self.cid,
  192. version: *version,
  193. timestamp: self.ctimestamp,
  194. changeset: self.cchangeset,
  195. uid: self.cuid,
  196. user_sid: self.cuser_sid,
  197. lat: self.clat,
  198. lon: self.clon,
  199. keys_vals_indices: &self.keys_vals_slice[start_index..end_index],
  200. })
  201. }
  202. _ => None,
  203. }
  204. }
  205. fn size_hint(&self) -> (usize, Option<usize>) {
  206. self.dids.size_hint()
  207. }
  208. }
  209. impl<'a> ExactSizeIterator for DenseNodeIter<'a> {}
  210. /// An iterator over the tags in a dense node.
  211. #[derive(Clone, Debug)]
  212. pub struct DenseTagIter<'a> {
  213. block: &'a osmformat::PrimitiveBlock,
  214. keys_vals_indices: std::slice::Iter<'a, i32>,
  215. }
  216. //TODO return Result
  217. impl<'a> Iterator for DenseTagIter<'a> {
  218. type Item = (&'a str, &'a str);
  219. fn next(&mut self) -> Option<Self::Item> {
  220. match (self.keys_vals_indices.next(), self.keys_vals_indices.next()) {
  221. (Some(&key_index), Some(&val_index)) => {
  222. let k_res = str_from_stringtable(self.block, key_index as usize);
  223. let v_res = str_from_stringtable(self.block, val_index as usize);
  224. if let (Ok(k), Ok(v)) = (k_res, v_res) {
  225. Some((k, v))
  226. } else {
  227. None
  228. }
  229. }
  230. _ => None,
  231. }
  232. }
  233. fn size_hint(&self) -> (usize, Option<usize>) {
  234. let len = self.keys_vals_indices.len() / 2;
  235. (len, Some(len))
  236. }
  237. }
  238. impl<'a> ExactSizeIterator for DenseTagIter<'a> {}
  239. /// An iterator over the tags of a node. It returns a pair of indices (key and value) to the
  240. /// stringtable of the current `PrimitiveBlock`.
  241. #[derive(Clone, Debug)]
  242. pub struct DenseRawTagIter<'a> {
  243. keys_vals_indices: std::slice::Iter<'a, i32>,
  244. }
  245. //TODO return Result
  246. impl<'a> Iterator for DenseRawTagIter<'a> {
  247. type Item = (i32, i32);
  248. fn next(&mut self) -> Option<Self::Item> {
  249. match (self.keys_vals_indices.next(), self.keys_vals_indices.next()) {
  250. (Some(&key_index), Some(&val_index)) => Some((key_index, val_index)),
  251. _ => None,
  252. }
  253. }
  254. fn size_hint(&self) -> (usize, Option<usize>) {
  255. let len = self.keys_vals_indices.len() / 2;
  256. (len, Some(len))
  257. }
  258. }
  259. impl<'a> ExactSizeIterator for DenseRawTagIter<'a> {}