Open JosiahParry opened 6 months ago
I forgot to add the geojson! guerry.geojson.zip
Thanks! I'll take a look when I have time. The search
method is directly ported from upstream, and so that should be reliable (it has matched shapely/GEOS). The intersection candidates is my own addition.
Contributions welcome 😉 . I can describe/document the tree structure better if you're interested! (I actually have a half-written blog post on flatbush that I never finished)
I can confirm that the search()
method works well! I'm able to identify polygon queen contiguity with a function like this.
pub fn search_tree(left: OwnedRTree<f64>, targets: PolygonArray<i32>) -> Vec<(usize, usize, f64)> {
let mut neighbors = Vec::new();
let _ = targets.iter().enumerate().for_each(|(i, target)| {
let geom = target.unwrap();
let (min, max) = bounding_rect_polygon(&geom);
let mut candidates = left.search(min[0], min[1], max[0], max[1]);
candidates.sort();
for c in candidates {
if geom.to_geo().intersects(&targets.get(c).unwrap().to_geo()) {
neighbors.push((i, c, 1.0));
}
}
});
neighbors
}
I tried toying around with the tree traversal but im a bit out of my depth when it comes to recursion and tree searching. I'll try and find some more time to maybe pluck around in the source code at a later point
pub fn two_tree_candidates(left: OwnedRTree<f64>, right: OwnedRTree<f64>) -> Vec<Vec<usize>> {
let res = right
.as_ref()
.root()
.children()
.flat_map(|node| recursive_search(&node, &left))
.collect::<Vec<_>>();
res
}
fn recursive_search<'a>(
node: &'a Node<'a, f64, RTreeRef<'a, f64>>,
left: &OwnedRTree<f64>,
) -> Vec<Vec<usize>> {
if node.is_leaf() {
let candidate = left.search(node.min_x(), node.min_y(), node.max_x(), node.max_y());
vec![candidate]
} else if node.is_parent() {
node.children()
.flat_map(|child| recursive_search(&child, left))
.collect()
} else {
Vec::new()
}
}
I can confirm that the
search()
method works well!
Indeed, there are never any bugs in @ mourner's code 😉
I think the gist of my tree traversal is sound. It's probably just missing a check somewhere.
I put together a small derived repro in https://github.com/kylebarron/geo-index/pull/51. Run with cargo run -- --debug
. It's simplest to remove geoarrow from the picture here.
One of the issues is that https://github.com/kylebarron/geo-index/blob/159f2dbbe19538fb7bc72d74b610074d5a6b3c47/src/rtree/traversal.rs#L56 is backwards and should be <
instead. So that meant that the iterator was never recursing: https://github.com/kylebarron/geo-index/blob/159f2dbbe19538fb7bc72d74b610074d5a6b3c47/src/rtree/traversal.rs#L190
Fixing that gives endless recursion, so I still have another issue somewhere. It's probably that I'm mixing parent and child intersections somewhere
I was trying to give geo-index a spin with the use case of finding self-intersecting geometries (contiguity). At minimum, we expect each geometry to be an intersection candidate with itself. Using geo-index only 1 intersection candidate is found. When compared to rstar, all candidates are found.
Repro below. Please excuse any horrendous use of geoarrow 🙃