Replacing Small Angles in a Polygon with Bigger Ones - algorithm

I have the vertex data of a 2D polygonal region that contains the position of each vertex. My task is to calculate the angles throughout the polygon and replace the vertices with small angles (let's say smaller than 120 degrees) with bigger ones. For example, if three points (ABC) make an angle of 90 degrees, I want to replace the middle point (B) with another one that makes 120 degrees with the other two points.
I want to know if I can write an algorithm to find a new position of the vertex B, given the x-y coordinates of A and C and the 120 degrees angle between ABC (I calculated the current angle so you don't need to write how to do that). Note that, I am not looking for a unique point (there is no unique point), just looking for an angle calculation to replace the point. If you know other methods to do this kind of replacements, they are welcome too.

You have a triangle ABC with B the "small" angle that you want to replace with a larger angle. Call the new location B'. Here is the construction. Let D be the midpoint of AC, i.e., D = (A+B)/2. You want to place B' on the segment BD.
Any location along BD will result in a larger angle at B', with an angle of 180 when B'=D.
Pick a parameter t in [0,1]. Then place B' = (1-t) B + t D.
Now, there is a flaw here (besides that pointed out by spug). It may be that moving B to B' causes AB'C to hit other
parts of the polygon, and so it is no longer simple. You'll have to decide whether you want to compute a t that is guaranteed not to cause self-intersection.

Related

Algorithm for bending a series of vertices at an arbitrary angle?

I am looking for some information on how to "bend" an arbitrary list of points/vertices similar to the bend modifier you can find in typical 3D modelling programs.
I want to provide a list of points, a rotation focal point, and a "final angle." For my purposes, I will always be saying "points at minimum y of the set will not change, points at maximum y will be rotated at the maximum angle, everything in between is interpolated."
Example Image of starting configuration and desired result, given a 90 degree rotation:
Can anyone suggest a resource that would explain how to go about this? I'm prepared to code it (C++) but I'm wracking my brain on a concept that would make this work. It would be easy to generate the vertices, but the application I'm writing this for takes in user-created content and needs to bend it.
(Edited to add: I don't need a miracle matrix or deep equation solution... if you say something like "for each vertex, do this" that's good enough to get the green checkmark)
Thanks!
You seem to be transforming a straight line to a circular arc, preserving distances between adjacent points.
So, if the point A is the one you want to hold constant, pick another point B to be the center of that circle. (The nearer B is to A, the more severe the bending.) Now for any point C you want to transform, break the vector C-B into the component parallel to A-B (call that component R) and the component perpendicular to it (call that k). The magnitude of R will be the radius of the circle you map C to, and you can transform the magnitude of 'k' into distance along that circle:
theta = |k|/|R|
C` = B + R cos(theta) + k|R|/|k| sin(theta)

Assistance on creating algorithm for creating box around arc

I am looking for some assistance on creating an algorithm that is able to calculate a bounding box for an arc. Typically, this would be a simple problem. However, I am required to have one of the edges of the box to be the line that connects the starting point and the ending point of the arc.
I am having difficulty in developing an algorithm that is able to compute the additional two points of the rectangle.
Here is a picture of what I am attempting to calculate:
The two purple dots, I need to develop an algorithm that will determine these two locations. The green dots are the known points that can be inputs. Additionally, I do know the radius and the center of the arc.
I would need the algorithm to handle the different cases for when line AB is vertical, has a + slope, and has a - slope.
I have been considering a few directions. For example, I know that the line through point E is parallel to line AB. Since it is parallel, that means they will have the same slopes and the line from point A to the purple point is perpendicular to this line. I can then consider the intersection point of the line through E and this perpendicular line.
This method seems messy because then I would need to consider the cases for when the slope of line AB is infinite and 0. I am wondering if there is some algorithm that could account for that automatically (or not even consider the slope at all for line AB)
You claim to know points A, B, C, D, E, and that the amplitude of the sustaining angle of the circular arc does not exceed 180° (semi circle).
Let P1, and P2, the two points that complement the bounding box - (in the drawing, P1 is the purple point above A, and P2 the one above B).
Using vectors:
E-C = vector perpendicular to segment AB', i/e subtract C from E; its magnitude is equal to the distance EC.
P1 = A + (E-C)
P2 = B + (E-C)
Bounding Box = Rectangle A, P1, P2, B
If you need a closer fit, you can replace vector (E-C) with vector (D-C) to place the bounding segment P1P2 tangent to D

Fast algorithm to calculate 3D ray / triangle edge intersections for a large number of triangles

I have a triangle ABC in 3D space and a ray in plane of the triangle given by starting point E (always inside or on the triangle's edge) and direction vector d.
The vertices A, B and C as well as E and d are given in 3D coordinates {x,y,z}.
I am looking for an algorithm to calculate the intersection of the ray with the triangle's edge P.
I can do 3 ray / line segment intersection tests for the 3 edges of the triangle but since I have to do this for a large number of triangles I am looking for a more efficient and faster algorithm.
What is the best way to do this?
Could Barycentric Coordinates help?
Could Barycentric Coordinates help?
It may. It depends a bit on how highly optimized your non-barycentric code is, but I'd say that using barycentric coordinates it's at least easier to write code which is both maintainable and performant.
As far as I can tell, your whole setup is essentially 2d, with both the point E and the direction d contained within the plane spanned by A,B,C. So you have
E = aE*A + bE*B + cE*C with aE+bE+cE=1
d = ad*A + bd*B + cd*C with ad+bd+cd=0
Now you have two subproblems:
How to obtain the barycentric coordinates efficiently
How to find the point of intersection
Let's start with the latter. You simply add to E as many multiples of d until the c coordinate becomes zero.
P = E - (cE/cd)*d
Depending on your setup, you might also be fine using homogeneous coordinates, in which case you could write this as P = cd*E - cE*d.
How do you turn x,y,z coordinates of d and E into barycentric a,b,c? Well, that's just a system of linear equations. You could use the inverse of the matrix formed by the vectors A,B,C. Again, if you are dealing with homogeneous coordinates, you can use the adjunct instead of the inverse.
Here is the homogeneous approach spelled out:
aE = (By*Cz-Bz*Cy)*Ex + (Bz*Cx-Bx*Cz)*Ey + (Bx*Cy-By*Cx)*Ez
bE = (Cy*Az-Cz*Ay)*Ex + (Cz*Ax-Cx*Az)*Ey + (Cx*Ay-Cy*Ax)*Ez
cE = (Ay*Bz-Az*By)*Ex + (Az*Bx-Ax*Bz)*Ey + (Ax*By-Ay*Bx)*Ez
ad = (By*Cz-Bz*Cy)*dx + (Bz*Cx-Bx*Cz)*dy + (Bx*Cy-By*Cx)*dz
bd = (Cy*Az-Cz*Ay)*dx + (Cz*Ax-Cx*Az)*dy + (Cx*Ay-Cy*Ax)*dz
cd = (Ay*Bz-Az*By)*dx + (Az*Bx-Ax*Bz)*dy + (Ax*By-Ay*Bx)*dz
aP = cd*aE - cE*ad
bP = cd*bE - cE*bd
Px = aP/(aP+bP)*Ax + bP/(aP+bP)*Bx
Py = aP/(aP+bP)*Ay + bP/(aP+bP)*By
Pz = aP/(aP+bP)*Az + bP/(aP+bP)*Bz
The first three lines convert E to barycentric coordinates, the next three lines d. Then we compute the barycentric coordinates of P, and turn these back into Cartesian coordinates. In that step we also dehomogenize them, i.e. divide by the sum of the barycentric coordinates.
On the whole, there is a considerable amount of code here. You can reduce the number of operations by moving common expressions to dedicated variables, particularly if your compiler doesn't do that for you. One benefit is that you won't need any divisions except for the final dehomogenization, i.e. the division by (a+b). If you compute 1/(a+b) once, you can make do with but a single division, which is good for performance.
The real benefit of the above code however is likely that you can do many nice things with the barycentric coordinates that you couldn't easily do with other coordinate systems. For example, if you want to check whether the ray hits the line AB on the line segment or somewhere outside the triangle, just check whether aP*bP > 0.
Time complexity is O(1)
It could potentially help.
In case we are talking about 3D and all your points lie on one plane. In cartesian coordinates you need to solve three linear systems to find intersection with three lines, and then determinate whether intersections lies on edge or not.
Or you need to find barycentric coordinates of two points on line. Point A(a1,a2,a3) = E and B(b1,b2,b3) = E+d. Equation of line is
Now you still need to solve three linear systems (where one of the mu = 0 and sum of the others = 1). But it will be 2x2 systems that easer to solve. And then check signes of found roots to detrerminate whether found point lies on edge or not.
Temporarily ignore the axis for which d has the smallest component, and treat the resulting 2D problem, just as we see on your illustration.
You can precompute the equation of the line of support of the ray, in the form ax + by + c = 0 (assuming z was ignored). Plug the coordinates of the three vertices in this expression, and the signs will tell you on what side of the line the vertices are.
The two intersections with the line occur on the edges having different signs at the endpoints.
Then, to determine which is the right edge, the sign of the angle between the ray and the third egde will do (if I am right);
When you know which edge, you can compute the parameter of the parametric equation of the side, which you can deduce from the previously computed signs. For instance, along the edge AB, t = Sb / (Sb - Sa). Also compute 1 - t;
Finally, use the t value to interpolate between the endpoints, this time in 3D.
The computational cost is
evalutation of the three signs Sa, Sb, Sc, taking 6 + and 6 x;
selection of the two edge candidates, taking two or three comparisons;
selection of the single candidate, taking a 2D cross product, 3 + and 2 x and a comparison;
computation of the interpolation parameter, 2 +, 1 /;
final 3D interpolation, 3 +, 6 x.
Will be hard to do shorter.
See the paper
Fast, minimum storage ray-triangle intersection,
by Tomas Möller and Ben Trombone,
in
Journal of Graphics Tools, 2(1):21–28, 1997.
See also this page.
The authors say:
One advantage of this method is that the plane equation need not be computed on the fly nor be stored, which can amount to significant memory savings for triangle meshes. As we found our method to be comparable in speed to previous methods, we believe it is the fastest ray-triangle intersection routine for triangles that do not have precomputed plane equations.

How to find a ray that intersects a polygon minimum times?

Let P be a simple, but not necessarily convex, polygon and q an arbitrary
point not necessarily in P.
Design an efficient algorithm to find a line segment originating from q that intersects the minimum number of edges of P.
If q is your point in the space of 2D, we can write q(x,y). We know that a polyhedron have the edges(E), vertices(V) and faces(F) which all of this terms are related with the formula V - E + F = 2 from the Euler's theorem but the problem turns out to be easier since it is for a polygon.
So the plain is to find an edge and calcule the direction vector of the point q(x,y) to the center of the edge, doing this (and if the polygon is convex) we are sure that this line segment will only goes through one edge of P.
The calculation will need a little of linear algebra, but it is not that difficult, for example:
1 - Find the distance from a line to a point (so we can find the closest edge to use in this problem):
2 - Also, a good idea would be to find the point on this line which is closest to (x0,y0) has coordinates:
Where the equation of the line is ax + by + c = 0 and the (x0,y0) is an arbitrary point not necessarily in P.
So, now we can find the point k(x,y) on the line that is closest to the initial point q(x0,y0), doing |q-k| = d. Where d is the distance that we just calculate. After that you already have everything that you need to find a line segment originating from q that intersects the minimum number of edges of P.
Some places where you can study and find more about this topic:
Wiki
mathwords
Think of doing this on a map, so you can think of directions like North, South, East, West, and bearings.
If you have a ray going in a particular direction from q out to infinity, whether it intersects a line between points A and B depends only on the bearing of the ray, and the bearings from q to A and B: if the bearing of the ray is within the range spanned by the bearing from q to A and the bearing from q to B, taking this in the direction of the line, then the ray will intersect the line.
So you can reduce this to a simpler problem. Imagine that all the points are in a circle around q, and the lines are arcs of this circle. Now you need to find a point on this circle which is overlapped by the minimum number of arcs. You will also make life very much easier if you divide each arc that spans 0 degrees into two at 0, cutting e.g. an arc from 320 degrees round to 40 degrees into one from 320 degrees to 360=0 degrees, and one from 0 degrees to 40 degrees.
Good candidate points for this are points just clockwise of each point in the circle. Now order each arc so that it is from a low angle to a high angle, sort the arcs by low angle, and work through them in order, incrementing a counter when you see the start of an arc, and decrementing it when you see the end of an arc (you don't need to worry about arcs that wrap across 0=360 degrees because you have just made sure that there aren't any). The point you want to find is the one associated with the smallest value of the counter.
Taking q as the origin of the coordinates, compute the polar arguments of the vertices. This is done in linear time.
Then every edge spans an interval of angles. To handle the wraparound, you can split the intervals that cross the 360° border.
You turned the problem in an instance of 1D intervals overlap. This is readily solved in O(N Log(N)) time.

calculate the area of a polygon in ruby

I have an array of latitude/longitude coordinate pairs that represent a polygon. I'm trying to determine the total area within that polygon. How would I go about doing that in Ruby?
Here's an example array of the polygon:
[[37.7663613767094, -122.452969210084], [37.7674219449606, -122.444718340349], [37.7701838510542, -122.445330289514], [37.7709974013834, -122.439159589248], [37.7700761930893, -122.438861402472], [37.7703501163684, -122.436868738421], [37.7712650571321, -122.437078116573], [37.7736056746515, -122.437533130227], [37.7714671036087, -122.453964210266], [37.7663613767094, -122.452969210084]]
It probably doesn't matter that much on the language. You can make use of the formula mentioned in here for calculating the area of a polygon:
http://mathworld.wolfram.com/PolygonArea.html
Assuming your points are (x1, y1) (x2, y2) .. (xn, yn) and they enclose a small area:
Area = 0.5 * (x1 * y2 - x2 * y1 + x2 * y3 - x3 * y2 ..... + xn * y1 - x1 * yn)
Note: This won't work for larger areas, for which you need to use more complex method to calculate the area, which involves angular co-ordinates. But, this does the job for small areas, which can be assumed to be planar.
Edit:
To get area in sq miles, you can do the following, from there, convert to whatever units you want.
areaInSqMiles = Area * (60 * 60 * 1.15 * 1.15)
language independent solution:
GIVEN: a polygon can ALWAYS be composed by n-2 triangles that do not overlap (n = number of points OR sides). 1 triangle = 3 sided polygon = 1 triangle; 1 square = 4 sided polygon = 2 triangles; etc ad nauseam QED
therefore, a polygon can be reduced by "chopping off" triangles and the total area will be the sum of the areas of these triangles. try it with a piece of paper and scissors, it is best if you can visualize the process before following.
if you take any 3 consecutive points in a polygons path and create a triangle with these points, you will have one and only one of three possible scenarios:
resulting triangle is completely inside original polygon
resulting triangle is totally outside original polygon
resulting triangle is partially contained in original polygon
we are interested only in cases that fall in the first option (totally contained).
every time we find one of these, we chop it off, calculate its area (easy peasy, wont explain formula here) and make a new polygon with one less side (equivalent to polygon with this triangle chopped off). until we have only one triangle left.
how to implement this programatically:
create an array of points. run the array making triangles from points x, x+1 and x+2. transform each triangle from a shape to an area and intersect it with area created from polygon. IF the resulting intersection is identical to the original triangle, then said triangle is totally contained in polygon and can be chopped off. remove x+1 from the array and start again from x=0. otherwise, move to next point x+1 in array.
additionally if you are looking to integrate with mappping and are starting from geopoints, you must convert from geopoints to screenpoints. this requires deciding a modelling and formula for earths shape (though we tend to think of the earth as a sphere, it is actually an irregular ovoid (eggshape), with dents. there are many models out there, for further info wiki.
You can use this library which wraps GEOS (a C geospatial library itself a port of the JTS).
https://github.com/dark-panda/ffi-geos
This library can handle the calculations in coordinate space and takes care of the approximations.
Depending on how much accuracy you need I would project the data first to an appropriate projection (not Mercator). Then calculate your area
There is an awesome example on how to multiply verticies. Essentially exactly what you would like to do!!
http://www.wikihow.com/Calculate-the-Area-of-a-Polygon
Some techniques for this include integration (divide the polygon into latitudinal strips and integrate. You can also project onto a flat surface and calculate that area.

Resources