rstar::RTree -- how to store objects meta-info (like ID)?

Here's a simple example with storing points in rstar::RTree, and then searching if they're within a distance from a line.

Now, RTree returns me an iterator on the objects. But they're pure geometry without meta info, like IDs.

I could actually just make a HashMap<Point/Rect, MyIDType> and call HashMap.get(...), but neither rstar::Rectangle, nor geo::Point can be hashed (and both the type & trait aren't mine, I can't impl them).

The only possible solution seems to implement own RTreeObject type with id inside.

Is there an easier solution?

On the other hand, trait RTreeObject has only one method, so this should be easy.

I'll post an update.

Actually, that was easy, see the example.

use rstar::{RTree, RTreeObject, AABB};
use rand::{thread_rng, Rng};
use geo::{Point, line_string, Translate, LineString};

type pp = Point<f64>;
#[derive(Debug)]
struct MyPt {
	id: i32,
	pt: pp,
	buf: f64,
}

impl RTreeObject for MyPt {
	type Envelope = AABB<pp>;
	fn envelope(&self) -> Self::Envelope {
		let p1 = self.pt.translate(-self.buf, -self.buf);
		let p2 = self.pt.translate(self.buf, self.buf);
		AABB::from_corners(p1, p2)
	}
}

fn main() {
	// generating 30 points at random x&y in range [0..1000)
	let mut rng = thread_rng();
	let buf = 50.0;
	let v:Vec<MyPt> = (0..30).map(|id|
		MyPt { id, 
               pt: (rng.gen_range(0f64..1000f64),
                    rng.gen_range(0f64..1000f64)).into(),
               buf }).collect();

	let rt = RTree::bulk_load(v);

	let ls:LineString = line_string![(x: 0.0, y: 0.0), (x: 900.0, y: 100.0), (x: 1000.0, y: 1000.0)];

	// let's search for points in the buffer
	for l in ls.lines() {
		for k in rt.locate_in_envelope_intersecting(&l.envelope()) {
			println!("{:?}", k);
		}
	}
}

Note that we also have the GeomWithData struct to make this a bit easier, though your method also works.

1 Like