How to efficient extract new polygons form the exist polygons - algorithm

the polygons image
All of the polygons are simply, there are no holes in them.
board polygon(P0 to P7)
Red polygon (R0 to R6)
Green polygon (G0 G1 P2 G3)
Yellow polygon(Y0 to Y3)
I want to got new four polygons marked as 1 to 4 , polygon 1's coordinates are(J7 J10 R5 R4).
When I use polygon clipping algorithm, I can got the results easy , board diff(red union green union yellow). But when I have more than 10,000 polygons, I need a long time to get my results. My polygons are simply and my result polygons are simply also, there are no holes in the result polygons also.
You know I can find out the four polygons form the image easy using eyes, but how to find them using algorithm.
Thanks.

If all vertices of your computed black polygons do not have more than 2 edges intersecting at the vertex, then there may be a faster way than a more general tool.
Since the number of polygons is on the order of 10000, first try computing the intersection points of all pairs of polygons, and hopefully the number of intersection points is small enough (like 10 million or less). Then, for each intersection point test to see if it is contained in the interior of another polygon (in case you have multiple polygons that jointly overlap). Testing to see if a point is contained in the interior of a polygon can be done quickly, you can read how online. Then, all intersection points that are not contained in another polygon, which note also contains all the original polygon vertices that are not contained in the interior of a polygon, these are the vertices for the "black" polygons you want to compute. These points should be stored with a secondary structure that for each polygon edge, it stores all the stored intersection points along that edge, in sorted order. Similarly, for each stored vertex and intersection point you should store the edges that intersect at that point, and the location of the intersection point in the previous structure. So then pick any stored intersection point that hasn't been used yet in a black polygon, and pick one edge that defines the intersection point. Then you move to the neighboring intersection point along the edge which has the property that the part of the edge between the two intersection points does not pass inside a polygon. Then continue by similarly moving along the other edge that defines the neighboring intersection point. Continue until you reach the vertex you started at; this defines one black polygon. Then you can pick a new unused stored intersection point and repeat. Since your polygons have no holes, this will find all black polygons.

Related

Best way to merge overlapping convex polygons into a single concave polygon?

