Draw arbitrary convex shape knowing the lengths of its sides - drawing

I've got a list of values, which are the lengths of the sides of an arbitrary convex shape (polygon).
How can I draw this shape? What algorithm can help me with this task?
For example, I have a list: 2, 5, 2, 3. The drawing has to look like this:

There is a relatively simple (if somewhat math heavy) O(N log N) to O(N^2) (depending on implementation) recursive geometry/trigonometry based solution to this.
The concept starts with a line segment with length equal to the sum of the lengths.
Break that line segment into a triangle (see related info near bottom).
Recursively break each edge of the triangle into more triangles as needed.
Step 2, requires ensuring that smaller two edges of the triangle are longer than the bigger one.
Step 3, can be done by turning a triangle into 2 triangles.
For the input and outputs I would use:
Input: List of edges
Output: list of interior angles.
So output[a] is the interior angle of the vertex either before after the edge at input[a].
A good reference is located here.
Method #1 gif, shows the triangles at for that many vertices.
Method #2 gif, P is an example of where the break might occur in step 2.
Method #4 gif, here P could be considered moved out like in #3, note that in this case, the line lengths would not be to scale and in fact would be unknown. Notice that only the vertex positions of a1 and a2 would change. Resulting in changes to the interior angles of the vertices before and after a1 and a2. In this case, a1,a2,a3,an,p.
As for determining the interior angles. Use trigonometry and/or geometry. Given 3 sides of a triangle, it's possible to determine what the angles are. Given 2 sides and an angle (or 1 angle and 2 sides) it's possible to determine the missing sides and angles.
Of course, you may have to be careful as to where you break the edge so a triangle can be formed.

I will quote here an answer I posted on MathOverflow:
A chain of edges can close iff the longest edge is not longer than the sum of the lengths of all the other edges.
In your example, the longest edge is 5, and it is not longer than 2+2+3=7.
If you replace the edge of length 5 by an edge of length 8, then the four segments
cannot close to a convex polygon.
Whenever you have more than 3 edges, the resulting convex polygon is not
uniquely determined: there is flexibility in its shape.
See the references cited above for pointers to proofs.

Related

I'm looking for an algorithm for finding the convex hull of a set of 3D points [duplicate]

