I'm looking for a way to generate a set of random sided, but regular, polygons, inside a given rectangle or sector of a circle. To better explain, my given 2d space should have a random arrangement of regular polygons with various numbers of sides, so, e.g, if two hexagons are separated by a rectangle equal in length to their sides, the whole space cannot be filled with only more hexagons, some triangles may be required, etc.
I'm looking for one segment of a sort of kaleidoscope effect.
You are looking for tiling algorithms. See, for example, Penrose Tiler and Tilings and Tesselations pages for a start.
Another approach, I can think of:
First decide on how many objects you want. Say 'N'
Randomly Select 3 Points in your 2D Space.
Make use of 3 points to get a virtual triangle.
Now Select another point such a way that the point is outside the virtual triangle. Now form another virtual triangle by joining this point to 2 points from previous virtual triangle and then recurisevely form "N" virtual trianlges. Incase virtual triangles crossed, then you ignore the bigger trianlge and take triangles which had formed because of crossing points as new virtualtriangles
Now Generate a INSCRIBED Circle virtually to all virtual triangles which will never be able to intersect another virtual triangle since all virtual triangles are formed by without crossing any of the triangles as expalined above.
Make use of virtual circles to form any number of regular sides by dividing 360 degress to equal slices.
Now You can draw random regular polygons
I'm not sure I understand the requirements, but you can generate random regular polygons by randomly generating the following numbers:
radius (0 to whatever)
x and y of center (must be within radius of edges)
number of points (3 to whatever)
rotation (0 to 360)
To prevent overlapping, you can test each new polygon against each existing polygon and reject the new one if the distance between the centers is less than the sum of the radii.
Drawing the polygons is then a simple trig exercise.
See: "Heuristics for Generation of Random Polygons"
Generate N random points on a plane and extract the convex hull of the object (that is, if all polygons should be convex).
You can trivially reject before generating the convex hull if one of the points is inside another polygon. If it's not you still need to test the generated polygon against other polygons near it. (If you need to do this often, a spatial data structure is probably a something to look into).
Related
This question is an extension on some computation details of this question.
Suppose one has a set of (potentially overlapping) circles, and one wishes to compute the area this set of circles covers. (For simplicity, one can assume some precomputation steps have been made, such as getting rid of circles included entirely in other circles, as well as that the circles induce one connected component.)
One way to do this is mentioned in Ants Aasma's and Timothy's Shields' answers, being that the area of overlapping circles is just a collection of circle slices and polygons, both of which the area is easy to compute.
The trouble I'm encountering however is the computation of these polygons. The nodes of the polygons (consisting of circle centers and "outer" intersection points) are easy enough to compute:
And at first I thought a simple algorithm of picking a random node and visiting neighbors in clockwise order would be sufficient, but this can result in the following "outer" polygon to be constructed, which is not part of the correct polygons.
So I thought of different approaches. A Breadth First Search to compute minimal cycles, but I think the previous counterexample can easily be modified so that this approach results in the "inner" polygon containing the hole (and which is thus not a correct polygon).
I was thinking of maybe running a Las Vegas style algorithm, taking random points and if said point is in an intersection of circles, try to compute the corresponding polygon. If such a polygon exists, remove circle centers and intersection points composing said polygon. Repeat until no circle centers or intersection points remain.
This would avoid ending up computing the "outer" polygon or the "inner" polygon, but would introduce new problems (outside of the potentially high running time) e.g. more than 2 circles intersecting in a single intersection point could remove said intersection point when computing one polygon, but would be necessary still for the next.
Ultimately, my question is: How to compute such polygons?
PS: As a bonus question for after having computed the polygons, how to know which angle to consider when computing the area of some circle slice, between theta and 2PI - theta?
Once we have the points of the polygons in the right order, computing the area is a not too difficult.
The way to achieve that is by exploiting planar duality. See the Wikipedia article on the doubly connected edge list representation for diagrams, but the gist is, given an oriented edge whose right face is inside a polygon, the next oriented edge in that polygon is the reverse direction of the previous oriented edge with the same head in clockwise order.
Hence we've reduced the problem to finding the oriented edges of the polygonal union and determining the correct order with respect to each head. We actually solve the latter problem first. Each intersection of disks gives rise to a quadrilateral. Let's call the centers C and D and the intersections A and B. Assume without loss of generality that the disk centered at C is not smaller than the disk centered at D. The interior angle formed by A→C←B is less than 180 degrees, so the signed area of that triangle is negative if and only if A→C precedes B→C in clockwise order around C, in turn if and only if B→D precedes A→D in clockwise order around D.
Now we determine which edges are actually polygon boundaries. For a particular disk, we have a bunch of angle intervals around its center from before (each sweeping out the clockwise sector from the first endpoint to the second). What we need amounts to a more complicated version of the common interview question of computing the union of segments. The usual sweep line algorithm that increases the cover count whenever it scans an opening endpoint and decreases the cover count whenever it scans a closing endpoint can be made to work here, with the adjustment that we need to initialize the count not to 0 but to the proper cover count of the starting angle.
There's a way to do all of this with no trigonometry, just subtraction and determinants and comparisons.
I am given an ordered set of points in 2D space as an output of a previous process. Coordinate points will be given in the form ((x0,y0),(x1,y1),...,(xn,yn)), where the very last coordinate pair will be a repetition of the first pair (i.e x0 = xn and y0 = yn). In this way, I know that when I re-encounter the same coordinate, I have made a closed loop. I would like to be able to detect the enclosed area by the polygon. If a single closed loop is given, the output should be the enclosed area of that closed loop. Now say I have a separate set of points, similar to to the first set. If a set of many closed looped polygons is given, then if each polygon is separated in space from each other, the output should be each enclosed area. However, if some of the polygons enclose each other, it should be the area bounded between both of them. For example, if I have one closed loop polygon inside another, the output area should between both of them (or in other words, the area enclosed by the larger one minus the area enclosed by the smaller one). If I have more than one closed loop polygon inside of a single larger one, it should be the area enclosed by the larger one minus all the areas enclosed by the smaller ones).
For a case where I have a region A enclosed by a region B, where B is enclosed by a region C, there are three distinct regions.
Region C minus region B (bounded on the outside by polygon 1)
Region B minus region A (bounded on the outside by polygon 2)
Region A (bounded on the outside by polygon 3)
Of the three regions, I only want region 1) and region 3). The reason I do not take region 2) is because for all the bounded areas on my 2D plane, the outermost polygons always represent the boundaries of a relevant region, and the input that produced my sets of coordinates representing my closed loop polygons would never have given me the points for polygon 2 if in the end region 1) and region 2) were meant to be combined. It instead would have given me only polygon 1 and polygon 3, similar to the case I described above.
In summary,
- I am given enough information to know all the coordinate points for a set of closed loop polygons on a 2D plane and they are distinguishable from each other.
- I need to develop an algorithm that will take in the entire set of closed loops polygons and return enough information to describe a bounded area. In thinking about the problem, I think the output that I would want is to know whether for a each and every line segment of the a closed loop polygon, on which side of that line segment is inside and outside of the polygon.
- It should be able to resolve the case where I have polygons inside of polygons.
- Closed loop polygons will never share any points. Each set of coordinate points will be unique to a polygon.
My initial thoughts were calculate the centroid of the polygon and then compare all line segments to the centroid, but I don't think this would work for all cases.
Judging by the description of your input, splitting your input stream into separate polygons is a trivial task.
After that, in order to "return enough information to describe a bounded area" you can build the following data structure out of your polygons:
Separate all polygons into two classes: main polygons and hole polygons.
Main polygon is... well, the exterior border of a bounded area. It separates the interior of the bounded area from the "outside world".
Hole polygon is a polygon that describes a hole in some main polygon.
Each hole polygon is associated with exactly one main polygon
Each main polygon is associated with zero or more hole polygons
Optionally, you can order the vertices in main polygons counterclockwise and vertices in hole polygons clockwise. But this is not strictly necessary to satisfy the formal requirement of "describing a bounded area"
The resulting structure is two-tiered: you end you with a list of main polygons, and each main polygon might contain a list of its holes.
In your example, you have 4 main polygons. One of them contains two hole polygons.
So, all you need to do is to recognize hole polygons and properly associate them with their main polygons.
An industrial-strength approach for solving this task would be an application of sweep-line algorithm to the input polygons. It would easily perform the classification into main and hole polygons as well as build the proper association between them.
An ad-hoc algorithm might look as follows
Sort all polygons in order of increasing area
For each polygon p in the sorted order
Take any vertex v of p
Perform an "inside" test of v against all polygons of greater area than p (for example, by using a simple even-odd intersection test: How can I determine whether a 2D Point is within a Polygon?)
If the number of polygons that contain v is odd, p is a hole polygon. Otherwise, p is a main polygon
If p is a hole polygon, then the smallest-area polygon that contains v is its associated main polygon.
That's it.
I think the output that I would want is to know whether for a each and every line segment of the a closed loop polygon, on which side of that line segment is inside and outside of the polygon.
Compute the normal for the line segment (perpendicular line).
Compute the mid-point of the line segment (any point will do).
Intersect every other line segment with a ray projected from the mid-point in the direction of the normal.
Intuitively, each intersection means either entering or exiting another polygon. Since finally the ray will be outside all polygons, we can deduce that if the ray intersects an even number of other line segments, then the side of the line segment indicated by the normal is on the outside of the polygon. If odd, it's on the inside.
There are a couple of tricky cases: one is where the ray exactly intersects the end-point of two connected line segments. Be careful to only count this as one intersection. The other case is where the ray is parallel to and exactly overlaps another line segment. This should count as two intersections.
There are more efficient algorithms (e.g. involving triangulation), but this one is simplest.
Does anyone know a relatively fast algorithm for decomposing a set of polygons into their distinct overlapping and non-overlapping regions, i.e. Given a set of n polygons, find all the distinct regions among them?
For instance, the input would be 4 polygons representing circles as shown below
and the output will be all polygons representing the distinct regions shown in the different colours.
I can write my own implementation using polygon operations but the algorithm will probably be slow and time consuming. I'm wondering if there's any optimised algorithm out there for this sort of problem.
Your problem in called the map overlay problem. It can be solved in O(n*log(n)+k*log(k)) time, where n is the number of segments and k is the number of segment intersections.
First you need to represent your polygons as a doubly connected edge list, different faces corresponding to the interiors of different polygons.
Then use the Bentley–Ottmann algorithm to find all segment intersections and rebuild the edge list. See: Computing the Overlay of Two Subdivisions or Subdivision representation and map overlay.
Finally, walk around each cycle in the edge list and collect faces of that cycle's half-edges. Every set of the faces will represent a distinct overlapping region.
See also: Shapefile Overlay Using a Doubly-Connected Edge List.
I don't think it is SO difficult.
I have answered the similar question on the friendly site and it was checked by a smaller community:
https://cs.stackexchange.com/questions/20039/detect-closed-shapes-formed-by-points/20247#20247
Let's look for a more common question - let's take curves instead of polygons. And let's allow them to go out of the picture border, but we'll count only for simple polygons that wholly belong to the picture.
find all intersections by checking all pairs of segments, belonging to different curves. Of course, filter them before real check for intersection.
Number all curves 1..n. Set some order of segments in them.
For every point create a sequence of intersections SOI, so: if it starts from the border end, SOI[1] is null. If not, SOI[1]= (number of the first curve it is intersecting with, the sign of the left movement on the intersecting curve). Go on, writing down into SOI every intersection - number of curve if there is some, or 0 if it is the intersection with the border.
Obviously, you are looking only for simple bordered areas, that have no curves inside.
Pieces of curves between two adjacent non-null intersection points we'll call segments.
Having SOI for each curve:
for segment of the curve 1, starting from the first point of the segment, make 2 attempts to draw a polygon of segments. It is 2 because you can go to 2 sides along the first intersecting curve.
For the right attempt, make only left turns, for the left attempt, make only the right turns.
If you arrive at point with no segment in the correct direction, the attempt fails. If you return to the curve 1, it success. You have a closed area.
Remember all successful attempts
Repeat this for all segments of curve 1
Repeat this for all other curves, checking all found areas against the already found ones. Two same adjacent segments is enough to consider areas equal.
How to find the orientation of the intersection.
When segment p(p1,p2) crosses segment q(q1,q2), we can count the vector multiplication of vectors pXq. We are interested in only sign of its Z coordinate - that is out of our plane. If it is +, q crosses p from left to right. If it is -, the q crosses p from right to left.
The Z coordinate of the vector multiplication is counted here as a determinant of matrix:
0 0 1
p2x-p1x p2y-p1y 0
q2x-q1x q2y-q1y 0
(of course, it could be written more simply, but it is a good memorization trick)
Of course, if you'll change all rights for lefts, nothing really changes in the algorithm as a whole.
I've got some 2D polygons, each as a list of clockwise coordinates. The polygons are
simple (i.e. they may be concave but they don't intersect themselves) and they don't overlap eachother.
I need to subdivide these polygons into smaller polygons to fit a size constraint. Just like the original polygons, the smaller ones should be simple (non-self-intersecting) and the constraint is they should each fit within one 'unit square' (which, for sake of simplicity, I can assume to be 1x1).
The thing is, I need to do this as efficiently as possible, where 'efficient' means the lowest number of resulting (small) polygons possible. Computation time is not important.
Is there some smart algorithm for this? At first I thought about recursively subdividing each polygon (splitting it in half, either horizontally or vertically whichever direction is larger) which works, but I don't seem to get very optimal results with this. Any ideas?
Draw a circle with a center of one of the initial points of initial polygon and radius of your desired length constraint.
The circle will intersect at least two lines at two points. Now you have your first triangle by the biggest as possible. Then choose those intersections as next target. Do until there is no initial points left outside. You have your triangles as large as possible(so as few as possible)
Do not account the already-created triangle edges as an intersection point.
Resulting polygons are not always triangle, they can be quads too. Maybe larger point-numbers too!
They all just nearly equal to the desired size.
Fine-tuning the interior parts would need some calculation.
I suggest you use the following:
Triangulate the polygon, e.g. using a sweep line algorithm.
Make sure all the triangles do not violate the constraint. If one violates the constraint, first try edge-flips to fix it, otherwise subdivide on the longest edge.
Use dynamic programming to join the triangles, while maintaining the constraint and only joining adjacent polygons.
I have two 2D rectangles, defined as an origin (x,y) a size (height, width) and an angle of rotation (0-360°). I can guarantee that both rectangles are the same size.
I need to calculate the approximate area of intersection of these two rectangles.
The calculation does not need to be exact, although it can be. I will be comparing the result with other areas of intersection to determine the largest area of intersection in a set of rectangles, so it only needs to be accurate relative to other computations of the same algorithm.
I thought about using the area of the bounding box of the intersected region, but I'm having trouble getting the vertices of the intersected region because of all of the different possible cases:
I'm writing this program in Objective-C in the Cocoa framework, for what it's worth, so if anyone knows any shortcuts using NSBezierPath or something you're welcome to suggest that too.
To supplement the other answers, your problem is an instance of line clipping, a topic heavily studied in computer graphics, and for which there are many algorithms available.
If you rotate your coordinate system so that one rectangle has a horizontal edge, then the problem is exactly line clipping from there on.
You could start at the Wikipedia article on the topic, and investigate from there.
A simple algorithm that will give an approximate answer is sampling.
Divide one of your rectangles up into grids of small squares. For each intersection point, check if that point is inside the other rectangle. The number of points that lie inside the other rectangle will be a fairly good approximation to the area of the overlapping region. Increasing the density of points will increase the accuracy of the calculation, at the cost of performance.
In any case, computing the exact intersection polygon of two convex polygons is an easy task, since any convex polygon can be seen as an intersection of half-planes. "Sequential cutting" does the job.
Choose one rectangle (any) as the cutting rectangle. Iterate through the sides of the cutting rectangle, one by one. Cut the second rectangle by the line that contains the current side of the cutting rectangle and discard everything that lies in the "outer" half-plane.
Once you finish iterating through all cutting sides, what remains of the other rectangle is the result.
You can actually compute the exact area.
Make one polygon out of the two rectangles. See this question (especially this answer), or use the gpc library.
Find the area of this polygon. See here.
The shared area is
area of rectangle 1 + area of rectangle 2 - area of aggregated polygon
Take each line segment of each rectangle and see if they intersect. There will be several possibilities:
If none intersect - shared area is zero - unless all points of one are inside the other. In that case the shared area is the area of the smaller one.
a If two consecutive edges of one rectactangle intersect with a single edge of another rectangle, this forms a triangle. Compute its area.
b. If the edges are not consequtive, this forms a quadrilateral. Compute a line from two opposite corners of the quadrilateral, this makes two triangles. Compute the area of each and sum.
If two edges of one intersect with two edges of another, then you will have a quadrilateral. Compute as in 2b.
If each edge of one intersects with each edge of the other, you will have an octagon. Break it up into triangles ( e.g. draw a ray from one vertex to each other vertex to make 4 triangles )
#edit: I have a more general solution.
Check the special case in 1.
Then start with any intersecting vertex, and follow the edges from there to any other intersection point until you are back to the first intersecting vertex. This forms a convex polygon. draw a ray from the first vertex to each opposite vetex ( e.g. skip the vertex to the left and right. ) This will divide it into a bunch of triangles. compute the area for each and sum.
A brute-force-ish way:
take all points from the set of [corners of
rectangles] + [points of intersection of edges]
remove the points that are not inside or on the edge of both rectangles.
Now You have corners of intersection. Note that the intersection is convex.
sort the remaining points by angle between arbitrary point from the set, arbitrary other point, and the given point.
Now You have the points of intersection in order.
calculate area the usual way (by cross product)
.