| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- //! Iterate over the dense nodes in a `PrimitiveGroup`
-
- use block::str_from_stringtable;
- use error::Result;
- use proto::osmformat;
- use std;
-
- //TODO Add getter functions for id, version, uid, ...
- /// An OpenStreetMap node element from a compressed array of dense nodes (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Node)).
- #[derive(Clone, Debug)]
- pub struct DenseNode<'a> {
- block: &'a osmformat::PrimitiveBlock,
-
- /// The node id. It should be unique between nodes and might be negative to indicate
- /// that the element has not yet been uploaded to a server.
- pub id: i64,
- lat: i64,
- lon: i64,
- keys_vals_indices: &'a [i32],
- info: Option<DenseNodeInfo<'a>>,
- }
-
- impl<'a> DenseNode<'a> {
- /// return optional metadata about the ndode
- pub fn info(&'a self) -> Option<&'a DenseNodeInfo<'a>> {
- self.info.as_ref()
- }
-
- /// Returns the latitude coordinate in degrees.
- pub fn lat(&self) -> f64 {
- 1e-9 * self.nano_lat() as f64
- }
-
- /// Returns the latitude coordinate in nanodegrees (10⁻⁹).
- pub fn nano_lat(&self) -> i64 {
- self.block.get_lat_offset() + i64::from(self.block.get_granularity()) * self.lat
- }
-
- /// Returns the latitude coordinate in decimicrodegrees (10⁻⁷).
- pub fn decimicro_lat(&self) -> i32 {
- (self.nano_lat() / 100) as i32
- }
-
- /// Returns the longitude coordinate in degrees.
- pub fn lon(&self) -> f64 {
- 1e-9 * self.nano_lon() as f64
- }
-
- /// Returns the longitude in nanodegrees (10⁻⁹).
- pub fn nano_lon(&self) -> i64 {
- self.block.get_lon_offset() + i64::from(self.block.get_granularity()) * self.lon
- }
-
- /// Returns the longitude coordinate in decimicrodegrees (10⁻⁷).
- pub fn decimicro_lon(&self) -> i32 {
- (self.nano_lon() / 100) as i32
- }
-
- /// Returns an iterator over the tags of this node (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
- pub fn tags(&self) -> DenseTagIter<'a> {
- DenseTagIter {
- block: self.block,
- keys_vals_indices: self.keys_vals_indices.iter(),
- }
- }
-
- /// Returns an iterator over the tags of this node
- /// (See [OSM wiki](http://wiki.openstreetmap.org/wiki/Tags)).
- /// A tag is represented as a pair of indices (key and value) to the stringtable of the current
- /// `PrimitiveBlock`.
- pub fn raw_tags(&self) -> DenseRawTagIter<'a> {
- DenseRawTagIter {
- keys_vals_indices: self.keys_vals_indices.iter(),
- }
- }
- }
-
- /// An iterator over dense nodes. It decodes the delta encoded values.
- #[derive(Clone, Debug)]
- pub struct DenseNodeIter<'a> {
- block: &'a osmformat::PrimitiveBlock,
- dids: std::slice::Iter<'a, i64>, // deltas
- cid: i64, // current id
- dlats: std::slice::Iter<'a, i64>, // deltas
- clat: i64,
- dlons: std::slice::Iter<'a, i64>, // deltas
- clon: i64,
- keys_vals_slice: &'a [i32],
- keys_vals_index: usize,
- info_iter: Option<DenseNodeInfoIter<'a>>,
- }
-
- impl<'a> DenseNodeIter<'a> {
- pub(crate) fn new(
- block: &'a osmformat::PrimitiveBlock,
- osmdense: &'a osmformat::DenseNodes,
- ) -> DenseNodeIter<'a> {
- let info_iter = Some(DenseNodeInfoIter::new(block, osmdense.get_denseinfo()));
- DenseNodeIter {
- block,
- dids: osmdense.get_id().iter(),
- cid: 0,
- dlats: osmdense.get_lat().iter(),
- clat: 0,
- dlons: osmdense.get_lon().iter(),
- clon: 0,
- keys_vals_slice: osmdense.get_keys_vals(),
- keys_vals_index: 0,
- info_iter,
- }
- }
-
- pub(crate) fn empty(block: &'a osmformat::PrimitiveBlock) -> DenseNodeIter<'a> {
- DenseNodeIter {
- block,
- dids: [].iter(),
- cid: 0,
- dlats: [].iter(),
- clat: 0,
- dlons: [].iter(),
- clon: 0,
- keys_vals_slice: &[],
- keys_vals_index: 0,
- info_iter: None,
- }
- }
- }
-
- impl<'a> Iterator for DenseNodeIter<'a> {
- type Item = DenseNode<'a>;
-
- fn next(&mut self) -> Option<Self::Item> {
- match (
- self.dids.next(),
- self.dlats.next(),
- self.dlons.next(),
- self.info_iter.as_mut().and_then(|iter| iter.next()),
- ) {
- (Some(did), Some(dlat), Some(dlon), info) => {
- self.cid += *did;
- self.clat += *dlat;
- self.clon += *dlon;
-
- let start_index = self.keys_vals_index;
- let mut end_index = start_index;
- for chunk in self.keys_vals_slice[self.keys_vals_index..].chunks(2) {
- if chunk[0] != 0 && chunk.len() == 2 {
- end_index += 2;
- self.keys_vals_index += 2;
- } else {
- self.keys_vals_index += 1;
- break;
- }
- }
-
- Some(DenseNode {
- block: self.block,
- id: self.cid,
- lat: self.clat,
- lon: self.clon,
- keys_vals_indices: &self.keys_vals_slice[start_index..end_index],
- info,
- })
- }
- _ => None,
- }
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.dids.size_hint()
- }
- }
-
- impl<'a> ExactSizeIterator for DenseNodeIter<'a> {}
-
- /// Optional metadata with non-geographic information about a dense node
- #[derive(Clone, Debug)]
- pub struct DenseNodeInfo<'a> {
- block: &'a osmformat::PrimitiveBlock,
- /// The version of this element.
- version: i32,
- /// Timestamp
- timestamp: i64,
- /// The changeset id.
- changeset: i64,
- /// The user id.
- uid: i32,
- // String IDs for usernames.
- user_sid: i32,
- }
-
- impl<'a> DenseNodeInfo<'a> {
- /// Returns the version of this element.
- pub fn version(&self) -> i32 {
- self.version
- }
-
- /// Returns the changeset id.
- pub fn changeset(&self) -> i64 {
- self.changeset
- }
-
- /// Returns the user id.
- pub fn uid(&self) -> i32 {
- self.uid
- }
-
- /// Returns the user name.
- pub fn user(&self) -> Result<&'a str> {
- str_from_stringtable(self.block, self.user_sid as usize)
- }
-
- /// Returns the time stamp in milliseconds since the epoch.
- pub fn milli_timestamp(&self) -> i64 {
- self.timestamp * i64::from(self.block.get_date_granularity())
- }
- }
-
- /// An iterator over dense nodes info. It decodes the delta encoded values.
- #[derive(Clone, Debug)]
- pub struct DenseNodeInfoIter<'a> {
- block: &'a osmformat::PrimitiveBlock,
- versions: std::slice::Iter<'a, i32>,
- dtimestamps: std::slice::Iter<'a, i64>, // deltas
- ctimestamp: i64,
- dchangesets: std::slice::Iter<'a, i64>, // deltas
- cchangeset: i64,
- duids: std::slice::Iter<'a, i32>, // deltas
- cuid: i32,
- duser_sids: std::slice::Iter<'a, i32>, // deltas
- cuser_sid: i32,
- }
-
- impl<'a> DenseNodeInfoIter<'a> {
- fn new(
- block: &'a osmformat::PrimitiveBlock,
- info: &'a osmformat::DenseInfo,
- ) -> DenseNodeInfoIter<'a> {
- DenseNodeInfoIter {
- block,
- versions: info.get_version().iter(),
- dtimestamps: info.get_timestamp().iter(),
- ctimestamp: 0,
- dchangesets: info.get_changeset().iter(),
- cchangeset: 0,
- duids: info.get_uid().iter(),
- cuid: 0,
- duser_sids: info.get_user_sid().iter(),
- cuser_sid: 0,
- }
- }
- }
-
- impl<'a> Iterator for DenseNodeInfoIter<'a> {
- type Item = DenseNodeInfo<'a>;
-
- fn next(&mut self) -> Option<Self::Item> {
- match (
- self.versions.next(),
- self.dtimestamps.next(),
- self.dchangesets.next(),
- self.duids.next(),
- self.duser_sids.next(),
- ) {
- (Some(&version), Some(dtimestamp), Some(dchangeset), Some(duid), Some(duser_sid)) => {
- self.ctimestamp += *dtimestamp;
- self.cchangeset += *dchangeset;
- self.cuid += *duid;
- self.cuser_sid += *duser_sid;
- Some(DenseNodeInfo {
- block: self.block,
- version,
- timestamp: self.ctimestamp,
- changeset: self.cchangeset,
- uid: self.cuid,
- user_sid: self.cuser_sid,
- })
- }
- _ => None,
- }
- }
- }
-
- /// An iterator over the tags in a dense node.
- #[derive(Clone, Debug)]
- pub struct DenseTagIter<'a> {
- block: &'a osmformat::PrimitiveBlock,
- keys_vals_indices: std::slice::Iter<'a, i32>,
- }
-
- //TODO return Result
- impl<'a> Iterator for DenseTagIter<'a> {
- type Item = (&'a str, &'a str);
-
- fn next(&mut self) -> Option<Self::Item> {
- match (self.keys_vals_indices.next(), self.keys_vals_indices.next()) {
- (Some(&key_index), Some(&val_index)) => {
- let k_res = str_from_stringtable(self.block, key_index as usize);
- let v_res = str_from_stringtable(self.block, val_index as usize);
- if let (Ok(k), Ok(v)) = (k_res, v_res) {
- Some((k, v))
- } else {
- None
- }
- }
- _ => None,
- }
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- let len = self.keys_vals_indices.len() / 2;
- (len, Some(len))
- }
- }
-
- impl<'a> ExactSizeIterator for DenseTagIter<'a> {}
-
- /// An iterator over the tags of a node. It returns a pair of indices (key and value) to the
- /// stringtable of the current `PrimitiveBlock`.
- #[derive(Clone, Debug)]
- pub struct DenseRawTagIter<'a> {
- keys_vals_indices: std::slice::Iter<'a, i32>,
- }
-
- //TODO return Result
- impl<'a> Iterator for DenseRawTagIter<'a> {
- type Item = (i32, i32);
-
- fn next(&mut self) -> Option<Self::Item> {
- match (self.keys_vals_indices.next(), self.keys_vals_indices.next()) {
- (Some(&key_index), Some(&val_index)) => Some((key_index, val_index)),
- _ => None,
- }
- }
-
- fn size_hint(&self) -> (usize, Option<usize>) {
- let len = self.keys_vals_indices.len() / 2;
- (len, Some(len))
- }
- }
-
- impl<'a> ExactSizeIterator for DenseRawTagIter<'a> {}
|