diff --git a/Cargo.lock b/Cargo.lock index d5880c8..a7c5766 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "adler" @@ -178,6 +178,31 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "csv" version = "1.3.0" @@ -269,14 +294,15 @@ dependencies = [ [[package]] name = "geo" -version = "0.28.0" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f811f663912a69249fa620dcd2a005db7254529da2d8a0b23942e81f47084501" +checksum = "009245d261b86621c38d1c4e5a6578d52294e3e5445401d713584dfe42f8ae9c" dependencies = [ "earcutr", "float_next_after", "geo-types", "geographiclib-rs", + "i_overlay", "log", "num-traits", "robust", @@ -286,12 +312,13 @@ dependencies = [ [[package]] name = "geo-types" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff16065e5720f376fbced200a5ae0f47ace85fd70b7e54269790281353b6d61" +checksum = "b6f47c611187777bbca61ea7aba780213f5f3441fd36294ab333e96cfa791b65" dependencies = [ "approx", "num-traits", + "rayon", "rstar", "serde", ] @@ -346,6 +373,50 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "i_float" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fe043aae28ce70bd2f78b2f5f82a3654d63607c82594da4dabb8b6cb81f2b2" +dependencies = [ + "serde", +] + +[[package]] +name = "i_key_sort" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "347c253b4748a1a28baf94c9ce133b6b166f08573157e05afe718812bc599fcd" + +[[package]] +name = "i_overlay" +version = "1.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d5024b4346ff4699e2db65674bbcb3a7cb8c5a820e9745ec777a7cb2bb5f42" +dependencies = [ + "i_float", + "i_key_sort", + "i_shape", + "i_tree", + "rayon", +] + +[[package]] +name = "i_shape" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b44852d57a991c7dedaf76c55bc44f677f547ff899a430d29e13efd6133d7d8" +dependencies = [ + "i_float", + "serde", +] + +[[package]] +name = "i_tree" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "155181bc97d770181cf9477da51218a19ee92a8e5be642e796661aee2b601139" + [[package]] name = "indoc" version = "2.0.5" @@ -518,9 +589,9 @@ checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" [[package]] name = "proc-macro2" -version = "1.0.80" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -628,6 +699,26 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "robust" version = "1.1.0" @@ -712,9 +803,9 @@ dependencies = [ [[package]] name = "spade" -version = "2.6.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61addf9117b11d1f5b4bf6fe94242ba25f59d2d4b2080544b771bd647024fd00" +checksum = "93f5ef1f863aca7d1d7dda7ccfc36a0a4279bd6d3c375176e5e0712e25cb4889" dependencies = [ "hashbrown", "num-traits", @@ -742,9 +833,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.59" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -759,18 +850,18 @@ checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f" [[package]] name = "thiserror" -version = "1.0.58" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index c36d9e9..59beffa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,8 +21,8 @@ path = "src/geometry_from_osm.rs" [dependencies] approx = "0.5.1" flatbuffers = "24.3" -geo = "0.28" -thiserror = "1.0" +geo = "0.29" +thiserror = "2.0" osm4routing = "0.7.0" -clap = { version = "4.5.1", features = ["derive"] } +clap = { version = "4.5", features = ["derive"] } num-traits = "0.2" diff --git a/python/src/lib.rs b/python/src/lib.rs index e8dcad1..9ec9f0d 100644 --- a/python/src/lib.rs +++ b/python/src/lib.rs @@ -363,7 +363,7 @@ impl Builder { self.inner.add_node(id, coord.into(), properties) } - /// Add a new anchor by its cooordinates + /// Add a new anchor by its coordinates #[pyo3(signature = (id, coord, properties, name=None))] pub fn add_anchor( &mut self, @@ -391,7 +391,7 @@ impl Builder { /// Add a new segment /// /// The geometry represents the curve - /// start_node_index and end_node_index are the topological extremeties returned by `add_node` + /// start_node_index and end_node_index are the topological extremities returned by `add_node` pub fn add_segment( &mut self, id: &str, @@ -418,7 +418,7 @@ impl Builder { /// Add a linear referencing model /// - /// It is composed by the traversal identified by traversa_index (that represents the curve) + /// It is composed by the traversal identified by traversal_index (that represents the curve) /// and the anchors (that represent the milestones) pub fn add_lrm( &mut self, @@ -500,7 +500,7 @@ impl Builder { /// Orient the traversal according to two points /// - /// In the end, the first coordinate must be closer to the begining than the second + /// In the end, the first coordinate must be closer to the beginning than the second /// If both points are so far from the curve that they are projected to a end, we consider the offset to the curve pub fn orient_along_points( &mut self, diff --git a/src/builder.rs b/src/builder.rs index e27e667..a444ea9 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; use flatbuffers::{ForwardsUOffset, Vector, WIPOffset}; -use geo::Coord; +use geo::{Coord, Distance}; use crate::curves::{Curve, CurveError, CurveProjection, SphericalLineStringCurve}; @@ -18,7 +18,7 @@ pub type Properties = std::collections::HashMap; #[macro_export] /// Build a properties map: -/// `properties!("source" => "openstreetmap", "licence" => "ODbL")`. +/// `properties!("source" => "openstreetmap", "license" => "ODbL")`. macro_rules! properties { ($($k:expr => $v:expr),* $(,)?) => {{ core::convert::From::from([$(($k.to_owned(), $v.to_owned()),)*]) @@ -483,13 +483,13 @@ impl<'fbb> Builder<'fbb> { } } - /// Gives the euclidian distance between two traversals + /// Gives the euclidean distance between two traversals /// While working on spherical coordinates, this usually doesn’t make much sense, /// this is good enough to sort curves by distance pub fn euclidean_distance(&self, lrm_index_a: usize, lrm_index_b: usize) -> f64 { let a = &self.temp_traversal[lrm_index_a].curve.geom; let b = &self.temp_traversal[lrm_index_b].curve.geom; - geo::EuclideanDistance::euclidean_distance(a, b) + geo::Euclidean::distance(a, b) } /// Returns the position along the curve of the traversal @@ -515,7 +515,7 @@ impl<'fbb> Builder<'fbb> { /// Orient the traversal according to two points /// - /// In the end, the first coordinate must be closer to the begining than the second + /// In the end, the first coordinate must be closer to the beginning than the second /// If both points are so far from the curve that they are projected to a end, we consider the offset to the curve pub fn orient_along_points( &mut self, diff --git a/src/curves.rs b/src/curves.rs index deab8c6..9dd58b7 100644 --- a/src/curves.rs +++ b/src/curves.rs @@ -101,7 +101,7 @@ pub struct PlanarLineStringCurve { impl Curve for PlanarLineStringCurve { fn new(geom: LineString, max_extent: f64) -> Self { - let length = geom.euclidean_length(); + let length = geom.length::(); Self { max_extent, geom, @@ -144,7 +144,7 @@ impl Curve for PlanarLineStringCurve { Orientation::Clockwise => 1., _ => -1., }; - let offset = point.euclidean_distance(&self.geom) * sign; + let offset = Euclidean::distance(&self.geom, &point) * sign; Ok(CurveProjection { distance_along_curve, @@ -204,7 +204,7 @@ impl Curve for PlanarLineStringCurve { let line = self .geom .lines_iter() - .find(|line| line.euclidean_distance(&point) < self.length / 1e9) + .find(|line| Euclidean::distance(line, &point) < self.length / 1e9) .ok_or(CurveError::NotFiniteCoordinates)?; // translate to (0, 0) and normalize by the length of the curve to get unit vector of tangent @@ -238,7 +238,7 @@ impl Curve for PlanarLineStringCurve { let mut points = Vec::new(); for segment in self.geom.lines() { - let length = segment.euclidean_length(); + let length = segment.length::(); if cum_length + length >= start_fractional_length && points.is_empty() { let segment_fraction = (start_fractional_length - cum_length) / length; match segment.line_interpolate_point(segment_fraction) { @@ -317,8 +317,8 @@ impl SphericalLineStringCurve { let mut closest_dist_to_point = f64::infinity(); let mut fraction = 0.0; for segment in self.geom.lines() { - let segment_distance_to_point = segment.euclidean_distance(p); - let segment_length = segment.geodesic_length(); + let segment_distance_to_point = Euclidean::distance(&segment, p); + let segment_length = segment.length::(); let segment_fraction = segment.line_locate_point(p)?; // if any segment has a None fraction, return None if segment_distance_to_point < closest_dist_to_point { closest_dist_to_point = segment_distance_to_point; @@ -336,7 +336,7 @@ impl SphericalLineStringCurve { let fractional_length = total_length * fraction; let mut cum_length = f64::zero(); for segment in self.geom.lines() { - let length = segment.geodesic_length(); + let length = segment.length::(); if cum_length + length >= fractional_length { let segment_fraction = (fractional_length - cum_length) / length; return segment.line_interpolate_point(segment_fraction); @@ -363,7 +363,7 @@ impl SphericalLineStringCurve { impl Curve for SphericalLineStringCurve { fn new(geom: LineString, max_extent: f64) -> Self { - let length = geom.geodesic_length(); + let length = geom.length::(); Self { max_extent, geom, @@ -408,7 +408,7 @@ impl Curve for SphericalLineStringCurve { Orientation::Clockwise => 1., _ => -1., }; - let offset = projected_coords.geodesic_distance(&point) * sign; + let offset = Geodesic::distance(projected_coords, point) * sign; Ok(CurveProjection { distance_along_curve, @@ -431,7 +431,7 @@ impl Curve for SphericalLineStringCurve { // go through each segment and look for the one that frame the distance that we seek for segment in self.geom.lines() { - let segment_length = segment.geodesic_length(); + let segment_length = segment.length::(); if accumulated_length + segment_length >= fractional_length { let segment_fraction = (fractional_length - accumulated_length) / segment_length; let segment_start = Point::from(segment.start); @@ -439,7 +439,11 @@ impl Curve for SphericalLineStringCurve { // get the Point at a geodesic distance between two Points // of a certain fraction of length on this distance - return Ok(segment_start.geodesic_intermediate(&segment_end, segment_fraction)); + return Ok(Geodesic::point_at_ratio_between( + segment_start, + segment_end, + segment_fraction, + )); } accumulated_length += segment_length; } @@ -452,14 +456,12 @@ impl Curve for SphericalLineStringCurve { let max_point = geo::Point(self.geom.bounding_rect().unwrap().max()); // add max_extend distance in South and then West direction - let min_point_extended = min_point - .geodesic_destination(180., self.max_extent) - .geodesic_destination(270., self.max_extent); + let min_point_extended = Geodesic::destination(min_point, 180., self.max_extent); + let min_point_extended = Geodesic::destination(min_point_extended, 270., self.max_extent); // add max_extend distance in North and then East direction - let max_point_extended = max_point - .geodesic_destination(0., self.max_extent) - .geodesic_destination(90., self.max_extent); + let max_point_extended = Geodesic::destination(max_point, 0., self.max_extent); + let max_point_extended = Geodesic::destination(max_point_extended, 90., self.max_extent); Rect::new(min_point_extended, max_point_extended) } @@ -469,7 +471,7 @@ impl Curve for SphericalLineStringCurve { // to get the intersection(s) closer to the real closest path. fn intersect_segment(&self, segment: Line) -> Option { self.geom - .densify_haversine(self.densify_by) + .densify::(self.densify_by) .lines() .flat_map(|curve_line| { match geo::line_intersection::line_intersection(segment, curve_line) { @@ -493,18 +495,18 @@ impl Curve for SphericalLineStringCurve { let distance_along_curve = curve_position * self.length; // go through each segment and look for the one that frame the distance that we seek let mut accumulated_length = 0.; - for segment in self.geom.densify_haversine(self.densify_by).lines() { - let segment_length = segment.geodesic_length(); + for segment in self.geom.densify::(self.densify_by).lines() { + let segment_length = segment.length::(); if accumulated_length + segment_length >= distance_along_curve { // get Points from the segment that frame the point let start = geo::Point(segment.start); let end = geo::Point(segment.end); // get bearing from start Point and end Point of the segment, and add 90° clockwise rotation to it - let normal_vector_bearing = start.geodesic_bearing(end) + 90.; + let normal_vector_bearing = Geodesic::bearing(start, end) + 90.; // get end Point from the end of the segment for the normal vector bearing value and 1m of (haversine) length - let end_normal = end.geodesic_destination(normal_vector_bearing, 1.); + let end_normal = Geodesic::destination(end, normal_vector_bearing, 1.); return Ok((end_normal.x() - end.x(), end_normal.y() - end.y())); } @@ -532,7 +534,7 @@ impl Curve for SphericalLineStringCurve { let mut points = Vec::new(); for segment in self.geom.lines() { - let length = segment.geodesic_length(); + let length = segment.length::(); if cum_length + length >= start_fractional_length && points.is_empty() { let segment_fraction = (start_fractional_length - cum_length) / length; match segment.line_interpolate_point(segment_fraction) { diff --git a/src/lrm_scale.rs b/src/lrm_scale.rs index 973f761..9601088 100644 --- a/src/lrm_scale.rs +++ b/src/lrm_scale.rs @@ -255,11 +255,12 @@ impl LrmScale { } #[cfg(test)] -pub mod tests { +pub(crate) mod tests { use geo::point; use super::*; - pub fn scale() -> LrmScale { + + pub(crate) fn scale() -> LrmScale { LrmScale { id: "id".to_owned(), anchors: vec![ diff --git a/wasm/package.json b/wasm/package.json index 3d68c5b..fa719bd 100644 --- a/wasm/package.json +++ b/wasm/package.json @@ -6,19 +6,18 @@ "devDependencies": { "@wasm-tool/wasm-pack-plugin": "1.7.0", "css-loader": "7.1.2", - "html-webpack-plugin": "5.6.0", + "html-webpack-plugin": "5.6.3", "style-loader": "4.0.0", - "text-encoding": "^0.7.0", - "webpack": "5.95.0", + "webpack": "5.96.1", "webpack-cli": "5.1.4", "webpack-dev-server": "5.1.0" }, "dependencies": { "@turf/bbox": "7.1.0", "@turf/helpers": "7.1.0", - "alpinejs": "3.14.1", + "alpinejs": "3.14.5", "maplibre-gl": "4.7.1", - "pmtiles": "3.2.0" + "pmtiles": "4.0.1" }, "name": "liblrs", "version": "0.2.3",