Skip to content

Commit a83b3d9

Browse files
committed
wasm + html demo: add click to measure functionality
Signed-off-by: Baptiste Prevot <pro.baptiste.prevot@gmail.com>
1 parent 04d4cc9 commit a83b3d9

7 files changed

Lines changed: 107 additions & 17 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "liblrs"
3-
version = "0.2.2"
3+
version = "0.2.3"
44
edition = "2021"
55
description = "Library to manipulate linear referencing systems"
66
license = "MIT"

python/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "liblrs_python"
33
description = "Python bindings for liblrs: a library to work with linear referencing systems"
4-
version = "0.2.2"
4+
version = "0.2.3"
55
edition = "2021"
66
license = "MIT"
77
repository = "https://github.com/osrd-project/liblrs/"

wasm/html_demo/index.js

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
'use strict';
2-
import 'maplibre-gl/dist/maplibre-gl.css';
2+
import Bbox from '@turf/bbox';
3+
import * as turf from '@turf/helpers';
4+
import Alpine from 'alpinejs';
35
import * as maplibregl from 'maplibre-gl';
6+
import 'maplibre-gl/dist/maplibre-gl.css';
47
import { Protocol } from 'pmtiles';
5-
import { Lrs, LrmScaleMeasure, set_panic_hook } from '../pkg/liblrs_wasm';
6-
import * as turf from '@turf/helpers';
7-
import Bbox from '@turf/bbox'
8-
import Alpine from 'alpinejs'
8+
import { LrmScaleMeasure, Lrs, Point, set_panic_hook } from '../pkg/liblrs_wasm';
99

1010
// For the rust bindings: this allows us to have nice error messages
1111
set_panic_hook()
@@ -65,6 +65,17 @@ async function file_selected(el) {
6565
}
6666
});
6767

68+
69+
map.addLayer({
70+
'id': 'lrms-hitbox',
71+
'type': 'line',
72+
'source': 'lrms',
73+
'paint': {
74+
'line-width': 10,
75+
'line-opacity': 0
76+
}
77+
});
78+
6879
map.addLayer({
6980
'id': 'lrms-hover',
7081
'type': 'line',
@@ -156,6 +167,35 @@ async function file_selected(el) {
156167
}
157168
});
158169