Given a set of points S (x, y, z). How to find the convex hull of those points ?
I tried understanding the algorithm from here, but could not get much.
It says:
First project all of the points onto the xy-plane, and find an edge that is definitely on the hull by selecting the point with highest y-coordinate and then doing one iteration of gift wrapping to determine the other endpoint of the edge. This is the first part of the incomplete hull. We then build the hull iteratively. Consider this first edge; now find another point in order to form the first triangular face of the hull. We do this by picking the point such that all the other points lie to the right of this triangle, when viewed appropriately (just as in the gift-wrapping algorithm, in which we picked an edge such that all other points lay to the right of that edge). Now there are three edges in the hull; to continue, we pick one of them arbitrarily, and again scan through all the points to find another point to build a new triangle with this edge, and repeat this until there are no edges left. (When we create a new triangular face, we add two edges to the pool; however, we have to first check if they have already been added to the hull, in which case we ignore them.) There are O(n) faces, and each iteration takes O(n) time since we must scan all of the remaining points, giving O(n2).
Can anyone explain it in a more clearer way or suggest a simpler alternative approach.
Implementing the 3D convex hull is not easy, but many algorithms have been implemented, and code is widely available. At the high end of quality and time investment to use is CGAL. At the lower end on both measures is my own C code:
In between there is code all over the web, including this implementation of QuickHull.
I would suggest first try an easier approach like quick hull. (Btw, the order for gift wrapping is O(nh) not O(n2), where h is points on hull and order of quick hull is O(n log n)).
Under average circumstances quick hull works quite well, but processing usually becomes slow in cases of high symmetry or points lying on the circumference of a circle. Quick hull can be broken down to the following steps:
Find the points with minimum and maximum x coordinates, those are
bound to be part of the convex.
Use the line formed by the two points to divide the set in two
subsets of points, which will be processed recursively.
Determine the point, on one side of the line, with the maximum
distance from the line. The two points found before along with this
one form a triangle.
The points lying inside of that triangle cannot be part of the
convex hull and can therefore be ignored in the next steps.
Repeat the previous two steps on the two lines formed by the
triangle (not the initial line).
Keep on doing so on until no more points are left, the recursion has
come to an end and the points selected constitute the convex hull.
See this impementaion and explanation for 3d convex hull using quick hull algorithm.
Gift wrapping algorithm:
Jarvis's match algorithm is like wrapping a piece of string around the points. It starts by computing the leftmost point l, since we know that the left most point must be a convex hull vertex.This process will take linear time.Then the algorithm does a series of pivoting steps to find each successive convex hull vertex untill the next vertex is the original leftmost point again.
The algorithm find the successive convex hull vertex like this: the vertex immediately following a point p is the point that appears to be furthest to the right to someone standing at p and looking at the other points. In other words, if q is the vertex following p, and r is any other input point, then the triple p, q, r is in counter-clockwise order. We can find each successive vertex in linear time by performing a series of O(n) counter-clockwise tests.
Since the algorithm spends O(n) time for each convex hull vertex, the worst-case running time is O(n2). However, if the convex hull has very few vertices, Jarvis's march is extremely fast. A better way to write the running time is O(nh), where h is the number of convex hull vertices. In the worst case, h = n, and we get our old O(n2) time bound, but in the best case h = 3, and the algorithm only needs O(n) time. This is a so called output-sensitive algorithm, the smaller the output, the faster the algorithm.
The following image should give you more idea
GPL C++ code for finding 3D convex hulls is available at http://www.newtonapples.net/code/NewtonAppleWrapper_11Feb2016.tar.gz and a description of the O(n log(n)) algorithm at http://www.newtonapples.net/NewtonAppleWrapper.html
One of the simplest algorithms for convex hull computation in 3D was presented in the paper The QuickHull algorithm for Convex Hulls by Barber, etc from 1995. Unfortunately the original paper lacks any figures to simplify its understanding.
The algorithm works iteratively by storing boundary faces of some convex set with the vertices from the subset of original points. The remaining points are divided on the ones already inside the current convex set and the points outside it. And each step consists in enlarging the convex set by including one of outside points in it until no one remains.
The authors propose to start the algorithm in 3D from any tetrahedron with 4 vertices in original points. If these vertices are selected so that they are on the boundary of convex hull then it will accelerate the algorithm (they will not be removed from boundary during the following steps). Also the algorithm can start from the boundary surface containing just 2 oppositely oriented triangles with 3 vertices in original points. Such points can be selected as follows.
The first point has with the minimal (x,y,z) coordinates, if compare coordinates lexicographically.
The second point is the most distant from the first one.
The third point is the most distant from the line through the first two points.
The next figure presents initial points and the starting 2 oppositely oriented triangles:
The remaining points are subdivided in two sets:
Black points - above the plane containing the triangles - are associated with the triangle having normal oriented upward.
Red points - below the plane containing the triangles - are associated with the triangle having normal oriented downward.
On the following steps, the algorithm always associates each point currently outside the convex set with one of the boundary triangles that is "visible" from the point (point is within positive half-space of that triangle). More precisely each outside point is associated with the triangle, for which the distance between the point and the plane containing the triangle is the largest.
On each step of algorithm the furthest outside point is selected, then all faces of the current convex set visible from it are identified, these faces are removed from the convex set and replaced with the triangles having one vertex in furthest point and two other points on the horizon ridge (boundary of removed visible faces).
On the next figure the furthest point is pointed by green arrow and three visible triangles are highlighted in red:
Visible triangles deleted, back faces and inside points can be seen in the hole, horizon ridge is shown with red color:
5 new triangles (joining at the added point) patch the hole in the surface:
The points previously associated with the removed triangles are either become inner for the updated convex set or redistributed among new triangles.
The last figure also presents the final result of convex hull computation without any remaining outside points. (The figures were prepared in MeshInspector application, having this algorithm implemented.)

The search for a set of points with a minimum sum of lengths to rectangles. What is the algorithm?

