Area of polygon with list of (x,y) coordinates - python

It might seem a bit odd that I am asking for python code to calculate the area of a polygon with a list of (x,y) coordinates given that there have been solutions offered in stackoverflow in the past. However, I have found that all the solutions provided are sensitive to the order of the list of (x,y) coordinates given. For example, with the code below to find an area of a polygon:
def area(p):
return 0.5 * abs(sum(x0*y1 - x1*y0
for ((x0, y0), (x1, y1)) in segments(p)))
def segments(p):
return zip(p, p[1:] + [p[0]])
coordinates1 = [(0.5,0.5), (1.5,0.5), (0.5,1.5), (1.5,1.5)]
coordinates2 = [(0.5,0.5), (1.5,0.5), (1.5,1.5), (0.5,1.5)]
print "coordinates1", area(coordinates1)
print "coordinates2", area(coordinates2)
This returns
coordinates1 0.0
coordinates2 1.0 #This is the correct area
For the same set of coordinates but with a different order. How would I correct this in order to get the area of the non-intersecting full polygon with a list of random (x,y) coordinates that I want to make into a non-intersecting polygon?
EDIT: I realise now that there can be multiple non-intersecting polygons from a set of coodinates. Basically I am using scipy.spatial.Voronoi to create Voronoi cells and I wish to calculate the area of the cells once I've fed the coordinates to the scipy Voronoi function - unfortunately the function doesn't always output the coordinates in the order that will allow me to calculate the correct area.

Several non-intersecting polygons can be created from a random list of coordinates (depending on its order), and each polygon will have a different area, so it is essential that you specify the order of the coordinates to build the polygon (see attached picture for an example).

The Voronoi cells are convex, so that the polygon is unambiguously defined.
You can compute the convex hull of the points, but as there are no reflex vertices to be removed, the procedure is simpler.
1) sort the points by increasing abscissa; in case of ties, sort on ordinates (this is a lexicographical ordering);
2) consider the straight line from the first point to the last and split the point sequence in a left and a right subsequence (with respect to the line);
3) the requested polygon is the concatenation of the left subsequence and the right one, reversed.

Related

Random Rectangles without Overlapping some Pixels

I want to generate random rectangles. That is a pretty easy task. The issue is I need them to not overlap with any of these black dots:
Inverted for ease of sight:
Now I can just tell it to ignore any rectangles it generates if it overlaps with any black dots, but as the dot density increases, it gets to bogosort levels of inefficiency. Is there a more efficient way to do this?
You could use multiple randomly-generated quadtrees to generate a list of axis-aligned bounding boxes that do not contain any points, and then for each rectangle, randomly select an AABB from the list and then randomly generate a rectangle inside the AABB.
You don't need to retain the quadtree structure because you are only interested in the leaf nodes (which are AABBs). Start off with an AABB enclosing your entire 2D space and write a recursive function that accepts an AABB and a list of points. Create an empty list of AABBs and then call the function with the top-level bounding box and the point list.
Inside the function, randomly select one of the points to use as a splitting line, and randomly select an orientation (horizontal or vertical) or alternate horizontal and vertical. Create two lists of points made up of the points above and below the X or Y value of the splitting point, and two AABBs by splitting the AABB parameter using the point, then recursively call the function twice. If the function is called with an empty point list then add the AABB to your list and stop recursing.
If you call this from the top level multiple times you will have a whole bunch of overlapping AABBs in your list (provided the splitting points are selected randomly), so there won't be any obvious artifacts in the random generation. You can then randomly generate as many rectangles as you want.
The setup will be O(N log N) on the number of points (in the average case), and the random rectangle generation will be O(1).
To make the distribution more even, you could calculate the area of each AABB in your list and weight the probability of randomly selecting it based on its size. If you used a binary search tree to map your raw random number to your weighted AABBs, it would make your random generation O(log N)
Generate random line segment (that does not pass through any point) (green line on attached image)
Find distance to closest point on each side of the rectangle (red lines)
Choose random two points on the red lines that will belong to the sides of the rectangle (yellow dots)
Select a random white point.
Find the nearest black dot. This will be the radius of a circle
Create a circle centered at the random point.
Choose 2 points on the circle. Find their opposite point that pass by the center of the circle draw the rectangle from the 4 points.
P.S. Just be sure that the 2 points are not the diameter of the circle...
Here's my idea that is slightly different than what others have proposed. Here's the algorithm:
Create 2 arrays for the x and ys of the points. Copy the x and ys over and sort the arrays increaesingly.
Create a random x and random y. This will be the upper-left corner of the rectangle. Let's call them x1 and y1.
Do a binary search in the x array for the smallest x such that x >= x1.
Do a binary search in the y array for the largest y such that y <= y1.
if x1 == x or y1 == y: go to step 2 Note: we can't expand to create a rectangle.
Create a random x between x1 and the right bound x you found in step 3, exclusive on both ends. Call it x2.
Create a random y between y2 and the lower bound y you found in step 4, exclusive on both ends. Call it y2.
Save (x1, y1) and (x2, y2) as the left-upper and right-lower corners of your rectangle.
Repeat from step 2.
This algorithm has an initial time complexity of O(n * log n) and space complexity of O(n) for the preparation phase, where n is the number of given points. Each rectangle creation has a O(log n) time complexity for the binary search. I assume that the probability of collision between the left-upper corner of the rectangle and a point is so low that we can disregard it.
This approach also allows you to update the points in logarithmic time if you choosee the right data structure for them (something like a sorted map, sorted list, or similar depending on what it is called in a specific language).

