Rough test if points are inside/outside of convex hull - computational-geometry

I am working on an algorithm where I have to check whether points are inside or outside of the convex hull of some points. The problem is that
I have to check this for a lot of points: ~2000,
the point-cloud defining the convex hull has around 10000 points,
the dimensions I am working in is quite high: 10-50.
The only possible positive thing for my points are, that for every point x, there is also -x, thus the points define a pointsymmetric polytope, and the convex hull is not degenerate (has non-empty interior).
Right now I am doing this with linear programming, for example as in https://stackoverflow.com/a/11731437/8052809
To speed up my program, I want to estimate whether a point is for sure inside or outside the convex hull, prior to computing it exactly. In other words, I need some fast algorithm which can determine for some points whether they are inside or not, resp. whether they are outside or not - and for some points, the fast algorithm can't decide it.
This I am doing right now by first looking at the bounding box of my pointcloud, and second, the approach in https://stackoverflow.com/a/4903615/8052809 - comment by yombo.
But both methods can only determine if a point is for sure outside (and both methods are rather coarse).
Since most of the points I check are inside, I mostly need a test which determines if a point is for sure inside.
Long question short:
I need an algorithm which can test very fast, whether a point is inside/outside the convex hull or not.
The algorihm is allowed to report "inside", "no idea" and "outside".

In order to quickly purge away points that are certified to be inside the convex hull you can reuse the points you found in your bounding box computation.
Namely, the 2k points (of dimension k) containing the min and max value in every dimension.
You can construct a small (2k constraints) linear programming problem and purge away any point that is within the convex hull of these 2k points.
You can do this both for the query points and for the original point cloud, which will leave you with a smaller linear programming problem to solve for the remaining points.

Related

Efficient convex hull around rectangles (and checking if a point lies within the hull)

Is there an optimized way to get the convex hull, if I know my points are always arranged into two rectangles?
I programmed the classic convex hull algorithm (just by enumerating all points), but since I have a bunch of pairs of rectangles I was wandering if there might be a more efficient way to do it for this special case.
This is what I am talking about, to clarify:
I tried sorting the points in various ways, but I just cannot find a general rule to optimize it. Is the basic convex hull algorithm the most efficient way to do this case also?
Update
To clarify my final goal, I have ~100 rectangles already grouped into pairs of two, and thousands of points for which I have to check whether they lie within each of these convex hulls, in real time. Now that I've given some thought to it, I guess the convex hull part won't be the bottleneck in the entire operation (but there is still ~100 of them, and I am aiming for realtime 60fps processing), so I might as well use a plain ol' algorithm as #BartKiers suggested and then get back to this after profiling.
I will leave the question open for a while, perhaps someone has an idea for an optimization which might be useful anyway.
If I am right, you can enumerate all relevant configurations by noting that if the left side of a rectangle is more to the left than the left side of the other, then its two left vertices are on the convex hull.
With the same reasoning in the four cardinal directions, there are 16 distinct cases that you can hard-code.
Another way to look at it is to observe that the convex hull is the tightest bounding box of the two rectangles, with 0, 2 or 4 corners "cut off". Finding the bounding box is trivial, and you decide if a corner is to be cut when it does not belong to any of the rectangles.
You easily derive a point inclusion test from this rule. If you already have a bounding box test, it suffices to add the corner tests.

Bulk containment queries

