-
Notifications
You must be signed in to change notification settings - Fork 14
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
Distance from point to a line #8
Comments
Thank you for showing interest in contributing! You can definitely start working on it if you want, though i'd like a solution which can be expanded to more shapes and implementations. i'd probably go with a trait which can be implemented for multiple spatial structures - with the rstar PointDistance and RTreeObject traits being a implementation detail hidden behind this trait. For now this trait should probably just be similar to a SpatialAccess specific to lines, containing the methods to query the tree for lines. At some point i will likely need to come up with a more comprehensive solution to this, but that would require a bigger change and i haven't had the time for that lately. If you do start working on this i'd really appreciate a Draft PR right away. |
Thinking on this some more, you might need to change the SpatialAccess to allow inserting lines - which might require some more work and a custom trait for any shape including points, complicating matters further. I'm afraid that will take some more consideration. |
I think the solution is that instead of having Then the
I think the hard part is how to allow users to convert their own entities into a
Something like this:
Right now I'm testing this idea in my project, where I only have points/segments. (and i need the distance from a point to a segment) |
this is along the lines of what ive been thinking too, i started on a redesign of that handling over in the |
Just sharing an example implementation for arbitrary geoms.
/// Module with traits related to querying/tracking spatial entities
use std::marker::PhantomData;
use geo_types::{Line, Point as GeoPoint};
use rstar::RTreeObject;
use crate::ecs::query::{ReadOnlyWorldQuery, WorldQuery};
use crate::prelude::*;
/// Component that marks an entity as being tracked (added/updated to the r-tree)
#[derive(Component, Clone, Copy, Default)]
pub struct SpatialTracker;
// pub struct SpatialTracker<P: Point> {
// /// tracks the last envelope at which the entity was updated in the tree.
// pub last_envelope: Option<Envelope<Point=Point>>,
// }
pub type MySpatialTracker = SpatialTracker;
// pub type MySpatialTracker = SpatialTracker<MyRPoint>;
pub type PointTrackedSpatialQuery = TrackedSpatialQuery<PointSpatialWorldQuery, MyRTreeObject>;
pub type SegmentTrackedSpatialQuery = TrackedSpatialQuery<SegmentSpatialWorldQuery, MyRTreeObject>;
#[derive(WorldQuery)]
pub struct TrackedSpatialQuery<SubQuery, RObj>
where
SubQuery: SpatialWorldQuery<RObj>,
RObj: RTreeObject + Send + Sync,
{
pub entity: Entity,
pub subquery: SubQuery,
pub added_tracker: ChangeTrackers<SpatialTracker>,
pub spatial_tracker: &'static SpatialTracker,
// pub spatial_tracker: &'static mut SpatialTracker<Point>
#[world_query(ignore)]
_phantom: PhantomData<RObj>
}
impl<'a, SubQuery, RObj> TrackedSpatialQueryItem<'a, SubQuery, RObj>
where
SubQuery: SpatialWorldQuery<RObj>,
// <SubQuery as WorldQuery>::Item: SpatialWorldQueryItem<RObj>,
RObj: RTreeObject + Send + Sync
{
/// Returns true if the spatial `Marker` has been newly added
pub fn is_added(&self) -> bool {
self.added_tracker.is_added()
}
/// Returns true if the entity is not new, and has moved
pub fn is_moved(&self) -> bool
where <SubQuery as WorldQuery>::Item<'a>: SpatialWorldQueryItem<'a, RObj> {
!self.is_added() && self.subquery.is_moved()
}
/// Return the corresponding tree object
pub fn to_tree_object(self) -> RObj
where <SubQuery as WorldQuery>::Item<'a>: SpatialWorldQueryItem<'a, RObj> {
self.subquery.to_tree_object(self.entity)
}
}
/// A WorldQuery to query for entities that need to be inserted into an r-tree
pub trait SpatialWorldQuery<RObj>: ReadOnlyWorldQuery
where RObj: RTreeObject + Send + Sync {
type Item<'a>: SpatialWorldQueryItem<'a, RObj>;
}
/// The WorldQueryItem needs to satisfy certain requirements
pub trait SpatialWorldQueryItem<'a, RObj>
where RObj: RTreeObject + Send + Sync {
/// Returns true if the queries entity has moved
fn is_moved(&self) -> bool;
/// Converts the query items into a `RObj` that can be inserted into an r-tree
fn to_tree_object(self, entity: Entity) -> RObj;
}
#[derive(WorldQuery)]
/// Query for single-points that need to be inserted into the R-tree
pub struct PointSpatialWorldQuery {
pub position: &'static Position,
pub moved_tracker: ChangeTrackers<Position>
}
impl SpatialWorldQuery<MyRTreeObject> for PointSpatialWorldQuery {
type Item<'a> = PointSpatialWorldQueryItem<'a>;
}
impl SpatialWorldQueryItem<'_, MyRTreeObject> for PointSpatialWorldQueryItem<'_> {
fn is_moved(&self) -> bool {
self.moved_tracker.is_changed()
}
fn to_tree_object(self, entity: Entity) -> MyRTreeObject {
MyRTreeObject::new(Geom::Point(self.position.into()), entity)
}
}
#[derive(WorldQuery)]
/// Query for segments that need to be inserted into the R-tree
pub struct SegmentSpatialWorldQuery {
pub segment: SegmentQuery,
// A segment that moves always has their position moving, so we only need to check if
// the `Position` component got updated
pub moved_tracker: ChangeTrackers<Position>
}
impl SpatialWorldQuery<MyRTreeObject> for SegmentSpatialWorldQuery {
type Item<'a> = SegmentSpatialWorldQueryItem<'a>;
}
impl SpatialWorldQueryItem<'_, MyRTreeObject> for SegmentSpatialWorldQueryItem<'_> {
fn is_moved(&self) -> bool {
self.moved_tracker.is_changed()
}
fn to_tree_object(self, entity: Entity) -> MyRTreeObject {
let segment: Segment = self.segment.into();
let (start, end) = segment.to_pair();
let line = Line::new::<GeoPoint<f32>>(start.into(), end.into());
MyRTreeObject::new(Geom::Line(line), entity)
}
} |
Hi, Thanks for the crate!
My use-case is that I'd like to compute the Euclidean distance from a point to a line.
It looks like R-tree could support this kind of queries: https://docs.rs/rstar/latest/rstar/trait.PointDistance.html
I'm not entirely sure how it would look like.
The tree leaves already seem to be rectangles (collapsed to be a single point). So it should be do-able to update the tree to be able to handle lines as well?
What do you think? I might start working on this, but i'd like to hear your input
The text was updated successfully, but these errors were encountered: