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

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