To take a simple example, say there is 2 bounding boxes (not necessarily axis aligned), each defined by 6 planes.
Is there a good way to determine if the volumes defined by each set of planes overlap?
(Only true/false, no need for the intersecting volume).
A solution to this problem, if its general should be able to scale up to many sets of planes too.
So far the solutions I've come up with basically rely on converting each set of planes into geometry - (vertices & polygons), then performing the intersection as you would if you have to intersect any 2 regular meshes. However I was wondering if there was a more elegant method that doesn't rely on this.
The intersection volume (if any) is the set of all points on the right side of all planes (combined, from both volumes). So, if you can select 3 planes whose intersection is on the right side of all the remaining planes, then the two volumes have an intersection.
This is a linear programming problem. In your case, you only need to find if there is a feasible solution or not; there are standard techniques for doing this.
You can determine the vertices of one of your bodies by mutually intersecting all possible triples that its planes form, and then check whether each of the resulting vertices lies on the good side of the planes defining the second body. When each of the second body's planes is given as base vertex p and normal v, this involves checking whether (x-p).v>=0 .
Assume that your planes are each given as base vertices (p,q,r) and normals (u,v,w) respectively, where the normals form the columns of a matrix M, the intersection is x = inv(M).(p.u, q.v, r.w).
Depending on how regular your two bodies are (e.g. parallelepipeds), many of the dot products and matrix inverses can be precomputed and reused. Perhaps you can share some of your prerequisites.
Posting this answer since this is one possible solution (just from thinking about the problem).
first calculate a point on each plane set (using 3 planes), and simply check if either of these points is inside the other plane-set.This covers cases where one volume is completely inside another, but won't work for partially overlapping volumes of course.
The following method can check for partial intersections.
for one of the sets, calculate the ray defined by each plane-plane pair.
clip the each of these rays by the other planes in the set, (storing a minimum and maximum value per ray).
discard any rays that have a minimum value greater then their maximum.The resulting rays represent all 'edges' for the volume.
So far all these calculations have been done on a single set of planes, so this information can be calculated once and stored for re-use.
Now continue clipping the rays but this time use the other set of planes, (again, discarding rays with a min greater then the maximum).
If there are one or more rays remaining, then there is an intersection.
Note 0): This isn't going to be efficient for any number of planes, (too many On^2 checks going on). In that case converting to polygons and then using more typical geometry tree structures makes more sense.
Note 1): Discarding rays can be done as the plane-pairs are iterated over to avoid first having to store all possible edges, only to discard many.
Note 2): Before clipping all rays with the second set of planes, a quick check could be made by doing a point-inside test between the plane-sets (the point can be calculated using a ray and its min/max). This will work if one shape is inside another, however clipping the rays is still needed for a final result.
I have a number of polygons each represented as a list of points. I'm looking for a fast algorithm to go through the list of polygons and uncross all of the crossed edges until no crossed edges remain.
Psudocode for current version:
While True:
For each pair of polygons:
for edge1 in first_polygon:
for edge2 in second_polygon:
if edges_cross(edge1,edge2): # Uses a line segment intersection test
uncross_edges(first_polygon,second_polygon,edge1,edge2)
If no edges have been uncrossed:
break
This can be improved a fair bit by replacing the while loop with recursion. However, it's still rather poor in terms of performance.
Below is a simple example of the untangling*. The there'll actually be a large number of polygons and a fair number of points per polygon (around 10-500). The red line shows which two edges are being uncrossed. The result should always be a series of planar graphs, although not sure if there are multiple valid outcomes or just one.
Edit: This time I added the lines first then added the points, and used a bit more complex of a shape. Pretend the points are fixed.
First, let us illustrate what you want (if I got it right). Suppose you have two polygons, one of them has an edge (a, b) which intersects with an edge (s, r) of the other one. These polygons also have a clock-wise orientation, so you know the next vertex after b, and the next vertex after r. Since the edges crosses, you remove them both, and add four new ones. The new ones you add are: (a, r), (r, next(b)); (s, b), (b, next(r)). So you again have two polygons. This is illustrated in the following figure. Note that by initially removing only two edges (one from each polygon), all the crossing were resolved.
Speeding the trivial implementation of O(n^2) per iteration is not entirely easy, and 500 points per polygon is a very small amount to be worried about. If you decide that you need to improve this time, my initial suggestion would be to use the Bentley-Otmann algorithm in some smart way. The smart way involves running the algorithm, then when you find an intersection, you do the procedure above to eliminate the intersection, and then you update the events that guide the algorithm. Hopefully, the events to be handled can be updated without rendering the algorithm useless for this situation, but I don't have a proof for that.
It seems that you want to end up with an embedded planar polygon whose vertices are exactly a given collection of points. The desired "order" on the points is what you get by going around the boundary of the polygon and enumerating the vertices in the order they appear.
For a given collection of points in general there will be more than one embedded polygon with this property; for an example, consider the following list of points:
(-1,-1), (0,0), (1,0), (1,1), (0,1)
This list defines a polygon meeting your criteria (if I understand it correctly). But so does the following ordering of this list:
(-1,-1), (1,0), (0,0), (1,1), (0,1)
Here is one algorithm that will work (I don't know about fast).
First, sort your points by x-coordinate (eg with quicksort) in increasing order (call this list L).
Second, find the convex hull (eg with quickhull); the boundary of the convex hull will contain the leftmost and rightmost points in the sorted list L (call these L[1] and L[n]); let S be the subset of points on the boundary between L[1] and L[n].
The list you want is S in the order it appears in L (which will also be the order it appears in the boundary of the convex hull) followed by the other elements L-S in the reverse of the order they appear in L.
The first two operations should usually take time O(n log n) (worst case O(n^2)); the last will take time O(n). The polygon you get will be the lower boundary of the convex hull (from left to right, say), together with the rest of the points in a "zigzag" above them going from right to left.
I have, as input, an arbitrary "formation", which is a list of rectangles, F:
And as another input, an unordered list of 2D points, P:
In this example, I consider P to match the formation F, because if P were to be rotated 45° counter-clockwise, each rectangle in F will be satisfied by containing a point. It would also be considered a match if there were an extraneous point in P which did not fall into a rectangle.
Neither the formation, nor point inputs, have any particular origin, and the scale between the two are not required to be the same, e.g., the formation could describe an area of a kilometer, and the input points could describe an area of a centimeter. And lastly, I need to know which point ended up in which node in the formation.
I'm trying to develop a general-purpose algorithm that satisfies all of these constraints. It will be executed millions of times per second against a large database of location information, so I'm trying to "fail out" as soon as I can.
I've considered taking the angles between all points in both inputs and comparing them, or calculating and comparing hulls, but every approach seems to fall apart with one of the constraints.
Points in the formation could also easily be represented as circles with an x,y origin and tolerance radius, and that seems to simplify the approaches I've tried so far. I'd appreciate any solid plan-of-attack or A-Ha! insights.
I've had another thought - using polar coordinates this time.
The description was getting complex/ambiguous, so here is some code that hopefully illustrates the idea.
The gist is to express the formations and points in terms of polar coordinates, with the origin in the center of the formation/point set. It then becomes a lot easier to find the rotation and scaling factors of the transform between points and formations. The translation component is trivially found by comparing the average of the point set and of the formation zone set.
Note that this approach will treat your formation zones not as squares or circles, but as sections of circle segments. Hopefully this is a fudge that you can live with.
It will also not return the exact scaling and rotation terms of a valid mapping transform. It will give you a mapping between formation zones and points, and a good approximation of the final rotation and scaling factors. This approximation could be very quickly refined into a valid solution via a simple relaxation scheme. It will also quickly disregard invalid point sets.
One approach would be to express the point sets and formations in relative coordinate systems.
For each point set and formation:
Identify the most mutually-distant pair of points, call them A and B
Identify the point farthest from the line through A and B, call it C. Ensure that C is on the left of the line AB - you may need to swap A and B to make this so.
Express the rest of the points in terms of A, B and C. This is a simple matter of finding the closest point D on the line through AB for each point, and scaling such that all distances are in terms of the distance between A and B. The distance from A to D is your relative x coordinate, and the distance from D to the point is the y.
For example, if you find that A and B are ten units apart, and that C is 5 units distant from the midpoint of AB, then the relative coordinates would be:
A: (0,0)
B: (1,0)
C: (0.5,0.5)
You can then compare the point sets and formations independently of the global coordinate system. Note that the distance tolerances to find a match also have to be scaled in terms of AB.
I can easily imagine problem formations for this approach, where the choices of A, B and C are difficult to make unambiguously, but it's a start.
I have an interesting problem here I've been trying to solve for the last little while:
I have 3 circles on a 2D xy plane, each with the same known radius. I know the coordinates of each of the three centers (they are arbitrary and can be anywhere).
What is the largest triangle that can be drawn such that each vertex of the triangle sits on a separate circle, what are the coordinates of those verticies?
I've been looking at this problem for hours and asked a bunch of people but so far only one person has been able to suggest a plausible solution (though I have no way of proving it).
The solution that we have come up with involves first creating a triangle about the three circle centers. Next we look at each circle individually and calculate the equation of a line that passes through the circle's center and is perpendicular to the opposite edge. We then calculate two intersection points of the circle. This is then done for the next two circles with a result of 6 points. We iterate over the 8 possible 3 point triangles that these 6 points create (the restriction is that each point of the big triangle must be on a separate circle) and find the maximum size.
The results look reasonable (at least when drawn out on paper) and it passes the special case of when the centers of the circles all fall on a straight line (gives a known largest triangle). Unfortunate i have no way of proving this is correct or not.
I'm wondering if anyone has encountered a problem similar to this and if so, how did you solve it?
Note: I understand that this is mostly a math question and not programming, however it is going to be implemented in code and it must be optimized to run very fast and efficient. In fact, I already have the above solution in code and tested to be working, if you would like to take a look, please let me know, i chose not to post it because its all in vector form and pretty much impossible to figure out exactly what is going on (because it's been condensed to be more efficient).
Lastly, yes this is for school work, though it is NOT a homework question/assignment/project. It's part of my graduate thesis (abet a very very small part, but still technically is part of it).
Thanks for your help.
Edit: Heres a new algorithm that i came up with a little while ago.
Starting at a circle's centre, draw a line to the other two centres. Calculate the line that bisects the angle created and calculate the intersections between the circle and the line that passes through the centre of your circle. You will get 2 results. Repeat this for the other two circles to get a total of 6 points. Iterate over these 6 points and get 8 possible solutions. Find the maximum of the 8 solutions.
This algorithm will deal with the collinear case if you draw your lines in one "direction" about the three points.
From the few random trials i have attempted using CAD software to figure out the geometries for me, this method seems to outperform all other methods previously stated However, it has already been proven to not be an optimal solution by one of Victor's counter examples.
I'll code this up tomorrow, for some reason I've lost remote access to my university computer and most things are on it.
I've taken the liberty of submitting a second answer, because my original answer referred to an online app that people could play with to get insight. The answer here is more a geometric argument.
The following diagram illuminates, I hope, what is going on. Much of this was inspired by #Federico Ramponi's observation that the largest triangle is characterized by the tangent at each vertex being parallel to the opposite side.
(source: brainjam.ca)
The picture was produced using a trial version of the excellent desktop program Geometry Expressions. The diagram shows the three circles centered at points A,E, and C. They have equal radii, but the picture doesn't really depend on the radii being equal, so the solution generalizes to circles of different radii. The lines MN, NO, and OM are tangent to the circles, and touch the circles at the points I,H, and G respectively. The latter points form the inner triangle IHG which is the triangle whose size we want to maximize.
There is also an exterior triangle MNO which is homethetic to the interior triangle, meaning that its sides are parallel to that of IHG.
#Federico observed that IHG has maximal area because moving any of its vertices along the corresponding circle will result an a triangle that has the same base but less height, therefore less area. To put it in slightly more technical terms, if the triangle is parameterized by angles t1,t2,t3 on the three circles (as pointed out by #Charles Stewart, and as used in my steepest descent canvas app), then the gradient of the area w.r.t to (t1,t2,t3) is (0,0,0), and the area is extremal (maximal in the diagram).
So how is this diagram computed? I'll admit in advance that I don't quite have the full story, but here's a start. Given the three circles, select a point M. Draw tangents to the circles centered at E and C, and designate the tangent points as G and I. Draw a tangent OHN to the circle centered at A that is parallel to GI. These are fairly straightforward operations both algebraically and geometrically.
But we aren't finished. So far we only have the condition that OHN is parallel to GI. We have no guarantee that MGO is parallel to IH or that MIN is parallel to GH. So we have to go back and refine M. In an interactive geometry program it's no big deal to set this up and then move M until the latter parallel conditions are met (by eyeballs, anyways). Geometry Expressions created the diagram, but I used a bit of a cheat to get it to do so, because its constraint solver was apparently not powerful enough to do the job. The algebraic expressions for G, I, and H are reasonably straightforward, so it should be possible to solve for M based on the fact that MIHG is a parallelogram, either explicitly or numerically.
I should point out that in general if you follow the construction starting from M, you have two choices of tangent for each circle, and therefore eight possible solutions. As in the other attempted answers to the question, unless you have a good heuristic to help you choose in advance which of the tangents to compute, you should probably compute all eight possible triangles and find the one with maximum area. The other seven will be extremal in the sense of being minimal area or saddle points.
That's it. This answer is not quite complete in that it leaves the final computation of M somewhat open ended. But it's reduced to either a 2D search space or the solution of an ornery but not humongous equation.
Finally, I have to disagree with #Federico's conclusion that this confirms that the solution proposed by the OP is optimal. It's true that if you draw perpendiculars from the circle centers to the opposite edge of the inner triangle, those perpendiculars intersect the circle to give you the triangle vertex. E.g. H lies on the line through A perpendicular to GI), but this is not the same as in the original proposed solution (which was to take the line through A and perpendicular to EC - in general EC is not parallel to GI).
I've created an HTML5 canvas app that may be useful for people to play with. It's pretty basic (and the code is not beautiful), but it lets you move three circles of equal radius, and then calculates a maximal triangle using gradient/steepest descent. You can also save bitmaps of the diagram. The diagram also shows the triangle whose vertices are the circle centers, and one of the altitudes. Edit1: the "altitude" is really just a line segment through one of the circle centers and perpendicular to the opposite edge of the triangle joining the centers. It's there because some of the suggested constructions use it. Edit2: the steepest descent method sometimes gets stuck in a local maximum. You can get out of that maximum by moving a circle until the black triangle flips and then bringing the circle back to its original position. Working on how to find the global maximum.
This won't work in IE because it doesn't support canvas, but most other "modern" browsers should work.
I did this partially because I found some of the arguments on this page questionable, and partially because I've never programmed a steepest descent and wanted to see how that worked. Anyways, I hope this helps, and I hope to weigh in with some more comments later.
Edit: I've looked at the geometry a little more and have written up my findings in a separate answer.
Let A, B, C be the vertexes of your triangle, and suppose they are placed as in your solution.
Notice that the key property of your construction is that each of the vertexes lies on a tangent to its circle which is parallel to the opposite side of the triangle. Obviously, the circle itself lies entirely on one side of the tangent, and in the optimal solution each tangent leaves its circle on the same side as the other vertexes.
Consider AB as the "base" of the triangle, and let C float in its circle. If you move C to another position C' within the circle, you will obtain another triangle ABC' with the same base but a smaller height, hence also with a smaller area:
figure 1 http://control.ee.ethz.ch/~ramponif/stuff/circles1.png
For the same reason, you can easily see that any position of the vertexes that doesn't follow your construction cannot be optimal. Suppose, for instance, that each one of the vertexes A', B', C' does not lie on a tangent parallel to the side connecting the other two.
Then, constructing the tangent to the circle that contains (say) C', which is parallel to A'B' and leaves the circle on the same side as A'B', and moving C' to the point of tangency C, it is always possible to construct a triangle A'B'C which has the same base, but a greater height, hence also a greater area:
figure 2 http://control.ee.ethz.ch/~ramponif/stuff/circles2.png
Since any triangle that does not follow your construction cannot be optimal, I do believe that your construction is optimal. In the case when the centers of the circles are aligned I'm a bit confused, but I guess that it is possible to prove optimality along the same lines.
I believe this is a convex optimization problem (no it's not, see below), and hence can be solved efficiently using well known methods.
You essentially want to solve the problem:
maximize: area(v1,v2,v3) ~ |cross((v2-v1), (v3-v1))|
such that: v1 in C1, v2 in C2, v3 in C3 (i.e., v_i-c_i)^2 - r_i^2 <= 0)
Each of the constraints are convex, and the area function is convex as well. Now, I don't know if there is a more efficient formulation, but you can at least use an interior point method with derivatives since the derivative of the area with respect to each vertex position can be worked out analytically (I have it written down somewhere...).
Edit: grad(area(v1,v2,v3))(v_i) = rot90(vec(vj,vk)), where vec(a,b) is making a 2D vector starting at a and ending at b, and rot90 means a positive orientation rotation by 90 degrees, assuming (vi,vj,vk) was positively oriented.
Edit 2: The problem is not convex, as should be obvious considering the collinear case; two degenerate solutions is a sure sign of non-convexity. However, the configuration starting at the circle centers should be in the globally optimal local maximum.
Not optimal, works well when all three are not colinear:
I don't have a proof (and therefore don't know if it's guaranteed to be biggest). Maybe I'll work on one. But:
We have three circles with radius R with positions (from center) P0, P1, and P2. We wish to find the vertices of a triangle such that the area of the triangle is maximum, and the vertices lie on any point of the circles edges.
Find the center of all the circles and call that C. Then C = (P0 + P1 + P2) / 3. Then we find the point on each circle farthest from C.
Find vectors V0, V1, and V2, where Vi = Pi - C. Then find points Q0, Q1, and Q2, where Qi = norm(Vi) * R + Pi. Where norm indicates normalization of a vector, norm(V) = V / |V|.
Q0, Q1, and Q2 are the vertices of the triangle. I assume this is optimal because this is the farthest the vertices could be from each other. (I think.)
My first thought is that you should be able to find an analytic solution.
Then the equations of the circles are:
(x1-h1)^2 + (y1-k1)^2 = r^2
(x2-h2)^2 + (y2-k2)^2 = r^2
(x3-h3)^2 + (y3-k3)^2 = r^2
The vertices of your triangle are (x1, y1), (x2, y2), and (x3, y3). The side lengths of your triangle are
A = sqrt((x1-x2)^2 + (y1-y2)^2)
B = sqrt((x1-x3)^2 + (y1-y3)^2)
C = sqrt((x2-x3)^2 + (y2-y3)^2)
So the area of the triangle is (using Heron's formula)
S = (A+B+C)/2
area = sqrt(S(S-A)(S-B)(S-C))
So area is a function of 6 variables.
At this point I realize this is not a fruitful line of reasoning. This is more like something I'd drop into a simulated annealing system.
So my second thought is to choose the point on circle with centre A as follows: Construct line BC joining the centres of the other two circles, then construct the line AD that is perpendicular to BC and passes through A. One vertex of the triangle is the intersection of AD and circle with centre A. Likewise for the other vertices. I can't prove this but I think it gives different results than the simple "furthest from the centre of all the circles" method, and for some reason it feels better to me. I know, not very mathematical, but then I'm a programmer.
Let's assume the center of the circles to be C0,C1 and C2; and the radius R.
Since the area of a triangle is .5*base*height, let's first find the maximum base that can be constructed with the circles.
Base = Max {(|C0-C1|+2R),(|C1-C2|+2R,(|C2-C0|+2R}
Once the base length is determined between 2 circles, then we can find the farthest perpendicular point from the base line to the third circle. (product of the their slopes is -1)
For special cases such as circles aligned in a single line, we need to perform additional checks at the time of determining the base line.
It appears that finding the largest Apollonius circle for the three circles and then inscribing an equilateral triangle in that circle would be a solution. Proof left as an exercise ;).
EDIT
This method has issues for collinear circles like other solutions here, too and doesn't work.
Some initial thoughts.
Definition Call the sought-after triangle, the maximal triangle. Note that this might not be unique: if the circles all have the same centre, then there are infinitely many maximal triangles obtained by rotation around the center, and if the centres are colinear, then there will be two maximal triangles, each a mirror image of the other.
Definition Call the triangle (possibly, degenerately, either a point or a line) whose vertices are the centres of the circles the interior triangle.
Observation The solution can be expressed as three angles, indicating where on the circumference of each circle the triangle is to be found.
Observation Given two exterior vertices, we can determine a third vertex that gives the maximal area: draw the altitude of the triangle between the two exterior vertices and the centre of the other circle. This line intersects the circumference in two places; the further away point is the maximising choice of third vertex. (Fixed incorrect algorithm, Federico's argument can be adapted to show correctness of this observation)
Consequence The problem is reduced to from a problem in three angles to one in two.
Conjecture Imagine the diagram is a pinboard, with three pins at the three centres of the circles. Imagine also a closed loop of string of length equal to the perimiter of the interior triangle, plus the radius of a circle, and we place this loop around the pins. Take an imaginary pen and imaginarily draw the looping figure where the loop is always tight. I conjecture that the points of the maximal triangle will all lie on this looping figure, and that in the case where the interior triangle is not degenerate, the vertices of the maximal triangle will be the three points where the looping figure intersects one of the circle circumferences. Many counterexamples
More to follow when I can spare time to think about it.
This is just a thought, no proof or math to go along with the construction just yet. It requires that the circle centers not be colinear if the radii are the same for each circle. This restriction can be relaxed if the radii are different.
Construction:
(1) Construct a triangle such that each side of the triangle is tangent to two circles, and therefore, each circle has a tangent point on two sides of the triangle.
(2) Draw the chord between these two tangent points on each circle
(3) Find the point on the boundary of the circle on the extended ray starting at the circle's center through the midpoint of the chord. There should be one such point on each of the three circles.
(4) Connect them three points of (3) to fom a triangle.
At that point I don't know if it's the largest such triangle, but if you're looking for something approximate, this might be it.
Later: You might be able to find an approximate answer for the degenerate case by perturbing the "middle" circle slightly in a direction perpendicular to the line connecting the three circles.