170+
171+
172+
map.on('mouseenter', 'lrms-hitbox', () => {
173+
map.getCanvas().style.cursor = 'pointer'
174+
})
175+
map.on('mouseleave', 'lrms-hitbox', () => {
176+
map.getCanvas().style.cursor = ''
177+
})
178+
179+
180+
map.on('click', 'lrms-hitbox', (e) => {
181+
182+
let lrm_id = e.features[0].id;
183+
let clicked_point = new Point(e.lngLat.lng, e.lngLat.lat);
184+
185+
let projection = lrs.lookup(clicked_point, lrm_id)[0];
186+
187+
let window_lrms = window.Alpine.store('lrms')
188+
189+
window_lrms.selectedFeature = curves_features[lrm_id];
190+
let offset = Math.round(projection.measure.scale_offset)
191+
window_lrms.pkStart = projection.measure.anchor_name + '+' + String(offset).padStart(3, "0");
192+
193+
window_lrms.startMeasure = projection.measure;
194+
let point = lrs.resolve(lrm_id, projection.measure)
195+
window_lrms.pkStartPoint = turf.point([point.x, point.y]);
196+
window_lrms.handlePks(false)
197+
});
198+
159199
return {
160200
features: curves_features,
161201
filename: file.name,
@@ -271,12 +311,14 @@ Alpine.store('lrms', {
271311
this.endMeasure = null;
272312
}
273313
},
274-
handlePks() {
314+
handlePks(move_window = true) {
275315
const points = [this.pkStartPoint, this.pkEndPoint].filter(p => p !== null)
276316
const geojson = turf.featureCollection(points);
277317
map.getSource('pr').setData(geojson);
278318
if (points.length === 1) {
279-
map.flyTo({ center: points[0].geometry.coordinates, zoom: 15 })
319+
if (move_window) {
320+
map.flyTo({ center: points[0].geometry.coordinates, zoom: 15 })
321+
}
280322
} else {
281323
map.fitBounds(Bbox(geojson), { padding: 30 })
282324
const range = this.lrs.resolve_range(this.selectedFeature.id, this.startMeasure, this.endMeasure)

wasm/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wasm/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"pmtiles": "3.2.0"
2222
},
2323
"name": "liblrs",
24-
"version": "0.2.2",
24+
"version": "0.2.3",
2525
"repository": {
2626
"type": "git",
2727
"url": "https://github.com/osrd-project/liblrs/"

wasm/src/lib.rs

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
//! High level extensions meant for an easy usage
22
//! Those functions are exposed in wasm-bindings
33
4-
use liblrs::lrs_ext::*;
4+
use liblrs::{
5+
lrs::{LrmHandle, LrsBase},
6+
lrs_ext::*,
7+
};
58
use wasm_bindgen::prelude::*;
69

710
#[wasm_bindgen]
@@ -20,6 +23,17 @@ pub struct Point {
2023
pub y: f64,
2124
}
2225

26+
#[wasm_bindgen]
27+
impl Point {
28+
/// Build a new geographical point.
29+
///
30+
/// When using spherical coordinates, longitude is x and latitude y
31+
#[wasm_bindgen(constructor)]
32+
pub fn new(x: f64, y: f64) -> Self {
33+
Self { x, y }
34+
}
35+
}
36+
2337
impl From<geo_types::Point> for Point {
2438
fn from(value: geo_types::Point) -> Self {
2539
Self {
@@ -29,6 +43,12 @@ impl From<geo_types::Point> for Point {
2943
}
3044
}
3145

46+
impl From<Point> for geo_types::Point<f64> {
47+
fn from(value: Point) -> Self {
48+
Self::new(value.x, value.y)
49+
}
50+
}
51+
3252
impl From<geo_types::Coord> for Point {
3353
fn from(value: geo_types::Coord) -> Self {
3454
Self {
@@ -39,12 +59,13 @@ impl From<geo_types::Coord> for Point {
3959
}
4060

4161
#[wasm_bindgen(getter_with_clone)]
62+
#[derive(Clone)]
4263
/// Represent a position on an [`LrmScale`] relative as an `offset` to an [`Anchor`].
4364
pub struct LrmScaleMeasure {
4465
/// `name` of the reference [`Anchor`].
45-
anchor_name: String,
66+
pub anchor_name: String,
4667
/// `offset` to the reference [`Anchor`].
47-
scale_offset: f64,
68+
pub scale_offset: f64,
4869
}
4970

5071
#[wasm_bindgen]
@@ -102,6 +123,15 @@ impl From<&liblrs::lrm_scale::Anchor> for Anchor {
102123
}
103124
}
104125

126+
#[wasm_bindgen(getter_with_clone)]
127+
/// The result of a projection onto an [`LrmScale`].
128+
pub struct LrmProjection {
129+
/// Contains `measure` ([`LrmScaleMeasure`]) and `lrm` ([`LrmHandle`]).
130+
pub measure: LrmScaleMeasure,
131+
/// How far from the [`Lrm`] is the [`Point`] that has been projected.
132+
pub orthogonal_offset: f64,
133+
}
134+
105135
#[wasm_bindgen]
106136
impl Lrs {
107137
/// Load the data.
@@ -155,6 +185,24 @@ impl Lrs {
155185
.resolve_range(lrm_index, &from.into(), &to.into())
156186
.map(|coords| coords.into_iter().map(|coord| coord.into()).collect())
157187
}
188+
189+
/// Projects a [`Point`] on all applicable [`Traversal`]s to a given [`Lrm`].
190+
/// The [`Point`] must be in the bounding box of the [`Curve`] of the [`Traversal`].
191+
/// The result is sorted by `orthogonal_offset`: the nearest [`Lrm`] to the [`Point`] is the first item.
192+
pub fn lookup(&self, point: Point, lrm_handle: usize) -> Vec<LrmProjection> {
193+
self.lrs
194+
.lrs
195+
.lookup(point.into(), LrmHandle(lrm_handle))
196+
.iter()
197+
.map(|p| LrmProjection {
198+
measure: LrmScaleMeasure {
199+
anchor_name: p.measure.measure.anchor_name.to_owned(),
200+
scale_offset: p.measure.measure.scale_offset,
201+
},
202+
orthogonal_offset: p.orthogonal_offset,
203+
})
204+
.collect()
205+
}
158206
}
159207

160208
#[wasm_bindgen]

0 commit comments

Comments
 (0)