Shift trace of polygon by given vector - algorithm

I need algorithm to get shift trace of given polygon by given 2d-vector.
Given valid polygon with no holes, but possibly concave.
Operation performs on plane, so the result might be a polygon, possibly with holes.
If it simplifies the task, outer polygon is enough.
It looks simple to describe, but I find it complex to realize, so I look for some ready solutions, preferably in c#.

Suppose you have a polygon P given by the points A1, A2, ... , An.
Now you decide to shift it by X on the x-axis and Y on the y-axis.
You can do this to each point individually to get the ending location of the polygon.
Let's call the shifted polygon Q givng by points B1, B2, ... , Bn.
Then all you need to do is draw the following parallelograms:
(A1 A2 B2 B1), (A2 A3 B3 B2), (A3 A4 B4 B3), ... , (An-1 An Bn Bn-1) , (An A1 B1 Bn)
At this point you will have filled in the shape you want.
Some of the parallelograms will overlap, but that is okay, since you are just filling them all in with the same red color.
By doing it this way, you also get your second example to turn out correctly, (the bottom right corner of the hole in the middle should be diagonal, because of the lip sliding into position).

Related

I am interested in drawing the solution for various ODEs and PDEs

How to draw the solution y=sinx+c for the ODE dy/dx = cosx?
I tried in excel but did not reach a solution.
I am new to this.
Please help
If you really want to do that in Microsoft Excel, then you can implement, for example, the Euler method for simplicity as follows:
B1 cell : initial value of y, for example, 0
B3 cell : initial value of x, for example, 0
B4 cell : step size, for example, 0.1, which should be sufficiently small
D1 cell : =$B$2
E1 cell : =$B$1
D2 cell : =D1+$B$3
E2 cell : =E1+COS(D1)*$B$3
Next, select the D2 cell and copy it to D3, D4, ... by dragging the fill handle, up to the point that you want to get. Then, select the E2 cell and copy it to E3, E4, ... by double-clicking the fill handle. This gives (x, y) data in D and E columns, and you can make a plot with them. The above initial values correspond to c=0 in your equation.

What algorithm can be used to detect gaps between polygons?

What algorithms are used to find gaps between adjacent polygons (example pictures show 2 adjacent polygons and a shaded 'gap' between them), and is there a common name for this type of operation? Polygons in my input may have coincident vertices, segments, both, or neither. Polygons are represented as ordered lists of points. Adjacent polygons are defined as having at least one coincident point or segment.
I am developing in Go (and have access to the GEOS library), but any references to algorithm steps or implementations in common languages would be helpful.
This might not be what you were looking for, but something like this might get the job done.
Suppose you can calculate a list of all points of intersection p1, p2, …, pk between the perimeters of the two polygons. Let v1, v2, …, vn be the vertices of the first polygon, and w1, w2, …, wm be the vertices of the second polygon.
First, create two ordered collections c1 and c2, where c1 contains p1, p2, …, pk and v1, v2, …, vn, in order (so that if going around the perimeter of the polygon in the clockwise direction, the vertices appear in the list in the order visited), and c2 contains p1, p2, … pk and w1, v2, …, vm ordered in the same way.
Now, between every two adjacent p(i%k) and p((i+1)%k) there is some overlap or gap. This overlap or gap may be degenerate iff the vertices appearing in c1 and c2 between these two points of intersection are the same; in this case, the polygon traced out has area zero and may be discarded. Otherwise, we must see whether the vertices in c1 and c2 appearing between the points of intersection define a gap or an overlap.
If we have an easy/cheap way of testing whether a point is contained within the original polygon, simply choose a point in the space (e.g., the center of the triangle formed by one of the points of intersection and each of the adjacent points in c1 and c2 is guaranteed to be inside the space) and see whether the point is included in either c1 or c2 (it cannot be in one and not the other; why?). If the point is included, then you have an overlap; otherwise, you have a gap.
Indeed, we do have an easy way. If we are going around the first polygon in clockwise order, then if the point identified above (the middle of the triangle so described) is to the right of the line segment formed by the point of intersection and the vertex in c1 adjacent to it, then it's an overlap; otherwise, it's a gap. Alternatively, you can go clockwise around the points in c2 and use the same rule to tell.
To see whether a point is to the left or right of a vector:
take the vector (e.g., the point of intersection to the adjacent point in either c1 or c2)
take the vector to the candidate point (e.g., the center of the triangle described earlier)
Compute the 3-dimensional cross product
The sign of the z-coordinate of the resulting vector gives the answer.
In this example:
p1, p2, p3 ~ (3.1, 5.5), (3.3, 4), (3.8, 2)
v1, v2, v3, v4, v5 ~ (1, 0), (1, 8), (4, 4.5), (2, 3), (3.8, 2)
w1, w2, w3, w4 ~ (4, 1), (3, 5), (4, 9), (9, 5)
c1 ~ (v1, v2, p1, v3, p2, v4, p3=v5)
c2 ~ (w1, p3, p2, w2, p1, w3, w4)
pairs of points of intersection adjacent in c1:
x1 = (p1, p2), x2 = (p2, p3), x3 = (p3, p1)
pairs of points of intersection adjacent in c2:
y1 = (p3, p2), y2 = (p2, p1), y3 = (p1, p3)
triangle for x1 has vertices (p1, v3, w2), middle is
~ ((3.1+4+3)/3, (5.5+4.5+5)/3) = (3.3, 5)
vector from p1 to v3 ~ (0.9, -1)
vector from p1 to middle of triangle ~ (0.2, -0.5)
cross product of p1-v3 x middle of triangle vector:
+0.9 -1.0 +0.0
+0.2 -0.5 +0.0
i j k
=> -0.45k
this has a negative sign, so this is an overlap
triangle for x2 has vertices (p2, v4, p3=v5), middle is
~ ((3.3+2+3.8)/3, (4+3+2)/3) = (3, 3)
vector from p2 to v4: (-1.3, -1)
vector from p2 to middle of triangle: (-0.3, -1)
cross product of p2-v4 and middle of triangle vector:
-1.3 -1.0 +0.0
-0.3 -1.0 +0.0
i j k
=> 1.3k
this has a positive sign, so this must be a gap