Good day.
I have the task of finding the set of points in 2D space for which the sum of the distances to the rectangles is minimal. For example, for two rectangles, the result will be the next area (picture). Any point in this area has the minimum sum of lengths to A and B rectangles.
Which algorithm is suitable for finding a region, all points of which have the minimum sum of lengths? The number of rectangles can be different, they are randomly located. They can even overlap each other. The sides of the rectangles are parallel to the coordinate axes and cannot be rotated. The region must be either a rectangle or a line or a point.
Hint:
The distance map of a rectangle (function that maps any point (x,y) to the closest distance to the rectangle) is made of four slanted planes (slope 45°), four quarter of cones and the rectangle itself, which is at ground level, forming a continuous surface.
To obtain the global distance map, it "suffices" to sum the distance maps of the individual rectangles. A pretty complex surface will result. Depending on the geometries, the minimum might be achieved on a single vertex, a whole edge or a whole face.
The construction of the global map seems more difficult than that of a line arrangement, due to the conic patches. A very difficult problem in the general case, though the axis-aligned constraint might ease it.
Add on Yves's answer.
As Yves described, each rectangle 'divide' plane into 9 parts and adds different distance method in to the sum. Middle part (rectangle) add distance 0, side parts add coordinate distance to that side, corner parts add point distance to that corner. With that approach plan has to be divided into 9^n parts, and distance sum is calculated by adding appropriate rectangle distance functions. That is feasible if number of rectangles is not too large.
Probably it is not needed to calculate all parts since it is easy to calculate some bound on part min value and check is it needed to calculate part at all.
I am not sure, but it seems to me that global distance map is convex function. If that is the case than it can be solved iteratively by similar idea as in linear programming.

How to distinguish between an inbound and an outbound edge of a polygon?

The basics of Weiler-Atherton Polygon Clipping algorithm are:
Start from the first edge which is going inside the clipping area.
When an edge of a candidate/subject polygon enters the clipping area, save the intersection point.
When an edge of a candidate/subject polygon exits the clipping area, save the intersection point and follow the clipping polygon.
How to distinguish between an inbound and an outbound edge of a polygon?
It seems like finding inbound edges invole another huge algorithm and thereby affects the efficiency of the algorithm.
Another question is, how can I find the first inbound intersection?
This answer seems to be shedding some light on the problem. But, sadly it doesn't work.
For example, if I reverse the direction of vectors, the angle is not negated.
https://www.wolframalpha.com/input/?i=angle+between+vector+%7B0%2C180%7D+%7B180%2C0%7D
https://www.wolframalpha.com/input/?i=angle+between+vector+%7B0%2C180%7D+%7B-180%2C0%7D
First, a reminder that the Weiler–Atherton algorithm uses polygons defined by vertices in a specific order, clockwise. In short, you test for edges going in or out by traversing the polygon clockwise. The first edge going in (and therefore the first inbound intersection) is simply the first edge you traverse which started outside the clipping area (see below).
Also, the algorithm is typically run in two phases. First find all intersections, these are added to a list of vertices for your polygons, inserted at the correct position. During this phase you would typically mark whether each vertex is within the other polygon. For the second phase, traverse the vertices to determine clipping polygons.
Lets try some examples. Take a triangle defined by vertices A,B,C, and a rectangle w,x,y,z. The triangle will be the clipping area, rectangle is the subject.
The list of points we have generated for the subject is therefore w,x,R,Q,y,z. The triangle list is now A,B,Q,C,R.
Starting at w, R is the first intersection, it is inbound because the previous point (x) is outside. The traversal of the area will be R,Q,C, and back to R(done).
The intersections are unlabeled here, but they will still be R and Q. The list of points we have generated for the subject is therefore w,x,R,y,Q,z. The triangle list is now A,B,C,Q,R.
The clipping traversal is R,y,Q, and R(done)
Let P and Q be two polygons. One can pick any vertex v of P in order to determine the position of v with respect to Q (i.e inside or outside it) via the ray casting algorithm (or any other algorithm that suits all the requirements of the problem).
You only need to determine the position of one such vertex v of P with respect to Q in this manner because the position of the other vertices of P can be inferred by iterating over the ordered set of vertices and intersection points of P.
Lets say v is outside Q. Then, by iterating over the ordered set of vertices and intersection points of P, the first intersection point one finds is laying on an entering edge. If v is inside Q, the first intersection point one finds is laying on an exiting edge. Keep in mind that one edge can be both entering and exiting, depending on the number of intersection points laying on it.
The idea behind the ray casting algorithm is simple, but one should pick vertex v of P if |V(P)|>=|V(Q)| and v of Q otherwise (in order to lower the impact the ray casting algorithm has on the overall performance, though not significantly).
You do not necessarily need to start at the first inbound intersection, this is fine when you are looking at the polygons drawn on a piece of paper and can drop your pen wherever you want, but as you noted would require more effort to find when coding it.
You just need to make sure you get all the intersections calculated for your two polygons first walking around the source polygons line segments checking for intersections with the clipping polygons line segments. At this point it does not matter whether it is inside or outside.
Once you have all the intersections and your two polygons points in order (I think I had two lists that could link to each other), walk around your source polygon point by point. If your first source polygon point is inside the clip polygon that is the first point of your solution polygon, if not the first point of your solution polygon is the first intersection with the clip polygon.
Once you have your first solution point each point from there is the next solution point. As you hit intersections you switch to the other polygon and carry on until you return back to your first solution point.
It has been a while since I have coded this, but if I remember correctly points that can catch you out are when polygons are entirely inside each other (in which case the contained one is your solution) and make sure you are prepared for more than one solution polygon if you have some odd polygon shapes.