Implementing collisions using the Separating axis theorem and Pygame [duplicate]

This is what I am currently doing:
Creating 4 axis that are perpendicular to 4 edges of 2 rectangles. Since they are rectangles I do not need to generate an axis (normal) per edge.
I then loop over my 4 axes.
So for each axis:
I get the projection of every corner of a rectangle on to the axis.
There are 2 lists (arrays) containing those projections. One for each rectangle.
I then get the dot product of each projection and the axis. This returns a scalar value
that can be used to to determine the min and max.
Now the 2 lists contain scalars and not vectors. I sort the lists so I can easily select the min and max values. If the min of box B >= the max of box A OR the max of box B <= the min of box A then there is no collision on that axis and no collision between the objects.
At this point the function finishes and the loop breaks.
If those conditions are never met for all the axis then we have a collision
I hope this was the correct way of doing it.
The python code itself can be found here http://pastebin.com/vNFP3mAb
Also:
http://www.gamedev.net/page/reference/index.html/_/reference/programming/game-programming/collision-detection/2d-rotated-rectangle-collision-r2604
The problem i was having is that the code above does not work. It always detects a a collision even where there is not a collision. What i typed out is exactly what the code is doing. If I am missing any steps or just not understanding how SAT works please let me know.
In general it is necessary to carry out the steps outlined in the Question to determine if the rectangles "collide" (intersect), noting as the OP does that we can break (with a conclusion of non-intersection) as soon as a separating axis is found.
There are a couple of simple ways to "optimize" in the sense of providing chances for earlier exits. The practical value of these depends on the distribution of rectangles being checked, but both are easily incorporated in the existing framework.
(1) Bounding Circle Check
One quick way to prove non-intersection is by showing the bounding circles of the two rectangles do not intersect. The bounding circle of a rectangle shares its center, the midpoint of either diagonal, and has diameter equal to the length of either diagonal. If the distance between the two centers exceeds the sum of the two circles' radii, then the circles do not intersect. Thus the rectangles also cannot intersect. If the purpose was to find an axis of separation, we haven't accomplished that yet. However if we only want to know if the rectangles "collide", this allows an early exit.
(2) Vertex of one rectangle inside the other
The projection of a vertex of one rectangle on axes parallel to the other rectangle's edges provides enough information to detect when that vertex is inside the other rectangle. This check is especially easy when the latter rectangle has been translated and unrotated to the origin (with edges parallel to the ordinary axes). If it happens that a vertex of one rectangle is inside the other, the rectangles obviously intersect. Of course this is a sufficient condition for intersection, not a necessary one. But it allows for an early exit with a conclusion of intersection (and of course without finding an axis of separation because none will exist).
I see two things wrong. First, the projection should simply be the dot product of a vertex with the axis. What you're doing is way too complicated. Second, the way you get your axis is incorrect. You write:
Axis1 = [ -(A_TR[0] - A_TL[0]),
A_TR[1] - A_TL[1] ]
Where it should read:
Axis1 = [ -(A_TR[1] - A_TL[1]),
A_TR[0] - A_TL[0] ]
The difference is coordinates does give you a vector, but to get the perpendicular you need to exchange the x and y values and negate one of them.
Hope that helps.
EDIT Found another bug
In this code:
if not ( B_Scalars[0] <= A_Scalars[3] or B_Scalars[3] >= A_Scalars[0] ):
#no overlap so no collision
return 0
That should read:
if not ( B_Scalars[3] <= A_Scalars[0] or A_Scalars[3] <= B_Scalars[0] ):
Sort gives you a list increasing in value. So [1,2,3,4] and [10,11,12,13] do not overlap because the minimum of the later is greater than the maximum of the former. The second comparison is for when the input sets are swapped.

Triangulation patterns in .ifc file format using coordinates and indexes

