Skip to content

Commit

Permalink
Merge pull request #250 from NREL/rjf/wkb
Browse files Browse the repository at this point in the history
Rjf/wkb
  • Loading branch information
robfitzgerald authored Aug 30, 2024
2 parents 0eae046 + 427299f commit 22f24d7
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 10 deletions.
1 change: 1 addition & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ itertools = { version = "0.12.0" }
chrono = "0.4.26"
regex = "1.9.5"
wkt = { version = "0.10.3", features = ["serde"] }
wkb = "0.7.1"
config = "0.14"
ordered-float = { version = "4.1.1", features = ["serde"] }
allocative = "0.3.1"
Expand Down
1 change: 1 addition & 0 deletions rust/routee-compass-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ itertools = { workspace = true }
chrono = { workspace = true }
regex = { workspace = true }
wkt = { workspace = true }
wkb = { workspace = true }
allocative = { workspace = true }
39 changes: 35 additions & 4 deletions rust/routee-compass-core/src/util/geo/geo_io_utils.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::util::fs::{fs_utils, read_utils};
use geo::{LineString, Point};
use geo::{Coord, LineString, Point};
use itertools::Itertools;
use kdam::{Bar, BarExt};
use std::path::Path;
use wkt::TryFromWkt;
use wkb;
use wkt::{ToWkt, TryFromWkt};

/// reads a collection of LINESTRINGS
pub fn read_linestring_text_file<F: AsRef<Path>>(
Expand All @@ -23,7 +25,7 @@ pub fn read_linestring_text_file<F: AsRef<Path>>(
let _ = pb.update(1);
});
let geoms: Box<[LineString<f32>]> =
read_utils::read_raw_file(filepath, parse_linestring, Some(cb))?;
read_utils::read_raw_file(filepath, parse_wkt_linestring, Some(cb))?;
Ok(geoms)
}