How to render a circle with as few vertices as possible?

I'm trying to figure out how to decide how many vertices I need to have to make my circle look as smooth as possible.
Here is an example of two circles, both having 24 vertices:
As you see, the bigger the circle becomes, the more vertices I need to hide the straight lines.
At first I thought that the minimum length of one line on the edge should be 6px, but that approach failed when I increased the circle size: I got way too many vertices. I also thought about calculating the angles, but I quickly realised that angles doesn't differ on different sized circles. I also checked this answer, but I don't have a clue how to convert it into code (and some weird stuff there: th uses itself for calculating itself), and I think it doesn't even work, since the author is using the angle from one slice to the middle of circle, which doesn't change if the circle gets larger.
Then I realised that maybe the solution is to check the angle between two vertices at the edges, in this way:
As you see, the fewer vertices, the bigger the lengths are for those triangles. So this has to be the answer, I just don't know how to calculate the number of vertices by using this information.
The answer you link to actually implements exactly the idea you propose at the end of your question.
The decisive formula that you need from that answer is this one:
th = arccos(2 * (1 - e / r)^2 - 1)
This tells you the angle between two vertices, where r is the radius of the circle and e is the maximum error you're willing to tolerate, i.e. the maximum deviation of your polygon from the circle -- this is the error marked in your diagram. For example, you might choose to set e to 0.5 of a pixel.
Because th is measured in radians, and 360 degrees (a full circle) is equal to 2*pi in radians, the number of vertices you need is
num_vertices = ceil(2*pi/th)
In case you want to draw the polygon triangles from the center of the circle, the formula for the required number of sides is:
sides = PI / arccos(1 - error / radius)
where error is the maximum deviation of polygon from the circle, in pixels and radius is also expressed in pixels.
Error 0.33 seems to produce results indistinguishable from an ideal circle. Circles drawn at error 0.5, on close inspection still show some subtly visible angles between sides, especially visible in small circles.
This function obviously breaks down when radius is much smaller than error, and may produce NaN values. You may want to use a special case (for example draw 3 sides) in this situation.
The graph below shows number of sides obtained from the function, with error set to 0.33:
First of all, if you are using OpenGL or DirectX you can significantly decrease the number of vertices by using a triangle fan structure.
As for the problem of the amount of vertices, I would imagine the number of vertices required for a smooth circle to scale with the circumference. This scales with r, so I would advice to find a good factor A such that:
#vertices = A * r
The angles are the same in the two cases of 24 vertices.
But with larger circle, the human eye is able to better see the individual straight lines.
So you need some heuristic that takes into account
the angle between two consecutive line segments in the curve, and
the size, and possibly
the scaling for display.
The third point is difficult since one does not in general know the size at which some graphic will be displayed. E.g., an SVG format picture can be displayed at any size. The most general solution, I think, is to have direct support for various figures (Bezier lines, circles, etc.) in the renderer, and then define the figure with a few parameters instead of as a sequence of points. Or, define it in terms of some figure that the renderer supports, e.g. as a sequence of connected Bezier curves. That way, the renderer can add the necessary number of points to make it look smooth and nice.
However, I guess that you're not creating a renderer, so then perhaps only the first two points above are relevant.