I've posted this in another forum as well due to the mathematical nature of the issue:
forum post
I have an .ifc file in which the raw data exported describes a wall in the xy plane by a set of coordinates and their corresponding indexes according to the link explanation:
Explanation
I have a txt where the data is divided into the coordinates in xyz space, then indexes and some other data.
I was hoping that someone can help me understand how to link the indexes to their corresponding coordinates. There are 164 coordinate pairs and 324 index pairs so it doesn't make sense to me that each index relates to only 1 coordinate pair.
The goal is to establish a relationship between indexes and coordinates such that this type of data can output the wall thickness, which is in this case '10'. I was thinking that (according to the link above) by taking the first triangle described, it should describe the edge of the wall in 3D and therefore give us one of its sides as the shortest segment in the wall which is the thickness.
I received an answer in the mentioned forum post, that I should
"...expanding out each coordinate in terms of X's, Y's, and Z's [instead of (X,Y,Z) triples) and then use every index triple to get the actual coordinate for the individual coordinate instead of one triple.
So for example you have X[], Y[] and Z[] and you have an index (a,b,c) then you find X[a], Y[b], and Z[c] not Point(a,b,c)... "
I didn't quite understand this explanation, and would appreciate any help or further explanation in order to achieve my goal.
Thank you
Let's start with the cordinates (IfcCartesianPointList3D): each one is a triplet, resulting in a Point with (x,y,z) coordinates.
Then the IfcTriangulatedFaceSet uses indices to construct triangles. It has 2 indexing modes: direct and indirect via PnIndex. The indexing mode is determined by the existence of an array for PnIndex (attribute number 5). Take note that I call these variants direct and indirect - they aren't mentioned that way in the IFC documentation.
Direct indexing
PnIndex is not set. Lets look at an (simple and constructed) example:
#100=IFCCARTESIANPOINTLIST(((0,0,0),(1,0,0),(1,1,0),(0,1,0)));
#101=IFCTRIANGULATEDFACESET(
/*reference to the points*/ #100,
/*no normals*/ $,
/*no indication if closed or open*/ $,
/*coordinate indices*/ ((1,2,3),(1,3,4)),
/*no PnIndex*/ ());
This describes a square lying in the x-y-plane. Each entry in attribute CoordIndex is a triplet giving a one-based index into a point in the IfcCartesianPointList. This means there are two triangles constructed from the following points:
(0,0,0) (1,0,0) (1,1,0)
(0,0,0) (1,1,0) (0,1,0)
Indirect indexing
Lets build further on the previous example:
#100=IFCCARTESIANPOINTLIST(((0,0,0),(1,0,0),(1,1,0),(0,1,0)));
#101=IFCTRIANGULATEDFACESET(
/*reference to the points*/ #100,
/*no normals*/ $,
/*no indication if closed or open*/ $,
/*coordinate indices*/ ((1,2,3),(1,3,4)),
/*PnIndex*/ (2,3,4,1));
This time there is PnIndex set. It adds a level of indirection to access the points. Triplets from CoordIndex point into PnIndex (1-based). The value found in PnIndex is then used to access the IfcCartesianPointList.
So for the first triangle we have: (1,2,3) in CoordIndex. These point to 2, 3 and 4 in PnIndex. These result in the following points from the point list: (1,0,0) (1,1,0) (0,1,0)
Repeating the procudure for the second triangle (1,3,4) we get values 2, 4, 1 from PnIndex and the following points: (1,0,0) (0,1,0) (0,0,0)
It is again a square, but this time with a different triangulation.
Now if you want to know your wall thickness you will need to calculate the extents from the resulting geometry. If your wall is aligned with the coordinate system axes this is easy (get the difference between the smallest and largest X, Y and Z). If it is not, you might need to transform the points or look further into 3D-extent calculations (my knowledge ends there).
In a triangulation it's roughly num of triangles = 2 * num of vertices.
A wall (e.g. a rectangle) may be described by two triangles that share an edge and the two vertices of this edge.
Instead of describing the whole model triangle by triangle, each with its three vertices, or edge by edge, it's cheaper, avoids repeating vertex data, to set an index for each vertex and set a triangle by the three indices of its vertices. This is usually called "indexed rendering".

Width of an arbitrary polygon

