geo icon indicating copy to clipboard operation
geo copied to clipboard

GeometryGraph and PreparedGeometry multi-threaded (Send)

Open gauteh opened this issue 1 year ago • 11 comments

Make GeometryGraph and PreparedGeometry Send so that it can be used by multiple threads.

Based on and depends on: https://github.com/georust/geo/pull/1197

gauteh avatar Jul 08 '24 17:07 gauteh

#1197 has been merged - could you do a rebase or merge to minimize the diff?

michaelkirk avatar Jul 26 '24 20:07 michaelkirk

I have rebased, but I haven't had time to work any further on this yet (feel free to make changes if you have time).

gauteh avatar Jul 27 '24 14:07 gauteh

Some of the test fails seem like numeric precision errors, they are also present on main. There is one failing test left (debug assert), which I don't know why is failing.

 3  failed: algorithm::interior_point::test::polygon_cell_test                          ▐
 thread 'algorithm::interior_point::test::polygon_cell_test' panicked at geo/src/algorit▐
 hm/relate/geomgraph/edge_end_bundle_star.rs:112:21:                                    ▐
 side_location conflict with coordinate: Coord { x: 2.0, y: 1.0 }, right_location: Insid▐
 e, current_location: Outside                                                           ▐

gauteh avatar Aug 16 '24 08:08 gauteh

The lifetime in prepared geometry is tedious to work with. Could that be replaced by a Cow or maybe a owned version of the geometrygraph?

gauteh avatar Aug 16 '24 09:08 gauteh

The lifetime in prepared geometry is tedious to work with. Could that be replaced by a Cow or maybe a owned version of the geometrygraph?

Just realized that is exactly how it is now...

gauteh avatar Aug 16 '24 13:08 gauteh

This seems to be working now.

It appears that a new geometrygraph + intersection matrix is created for every point I want to check against the preparedgeometry.

gauteh avatar Aug 17 '24 12:08 gauteh

It appears that a new geometrygraph + intersection matrix is created for every point I want to check against the preparedgeometry.

Can you expand on this and / or illustrate it with a minimal test case?

urschrei avatar Aug 17 '24 12:08 urschrei

My use case is roaring-landmask, here's a PR where I am running against these changes: https://github.com/gauteh/roaring-landmask/pull/28, in https://github.com/gauteh/roaring-landmask/blob/georust-prepared/src/shapes.rs#L129 I check if a point is in any of the polygons using is_covers:

self.geom.relate(&p).is_covers()

this creates a geometrygraph of the point p and tests it against the PreparedGeometry. I believe geos has a PreparedPolygon/PreparedMultiPolygon with specializations for checking various relates towards a point.

In roaring-landmask this may be tested with e.g.: cargo test --features nightly --release -j 1 many -- --nocapture

gauteh avatar Aug 17 '24 13:08 gauteh

It appears that a new geometrygraph + intersection matrix is created for every point I want to check against the preparedgeometry.

That's right. The difference with PreparedGeometry is that the Polygon's geometry graph isn't created from scratch every time.

The point's graph will be created from scratch, since it's a different point every time, but it should also be a pretty trivial graph.

I check if a point is in any of the polygons using is_covers:

Note that in the case of points and polygons, polygon.relate(points).is_covers() is the same as polygon.instersects(point).

The GeometryGraph is a very general tool, built to handle all the de-9im relations for all geometry types. If you are only interested in "point intersects polygon" checks, there is likely a faster approach involving less machinery - maybe ray casting, but I don't think we have an implementation of that yet.

michaelkirk avatar Aug 17 '24 17:08 michaelkirk

It appears that a new geometrygraph + intersection matrix is created for every point I want to check against the preparedgeometry.

That's right. The difference with PreparedGeometry is that the Polygon's geometry graph isn't created from scratch every time.

The point's graph will be created from scratch, since it's a different point every time, but it should also be a pretty trivial graph.

Indeed, the tree has no members.

I check if a point is in any of the polygons using is_covers:

Note that in the case of points and polygons, polygon.relate(points).is_covers() is the same as polygon.instersects(point).

Is there any performance difference? Or exactly the same?

The GeometryGraph is a very general tool, built to handle all the de-9im relations for all geometry types. If you are only interested in "point intersects polygon" checks, there is likely a faster approach involving less machinery - maybe ray casting, but I don't think we have an implementation of that yet.

So it appears, and that makes sense (to start with). I think that this PR is mostly functional now. I had to make a few slightly messy changes to satisfy borrowing rules, without doing a much greater re-structuring. There is some cleanup to be done, but it should be a useful feature (and actually a pretty cool plus over geos, where it is not safe to share the PreparedGeometry) to other applications. Sadly, I don't think it will make much difference to my issue (https://github.com/georust/geo/issues/1184).

gauteh avatar Aug 18 '24 06:08 gauteh

@michaelkirk I've rebased and tidied this up and appeased young master Clipperton – I only have one query regarding the "satisfy rust's borrowing rules section" but otherwise this hasn't added any obvious complexity to our GeomGraph machinery (though it's difficult to imagine how that would be possible…), and the Send bound will probably come in useful at some point. WDYT?

urschrei avatar Oct 28 '24 21:10 urschrei

@gauteh I'm going to convert this to a draft until the comments and merge conflicts are addressed

frewsxcv avatar Sep 27 '25 16:09 frewsxcv

Development seems to have stalled on this, so I'm going to close this pull request. @gauteh If you get around to resuming work on this, please reopen!

frewsxcv avatar Nov 05 '25 16:11 frewsxcv