I have a convex shape defined by a set of vertices. I also have a large set of points and I would like to test which are contained in the convex shape. Currently I just use an open source linear programming solver for each point independently with a constant objective function. See chapter 11.4 of http://www.stanford.edu/~boyd/cvxbook/bv_cvxbook.pdf for more details.
However this is quite slow even in 100 dimensions. Is there a way to use the fact that all the query points are known in advance to speed the process up?
edit Fixed typo in question.
My suggestion would be to find the convex hull of the points inside the shape. I can't immediately think of a way to get this directly from an LP solver, but you can find the point nearest to a given hyperplane of the shape by adding a linear term for that hyperplane to the objective function. Repeat this for all edges of the shape, and for each edge repeat it several times, eliminating the most recent solution each time to pick up increasingly distant contained points. This should give you a number of points "close" to and inside the hyperplane.
Once you have the hull, you should then be able to classify all other points as being inside or outside it relatively quickly. I'm sure there are algorithms to do this fairly quickly, though I'm not aware of any. One potentially useful method that could get rid of a lot of internal points would be: if the space is n-dimensional, pick n+1 points on the hull and test every point to see whether it's a convex combination of these points (using linear algebra).

Calculation of centroid & volume of a polyhedron when the vertices are given

Given the location of vertices of a convex polyhedron (3D), I need to calculate the centroid and volume of the polyhedron. Following code is available at Mathworks site.
function C = centroid(P)
k=convhulln(P);
if length(unique(k(:)))<size(P,1)
error('Polyhedron is not convex.');
end
T = delaunayn(P);
n = size(T,1);
W = zeros(n,1);
C=0;
for m = 1:n
sp = P(T(m,:),:);
[null,W(m)]=convhulln(sp);
C = C + W(m) * mean(sp);
end
C=C./sum(W);
return
end
The code is elegant but is terribly slow. I need to calculate the volume and centroid of thousands of polyhedrons hundreds of times. Using this code in its current state is not feasible. Does anyone know a better approach or can this code be made faster? There are some minor changes I can think of such as, replacing mean with expression for mean.
There is a much simpler approach to calculate the volume with minimal effort. The first flavour uses 3 local topological information sets of the polyhedron, the tangent unit vector of the edges, the unit vectors of the in-plane normal on this tangent and the unit vector of the facet itself (which are very simple to extract from the vertices). Please refer to Volume of a Polyhedron for further details.
The second flavour uses the face areas, the normal vectors and the face barycenters to calculate the polyhedron volume according to this Wikipedia Article.
Both algorithms are rather simple and very easy to implement and through the simple summing structure easy to vectorize too. I suppose that both approaches will be much faster than doing a fully fledged tesselation of the polyhedron.
The centroid of the polyhedron can then be calculated by applying the divergence theorem transferring the integration over the full polyhedron volume into an integration over the polyhedron surface. A detailed description can be found in Calculating the volume and centroid of a polyhedron in 3d. I did not check if the tesselation of the polyhedron into triangles is really necessary or one could work with the more complex polygon surfaces of the polyhedron too, but in any case the area tessellation of the faces is much simpler than the volume tesselation.
In total such a combined approach should be much faster than the volume approach.
Thinking your only option if quickhull isn't good enough is cudahull if you want exact solutions. Although, even then you're only going to get about a 40x increase max (it seems).
I'm assuming that your the convex hulls you make each have at least 10 vertices (if it's much less than that, there isn't much you can do). If you don't mind "close enough" solutions. You could create a version of quickhull that limits the number the of vertices per polygon. The number of vertices you limit the calculation to will also allow for calculation of maximum error if needed.
The thing is that as the number of vertices on the convex hull approach infinity, you end up with a sphere. This means due to the way quick hull works, each additional vertex you add to the convex hull has less of an effect* than the ones before it.
*Depending on how quickhull is coded, this may only be true in a general sense. Making this true in practice would require modifying quickhull's recursion algorithm, so while the "next vertex" is always calculated (except for after the last vertex is added, or no points remain for that section), vertices are actually added to the convex hull in the order that maximizes the increase to the polyhedrons volume (likely by order of most distant to least distant). You'll incur some performance cost for keeping track of the order to add vertex's but as long as the ratio of pending convex hull points vs pending points is high enough, it should be worth it. As for error, the best option is probably to stop the algorithm either when the actual convex hull is reached, or the max increase to volume gets smaller than a certain fraction of the current total volume. If performance is more important, then simply limit the number of convex hull points per polygon.
You could also look at the various approximate convex hull algorithms, but the method I outlined above should work well for volume/centroid approximation with ability to determine error.
How much you can speed up your code depends a lot on how you want to calculate your centroid. See this answer about centroid calculation for your options. It turns out that if you need the centroid of the solid polyhedron, you're basically out of luck. If, however, only the vertices of the polyhedron have weight, then you could simply write
[k,volume] = convhulln(P);
centroid = mean(P(k,:));

