Fit maximum convex hull to interior of a set of points - geometry

I'd like to find the largest convex hull which fits in the interior of a set of points. I have a set of points which are roughly circular, with a large number of outlier points outside of the circle I'd like to fit. Imagine a circle with "solar flares"... I want to fit the circle and completely ignore the flares. I've tried various fit and culling strategies, but they aren't working well.
I've searched quite a bit and not found a solution. Thanks in advance.

The notion you need may be alpha shapes. The convex hull is a sub-set of the alpha-shape for an extreme value for alpha. The alpha shape is fitting a set of point closer than the convex hull with some values for alpha.
Theory has been developed by Edelbrunner. This is a good start: http://www.mpi-inf.mpg.de/~jgiesen/tch/sem06/Celikik.pdf
For computation, you must: compute delaunay triangulation and/or voronoi diagram, then select points that observe one condition.
Example alpha shape:
This is in fact a concave hull, and it may disregard outliers.

Related

Fit rectangle of given aspect ratio around a set of points

Given a set of points in 2D space, how would I find a smallest (rotated) rectangle of a given aspect ratio that encloses the points?
I found several questions about fitting arbitrary rectangles (by looking at the angle of the edges of the convex hull), but that approach does not seem to carry over easily.

Expanding Convex Hull to Reduce Sides