I am working with several convex polygons that overlap each other and I need to combine them back together to form one single polygon that may be convex or concave.
The problem is always as follows:
1) The polygons that I need to merge together are always convex.
2) The vertices of each polygon are defined in clockwise order.
3) The polygons are never in any specific order.
4) The final polygon can only be simple convex or concave polygon, i.e. no self-intersection, no duplicate vertices or holes in the shape.
Here is an example of the kind of polygons that I am working with.
![overlapping convex polygons]"image removed")
My current approach is to start from the first polygon and vertex by vertex I loop through all vertices of all of the polygons to find overlap. If there is no overlap, I store the vertex for the final outline and continue.
Upon finding overlapping vertices, I determine which polygon to continue to by measuring the angles of the possible paths and by choosing the one that leads towards the outside of the shape.
This method works until I encounter polygons that do not have vertices overlapping each other, but instead one polygon's vertex is overlapping another polygon's side, as is the case with the rectangle in the image.
I am currently planning on solving these situations by running line intersect checks for all shapes that I have not yet processed, but I am convinced that this cannot be the easiest or the best method in terms of performance.
Does someone know how I should approach this problem in a more efficient manner and/or universal manner?
I solved this issue and I'm posting the answer here in case someone else runs into this issue as well.
My first step was to implement a pre-processing loop based on trincot's suggestions.
I calculated the minimum and maximum x and y bounds for each individual shape.
I used these values to determine all overlapping shapes and I stored a simple array for each shape that I could later use to only look at shapes that can overlap each other.
Then, for the actual loop that determines the outline of the final polygon:
I start from the first shape and simply compare its vertices to those of the nearby shapes. If there is at least one vertex that isn't shared by another vertex, it must be on the outer edge and the loop starts from there. If there are only overlapping vertices, then I add the first shape to a table for all checked shapes and repeat this process with another shape until I find a vertex that is on the outer edge.
Once the starting vertex is found, the main loop will check the vertices of the starting shape one by one and measure how far from the given vertex is from every nearby shapes' edges. If the distance is zero, then the vertex either overlaps with another shape's vertex or the vertex lies on the side of another shape.
Upon finding the aforementioned type of vertex, I add the previous shape's number to the table of checked shapes so that it isn't checked again. Then, I check if there are other shapes that share this particular vertex. If there are, then I determine the outermost shape and continue from there, starting back from step 2.
Once all shapes have been checked, I check that all non-overlapping vertices from the starting shape were indeed added to the outline. If they weren't, I add them at the end.
There may be computationally faster methods, but I found this one to be simple to write, that it meets all of my requirements and it is fast enough for my needs.
Given a vertex, you could speed up the search of an "overlapping" vertex or edge as follows:
Finding vertices
Assuming that the coordinates are exact, in the sense that if two vertices overlap, they have exactly the same x and y coordinates, without any "error" of imprecision, then it would be good to first create a hash by x-coordinate, and then for each x-entry you would have a hash by y-coordinate. The value of that inner hash would be a list of polygons that have that vertex.
That structure can be built in O(n) time, and will allow you to find a matching vertex in constant time.
Only if that gives no match, you would go to the next algorithm:
Finding edges
In a pre-processing step (only once), create a segment tree for these polygons where a "segment" corresponds to a min/max x-coordinate range for a particular polygon.
Given a vertex, use the segment tree to find the polygons that are in the right x-coordinate range, i.e. where the x-coordinate of the vertex is within the min/max range of x-coordinates of the polygon.
Iterate those polygons, and eliminate those that do not have an y-coordinate range that has the y-coordinate of the vertex.
If no polygons remain, the vertex does not participate in any edge of another polygon.
You cannot get more than one polygon here, since that would mean another polygon shares the vertex, which is a case already covered by the hash-based algorithm.
If you get just one polygon, then continue your search by going through the edges of that polygon to find a match -- which is what you already planned on doing (line intersect check), but now you would only need to do it for one polygon.
You could speed that line intersect check up a little bit by first filtering the edges to those that have the right x-range. For convex polygons you would end up with at most two edges. At most one of those two will have the right y-range. If you get such an edge, check whether the vertex is really on that edge.

Triangle enclosing the biggest number of points