Expand Down Expand Up @@ -72,7 +74,7 @@ pub fn concat_linestrings(linestrings: Vec<&LineString<f32>>) -> LineString<f32>
/// # Returns
///
/// * a linestring
pub fn parse_linestring(_idx: usize, row: String) -> Result<LineString<f32>, std::io::Error> {
pub fn parse_wkt_linestring(_idx: usize, row: String) -> Result<LineString<f32>, std::io::Error> {
let geom: LineString<f32> = LineString::try_from_wkt_str(row.as_str()).map_err(|e| {
let msg = format!(
"failure decoding LineString from lookup table. source: {}; error: {}",
Expand All @@ -83,6 +85,35 @@ pub fn parse_linestring(_idx: usize, row: String) -> Result<LineString<f32>, std
Ok(geom)
}

pub fn parse_wkb_linestring(_idx: usize, row: String) -> Result<LineString<f32>, std::io::Error> {
let mut c = row.as_bytes();
let geom = wkb::wkb_to_geom(&mut c).map_err(|e| {
let msg = format!("failure decoding WKB string: {:?}", e);
std::io::Error::new(std::io::ErrorKind::InvalidData, msg)
})?;
match geom {
geo::Geometry::LineString(l) => {
// somewhat hackish solution since we cannot choose f32 when parsing wkbs
let coords32 =
l.0.into_iter()
.map(|c| Coord {
x: c.x as f32,
y: c.y as f32,
})
.collect_vec();
let l32 = LineString::new(coords32);
Ok(l32)
}
_ => {
let msg = format!(
"decoded WKB expected to be linestring, found: {}",
geom.to_wkt()
);
Err(std::io::Error::new(std::io::ErrorKind::InvalidData, msg))
}
}
}

#[cfg(test)]
mod test {

Expand Down
1 change: 1 addition & 0 deletions rust/routee-compass/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ geo-types = { workspace = true }
geojson = { workspace = true }
rstar = { workspace = true }
wkt = { workspace = true }
wkb = { workspace = true }
env_logger = { workspace = true }
kdam = { workspace = true }
log = { workspace = true }
Expand Down
4 changes: 2 additions & 2 deletions rust/routee-compass/src/app/geom/geom_app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use geo::LineString;
use kdam::Bar;
use kdam::BarExt;
use routee_compass_core::util::fs::{fs_utils, read_utils};
use routee_compass_core::util::geo::geo_io_utils::parse_linestring;
use routee_compass_core::util::geo::geo_io_utils::parse_wkt_linestring;
use std::io::ErrorKind;

pub struct GeomAppConfig {
Expand Down Expand Up @@ -38,7 +38,7 @@ impl TryFrom<&GeomAppConfig> for GeomApp {
});

let op = |idx: usize, row: String| {
let result = parse_linestring(idx, row)?;
let result = parse_wkt_linestring(idx, row)?;
Ok(result)
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl TraversalPlugin {
let _ = pb.update(1);
});
let geoms =
read_raw_file(filename, geo_io_utils::parse_linestring, Some(cb)).map_err(|e| {
read_raw_file(filename, geo_io_utils::parse_wkt_linestring, Some(cb)).map_err(|e| {
PluginError::FileReadError(filename.as_ref().to_path_buf(), e.to_string())
})?;
println!();
Expand Down Expand Up @@ -154,7 +154,7 @@ fn construct_route_output(
mod tests {

use routee_compass_core::util::{
fs::read_utils::read_raw_file, geo::geo_io_utils::parse_linestring,
fs::read_utils::read_raw_file, geo::geo_io_utils::parse_wkt_linestring,
};

use std::path::PathBuf;
Expand All @@ -171,7 +171,7 @@ mod tests {

#[test]
fn test_geometry_deserialization() {
let result = read_raw_file(mock_geometry_file(), parse_linestring, None).unwrap();
let result = read_raw_file(mock_geometry_file(), parse_wkt_linestring, None).unwrap();
assert_eq!(result.len(), 3);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::HashMap;

use super::traversal_ops as ops;
use crate::plugin::plugin_error::PluginError;
use geo::LineString;
use geo::{CoordFloat, Geometry, LineString};
use routee_compass_core::{
algorithm::search::{edge_traversal::EdgeTraversal, search_tree_branch::SearchTreeBranch},
model::road_network::vertex_id::VertexId,
Expand All @@ -15,6 +15,8 @@ use wkt::ToWkt;
pub enum TraversalOutputFormat {
// concatenates all LINESTRINGS and returns the geometry as a WKT
Wkt,
// concatenates all LINESTRINGS and returns the geometry as a WKB
Wkb,
// returns the properties of each link traversal as a JSON array of objects
Json,
// returns the geometries and properties as GeoJSON
Expand All @@ -35,6 +37,12 @@ impl TraversalOutputFormat {
let route_wkt = route_geometry.wkt_string();
Ok(serde_json::Value::String(route_wkt))
}
TraversalOutputFormat::Wkb => {
let linestring = ops::create_route_linestring(route, geoms)?;
let geometry = geo::Geometry::LineString(linestring);
let wkb_str = geometry_to_wkb_string(&geometry)?;
Ok(serde_json::Value::String(wkb_str))
}
TraversalOutputFormat::Json => {
let result = serde_json::to_value(route)?;
Ok(result)
Expand Down Expand Up @@ -63,6 +71,12 @@ impl TraversalOutputFormat {
let route_wkt = route_geometry.wkt_string();
Ok(serde_json::Value::String(route_wkt))
}
TraversalOutputFormat::Wkb => {
let route_geometry = ops::create_tree_multilinestring(tree, geoms)?;
let geometry = geo::Geometry::MultiLineString(route_geometry);
let wkb_str = geometry_to_wkb_string(&geometry)?;
Ok(serde_json::Value::String(wkb_str))
}
TraversalOutputFormat::Json => {
let result = serde_json::to_value(tree.values().collect::<Vec<_>>())?;
Ok(result)
Expand All @@ -83,6 +97,23 @@ impl TraversalOutputFormat {
}
}

fn geometry_to_wkb_string<T: CoordFloat + Into<f64>>(
geometry: &Geometry<T>,
) -> Result<String, PluginError> {
let bytes = wkb::geom_to_wkb(geometry).map_err(|e| {
PluginError::PluginFailed(format!(
"failed to generate wkb for geometry '{:?}' - {:?}",
geometry, e
))
})?;
let wkb_str = bytes
.iter()
.map(|b| format!("{:02X?}", b))
.collect::<Vec<String>>()
.join("");
Ok(wkb_str)
}

#[cfg(test)]
mod test {
use super::*;
Expand Down

0 comments on commit 22f24d7

Please sign in to comment.