polygon triangulation reflex vertex - computational-geometry

Hi i am trying to perform polygon triangulation. I understood the ear clipping method for a simple Polygon ( Concave or Convex ). i am stuck at finding whether a vertex is reflex or not . what i have read at multiple places is about clock-wise and counter clockwise orientations which i am unable to understand . in short what are those orientations referring to and please give me some hint on checking whether the vertex is reflex or not .
here is the link of an article i am following:
and here is formula they have used:
// Input
VECTOR a, b, c; // the parts of our triangle.
// if (b.x - a.x) * (c.y - b.y) - (c.x - b.x) * (b.y - a.y) > 0
// we are counter-clockwise
whats the point here i am unable to comprehend.

Your input polygon is in most cases a list of consecutive vertices, they represent your polygon in counter clockwise order. That means when walking along the boundary of the polygon (if without holes) the interior of it should be to the left of every edge traversed. If one wants to know if a single vertex is convex or reflex (convex meaning internal angle smaller than 180°, reflex otherwise) then there are several methods. The most commonly used is to apply the determinate. The determinate gives us as result greater zero if the vertices form a left turn, which means that three consecutive vertices a,b, and c form a convex angle at b; and less than zero otherwise. Now the formula: (b.x - a.x) * (c.y - b.y) - (c.x - b.x) * (b.y - a.y) > 0 does exactly that. It transforms the three vertices into two direction vectors: b-a and c-b then the determinate of this is already the given formula and tells us if a left or right turn occurs on b.
Edit, due to the question in the comment:
Let us choose a=(2 1), b=(5 4), and c=(3 6). Thus, the orientation as shown on the right picture is given by s=b-a=(3 3) and t=c-b=(-2 2). Now det(s t) gives us s.x*t.y - t.x*s.y = 3*2 - (-2)*3 = 12 > 0. Therefore, if we stand at point a and we walk to b, we have to take a left turn to get to c.

Related

Finding the length of 3 rectangles so that they share one corner to form a triangle, given a common width and 3 points

Hi sorry for the confusing title.
I'm trying to make a race track using points. I want to draw 3 rectangles which form my roads. However I don't want these rectangles to overlap, I want to leave an empty space between them to place my corners (triangles) meaning they only intersect at a single point. Since the roads have a common width I know the width of the rectangles.
I know the coordinates of the points A, B and C and therefore their length and the angles between them. From this I think I can say that the angles of the yellow triangle are the same as those of the outer triangle. From there I can work out the lengths of the sides of the blue triangles. However I don't know how to find the coordinates of the points of the blue triangles or the length of the sides of the yellow triangle and therefore the rectangles.
This is an X-Y problem (asking us how to accomplish X because you think it would help you solve a problem Y better solved another way), but luckily you gave us Y so I can just answer that.
What you should do is find the lines that are the edges of the roads, figure out where they intersect, and proceed to calculate everything else from that.
First, given 2 points P and Q, we can write down the line between them in parameterized form as f(t) = P + t(Q - P). Note that Q - P = v is the vector representing the direction of the line.
Second, given a vector v = (x_v, y_v) the vector (y_v, -x_v) is at right angles to it. Divide by its length sqrt(x_v**2 + y_v**2) and you have a unit vector at right angles to the first. Project P and Q a distance d along this vector, and you've got 2 points on a parallel line at distance d from your original line.
There are two such parallel lines. Given a point on the line and a point off of the line, the sign of the dot product of your normal vector with the vector between those two lines tells you whether you've found the parallel line on the same side as the other, or on the opposite side.
You just need to figure out where they intersect. But figuring out where lines P1 + t*v1 and P2 + s*v2 intersect can be done by setting up 2 equations in 2 variables and solving that. Which calculation you can carry out.
And now you have sufficient information to calculate the edges of the roads, which edges are inside, and every intersection in your diagram. Which lets you figure out anything else that you need.
Slightly different approach with a bit of trigonometry:
Define vectors
b = B - A
c = C - A
uB = Normalized(b)
uC = Normalized(c)
angle
Alpha = atan2(CrossProduct(b, c), DotProduct(b,c))
HalfA = Alpha / 2
HalfW = Width / 2
uB_Perp = (-uB.Y, ub.X) //unit vector, perpendicular to b
//now calculate points:
P1 = A + HalfW * (uB * ctg(HalfA) + uB_Perp) //outer blue triangle vertice
P2 = A + HalfW * (uB * ctg(HalfA) - uB_Perp) //inner blue triangle vertice, lies on bisector
(I did not consider extra case of too large width)

How to do Ray and Triangle Edge intersect?

