# [geo-rust] Compare sets of geoms? (requires Float vs Hash/Eq traits)

I have rstar::RTree and try to check if objects should be updated there, by comparing the old ones in the index and the new ones.

The problem is that RTree requires that the geometry has Float inside, but this forbids `Hash` & `Eq`, which are required to compare sets of geoms (with HashSet). I thought of BTreeSet, but that requires `Ord` which is weirder for geometries.

Geo-types docs say that Hash, PartialEq and Eq are supported for T's that support these traits -- and that's not floats, right?

I wrote just a check if old_geoms entriy is in new_geoms vector, and vice versa. But this must be slow, or not? (Apart from being O(n^2))

Is there a light way to check the difference of sets of geoms? Or we're doomed, and I have just to put a warning that such index update is a very costy operation? (I assume that "remove all & insert all new" strategy is costier, given that the update is 1..3 elements, while the rtree is big (100K objects).)

``````[#derive(... Hash, PartialEq, Eq)]
struct MyRTreeEntry { geom: Point, id: MyId }
impl RTreeObject for MyRTreeEntry {
type Envelope = AABB<Point>;
fn envelope(&self) -> AABB<Point> { self.geom.envelope() }
}
let mut tree: RTree<MyRTreeEntry> = ...
let old_entries = vec![entry1, entry2, entry3]; // this should be HashMap ideally
let new_entries = vec![entry3, entry2, entry4]; // this should be HashMap ideally

for e in old_entries.iter() {
if !new_entries.contains(e) {
tree.remove(e);
}
}

for e in new_entries.iter() {
if !old_entries.contains(e) (
tree.insert(e);
}
}
``````

Why does it say that? I couldn't confirm that with a quick glance at the docs.

Anyway, an easy solution would be to wrap `ordered_float::NotNan` in a newtype and implement all the required traits (`Float`, `Ord`, `Hash`, etc.) for it.

1 Like

Ok, will try.

This simple code reproduces the problem. Even though I also couldn't find where Float is required.

``````use rstar::RTree;
use geo::Point;

pub struct Test {
geoindex: RTree<Point<i64>>
}
``````

Error:

``````937 |     geoindex: RTree<Point<i64>>
|               ^^^^^^^^^^^^^^^^^ the trait `num_traits::float::Float` is not implemented for `i64`
|
= help: the following other types implement trait `num_traits::float::Float`:
f32
f64
= note: required for `geo::Point<i64>` to implement `rstar::Point`
= note: required for `geo::Point<i64>` to implement `RTreeObject`
``````

Can you implement `Hash` for `RTreeEntry` by delegating to the implementation on the `id` field rather than deriving it? Does each entry have a unique `id`?

Yes, ids are unique, and it's enforced elsewhere, but I need to watch if the objects and their ids are the same, but geometries have changed.

Actually, what worked was wrapping into OrderedFloat, making struct like `Point<OrderedFloat<f64>>`. Thanks!

and the code to create such struct:

``````fn pof(x: f64, y: f64) -> Point<OrderedFloat<f64>> {
Point::new(x.into(), y.into())
}
``````