Collision detection between two general hexahedrons

I have 2 six faced solids. The only guarantee is that they each have 8 vertex3f's (verticies with x,y and z components). Given this, how can I find out if these are colliding?
I'm hesitant to answer after you deleted your last question while I was trying to answer it and made me lose my post. Please don't do that again. Anyway:
Not necessarily optimal, but obviously correct, based on constructive solid geometry:
Represent the two solids each as an intersection of 6 half-spaces. Note that this depends on convexity but nothing else, and extends to solids with more sides. My preferred representation for halfspaces is to choose a point on each surface (for example, a vertex) and the outward-pointing unit normal vector to that surface.
Intersect the two solids by treating all 12 half-spaces as the defining half-spaces for a new solid. (This step is purely conceptual and might not involve any actual code.)
Compute the surface/edge representation of the new solid and check that it's non-empty. One approach to doing this is to initially populate your surface/edge representation with one surface for each of the 12 half-spaces with edges outside the bounds of the 2 solids, then intersect its edges with each of the remaining 11 half-spaces.
It sounds like a bit of work, but there's nothing complicated. Only dot products, cross products (to get the initial representation), and projections.
It seems I'm too dumb to quit.
Consider this. If any edge of solid 1 intersects any face of solid 2, you have a collision. That's not quite comprehensive because there are case when one is is fully contained in the other, which you can test by determining if the center of either is contained in the other.
Checking edge face intersection works like this.
Define the edge as vector starting from one vertex running to the other. Take note of the length, L, of the edge.
Define the plane segments by a vertex, a normal, an in-plane basis, and the positions of the remaining vertices in that basis.
Find the intersection of the line and the plane. In the usual formulation you will be able to get both the length along the line, and the in-plane coordinates of the intersection in the basis that you have chosen.
The intersection must line as length [0,L], and must lie inside the figure in the plane. That last part is a little harder, but has a well known general solution.
This will work. For eloquence, I rather prefer R..'s solution. If you need speed...well, you'll just have to try them and see.
Suppose one of your hexahedrons H1 has vertices (x_1, y_1, z_1), (x_2, y_2, z_2), .... Find the maximum and minimum in each coordinate: x_min = min(x_1, x_2, ...), x_max = max(x_1, x_2,...), and so on. Do the same for the other hexahedron H2.
If the interval [x_min(H1), x_max(H1)] and the interval [x_min(H2), x_max(H2)] do not intersect (that is, either x_max(H1) < x_min(H2) or x_max(H2) < x_min(H1)), then the hexahedrons cannot possibly collide. Repeat this for the y and z coordinates. Qualitatively, this is like looking at the shadow of each hexahedron on the x-axis. If they don't overlap, the polyhedrons can't collide.
If any of the intervals do overlap, you'll have to move on to more precise collision detection. This will be a lot trickier. The obvious brute force method is to check if any of the edges of one intersects any of the faces of the other, but I imagine you can do a lot better than that.
The brute force way to check if an edge intersects a face... First you'd find the intersection of the line defined by the edge with the plane defined by the face (see wikipedia, for example). Then you have to check if that point is actually on the edge and the face. The edge is easy - just see if the coordinates are between the coordinates of the two vertices defining the edge. The face is trickier, especially with no guarantees about it being convex. In the general case, you'll have to just see which side of the half-planes defined by each edge it's on. If it's on the inside half-plane for all of them, it's inside the face. I unfortunately don't have time to type that all up now, but I bet googling could aid you some there. But of course, this is all brute force, and there may be a better way. (And dmckee points out a special case that this doesn't handle)