how do I determine a cross shape with given vertices - algorithm

I am having trouble forming an algorithm to determine if 12 vertices that was inputted by a user in any order, will form a cross shape in a 2D plane.
From the way I looked at it, it can be two rectangle intersecting.
Should I choose to brute force it by comparing the distances,
I will end up having 67 distances from the 12 vertices, which to compare all of them would not be feasible.
Is there any characteristic of a cross or shape that I could use?

What you want is a cross shape define by two intersecting rectilinear rectangles with protrusions greater than zero on all four sides. I believe the following algorithm will fully determine that for you.
Insure that none of the 12 points is identical.
There should only be 4 distinct X values among the 12 points. Put them in ascending order into an array that we’ll call your X-vector.
Do the same with Y values creating a Y-vector with 4 distinct values.
Make a 4x4 array, initializing all cells to zero.
Go through each of the 12 values using their X and Y values along with the X-vector and Y-vector to select a cell in the 4x4 array to increment. Thus if you had a point (12,9) and 12 was at the [0] entry of the X-vector and 9 was in the [2]entry of the Y-vector, you would increment the [0,2] cell of the 4x4 array.
Now your 4x4 Array should look exactly like this:
0, 1, 1, 0
1, 1, 1, 1
1, 1, 1, 1
0, 1, 1, 0
If so, then it is a cross as you have defined it. And if not, or if it fails at any previous step, the it is not a cross.

Something like the following should work:
collect the points in a set or list
iterate the points and find the distinct X and Y coordinates; there should be exactly four different values for X and Y, respectively; if there are more or fewer, it's not a cross-shape
sort the distinct X and Y coordinates and call them x1 through x4 and y1 through y4
check whether the original list of points contains exactly the points (x1, y2), (x1, y3), (x2, y1), (x2, y2), (x2, y3), (x2, y4), (x3, y1), (x3, y2), (x3, y3), (x3, y4), (x4, y2), and (x4, y3), in any order
if there are other properties to be met, e.g. the four arms having same lengths, check those, too, using the identified distinct X and Y values

Related

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

Find highest possible x and y value of Points

I have measured points for fitting lines. The number of points I have measured in x-direction is the first value of the Point (e.g. X1) and the second value of this point are the measured points in y-direction.
X1(2,9)
X2(9,3)
X3(5,4)
X4(6,4)
This means,that e.g. in X3 I have measured 5 points in x-direction and in y-direction I have measured 4 points. With the points in x-direction I will fit a line in x-direction and with the points in y-direction, I will fit a line in y-direction. To get better results, more points in x direction and y-direction are better then less. For example it is better to choose X4, then X1, because in X1 I have in y-direction 9-Points, but in x-direction only 2 points, which will give me a poor result in x-direction. In X4 I have both: a high number of points in x and in y-direction. So I can be sure, that the lines will be good enough. So I want to find this X#, where I have a (the) high(est) number of points in x and in y direction
Have you tried checking your code? It seems like your X is on an ascending order and your Y is using the opposite order. Maybe like insert both x and y values on a variable then sort them with the same order as you want them to be.
You would need to write a function that ranks the 'fitness' of a point.
def fitness(point):
'''
ranks a point by the total number of points,
minus the difference between the number of x and y points.
uses total number of points as a secondary rank
'''
num_points = sum(point)
xydiff = max(point) - min(point)
return num_points - xydiff, num_points
The above function should be adjusted, depending on how you want to want to weight the points.
>>> points = [(2,9), (9,3), (5,4), (6,4)]
>>> sorted(points, key=fitness, reverse=True)
[(6, 4), (5, 4), (9, 3), (2, 9)]
>>> max(points, key=fitness) # the most fit point
(6, 4)

Fast algorithm for testing if every rectangle built using any two points from a list contains a third point from that list