I'm facing problem intersecting ray with triangle edges. Actually, I'm trying to pick/intersect with triangle, vertex, edge of a mesh using Mouse. So I made ray from the Mouse current position and then I intersect it with the mesh elements like triangle/polygon, vertex, edge etc to work with it. Basically, 3d modeling stuffs. Intersecting with triangle was easy and fun. And the vertex part was tricky.
But now, I don't know how to intersect/pick with triangle edges. I mean how I treat them when intersecting with the Mouse Ray? First I thought they can be treated like a 3D line. But eventually failed to do the Ray and the Line intersect. Searched on the Internet but not found any helpful info. Although I found some open source projects are using OpenGL built-in picking features to pick/intersect with Edge. But in my case, I can't use that. :(
My current edge picking code structure looks like the following:
void pickEdge(Ray ray, Scene scene)
{
for each object in scene
{
mesh = getMesh(object)
for each triangle in mesh
{
for each edge in triangle
{
v1 = getV1(edge)
v2 = getV2(edge)
// Do intersect with 'ray' and 'v1', 'v2'. But how?
}
}
}
}
So I'm stuck here and really need some help. Any idea, algorithm or a small help is greatly appreciated.
In your case problem of finding intersection between triangle and ray in 3D space can be boiled down to finding point location (INSIDE, OUTSIDE, ON BOUNDARY) in triangle in 2D space (plane). All you should do is project triangle on screen plane, find intersection on edge and perform reverse projection on edge. Position of point is position of mouse. The only problem is to treat degenerate cases like mapping triangle into line segment. But I think it will not be problem, because such cases can be easily coped.
Please give a look to the algorithms at the end of this page and more in general all the ones that this website offers: http://geomalgorithms.com/a05-_intersect-1.html
The first approach is to orthogonally project the edge (and the ray) to a plane perpendicular to the ray, and then to compute the distance of the projected ray to the projected edge.
Ie., first you determine two orthogonal vectors rdir1, rdir2 orthogonal to your ray.
Then you calculate the projection of your ray (its base point) to this plane, which will simply yield a 2d point rp.
Then you project the edge to that plane, by simply applying dot products:
pv1 = new Vector2(DotProduct(v1, rdir1), DotProduct(v1, rdir2))
pv2 = new Vector2(DotProduct(v2, rdir1), DotProduct(v2, rdir2))
Now you can compute the distance from this 2d line pv1, pv2 to the point rp.
Provided that the direction of the edge is taken from the view matrix's "forward" direction, then two vectors orthogonal to that would be the view matrix's left and right vectors.
Doing the above recipe will then yield something similar to projecting the edge to the screen. Hence, alternatively you could project the edge to the screen and work with those coordinates.
First of all, what is the distance between two geometric objects A and B ? It is the minimal distance between any two points on A and B, ie. dist(A,B) = min { EuclideanLength(x - y) | x in A, y in B}. (If it exists and is unique, which it does in your case.)
Here EuclideanLength((x,y,z)) = sqrt(x^2 + y^2 + z^2) as you already know. Because sqrt is strictly increasing it suffices to minimize SquareEuclideanLength((x,y,z)) = x^2 + y^2 + z^2, which greatly simplifies the problem.
In your question the objects are a line segment A := {v1 + t*(v2-v1) | 0 <= t <= 1} and a line B := {p + s*d | s is any real number}. (Don't worry that you asked about a ray, a line is really what you want.)
Now calculating the distance comes down to finding appropriate t and s such that SquareEuclideanLength(v1 + t*(v2-v1) - p - s*d) is minimal and then computing EuclideanLength(v1 + t*(v2-v1) - p - s*d) to get the real distance.
To solve this we need some analytic geometry. Because d is not zero, we can write each vector v as a sum of a part that is orthogonal to d and a part that is a multiple of d: v = Ov + Mv. For such an "orthogonal decomposition" it always holds SquareEuclideanLength(v) = SquareEuclideanLength(Ov) + SquareEuclideanLength(Mv).
Because of d = Md in the above
SquareEuclideanLength(v1 + t*(v2-v1) - p - s*d) =
SquareEuclideanLength(Ov1 + t*(Ov2-Ov1) - Op)
+ SquareEuclideanLength(Mv1 + t*(Mv2-Mv1) - Mp - s*d)
the left addend does not depend on s and however you chose t you can find an s such that the right addend is 0 ! (Remember that Mv1, Mv2, ... are multiples of d.)
Hence to find the minimum you just have to find such maps O, M as above and find the minimizer t.
Assuming that d is normalized, these are actually given by Ov := CrossProduct(v, d) and Mv := DotProduct(v, d)*d, but just believe me, that this also works if d is not normalized.
So the recipe for finding the distance is now: find 0 <= t <= 1 that minimizes
SquareEuclideanLength(Cross(v1 - p, d) + t*Cross(v2 - v1, d))
= SquareEuclideanLength(Cross(v1 - p, d))
+ 2*t*Dot(Cross(v1 - p, d), Cross(v2 - v1, d))
+ t^2 SquareEuclideanLength(Cross(v2 - v1, d)).
You will already know this formula from Point-Line distance calculation (that's what it is) and it is solved by differentiating with respect to t and equalling 0.
So the minimizer of this equation is
t = -Dot(Cross(v1 - p, d), Cross(v2 - v1, d))/SquareEuclideanLength(Cross(v2 - v1, d))
Using this t you calculate v1 + t*(v2 - v1), the point on the line segment A that is closest to line B and you can plug this into your point-line distance algorithm to find the sought after distance.
I hope this helps you !

How do I calculate the area of a non-convex polygon?

Assuming that the polygon does not self-intersect, what would be the most efficient way to do this? The polygon has N vertices.
I know that it can be calculated with the coordinates but is there another general way?
The signed area, A(T), of the triangle T = ((x1, y1), (x2, y2), (x3, y3)) is defined to be 1/2 times the determinant of the following matrix:
|x1 y1 1|
|x2 y2 1|
|x3 y3 1|
The determinant is -y1*x2 + x1*y2 + y1*x3 - y2*x3 - x1*y3 + x2*y3.
Given a polygon (convex or concave) defined by the vertices p[0], p[1], ..., p[N - 1], you can compute the area of the polygon as follows.
area = 0
for i in [0, N - 2]:
area += A((0, 0), p[i], p[i + 1])
area += A((0, 0), p[N - 1], p[0])
area = abs(area)
Using the expression for the determinant above, you can compute A((0, 0), p, q) efficiently as 0.5 * (-p.y*q.x + p.x*q.y). A further improvement is to do the multiplication by 0.5 only once:
area = 0
for i in [0, N - 2]:
area += -p[i].y * p[i+1].x + p[i].x * p[i+1].y
area += -p[N-1].y * p[0].x + p[N-1].x * p[0].y
area = 0.5 * abs(area)
This is a linear time algorithm, and it is trivial to parallelize. Note also that it is an exact algorithm when the coordinates of your vertices are all integer-valued.
Link to Wikipedia article on this algorithm
The best way to approach this problem that I can think of is to consider the polygon as several triangles, find their areas separately, and sum them for the total area. All polygons, regular, or irregular, are essentially just a bunch of triangle (cut a quadrilateral diagonally to make two triangles, a pentagon in two cuts from one corner to the two most opposite ones, and the pattern continues on). This is quite simple to put to code.
A general algorithm for this can be coded as follows:
function polygonArea(Xcoords, Ycoords) {
numPoints = len(Xcoords)
area = 0; // Accumulates area in the loop
j = numPoints-1; // The last vertex is the 'previous' one to the first
for (i=0; i<numPoints; i++)
{ area = area + (Xcoords[j]+Xcoords[i]) * (Ycoords[j]-Ycoords[i]);
j = i; //j is previous vertex to i
}
return area/2;
}
Xcoords and Ycoords are arrays, where Xcoords stores the X coordinates, and Ycoords the Y coordinates.
The algorithm iteratively constructs the triangles from previous vertices.
I modified this from the algorithm provided Here by Math Open Ref
It should be relatively painless to adapt this to whatever form you are storing your coordinates in, and whatever language you are using for your project.
The "Tear one ear at a time" algorithm works, provided the triangle you remove does not contain "holes" (other vertices of the polygon).
That is, you need to choose the green triangle below, not the red one:
However, it is always possible to do so (Can't prove it mathematically right now, but you'l have to trust me). You just need to walk the polygon's vertices and perform some inclusion tests until you find a suitable triple.
Source: I once implemented a triangulation of arbitrary, non-intersecting polygons based on what I read in Computational Geometry in C by Joseph O'Rourke.
Take 3 consecutive points from the polygon.
Calculate the area of the resulting triangle.
Remove the middle of the 3 points from the polygon.
Do a test to see if the removed point is inside the remaining polygon or not. If it's inside subtract the triangle area from the total, otherwise add it.
Repeat until the polygon consists of a single triangle, and add that triangle's area to the total.
Edit: to solve the problem given by #NicolasMiari simply make two passes, on the first pass only process the vertices that are inside the remainder polygon, on the second pass process the remainder.

Merging two overlapping rectangles into the resulting polygon

I am looking for an algorithm that, given two rectangles that overlap partially or totally, finds the ordered list of vertexes that defines the polygon representing the sum of the two rectangles.
To be more specific:
I have as input two ordered list of points, representing the two rectangles
I know how to find the vertexes of the resulting polygon, which is formed by the vertexes of each rectangle which are outside the other rectangle, plus the intersection points between each edge of one rectangle with each edge of the other
I don't currently know how to order into an array the points, obtained as explained above, so that the element j and j+1 of the array represents the two vertexes of the same edge (this is what I mean by ordered list of vertexes).
Thanks in advance for any help
UPDATE :
I found a way to sort vertexes to obtain a polygon, as follows:
compute the vertexes centroid ( coords average )
sort the vertexes by the angle formed between the segment from the centroid and the vertex and any reference line passing by the centroid (e.g. the X axis ).
However, although I consistently obtain a polygon enclosing the two rectangles, without holes or intersecting edges, it is not always the polygon I want ( sometimes it includes extra area not belonging to one of the input rectangles ).
So I'm going back to the solution pointed in one of the comments, which is also described here:
polygon union without holes
Once you have the 4 vertices, you merely find the farther point using the distance formula (since it seems we can't make the assumption of a collinear or unrotated beginning rects)
So if you have points a = (xA, yA), b, c, d and you know these 4 points make a rectangle
float dist(Point a, Point b){
float dx = a.x - b.x;
float dy = a.y - b.y;
return Math.sqrt(dx * dx + dy * dy);
}
//somewhere else, where u need it
//put point A into index 0
Point curFarthest = b;
float distance = dist(a, b);
if (dist(a, c) > distance){
curFarther = c;
distance = dist(a, c);
} else if (dist(a, d) > distance){
curFarther = d;
curFarthest = dist(a, d);
}
//store curFarthest into index 2
// store the rest (exculding points a and curFarthest)
// into index 1 and 3 in no particular order
I am working on the same problem but I use a different approach(work still in progress).
Find the intersection points.
Distance of each point(vertices) with its neighboring connected points.
Using Dinics Algorithm find the Maxmimum flow.
Note: there will be a few special cases. But then again my problems revolves around polygons having 1 common point(vertice).

Diagonal of polygon is inside or outside?

I have three consecutive points of polygon, say p1,p2,p3. Now I wanted to know whether the orthogonal between p1 and p3 is inside the polygon or outside the polygon.
I am doing it by taking three vectors v1,v2 and v3. And the point before the point p1 in polygon say p0.
v1 = (p0 - p1)
v2 = (p2 - p1)
v3 = (p3 - p1)
With reference to this question, I am using the method shown in the accepted answer of that question. It is only for counterclockwise. What if my points are clockwise.
I am also knowing my whole polygon is clockwise or counterclockwise. And accordingly I select the vectors v1 and v2. But still I am getting some problem. I am showing one case where I am getting problem.
This polygon is counterclockwise. and It is starting from the origin of v1 and v2.
Since your points are cnosecutive, you can solve this problem by checking the orientation of the triangle p1 p2 p3. If the orientation is the same as the one of the polygon, then the diagonal is in the inside, else on the outside.
To determine the orientation of the triangle, the simplest way is to compute the signed area and check the sign. Compute
p1.x * p2.y + p2.x * p3.y + p3.x * p1.y - p2.x * p1.y - p3.x * p2.y - p1.x * p3.y
If the sign of this value is positive, the orientation is counterclockwise. If the sign is negative, the orientation is clockwise.
To be precise, the above method only gives you information on which side of the polygon the diagonal lies. Obviously, the polygon can still intersect the diagonal at later points.
Basically, a diagonal can be fully inside, fully outside, both inside and outside, and possibly overlapping one or more edges in all three cases. This makes it not entirely trivial to determine what you need.
From a mathematical side, there is actually not that much difference between the inside and the outside, except for such small details as the outside having infinite area. (At least for a 2D plane; on a sphere the inside and outside of a plygon are not sharply distinguished.)
You also have a subquestion about the ordering of your polygon edges. The easiest way is to sum all angles between adjacent edges in order. This will add up to N*(pi/2). For CCW polygons, N is positive.
[edit]
Once you know the direction, and if you have none of the hard cases listed above, the question is easy. The angle p0-p1-p2 is smaller than the angle p0-p1-p3. Hence, the edge p1-p3 lies at least partially outside the polygon. And if it crosses no other edge, it obviously lies fully outside the polygon.
Angle between any two vectors is
alpha = acos(v1.x * v2.x + v1.y * v2.y)
Since you now can have the angle between
v1 and v3 = alpha1; v1 and v2 = alpha2;
You can check if alpha2 is inside alpha1:
function normalize(a):
if a > 2 * pi then a - 2 * pi
else if a < 2 * pi then a + 2 * pi
else a
alpha1 = normalize(alpha1)
alpha2 = normalize(alpha2)
if (alpha2 < alpha1) then is_between
else is_not_between
This is not very complete, but you should get the idea.
EDIT: it won't work if the polygon is overlapping as MSalters noted.

Resources