We have sets of labeled points whose convex hulls do not overlap. There is some empty space between the convex hulls.
Given an unlabeled point that is not in our data we want to approximately determine which convex hull it lies within.
To make the computation faster, we want to reduce the number of sides on the convex hull (thus expanding the convex hull a bit, but not too much).
What algorithms could I use?
Update: Ideally I want to do the expansion under the constraint that it not intersect a given nearby polygon. (The motivation for this constraint is that I have several disjoint hulls and want to reduce the number of sides of all of them while still keeping them disjoint. But treat this as a parenthetical because I do not want to do a joint modification. I am happy to modify one hull while keeping the others constant. I am happy to hack this simple case to do a joint modification iteratively.)
Perhaps this is worth trying.
Find the convex hull A' of A union x, and the convex hull B' of B union x.
Select whichever increases the hull area the least.
In the example below, A' is the winner.
Added in response to comment:
One route is via "minimal enclosing k-gons":
Mictchell et al.: "Minimum-Perimeter Enclosing k-gon" 2006 (CiteSeer link)
Aggarwal et al.: "Minimum Area Circumscribing Polygons" 1985 (CiteSeer link)
O'Rourke et al.: "An optimal algorithm for fnding minimal enclosing triangles" 1986, Algorithmica (ACM link)
These algorithms are, however, quite intricate and unlikely to help much.
The "point in convex polygon" test is not so expensive, as it can be performed in Lg(N) comparisons by dichotomy (split the polygon in two with a straight line, recursively until you have a single triangle left). N is the number of sides. Actually, a polygon of 27 (resp. 130) sides will cost you the double (triple) of a triangle.
If you have many hulls, exhaustive comparisons of the point against every hull is a waste. There are better approaches such as using monotone subdivisions, which could lower the search time to O(Log(M)) query time for a total of M sides, after preprocessing.
I wouldn't be surprised if the saving of processing one less edge in your rough-phase contains check is outweighed by the increased false-positive rate of the inflated hull. Indeed, you might even be making more work for yourself - every point that passes the rough-phase check will have to also be checked against the true hull anyway.
Instead of trying to reduce the n in your O(n) contains check, I'd be tempted to go straight to something amortised O(1) for the rough passes:
1st pass - check against the axis-aligned bounding box (AABB). This gives quick rejection for the vast majority of points outside the polygon.
2nd pass - divide the AABB into a grid, where each grid quad is in one of three states: fully outside the hull, intersecting the hull edge or fully inside the hull. If your point lies in an "in" or "out" quad, you can stop here.
3rd pass - any point that lies in a grid quad that intersects the polygon is checked against the hull as normal.
The state of the grid can be computed ahead of time:
Initialise each grid quad to be outside of the hull
Use the algorithm linked in this answer to trace the edges of the hull over the grid and set all intersecting quads.
The grid now contains the outline of the hull, so use a simple floodfill or scanline approach to find and set all quads on the interior of the hull.
The resolution of the grid can be varied to give a tradeoff between memory cost (2 bits per quad) and false-positive rate (low-resolution grids will lead to more O(n) conventional hull checks).
It looks like your ultimate goal is not really about convex hulls, it is about solving the point location problem (https://en.wikipedia.org/wiki/Point_location). And you seem to be determined to solve it by simply iteratively checking your point against a number of convex hulls. While I understand where convex hulls come from (they actually represent sets of points), it is still not a reason to directly use them in the algorithm. Point location problem can be solved by a number of more efficent algorithms (like search tree based on trapezoidal decomposition), which are much less sensitive to the number of edges in your hulls.

Convex hull of (longitude, latitude)-points on the surface of a sphere

Standard convex hull algorithms will not work with (longitude, latitude)-points, because standard algorithms assume you want the hull of a set of Cartesian points. Latitude-longitude points are not Cartesian, because longitude "wraps around" at the anti-meridian (+/- 180 degrees). I.e., two degrees east of longitude 179 is -179.
So if your set of points happens to straddle the anti-meridian, you will compute spurious hulls that stretch all the way around the world incorrectly.
Any suggestions for tricks I could apply with a standard convex hull algorithm to correct for this, or pointers to proper "geospherical" hull algorithms?
Now that I think on it, there are more interesting cases to consider than straddling the anti-merdian. Consider a "band" of points that encircle the earth -- its convex hull would have no east/west bounds. Or even further, what is the convex hull of {(0,0), (0, 90), (0, -90), (90, 0), (-90, 0), (180, 0)}? -- it would seem to contain the entire surface of the earth, so which points are on its perimeter?
Standard convex hull algorithms are not defeated by the wrapping-around of the coordinates on the surface of the Earth but by a more fundamental problem. The surface of a sphere (let's forget the not-quite-sphericity of the Earth) is not a Euclidean space so Euclidean geometry doesn't work, and convex hull routines which assume that the underlying space is Euclidean (show me one which doesn't, please) won't work.
The surface of the sphere conforms to the concepts of an elliptic geometry where lines are great circles and antipodal points are considered the same point. You've already started to experience the issues arising from trying to apply a Euclidean concept of convexity to an elliptic space.
One approach open to you would be to adopt the definitions of geodesic convexity and implement a geodesic convex hull routine. That looks quite hairy. And it may not produce results which conform to your (generally Euclidean) expectations. In many cases, for 3 arbitrary points, the convex hull turns out to be the entire surface of the sphere.
Another approach, one adopted by navigators and cartographers through the ages, would be to project part of the surface of the sphere (a part containing all your points) into Euclidean space (which is the subject of map projections and I won't bother you with references to the extensive literature thereon) and to figure out the convex hull of the projected points. Project the area you are interested in onto the plane and adjust the coordinates so that they do not wrap around; for example, if you were interested in France you might adjust all longitudes by adding 30deg so that the whole country was coordinated by +ve numbers.
While I'm writing, the idea proposed in #Li-aung Yip's answer, of using a 3D convex hull algorithm, strikes me as misguided. The 3D convex hull of the set of surface points will include points, edges and faces which lie inside the sphere. These literally do not exist on the 2D surface of the sphere and only change your difficulties from wrestling with the not-quite-right concept in 2D to quite-wrong in 3D. Further, I learned from the Wikipedia article I referenced that a closed hemisphere (ie one which includes its 'equator') is not convex in the geometry of the surface of the sphere.
Instead of considering your data as latitude-longitude data, could you instead consider it in 3D space and apply a 3D convex hull algorithm? You may be able to then find the 2D convex hull you desire by analysing the 3D convex hull.
This returns you to well-travelled algorithms for cartesian convex hulls (albeit in three dimensions) and has no issues with wrap around of the coordinates.
Alternately, there's this paper: Computing the Convex Hull of a Simple Polygon on the Sphere (1996) which seems to deal with some of the same issues that you're dealing with (coordinate wrap-around, etc.)
If all your points are within a hemisphere (that is, if you can find a cut plane through the center of the Earth that puts them all on one side), then you can do a central a.k.a. gnomic a.k.a. gnomonic projection from the center of the Earth to a plane parallel to the cut plane. Then all great circles become straight lines in the projection, and so a convex hull in the projection will map back to a correct convex hull on the Earth. You can see how wrong lat/lon points are by looking at the latitude lines in the "Gnomonic Projection" section here (notice that the longitude lines remain straight).
(Treating the Earth as a sphere still isn't quite right, but it's a good second approximation. I don't think points on a true least-distance path across a more realistic Earth (say WGS84) generally lie on a plane through the center. Maybe pretending they do gives you a better approximation than what you get with a sphere.)
FutureNerd:
You are absolutely correct. I had to solve the exact same problem as Maxy-B for my application. As a first iteration, I just treated (lng,lat) as (x,y) and ran a standard 2D algorithm. This worked fine as long as nobody looked too close, because all my data were in the contiguous U.S. As a second iteration, though, I used your approach and proved the concept.
The points MUST be in the same hemisphere. As it turns out, choosing this hemisphere is non-trivial (it's not just the points' center, as I had initially guessed.) To illustrate, consider the following four points: (0,0), (-60,0), (+60,0) along the equator, and (0,90) the north pole. However you choose to define "center", their center lies on the north pole by symmetry and all four points are in the Northern Hemisphere. However, consider replacing the fourth point with, say (-19, 64) iceland. Now their center is NOT on the north pole, but asymmetrically drawn toward iceland. However, all four points are still in the Northern Hemisphere. Further, the Northern Hemisphere, as uniquely defined by the North Pole, is the ONLY hemisphere they share. So calculating this "pole" becomes algorithmic, not algebraic.
See my repository for the Python code:
https://github.com/VictorDavis/GeoConvexHull
This question has been answered a while ago, but I would like to sum up the results of my research.
The spherical convex hull is basically defined only for non-antipodal points. Supposing all the points are on the same hemisphere, you can compute their convex hull in two main ways:
Project the points to a plane using gnomonic/central projection and apply a planar convex hull algorithm. See Lin-Lin Chen, T. C. Woo, "Computational Geometry on the Sphere With Application to Automated Machining" (1992). If the points are on a known hemisphere, you can hard-code on which plane to project the points unto.
Adapt planar convex hull algorithms to the sphere. See C. Grima and A. Marquez, "Computational Geometry on Surfaces: Performing Computational Geometry on the Cylinder, the Sphere, the Torus, and the Cone", Springer (2002). This reference seems to give a similar method to the abstract referenced by Li-aung Yip above.
For reference, in Python I am working on an implementation of my own, which currently works only for points on the Northern hemisphere.
See also this question on Math Overflow.
All edges of a spherical convex hull can be viewed/treated as great circles (seminally, all edges of a convex hull in euclidean space can be treated as lines (rather than a line segment)). Each one of these great circles cuts the sphere into two hemispheres. You could thus conceive each great circle as a constraint. A point that is within the convex hull will be on each of the hemispheres defined by each constraint.
Each edge of the original polygon is a candidate edge of the convex hull. To verify if it is indeed an edge of the convex hull, you'd simply need to verify if all nodes of the polygon are on the hemisphere defined by the great circle that goes through the two nodes of the edge in question. However, we'd still need to create new edges that surpass the concave nodes of the polygon.
But lets rather shortcut / brute-forces this:
Draw a great circle between every pair of nodes in the polygon. Do this in both directions (i.e. the great circle connecting A to B and the great circle connecting B to A). For a polygon with N nodes, you will thus end up with N^2 great circle. Each one of these great circles is a candidate constraint (i.e. a candidate edge of the convex polygon). Some of these great circles will overlap with the edges of the original polygon, but most won't. Now, remember again: each great circle is a constraint that constrains the sphere to one hemisphere. Now verify if all nodes of the original polygon satisfy the constraint (i.e. if all nodes are on the hemisphere defined by the great circle). If yes, then this great circle is an edge of the convex hull. If, however a single node of the original polygon does not satisfy the constraint, then it isn't and you can discard this great circle.
The beauty of this is that once you converted your latitudes and longitudes into cartesian vectors pointing onto the unit sphere, it really just requires dot products and cross products
- You find the great circle that passes through two points on a sphere by its cross product
- A point is on the hemisphere defined by a great circle if the dot product of the great circle and the point is greater (or equal) to 0.
So even for polygons with a large number of edges, this brute force method should work just fine.

Make qhull/qvoronoi limit Voronoi to convex hull or given polygon

A planar Voronoi tesselation will always have unbounded polygons
(infinite regions).
How do I tell qhull/qvoronoi to intersect the tesselation with either
the original points' convex hull, or with a polygon I explicitly
specify (probably a rectangle).
Specific example ( https://github.com/barrycarter/bcapps/blob/master/bc-temperature-voronoi.pl ):
I map latitudes/longitudes (inaccurately) to the 2-D rectangle
(-180,180)*(-90,90), and apply qvoronoi to the result.
I can't handle unbounded polygons and Google Maps API dislikes
polygons that wander outside (-180,180)(-90,90) [actually, it's more like (-180,180)(-85,85) because Google uses Mercator]
Can I make qhull/qvoronoi intersect the polygons with the points'
convex hull and/or the (-180,180)*(-90,90) rectangle? Of course, the
convex hull is entirely contained within the rectangle.
If not, can another program do it? I suspect I could write this
myself, but would prefer an existing solution.

Minimize Polygon Vertices

What is a good algorithm for reducing the number of vertices in a polygon without changing the way it looks very much?
Input: A polygon, represented as a list of points, with way too many verticies: raw input from the mouse, for example.
Output: A polygon with much fewer verticies that still looks a lot like the original: something usable for collision detection, for example (not necessarily convex).
Edit: The solution to this would be similar to finding a multi-segmented line of best fit on a graph. It's called Segmented Least Squares in my algorithms book.
Edit2: The Douglas Peucker Algorithm is what I really want.
Edit: Oh look, Simplifying Polygons
You mentioned collision detection. You could go really simple and calculate a bounding convex hull around it.
If you cared about the concave areas, you can calculate a concave hull by taking the centroid of your polygon, and choosing a point to start. From the starting point rotate around the centroid, finding each vertex you want to keep, and assigning that as the next vertex in the bounding hull. The complexity of the algorithm would come in how you determined which vertices to keep, but I'm sure you thought of that already. You can throw all your vertices into buckets based on their location relative to the centroid. When a bucket gets more than an arbitrary number of vertices full, you can split it. Then take the mean of the vertices in that bucket as the vertex to use in your bounding hull. Or, forget the buckets, and when you're moving around the centroid, only choose a point if its more than a given distance from the last point.
Actually, you could probably just use all the vertices in your polygon as "cloud of points" and calculate the concave hull around that. I'll look for an algorithm link. Worst case on this would be a completely convex polygon.
Another alternative is to start with a bounding rectangle. For each vertex on the rectangle, find the distance from the point to the polygon. For the farthest vertex, split it into two more vertices and move them in some. Repeat until some proportion of either vertices or area is met. I'd have to think about the details of this one a little more.
If you care about the polygon actually looking similar, even in the case of a self-intersecting polygon, then another approach would be required, but it doesn't sound like thats necessary since you asked about collision detection.
This post has some details about the convex hull part.
There's a lot of material out there. Just google for things like "mesh reduction", "mesh simplification", "mesh optimization", etc.

Resources