polygon union without holes

Im looking for some fairly easy (I know polygon union is NOT an easy operation but maybe someone could point me in the right direction with a relativly easy one) algorithm on merging two intersecting polygons. Polygons could be concave without holes and also output polygon should not have holes in it. Polygons are represented in counter-clockwise manner. What I mean is presented on a picture. As you can see even if there is a hole in union of polygons I dont need it in the output. Input polygons are for sure without holes. I think without holes it should be easier to do but still I dont have an idea.
Remove all the vertices of the polygons which lie inside the other polygon: http://paulbourke.net/geometry/insidepoly/
Pick a starting point that is guaranteed to be in the union polygon (one of the extremes would work)
Trace through the polygon's edges in counter-clockwise fashion. These are points in your union. Trace until you hit an intersection (note that an edge may intersect with more than one edge of the other polygon).
Find the first intersection (if there are more than one). This is a point in your Union.
Go back to step 3 with the other polygon. The next point should be the point that makes the greatest angle with the previous edge.
You can proceed as below:
First, add to your set of points all the points of intersection of your polygons.
Then I would proceed like graham scan algorithm but with one more constraint.
Instead of selecting the point that makes the highest angle with the previous line (have a look at graham scan to see what I mean (*), chose the one with the highest angle that was part of one of the previous polygon.
You will get an envellope (not convex) that will describe your shape.
Note:
It's similar to finding the convex hull of your points.
For example graham scan algorithm will help you find the convex hull of the set of points in O (N*ln (N) where N is the number of points.
Look up for convex hull algorithms, and you can find some ideas.
Remarques:
(*)From wikipedia:
The first step in this algorithm is to find the point with the lowest
y-coordinate. If the lowest y-coordinate exists in more than one point
in the set, the point with the lowest x-coordinate out of the
candidates should be chosen. Call this point P. This step takes O(n),
where n is the number of points in question.
Next, the set of points must be sorted in increasing order of the
angle they and the point P make with the x-axis. Any general-purpose
sorting algorithm is appropriate for this, for example heapsort (which
is O(n log n)). In order to speed up the calculations, it is not
necessary to calculate the actual angle these points make with the
x-axis; instead, it suffices to calculate the cosine of this angle: it
is a monotonically decreasing function in the domain in question
(which is 0 to 180 degrees, due to the first step) and may be
calculated with simple arithmetic.
In the convex hull algorithm you chose the point of the angle that makes the largest angle with the previous side.
To "stick" with your previous polygon, just add the constraint that you must select a side that previously existed.
And you take off the constraint of having angle less than 180°
I don't have a full answer but I'm about to embark on a similar problem. I think there are two step which are fairly important. First would be to find a point on some polygon which lies on the outside edge. Second would be to make a list of bounding boxes for all the vertices and see which of these overlap. This means when you iterate through vertices, you don't have to do tests for all of them, only those which you know have a chance of intersecting (bounding box problems are lightweight).
Since you now have an outside point, you can now iterate through connected points until you detect an intersection. If you know which side is inside and which outside (you may need to do some work on the first vertex to know this), you know which way to go on the intersection. Then it's merely a matter of switching polygons.
This gets a little more interesting if you want to maintain that hole (which I do) in which case, I would probably make sure I had used up all my intersecting bounding boxes. You also didn't specify what should happen if your polygons don't intersect at all. But that's either going to be leave them alone (which could potentially be a problem if you're expecting one polygon out) or return an error.

Largest triangle from a set of points [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How to find largest triangle in convex hull aside from brute force search
I have a set of random points from which i want to find the largest triangle by area who's verticies are each on one of those points.
So far I have figured out that the largest triangle's verticies will only lie on the outside points of the cloud of points (or the convex hull) so i have programmed a function to do just that (using Graham scan in nlogn time).
However that's where I'm stuck. The only way I can figure out how to find the largest triangle from these points is to use brute force at n^3 time which is still acceptable in an average case as the convex hull algorithm usually kicks out the vast majority of points. However in a worst case scenario where points are on a circle, this method would fail miserably.
Dose anyone know an algorithm to do this more efficiently?
Note: I know that CGAL has this algorithm there but they do not go into any details on how its done. I don't want to use libraries, i want to learn this and program it myself (and also allow me to tweak it to exactly the way i want it to operate, just like the graham scan in which other implementations pick up collinear points that i don't want).
Don't know if this help, but if you choose two points from the convex hull and rotate all points of the hull so that the connecting line of the two points is parallel to the x-Axis, either the point with the maximum or the one with the minimum y-coordinate forms the triangle with the largest area together with the two points chosen first.
Of course once you have tested one point for all possible base lines, you can remove it from the list.
Here's a thought on how to get it down to O(n2 log n). I don't really know anything about computational geometry, so I'll mark it community wiki; please feel free to improve on this.
Preprocess the convex hull by finding for each point the range of slopes of lines through that point such that the set lies completely on one side of the line. Then invert this relationship: construct an interval tree for slopes with points in leaf nodes, such that when querying with a slope you find the points such that there is a tangent through those points.
If there are no sets of three or more collinear points on the convex hull, there are at most four points for each slope (two on each side), but in case of collinear points we can just ignore the intermediate points.
Now, iterate through all pairs of points (P,Q) on the convex hull. We want to find the point R such that triangle PQR has maximum area. Taking PQ as the base of the triangle, we want to maximize the height by finding R as far away from the line PQ as possible. The line through R parallel to PQ must be such that all points lie on one side of the line, so we can find a bounded number of candidates in time O(log n) using the preconstructed interval tree.
To improve this further in practice, do branch-and-bound in the set of pairs of points: find an upper bound for the height of any triangle (e.g. the maximum distance between two points), and discard any pair of points whose distance multiplied by this upper bound is less than the largest triangle found so far.
I think the rotating calipers method may apply here.
Off the top of my head, perhaps you could do something involving gridding/splitting the collection of points up into groups? Maybe... separating the points into three groups (not sure what the best way to do that in this case would be, though), doing something to discard those points in each group that are closer to the other two groups than other points in the same group, and then using the remaining points to find the largest triangle that can be made having one vertex in each group? This would actually make the case of all points being on a circle a lot simpler, because you'd just focus on the points that are near the center of the arcs contained within each group, as those would be the ones in each group furthest from the other two groups.
I'm not sure if this would give you the proper result for certain triangles/distributions of points, though. There may be situations where the resultant triangle isn't of optimal area, either because the grouping and/or the vertex choosing aren't/isn't optimal. Something like that.
Anyway, those are my thoughts on the problem. I hope I've at least been able to give you ideas for how to work on it.
How about dropping a point at a time from the convex hull? Starting with the convex hull, calculate the area of the triangle formed by each triple of adjacent points (p1p2p3, p2p3p4, etc.). Find the triangle with minimum area, then drop the middle of the three points that formed that triangle. (In other words, if the smallest area triangle is p3p4p5, drop P4.) Now you have a convex polygon with N-1 points. Repeat the same procedure until you are left with three points. This should take O(N^2) time.
I would not be at all surprised if there is some pathological case where this doesn't work, but I expect that it would work for the majority of cases. (In other words, I haven't proven this, and I have no source to cite.)

Resources