I need a way to characterize the size of sets of 2-D points, so I can determine whether to render them as individual points in a space or as representative polygons, dependent on the scale of the viewport. I already have an algorithm to calculate the convex hull of the set to produce the representative polygon, but I need a way to characterize its size. One obvious measure is the maximum distance between points on the convex hull, which is the diameter of the set. But I'm really more interested in the size of its cross-section perpendicular to its diameter, to figure out how narrow the bounding polygon is. Is there a simple way to do this, given the sorted list of vertices and and the indices of the furthest points (ideally in Python)?
Or alternatively, is there an easy way to calculate the radii of the minimal area bounding ellipse of a set of points? I have seen some approaches to this problem, but nothing that I can readily convert to Python, so I'm really looking for something that's turnkey.
You can compute:
the size of its cross-section perpendicular to its diameter
with the following steps:
Find the convex hull
Find the two points a and b which are furthest apart
Find the direction vector d = (a - b).normalized() between those two
Rotate your axes so that this direction vector lies horizontal, using the matrix:
[ d.x, d.y]
[-d.y, d.x]
Find the minimum and maximum y value of points in this new coordinate system. The difference is your "width"
Note that this is not a particularly good definition of "width" - a better one is:
The minimal perpendicular distance between two distinct parallel lines each having at least one point in common with the polygon's boundary but none with the polygon's interior
Another useful definition of size might be twice the average distance between points on the hull and the center
center = sum(convexhullpoints) / len(convexhullpoints)
size = 2 * sum(abs(p - center) for p in convexhullpoints) / len(convexhullpoints)

Separating Axis Theorem and Python

This is what I am currently doing:
Creating 4 axis that are perpendicular to 4 edges of 2 rectangles. Since they are rectangles I do not need to generate an axis (normal) per edge.
I then loop over my 4 axes.
So for each axis:
I get the projection of every corner of a rectangle on to the axis.
There are 2 lists (arrays) containing those projections. One for each rectangle.
I then get the dot product of each projection and the axis. This returns a scalar value
that can be used to to determine the min and max.
Now the 2 lists contain scalars and not vectors. I sort the lists so I can easily select the min and max values. If the min of box B >= the max of box A OR the max of box B <= the min of box A then there is no collision on that axis and no collision between the objects.
At this point the function finishes and the loop breaks.
If those conditions are never met for all the axis then we have a collision
I hope this was the correct way of doing it.
The python code itself can be found here http://pastebin.com/vNFP3mAb
Also:
http://www.gamedev.net/page/reference/index.html/_/reference/programming/game-programming/collision-detection/2d-rotated-rectangle-collision-r2604
The problem i was having is that the code above does not work. It always detects a a collision even where there is not a collision. What i typed out is exactly what the code is doing. If I am missing any steps or just not understanding how SAT works please let me know.
In general it is necessary to carry out the steps outlined in the Question to determine if the rectangles "collide" (intersect), noting as the OP does that we can break (with a conclusion of non-intersection) as soon as a separating axis is found.
There are a couple of simple ways to "optimize" in the sense of providing chances for earlier exits. The practical value of these depends on the distribution of rectangles being checked, but both are easily incorporated in the existing framework.
(1) Bounding Circle Check
One quick way to prove non-intersection is by showing the bounding circles of the two rectangles do not intersect. The bounding circle of a rectangle shares its center, the midpoint of either diagonal, and has diameter equal to the length of either diagonal. If the distance between the two centers exceeds the sum of the two circles' radii, then the circles do not intersect. Thus the rectangles also cannot intersect. If the purpose was to find an axis of separation, we haven't accomplished that yet. However if we only want to know if the rectangles "collide", this allows an early exit.
(2) Vertex of one rectangle inside the other
The projection of a vertex of one rectangle on axes parallel to the other rectangle's edges provides enough information to detect when that vertex is inside the other rectangle. This check is especially easy when the latter rectangle has been translated and unrotated to the origin (with edges parallel to the ordinary axes). If it happens that a vertex of one rectangle is inside the other, the rectangles obviously intersect. Of course this is a sufficient condition for intersection, not a necessary one. But it allows for an early exit with a conclusion of intersection (and of course without finding an axis of separation because none will exist).
I see two things wrong. First, the projection should simply be the dot product of a vertex with the axis. What you're doing is way too complicated. Second, the way you get your axis is incorrect. You write:
Axis1 = [ -(A_TR[0] - A_TL[0]),
A_TR[1] - A_TL[1] ]
Where it should read:
Axis1 = [ -(A_TR[1] - A_TL[1]),
A_TR[0] - A_TL[0] ]
The difference is coordinates does give you a vector, but to get the perpendicular you need to exchange the x and y values and negate one of them.
Hope that helps.
EDIT Found another bug
In this code:
if not ( B_Scalars[0] <= A_Scalars[3] or B_Scalars[3] >= A_Scalars[0] ):
#no overlap so no collision
return 0
That should read:
if not ( B_Scalars[3] <= A_Scalars[0] or A_Scalars[3] <= B_Scalars[0] ):
Sort gives you a list increasing in value. So [1,2,3,4] and [10,11,12,13] do not overlap because the minimum of the later is greater than the maximum of the former. The second comparison is for when the input sets are swapped.

Categories