Given set of 2D points find a triangle built from those points, that encloses the biggest number of points.
Brutal algorithm for this is just building triangles from every possible triad of points and checking how many points they enclose, but time complexity of this solution is O(n^4).
For the optimal solution I thought about first finding the convex hull of those points and arranging points inside this hull with some structure, but I can't figure it out.
Do you have any ideas about the optimal solution for this kind of problem?
In a set of n points, there are (n choose 3) triangles, and using brute force to check for each point whether it is contained in each triangle indeed has O(n4) complexity. To give a practical example of a few set sizes:
points: 100 1,000 10,000
triangles: 161,700 166,167,000 166,616,670,000
checks: 15,684,900 165,668,499,000 1,665,666,849,990,000
Below are a few geometrical ideas; they don't lead straight to a solution, but they can reduce the number of triangles that have to be checked.
Counter-example for convex hull
First of all, using only points on the convex hull is not guaranteed to give the optimal solution. Consider this counter-example:
The convex hull is the red rectangle. However, if we use two of its sides and a diagonal to form a triangle, the diagonal will cut through the central point cluster and leave out some of the points. And even if we only use 1 or 2 corners of the rectangle, combined with a point in the center, it will always cut through the blue triangle and leave out some points. The blue triangle, which has no points on the convex hull, is in fact the optimal solution.
Triangle contained in triangle
If you consider a triangle abc, and three points d, e and f contained within it, then the triangle def cannot be the triangle which contains the most points, because triangle abc contains at least three more points. Triangles made from a combination of points from abc and def, like abd, also contain fewer points than abc.
This means that finding a triangle and some points contained within it, allows you to discard a number of triangles. In the next paragraphs, we will use this idea to discard as many triangles as possible from having to be checked.
Expanding a triangle
If we consider a triangle made from three randomly chosen points a, b and c (named clock-wise), and then check whether all other points are on the left of right side of the lines |ab|, |bc| and |ca|, the points are partitioned into 7 zones:
If we replace a corner point of the triangle by a point in the adjacent coloured zone, e.g. zone LRL for point a, we get a larger triangle that contains triangle abc. If we randomly pick three points from zones LRL, LLR and RLL, we can expand the triangle like this:
We can then partition the points again using this new triangle a'b'c' (points already in zone RRR can be added to the new zone RRR without checking) and expand the triangle again as long as there is at least one point in the zones LRL, LLR or RLL.
If we have caught enough points inside the expanded triangle, we can now use the brute force algorithm, but skip any triangle which doesn't have a point outside of the expanded triangle a'b"c'.
If we haven't caught enough points to make that feasible, we can try again with another three random points. Note, however, that you should not use the union of the points contained within several triangles; three points which are each contained in another triangle, but not in the same triangle, can still be the triangle containing the most points.
Excluding triangles in multiple steps
We could repeatedly choose a random triangle, expand it maximally, and then mark the triangles made from three points on or inside the triangle, to then exclude these from the check. This would require storing a boolean for all possible triangles, e.g. in a 3D bit array, so it is only feasible for sets up to a few thousand points.
To simplify things, instead of expanding random triangles, we could do this with a number of randomly chosen triangles, or triangles made from points on the convex hull, or points far apart when sorted in the x or y-direction, or ... But any of these methods will only help us to find triangles which can be excluded, they will not give us optimal (or even good-enough) triangles by themselves.

calculate intersection area of two triangle

I have been trying to find an algorithm which computes the intersecting area of two triangles but I failed to find any. Can anybody give a clue how to write this algorithm?
I would like something like:
double getAreaOfIntersection(Vector2 p1,Vector2 p2, Vector2 p3,Vector2 p4,Vector2 p5,Vector2 p6 )
where pX represents the 2 triangles.
You could first compute the polygon which describes the intersection area by a clipping algorithm, e.g.:
Sutherland-Hodgman algorithm
Then you would compute the area of the resulting convex polygon, which is rather easy, see, e.g., here:
Area of a Convex Polygon
Determining wether or not a point lies within a given polygon is easy (and even easier for triangles since those are simple polygons). You can use the winding number algorithm (and the crossing number algorithm for simple polygons) which is implemented and well explained here.
Using this you can obtain all the vertices of your intersection polygon:
The vertices pX of a triangle that are contained in the other triangle as well
The points where the two triangles intersect (see intersection of line segments)
You will need to loop over your edges to find all the intersection points, so this should be quick enough as long as you only want to determine intersections of triangles but i would not suggest to try to find intersections of arbitrary polygons this way.

intersection of voronoi diagram with a line

Is there a computationally efficient way to determine the points of intersection of a straight line with all the edges of a given Voronoi tessellation in a rectangular plane area?
Thanks
Once you have your first intersection point, the rest is easy.
Prepare a database of edges: for each edge, list both polygons it belongs to, or say it is the outer edge (and so belongs to one polygon only). In your picture, the lower side of the rectangle would contain 4 edges of 4 different polygons.
Draw your line, find your first intersection point ([0, 0.25] in your picture, not circled). Say it's polygon A. Then the next intersection point (the lowest one circled in your picture) also belongs to A. You find the relevant edge with a binary search through the list of edges of A.
Now you have found the second edge of A, find out which other polygon it belongs to. Then use binary search to find which other edge of that other polygon the line intersects. And so on until you exit your rectangle.

Area of Intersection of Two Rotated Rectangles

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)
.

Resources