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

Add extreme point-finding #114

Merged
merged 17 commits into from
Apr 17, 2017
Merged

Add extreme point-finding #114

merged 17 commits into from
Apr 17, 2017

Conversation

urschrei
Copy link
Member

This PR allows the calculation of the indices containing the extreme (min and max) x and y values of a geometry (any geometry for which we can build a convex hull). There are some subtleties:

The algorithm is simple, and runs in O(n) time, but only works on convex geometries, which it expects to be oriented counter-clockwise. Since convex-hull processing using QuickHull is O(n log n) on average, that's the lower bound if the geometry needs to be processed first. However, if you know your geometries are convex and oriented, you can specify this, and get O(n) processing.

There's also a binary-search algorithm available, which cuts processing time to O(log n), but I haven't been able to make it work. It's available in a previous commit along with a link to the source, if anyone wants to have a look at it and figure out where the problem is – it incorrectly returns minimum x. The current algorithm is implemented using a wrapper function that allows the algorithms to be easily swapped out.

I've also defaulted to returning indices, not points, because this functionality is primarily intended as a helper for other algorithms.

@urschrei urschrei force-pushed the find_extreme_points branch from f42d3a4 to 32d789d Compare April 10, 2017 16:12
@urschrei
Copy link
Member Author

urschrei commented Apr 15, 2017

Argh, I've just realised that the indices are only valid for input geometries that are convex. Because the convex-hull algorithm alters vertex order and may remove vertices, the returned struct contains indices that are wrong if the input geometry wasn't convex to begin with.

It's trivial to use this work as the basis for a trait that returns the extreme points (which is useful functionality imo), and it's necessary to have the extreme indices of a convex geometry as part of the polygon-to-polygon distance functionality, but maybe it shouldn't be a public API?

since this trait can't return the indices of a non-convex polygon,
there's no need to specify what to do with an input polygon

This makes the trait publicly useless, since there's no simple way
of guaranteeing the convex property of the input geometry. However,
the trait is still useful as a helper for returning extreme points,
as an internal helper for returning extreme indices for
polygon-to-polygon distance

there's no simple way to restrict a trait's visibility until 1.18, so
we're currently back to the drawing board
Like ExtremeIndices, but for points
@frewsxcv
Copy link
Member

I think it's fine leaving it public, as long as the limitations of the algorithm are documented, I think it's fine. r=me if this is good to go

The input Polygon is now checked for convexity. This functionality
adds considerable complexity to the trait, but I feel like it's worth
it.
@urschrei
Copy link
Member Author

OK, the ExtremeIndices trait now checks the input Polygon for convexity, and returns a Result, which is the safest way to handle this, I think.

I'm using a wrapping index lookup to get the two previous points. I don't think I can over / underflow it, and it's guaranteed to always receive a valid index, since it's only called by .iter().enumerate(). Still, if someone could have a look at it, since I'm always nervous about doing manual index arithmetic.

I've also added an ExtremePoints trait, which I've made available to anything implementing ConvexHull + ExtremeIndices. I noticed that when you implement it like this, it doesn't explicitly show up in the docs as a trait available to the relevant structs – do I have to do anything else to get it to show up, or is it a doc limitation?

[ci skip]
}

// positive implies a -> b -> c is counter-clockwise, negative implies clockwise
pub fn cross_prod<T>(p_a: &Point<T>, p_b: &Point<T>, p_c: &Point<T>) -> T
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean for this to be public?

@frewsxcv
Copy link
Member

LGTM. r=me if it's ready

@urschrei
Copy link
Member Author

r=frewsxcv

@frewsxcv
Copy link
Member

bors r+

bors bot added a commit that referenced this pull request Apr 17, 2017
114: Add extreme point-finding r=frewsxcv
This PR allows the calculation of the indices containing the extreme (min and max) `x` and `y` values of a geometry (any geometry for which we can build a convex hull). There are some subtleties:

The algorithm is simple, and runs in `O(n)` time, but only works on convex geometries, which it expects to be oriented counter-clockwise. Since convex-hull processing using QuickHull is `O(n log n)` on average, that's the lower bound if the geometry needs to be processed first. However, if you know your geometries are convex and oriented, you can specify this, and get `O(n)` processing.

There's also a binary-search algorithm available, which cuts processing time to `O(log n)`, but I haven't been able to make it work. It's [available in a previous commit](urschrei@4f71b24#diff-6128c8bf9f8def540989e4f8abf862c7L85) along with a link to the source, if anyone wants to have a look at it and figure out where the problem is – it incorrectly returns minimum `x`. The current algorithm is implemented using a wrapper function that allows the algorithms to be easily swapped out.

I've also defaulted to returning indices, not points, because this functionality is primarily intended as a helper for other algorithms.
@bors
Copy link
Contributor

bors bot commented Apr 17, 2017

Build succeeded

@bors bors bot merged commit a969dab into georust:master Apr 17, 2017
@urschrei urschrei deleted the find_extreme_points branch April 17, 2017 16:40
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.

2 participants