-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lrs: expose planar coordinate system #86
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -3,62 +3,88 @@ | |||||
|
||||||
use geo::{Coord, Point}; | ||||||
|
||||||
use crate::curves::{Curve, SphericalLineStringCurve}; | ||||||
use crate::lrm_scale::Anchor; | ||||||
use crate::curves::{Curve, PlanarLineStringCurve, SphericalLineStringCurve}; | ||||||
use crate::lrm_scale::LrmScaleMeasure; | ||||||
use crate::lrs::{self, TraversalPosition}; | ||||||
use crate::lrs::{LrsBase, LrsError}; | ||||||
|
||||||
type Lrs = lrs::Lrs<SphericalLineStringCurve>; | ||||||
use crate::lrm_scale::{Anchor, LrmScaleError}; | ||||||
use crate::lrs::{Lrm, LrmHandle, LrmProjection, Lrs, LrsError}; | ||||||
use crate::lrs::{LrsBase, TraversalPosition}; | ||||||
|
||||||
/// Struct exposed to js. | ||||||
pub struct ExtLrs { | ||||||
/// The linear referencing system | ||||||
pub lrs: Lrs, | ||||||
pub enum ExtLrs { | ||||||
/// LRS with spherical coordinates. | ||||||
Spherical(Lrs<SphericalLineStringCurve>), | ||||||
/// LRS with planar coordinates. | ||||||
Planar(Lrs<PlanarLineStringCurve>), | ||||||
} | ||||||
|
||||||
impl ExtLrs { | ||||||
/// Load the data. | ||||||
pub fn load(data: &[u8]) -> Result<ExtLrs, String> { | ||||||
Lrs::from_bytes(data) | ||||||
.map(|lrs| Self { lrs }) | ||||||
.map_err(|err| err.to_string()) | ||||||
pub fn load(data: &[u8], planar: bool) -> Result<ExtLrs, String> { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The serialized data stores what kind of coordinates we are dealing with: https://github.com/OpenRailAssociation/liblrs/blob/main/schema/lrs.fbs#L8 (from the wording, we can see that it was a different use case that was initially though of, but it still work). This will however draw a lot of small issues. I’m not sure how we could get a nice overview of all the fiddling we’ll have to do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't really see the issues, could you elaborate ? Is it that
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It’s both.
|
||||||
if planar { | ||||||
Lrs::<PlanarLineStringCurve>::from_bytes(data).map(ExtLrs::Planar) | ||||||
} else { | ||||||
Lrs::<SphericalLineStringCurve>::from_bytes(data).map(ExtLrs::Spherical) | ||||||
} | ||||||
.map_err(|err| err.to_string()) | ||||||
} | ||||||
|
||||||
/// How many LRMs compose the LRS. | ||||||
pub fn lrm_len(&self) -> usize { | ||||||
self.lrs.lrm_len() | ||||||
match self { | ||||||
ExtLrs::Spherical(lrs) => lrs.lrm_len(), | ||||||
ExtLrs::Planar(lrs) => lrs.lrm_len(), | ||||||
} | ||||||
} | ||||||
|
||||||
/// Given a ID returns the corresponding lrs index (or None if not found) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
pub fn find_lrm(&self, lrm_id: &str) -> Option<usize> { | ||||||
match self { | ||||||
ExtLrs::Spherical(lrs) => lrs.get_lrm(lrm_id).map(|handle| handle.0), | ||||||
ExtLrs::Planar(lrs) => lrs.get_lrm(lrm_id).map(|handle| handle.0), | ||||||
} | ||||||
} | ||||||
|
||||||
fn get_lrm(&self, index: usize) -> &Lrm { | ||||||
match self { | ||||||
ExtLrs::Spherical(lrs) => &lrs.lrms[index], | ||||||
ExtLrs::Planar(lrs) => &lrs.lrms[index], | ||||||
} | ||||||
} | ||||||
|
||||||
/// Return the geometry of the LRM. | ||||||
pub fn get_lrm_geom(&self, index: usize) -> Result<Vec<geo::Coord>, String> { | ||||||
let lrm = self.lrs.lrms.get(index).ok_or("Invalid index")?; | ||||||
self.lrs | ||||||
.get_linestring(lrm.reference_traversal) | ||||||
.map_err(|err| err.to_string()) | ||||||
.map(|linestring| linestring.0) | ||||||
let lrm = self.get_lrm(index); | ||||||
match self { | ||||||
ExtLrs::Spherical(lrs) => lrs.get_linestring(lrm.reference_traversal), | ||||||
ExtLrs::Planar(lrs) => lrs.get_linestring(lrm.reference_traversal), | ||||||
} | ||||||
.map_err(|err| err.to_string()) | ||||||
.map(|linestring| linestring.0) | ||||||
} | ||||||
|
||||||
/// `id` of the [`LrmScale`]. | ||||||
pub fn get_lrm_scale_id(&self, index: usize) -> String { | ||||||
self.lrs.lrms[index].scale.id.clone() | ||||||
self.get_lrm(index).scale.id.clone() | ||||||
} | ||||||
|
||||||
/// All the [`Anchor`]s of a LRM. | ||||||
pub fn get_anchors(&self, lrm_index: usize) -> Vec<Anchor> { | ||||||
self.lrs.lrms[lrm_index].scale.anchors.to_vec() | ||||||
self.get_lrm(lrm_index).scale.anchors.to_vec() | ||||||
} | ||||||
|
||||||
/// Get the position given a [`LrmScaleMeasure`]. | ||||||
pub fn resolve(&self, lrm_index: usize, measure: &LrmScaleMeasure) -> Result<Point, LrsError> { | ||||||
let lrm = &self.lrs.lrms[lrm_index]; | ||||||
let lrm = self.get_lrm(lrm_index); | ||||||
let curve_position = lrm.scale.locate_point(measure)?.clamp(0., 1.0); | ||||||
|
||||||
let traversal_position = TraversalPosition { | ||||||
curve_position, | ||||||
traversal: lrm.reference_traversal, | ||||||
}; | ||||||
self.lrs.locate_traversal(traversal_position) | ||||||
match self { | ||||||
ExtLrs::Spherical(lrs) => lrs.locate_traversal(traversal_position), | ||||||
ExtLrs::Planar(lrs) => lrs.locate_traversal(traversal_position), | ||||||
} | ||||||
} | ||||||
|
||||||
/// Given two [`LrmScaleMeasure`]s, return a range of [`LineString`]. | ||||||
|
@@ -68,9 +94,8 @@ impl ExtLrs { | |||||
from: &LrmScaleMeasure, | ||||||
to: &LrmScaleMeasure, | ||||||
) -> Result<Vec<Coord>, String> { | ||||||
let lrm = &self.lrs.lrms[lrm_index]; | ||||||
let lrm = self.get_lrm(lrm_index); | ||||||
let scale = &lrm.scale; | ||||||
let curve = &self.lrs.traversals[lrm.reference_traversal.0].curve; | ||||||
let from = scale | ||||||
.locate_point(from) | ||||||
.map_err(|e| e.to_string())? | ||||||
|
@@ -80,9 +105,37 @@ impl ExtLrs { | |||||
.map_err(|e| e.to_string())? | ||||||
.clamp(0., 1.); | ||||||
|
||||||
match curve.sublinestring(from, to) { | ||||||
let sublinestring = match self { | ||||||
ExtLrs::Spherical(lrs) => lrs.traversals[lrm.reference_traversal.0] | ||||||
.curve | ||||||
.sublinestring(from, to), | ||||||
ExtLrs::Planar(lrs) => lrs.traversals[lrm.reference_traversal.0] | ||||||
.curve | ||||||
.sublinestring(from, to), | ||||||
}; | ||||||
|
||||||
match sublinestring { | ||||||
Some(linestring) => Ok(linestring.0), | ||||||
None => Err("Could not find sublinestring".to_string()), | ||||||
} | ||||||
} | ||||||
|
||||||
/// Given a point, return the [`LrmProjection`]s. | ||||||
pub fn lookup(&self, point: Point, lrm_handle: LrmHandle) -> Vec<LrmProjection> { | ||||||
match self { | ||||||
ExtLrs::Spherical(lrs) => lrs.lookup(point, lrm_handle), | ||||||
ExtLrs::Planar(lrs) => lrs.lookup(point, lrm_handle), | ||||||
} | ||||||
} | ||||||
|
||||||
/// Get the positon along the curve given a [`LrmScaleMeasure`] | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
/// The value will be between 0.0 and 1.0, both included | ||||||
pub fn locate_point( | ||||||
&self, | ||||||
lrm_index: usize, | ||||||
measure: &LrmScaleMeasure, | ||||||
) -> Result<f64, LrmScaleError> { | ||||||
let lrm = self.get_lrm(lrm_index); | ||||||
lrm.scale.locate_point(measure) | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,7 @@ | ||
//! High level extensions meant for an easy usage | ||
//! Those functions are exposed in wasm-bindings | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
use liblrs::{ | ||
lrs::{LrmHandle, LrsBase}, | ||
lrs_ext::*, | ||
}; | ||
use liblrs::{lrs::LrmHandle, lrs_ext::*}; | ||
use wasm_bindgen::prelude::*; | ||
|
||
#[wasm_bindgen] | ||
|
@@ -135,8 +132,8 @@ pub struct LrmProjection { | |
#[wasm_bindgen] | ||
impl Lrs { | ||
/// Load the data. | ||
pub fn load(data: &[u8]) -> Result<Lrs, String> { | ||
ExtLrs::load(data).map(|lrs| Self { lrs }) | ||
pub fn load(data: &[u8], planar: bool) -> Result<Lrs, String> { | ||
ExtLrs::load(data, planar).map(|lrs| Self { lrs }) | ||
} | ||
|
||
/// How many LRMs compose the LRS. | ||
|
@@ -191,7 +188,6 @@ impl Lrs { | |
/// The result is sorted by `orthogonal_offset`: the nearest [`Lrm`] to the [`Point`] is the first item. | ||
pub fn lookup(&self, point: Point, lrm_handle: usize) -> Vec<LrmProjection> { | ||
self.lrs | ||
.lrs | ||
.lookup(point.into(), LrmHandle(lrm_handle)) | ||
.iter() | ||
.map(|p| LrmProjection { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.