The problem is as it follows:
Given N (N <= 100,000) points by their Cartesian coordinates, test if every rectangle (with an area > 0) built using any two of them contains at least another point from that list either inside the rectangle or on his margin.
I know the algorithm for O(N^2) time complexity. I want to find the solution for O(N * logN). Memory is not a problem.
When I say two points define a rectangle, I mean that those two points are in two of its opposite corners. The sides of the rectangles are parallel to the Cartesian axes.
Here are two examples:
N = 4
Points:
1 1
3 5
2 4
8 8
INCORRECT: (the rectangle (1, 1) - (2, 4) doesn't have any point inside of it or on its margin).
N = 3
Points:
10 9
13 9
10 8
CORRECT.
Sort the points in order of the max of their coordinate pairs, from lowest to highest (O(n*log(n))). Starting with the lower-left point (lowest max coordinate), if the next point in the ordering does not share either the original point's x-value or its y-value (e.g. (1,2) and (5,2) share a y-coordinate of 2, but (1,2) and (2, 1) have neither coordinate in common), the set of points fails the test. Otherwise, move to the next point. If you reach the final point in this way (O(n)), the set is valid. The algorithm overall is O(n*log(n)).
Explanation
Two points that share a coordinate value lie along a line parallel to one of the axes, so there is no rectangle drawn between them (since such a rectangle would have area=0).
For a given point p1, if the next "bigger" point in the ordering, p2, is directly vertical or horizontal from p1 (i.e. it shares a coordinate value), then all points to the upper-right of p2 form rectangles with p1 that include p2, so there are no rectangles in the set that have p1 as the lower-left corner and lack an internal point.
If, however, the next-bigger point is diagonal from p2, then the p1 <-> p2 rectangle has no points from the set inside it, so the set is invalid.
For every point P = (a, b) in the set, search the nearest points of the form Y = (x, b) and X = (a, y) such that x > a and y > b.
Then, find if the rectangle defined by the two points X, Y contains any* internal point R besides P, X and Y. If that is the case, it's easy to see that the rectangle P, R does not contain any other point in the set.
If no point in the set exists matching the restrictions for X or Y, then you have to use (a, ∞) or (∞, b) respectively instead.
The computational cost of the algorithm is O(NlogN):
Looking for X or Y can be done using binary search [O(logN)] over a presorted list [O(NlogN)].
Looking for R can be done using some spatial tree structure as a quadtree or a k-d tree [O(logN)].
*) If X, Y contains more than one internal point, R should be selected as the nearest to P.
Update: the algorithm above works for rectangles defined by its botton-left and upper-right corners. In order to make it work also for rectangles defined by its botton-right and upper-left corners, a new point X' (such that it is the nearest one to P of the form X' = (a, y') where y' < b) and the corresponding rectangle defined by X', Y should also be considered for every point in the set.

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)

Counting number of co-ordinates in hypercube

In an N-dimensional grid the co-ordinates of a cell are denoted as X1, X2, ..., XN. Any cell with negative co-ordinate are colored white. The origin cell (the one with all zero co-ordinates) is colored as black. The color of a cell in (X1, X2, ..., XN) depends on the N cells with co-ordinates (X1-1, X2, ..., XN), (X1, X2-1, ..., XN), ...., (X1, X2, ..., XN-1). The cell is colored white if and only if the number of black colored cells among these N co-ordinates are even, otherwise the cell is colored black.
Now, given the starting and ending co-ordinate of sub-hypercube. All the co-ordinates will be non negative integers for which the query is done. We've to compute how many hyper cells in this sub hypercube are colored black?
Please suggest me hint, reference or anything which could help me to solve it.
This rule results in a well known fractal - The Sierpinski triangle
Here is an image of it in 2D:
A brute force algorithm:
fill the hypercube (the needed part) with value 'unknown'.
color[00000] = 1 #black
sum = 0
for each cell in sub-hypercube:
sum += getcolor(cell)
return sum
getcolor(cell):
if color[cell] == unknown
c = 0 #white
for each neighbour cell in decreasing direction within non-negative boundary:
c = c xor getcolor(neighbour)
color[cell] = c
return color[cell]

Resources