Skip to content

Commit

Permalink
Nodes have coordinates
Browse files Browse the repository at this point in the history
  • Loading branch information
Tristramg committed Sep 17, 2024
1 parent 0897c2a commit ef138d6
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 11 deletions.
16 changes: 14 additions & 2 deletions python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,8 @@ impl Builder {
}
}

pub fn add_node(&mut self, id: &str, properties: Properties) -> usize {
self.inner.add_node(id, properties)
pub fn add_node(&mut self, id: &str, coord: Point, properties: Properties) -> usize {
self.inner.add_node(id, coord.into(), properties)
}

#[pyo3(signature = (id, coord, properties, name=None))]
Expand Down Expand Up @@ -387,4 +387,16 @@ impl Builder {
pub fn euclidean_distance(&self, lrm_index_a: usize, lrm_index_b: usize) -> f64 {
self.inner.euclidean_distance(lrm_index_a, lrm_index_b)
}

pub fn get_nodes_of_traversal(&self, lrm_index: usize) -> Vec<usize> {
self.inner.get_nodes_of_traversal(lrm_index).to_vec()
}

pub fn get_node_coord(&self, node_index: usize) -> Point {
self.inner.get_node_coord(node_index).into()
}

pub fn reverse(&mut self, lrm_index: usize) {
self.inner.reverse(lrm_index)
}
}
1 change: 1 addition & 0 deletions schema/lrs.fbs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ table Segment {
table Node {
id:string (required);
properties:[Property];
geometry: Point;
}

/// A traversal is a path in a network.
Expand Down
57 changes: 50 additions & 7 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ pub struct Builder<'fbb> {
temp_traversal: Vec<TempTraversal>,
// Temporary [`Anchor`]s because we need to project them on the [`Traversal`] of each LRM they belong to.
temp_anchors: Vec<AnchorPosition>,
// Position of every node
nodes_coords: Vec<Coord>,
// Every node of a given traversal
nodes_of_traversal: Vec<Vec<usize>>,

// Final objects that will be in the binary file.
nodes: Vec<WIPOffset<Node<'fbb>>>,
Expand Down Expand Up @@ -130,12 +134,22 @@ impl<'fbb> Builder<'fbb> {
}
}

/// Gives the indexes of all the nodes of a traversal
pub fn get_nodes_of_traversal(&self, traversal_idx: usize) -> &[usize] {
&self.nodes_of_traversal[traversal_idx]
}

/// Add a new [`Node`].
pub fn add_node(&mut self, id: &str, properties: Properties) -> usize {
let properties = self.build_properties(properties);
let id = Some(self.fbb.create_string(id));
let node = Node::create(&mut self.fbb, &NodeArgs { id, properties });
self.nodes.push(node);
pub fn add_node(&mut self, id: &str, coord: Coord, properties: Properties) -> usize {
let point = Point::new(coord.x, coord.y);
let args = NodeArgs {
id: Some(self.fbb.create_string(id)),
geometry: Some(&point),
properties: self.build_properties(properties),
};

self.nodes_coords.push(coord);
self.nodes.push(Node::create(&mut self.fbb, &args));
self.nodes.len() - 1
}

Expand Down Expand Up @@ -209,16 +223,27 @@ impl<'fbb> Builder<'fbb> {
/// The existing [`Segment`]s are consumed and will not be accessible anymore.
pub fn add_traversal(&mut self, traversal_id: &str, segments: &[SegmentOfTraversal]) -> usize {
let mut coords = vec![];
let mut nodes_of_traversal = vec![];
for segment in segments {
let start_node = self.temp_segments[segment.segment_index].start_node_index as usize;
let end_node = self.temp_segments[segment.segment_index].end_node_index as usize;
if nodes_of_traversal.is_empty() {
nodes_of_traversal.push(end_node);
}
if segment.reversed {
nodes_of_traversal.push(start_node);
for &coord in self.temp_segments[segment.segment_index]
.geometry
.iter()
.rev()
{
coords.push(coord)
coords.push(coord);
}
} else {
if nodes_of_traversal.is_empty() {
nodes_of_traversal.push(start_node);
}
nodes_of_traversal.push(end_node);
for &coord in self.temp_segments[segment.segment_index].geometry.iter() {
coords.push(coord)
}
Expand All @@ -230,6 +255,7 @@ impl<'fbb> Builder<'fbb> {
curve: SphericalLineStringCurve::new(geo::LineString::new(coords), 100.),
segments: segments.to_vec(),
});
self.nodes_of_traversal.push(nodes_of_traversal);

self.temp_traversal.len() - 1
}
Expand Down Expand Up @@ -481,7 +507,12 @@ impl<'fbb> Builder<'fbb> {
let mut traversals = HashMap::<String, Vec<_>>::new();
let nodes_index: HashMap<_, _> = nodes
.iter()
.map(|n| (n.id, self.add_node(&n.id.0.to_string(), properties!())))
.map(|n| {
(
n.id,
self.add_node(&n.id.0.to_string(), n.coord, properties!()),
)
})
.collect();

for edge in edges.iter() {
Expand All @@ -507,6 +538,7 @@ impl<'fbb> Builder<'fbb> {
reversed,
})
.collect();

self.add_traversal(&srv_ref, &segments);
}
}
Expand All @@ -519,4 +551,15 @@ impl<'fbb> Builder<'fbb> {
let b = &self.temp_traversal[lrm_index_b].curve.geom;
geo::EuclideanDistance::euclidean_distance(a, b)
}

/// Reverses the direction of the traversal
pub fn reverse(&mut self, lrm_index: usize) {
self.temp_traversal[lrm_index].reverse();
self.nodes_of_traversal[lrm_index].reverse();
}

/// Returns the coordinates of a node
pub fn get_node_coord(&self, node_index: usize) -> Coord {
self.nodes_coords[node_index]
}
}
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ fn read_and_write_lrs() {
Coord { x: 0., y: 0. },
properties!("some key" => "some value"),
);
let start_node = builder.add_node("a", properties!());
let end_node = builder.add_node("b", properties!());
let start_node = builder.add_node("a", Coord { x: 0., y: 0. }, properties!());
let end_node = builder.add_node("b", Coord { x: 1., y: 1. }, properties!());
let segment_geometry = &[Coord { x: 0., y: 0. }, Coord { x: 1., y: 1. }];
let segment = SegmentOfTraversal {
segment_index: builder.add_segment("segment", segment_geometry, start_node, end_node),
Expand Down
17 changes: 17 additions & 0 deletions src/lrs_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,7 @@ impl<'a> flatbuffers::Follow<'a> for Node<'a> {
impl<'a> Node<'a> {
pub const VT_ID: flatbuffers::VOffsetT = 4;
pub const VT_PROPERTIES: flatbuffers::VOffsetT = 6;
pub const VT_GEOMETRY: flatbuffers::VOffsetT = 8;

#[inline]
pub unsafe fn init_from_table(table: flatbuffers::Table<'a>) -> Self {
Expand All @@ -1047,6 +1048,7 @@ impl<'a> Node<'a> {
args: &'args NodeArgs<'args>
) -> flatbuffers::WIPOffset<Node<'bldr>> {
let mut builder = NodeBuilder::new(_fbb);
if let Some(x) = args.geometry { builder.add_geometry(x); }
if let Some(x) = args.properties { builder.add_properties(x); }
if let Some(x) = args.id { builder.add_id(x); }
builder.finish()
Expand All @@ -1067,6 +1069,13 @@ impl<'a> Node<'a> {
// which contains a valid value in this slot
unsafe { self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Property>>>>(Node::VT_PROPERTIES, None)}
}
#[inline]
pub fn geometry(&self) -> Option<&'a Point> {
// Safety:
// Created from valid Table for this object
// which contains a valid value in this slot
unsafe { self._tab.get::<Point>(Node::VT_GEOMETRY, None)}
}
}

impl flatbuffers::Verifiable for Node<'_> {
Expand All @@ -1078,20 +1087,23 @@ impl flatbuffers::Verifiable for Node<'_> {
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<&str>>("id", Self::VT_ID, true)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<Property>>>>("properties", Self::VT_PROPERTIES, false)?
.visit_field::<Point>("geometry", Self::VT_GEOMETRY, false)?
.finish();
Ok(())
}
}
pub struct NodeArgs<'a> {
pub id: Option<flatbuffers::WIPOffset<&'a str>>,
pub properties: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Property<'a>>>>>,
pub geometry: Option<&'a Point>,
}
impl<'a> Default for NodeArgs<'a> {
#[inline]
fn default() -> Self {
NodeArgs {
id: None, // required field
properties: None,
geometry: None,
}
}
}
Expand All @@ -1110,6 +1122,10 @@ impl<'a: 'b, 'b> NodeBuilder<'a, 'b> {
self.fbb_.push_slot_always::<flatbuffers::WIPOffset<_>>(Node::VT_PROPERTIES, properties);
}
#[inline]
pub fn add_geometry(&mut self, geometry: &Point) {
self.fbb_.push_slot_always::<&Point>(Node::VT_GEOMETRY, geometry);
}
#[inline]
pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> NodeBuilder<'a, 'b> {
let start = _fbb.start_table();
NodeBuilder {
Expand All @@ -1130,6 +1146,7 @@ impl core::fmt::Debug for Node<'_> {
let mut ds = f.debug_struct("Node");
ds.field("id", &self.id());
ds.field("properties", &self.properties());
ds.field("geometry", &self.geometry());
ds.finish()
}
}
Expand Down

0 comments on commit ef138d6

Please sign in to comment.