I'm implementing the Expanding Polytope Algorithm, and I am unsure how to deduce the contact points from a point on the minkowski difference

I've been reading about the EPA from several sources, but they all seem to abruptly stop being useful after the closest point on the minkowski difference to the origin is located. Most of them say something along the lines of "With this information, we can then generate the local and global contact points and contact tangents," but I don't understand how that is even possible, much less how to do it. I don't see how someone could derive the minuend and subtrahend from a difference alone, and certainly not in a reasonable amount of time. What is the standard solution to this problem?
I am looking to implement this algorithm in 3D, if that changes the answer. Thanks
OP of the blog post here.
The post actually says how to compute the contact point in step 8 of the EPA algorithm:
Project the origin onto the closest triangle. This is our closest
point to the origin on the CSO’s boundary. Compute the barycentric
coordinates of this closest point with respect to the vertices from
the closest triangle. The barycentric coordinates are coefficients of
linear combination of vertices from the closest triangle. Linearly
combining the individual support points (original results from
individual colliders) corresponding to the vertices from the closest
triangle, with the same barycentric coordinates as coefficients, gives
us contact points on both colliders in their own model space. We can
then convert these contact points to world space.
Allow me to rephrase it here.
Let Ca, Cb, and Cc denote the three vertices of the triangle of the CSO that contains the closest point, denoted Cp, on the CSO boundary to the origin.
Compute the barycentric coordinate (x, y, z) of the triangle for Cp.
x Ca + y Cb + z Cc = Cp
Note that it is required that we keep the original support function results in global space from the two objects (A & B) used to obtain Ca, Cb, and Cc. Let Aa, Ab, and Ac denote the original support function results for object A. Let Ba, Bb, and Bc denote the original support function results for object B.
Ca = Aa + Ba
Cb = Ab + Bb
Cc = Ac + Bc
Using the barycentric coordinate (x, y, z) obtained earlier to linearly combine the original support function results from object A & B, we can compute the contact points on both objects, denoted Ap and Bp:
Ap = x Aa + y Ab + z Ac
Bp = x Ba + y Bb + z Bc
I hope this clarifies the computation process for you.

Tetrahedron orientation for triangle meshes

