Skip to content
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

Reorder cells in Voronoi diagram to match order of MultiPoint inputs. #320

Closed
wants to merge 232 commits into from

Conversation

dbaston
Copy link
Member

@dbaston dbaston commented May 9, 2020

This slows down the Voronoi creation process for a MultiPoint by about
25%, so it should probably be made opt-in or more efficient.

nilason and others added 30 commits September 23, 2019 16:44
Enables macro expansion with GEOS_DLL predefined. Addresses issue with doxygen generation of geom::Location
The previous default, CoordinateArraySequenceFactory, always creates a
heap-allocating CoordinateArraySequence, even for small sizes. This
commit defines DefaultCoordinateSequenceFactory that delegates to
FixedSizeCoordinateSequence for length <= 5. This is big enough to cover
some common cases like conversion of line segments, triangles, and
boxes into geometries.
Improves segment unary union perf test by 45%.
Improves performance of segment unary union benchmark by 85%.
- Change two tests to use GEOSEquals instead of WKT comparison, so
as not to be sensitive to component ordering.
- Change two tests to expect that the union of LINESTRING EMPTY is
LINESTRING EMPTY, instead of GEOMETRYCOLLECTION EMPTY. This is
consistent with JTS, as with how other types are handled.
Bypassing cascaded union of lines produces a different but still correct
result.
Including z was inconsistent with the behavior of the equality operator,
and caused equivalent coordinates to be hashed into different bins.

Identified by Raul Marín, debugged by Paul Ramsey.
Curiously, this case blows an exception on PostGIS, but not in the unit test.
References libgeos#859
@Komzpa
Copy link
Contributor

Komzpa commented May 9, 2020

This slows down the Voronoi creation process for a MultiPoint by about 25%, so it should probably be made opt-in or more efficient.

My guess it should be benchmarked not against old Voronoi but instead against old Voronoi + GEOSIntersects between each input point and output point, or, in case of PostGIS scenario, similar ST_Intersects.

@dr-jts
Copy link
Contributor

dr-jts commented May 9, 2020

This is using the site coordinate present in the userData matched with the input coordinate list, right?

If so, I'm surprised it adds so much time. Any ideas on why that might be?

And what is the size of the input the 25% number comes from? I would expect the matching to be close to linear, so it should be a decreasing proportion of the overall time as the input size grows.

@dbaston
Copy link
Member Author

dbaston commented May 9, 2020

This is using the site coordinate present in the userData matched with the input coordinate list, right?

Yup

If so, I'm surprised it adds so much time. Any ideas on why that might be?

STL maps are surprisingly slow, I guess because they're so heap-intensive. We saw a huge performance boost from removing a map in this same code. (Tracking QuadEdge visit status)

And what is the size of the input the 25% number comes from?

100,000 points. Runtime from 385ms to 500ms, so actually about 30%.

In 3.7 the runtime is well over 1000ms, so it's not the end of the world. But I don't see a hurry to merge it now; I'd like to try and find something a bit better.

@dr-jts
Copy link
Contributor

dr-jts commented May 9, 2020

STL maps are surprisingly slow, I guess because they're so heap-intensive. We saw a huge performance boost from removing a map in this same code. (Tracking QuadEdge visit status)

Well that's bogus. Is there a TreeMap equivalent, and if so would that be any faster?

In JTS it's possible to attach data to the site points, which means that the point index could be attached. Not sure if that's supported in GEOS?

@dbaston
Copy link
Member Author

dbaston commented May 9, 2020

I didn't do any better with a tree map.

Yes, I think attaching the index and carrying it through may be the better way to go. Kind of annoying to implement, though.

Nothing in the callgrind profile suggests it should be such a big performance hit -- the profile shows only 4% of runtime spend reordering the cells. But if you skip the reordering, the runtime difference is clear.

@dr-jts
Copy link
Contributor

dr-jts commented May 11, 2020

How about sorting the Voronoi cell coordinates and then using binary search to look them up by the input sites? Does STL have a class supporting binary search?

@dbaston
Copy link
Member Author

dbaston commented May 12, 2020

It doesn't quite work, because you end up defining a comparator to sort your cells based on their input site, but then you are trying to look up with the input site itself, which doesn't plug into that comparator. Then once you identify the site, you want to pull it into your reordered list, but you can't move it because you'd be leaving a null pointer behind, which would break subsequent binary searches. All of it can be dealt with, just not something I have the time to experiment with immediately.

@abellgithub
Copy link
Contributor

I'm not sure what you're doing here but here's another idea: Make a vector using std::iota(). sort with a comparator that compares Coordinates of the original polys. Do the same thing with voroni polys. Then you have two vectors of indices that show where elements in the voroni set go in the original set (both are sorted by Coordinate, which should correspond 1:1, right?)

Then:

for (i = 0; i < size; ++i)
{
   oidx = ovector[i];
  vidx = vvector[i];
  reorderedPolys[oidx] = std::move(voroniPolys[vidx]);
}

This suffers from having to allocate temp space :(
If I'm understanding, it sure would be nicer just to attach the index of the original poly to the voroni poly, but I guess that's hard? :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.