I have 2 triangles and vertices p0, p1, p2, p3. These two triangle share an edge. From these two triangle I want to make a tetrahedron given by the 4 vertices. The library which I work with requires that "the 4 vertices should be given such that the four vertex triples defining the tetrahedron faces in the drawing appear in counter-clockwise order when being viewed at from the outside" . Assuming one of the two triangles is p0, p1, p2 I calculate the normal as being (p1-p0) (cross) (p2-p0). Can someone please tell me a way to ensure that this condition is met ?
Short answer:
The condition is that p3 must be on the correct side of the plane determined by (p0, p1, p2).
So, after computing the normal for this plane, you need to determine if the vector from (say) p0 to p3 is pointing in the same direction of the normal, or the opposite direction, by taking the dot product dot(normal, p3-p0).
More mathematically speaking:
You need to find the determinant of the 4x4 matrix formed by the homogeneous coordinates of the four points. The sign of the determinant determines if the condition is met; the appropriate sign depends on the exact conventions used, but ideally it should be positive:
require:
0 < det(p0, p1, p2, p3)
== det [ p0.x p0.y p0.z 1 ]
[ p1.x p1.y p1.z 1 ]
[ p2.x p2.y p2.z 1 ]
[ p3.x p3.y p3.z 1 ]
If a particular ordered set of points has a negative determinant, you can fix it by swapping any two of the points (which will negate the determinant):
e.g., swapping p0 and p2:
det(p0, p1, p2, p3) = - det(p2, p1, p0, p3)
^ ^ ^ ^
or, more generally, switching between even and odd permutations of the four vertices.
If the determinant is zero, the four points are co-planar, and cannot be fixed like this.
Finally, the code:
A relatively simple way to compute this determinant with 3-d vector math:
let: v1 = p1 - p0
v2 = p2 - p0
v3 = p3 - p0
norm12 = cross(v1, v2)
-> determinant = dot(norm12, v3)
The final determinant is also known as the "triple product" of v1, v2, and v3.
Note that I have hesitated to try to decode the exact sign convention (i.e., whether you need the determinant to be positive or negative) from your question: the wording and diagram you supply is more than a bit confusing.
Since you have the original library and its documentation, though, you are in the best position to answer this question. As a last resort, you can try the empirical method: try both signs, and pick the one that doesn't blow up...

Getting a list of locations within a triangle in the form of x,y positions

Let's say I have a triangle given by the three integer vertices (x1,y1), (x2,y2) and (x3,y3). What sort of algorithm can I use to return a comprehensive list of ALL (x,y) integer pairs that lie inside the triangle.
The proper name for this problem is triangle rasterization.
It's a well researched problem and there's variety of methods to do it. The two popular methods are:
Scan line by scan line.
For each scan-line you require some basic geometry to recalculate
the start and the end of the line. See Bresenham's Line drawing algorithm.
Test every pixel in the bounding box to see if it is in the
triangle.
This is usually done by using barycentric co-ordinates.
Most people assume method 1) is more efficient as you don't waste time testing pixels that can are outside the triangle, approximately half of all the pixels in the bounding box. However, 2) has a major advantage - it can be run in parallel far more easily and so for hardware is usually the much faster option. 2) is also simpler to code.
The original paper for describing exactly how to use method 2) is written by Juan Pineda in 1988 and is called "A Parallel Algorithm for Polygon Rasterization".
For triangles, it's conceptually very simple (if you learn barycentric co-ordindates). If you convert each pixel into triangle barycentric coordinates, alpha, beta and gamma - then the simple test is that alpha, beta and gamma must be between 0 and 1.
The following algorithm should be appropriate:
Sort the triangle vertices by x coordinate in increasing order. Now we have two segments (1-2 and 2-3) on the one side (top or bottom), and one segment from the other one (1-3).
Compute coefficients of equations of lines (which contain the segments):
A * x + B * y + C = 0
A = y2 - y1
B = x1 - x2
C = x2 * y1 - x1 * y2
There (x1, y1) and (x2, y2) are two points of the line.
For each of ranges [x1, x2), (x2, x3], and x2 (special case) iterate over integer points in ranges and do the following for every x:
Find top bound as y_top = (- A1 * x - C1) div B1.
Find bottom bound as y_bottom = (- A2 * y - C2 - 1) div B2 + 1.
Add all points between (x, y_bottom) and (x, y_top) to the result.
This algorithm is for not strictly internal vertices. For strictly internal vertices items 3.1 and 3.2 slightly differ.
I suppose you have a list of pairs you want to test (if this is not what your problem is about, please specify your question clearly). You should store the pairs into quad-tree or kd-tree structure first, in order to have a set of candidates which is small enough. If you have few points, this is probably not worth the hassle (but it won't scale well if you don't do it).
You can also narrow down candidates further by testing against a bounding box for your triangle.
Then, for each candidate pair (x, y), solve in a, b, c the system
a + b + c = 1
a x1 + b x2 + c x3 = x
a y2 + b y2 + c y3 = y
(I let you work this out), and the point is inside the triangle if a b and c are all positive.
I like ray casting, nicely described in this Wikipedia article. Used it in my project for the same purpose. That method scales on other polygons too, including concave. Not sure about the performance, but it is easily coded, so you could try it yourself (I had no performance issues in my project)

Resources