Given some rectangles inside of a larger rectangle, is there any algorithm to split the remaining space into rectangles, and preferably as few as possible?
One way to solve the problem is to reduce the rectangles to a mesh. Each rectangle corner becomes a vertex (x,y) and each rectangle's side is a line that references two vertices. Vertices that are on a line (eg two rectangle are touching) must split the line at that vertex. There may only be one line joining any two vertices. The bounding rectangle is included.
Once you have the rectangles converted to a mesh then for each vertices count the number of lines that use that vertex.
If a vertex has only 2 lines joining it and is not a bounding corner, then it must be extended, it will have two optional directions, horizontal and vertical. There is no rule in which direction is the best so pick a random direction. In that direction and moving away from the lines coming to the vertex add a vertex to the closest intersecting line. Continue the process until no vertices (apart from the bounding corners) have less than 3 lines connected to it.
Now start at the top left most vertex and trace the lines in a clockwise direction, each 4 lines is a rectangle when you get back to the starting vertex you have a new rectangle Use the min and max vertex coordinates in the x and y direction to define the size of the rectangle. For each line decrease its vertices line count by 1. When a vertex has a line count of zero remove the vertex; When all vertices are removed you are done.
This will create the minimum number of rectangles possible.
To know if a solution is the minimum rectangle count check that each vertex has ONLY 3 lines joining it (Your example image is the minimum number of rectangle because no vertex has more than 3 lines joining it)
The only exception to this rule is if the existing rectangles are touching at a corner. Only existing vertices may have 4 lines joining.
Using a bsp tree: insert each rectangle edge in the tree. This will partition the space into convex subsets. Since your input are rectangles, the convex subsets can only be rectangles (https://en.wikipedia.org/wiki/Binary_space_partitioning).
Note that the partition depends on the order in which you insert the edges.
I'm not sure though that this will give you the minimum number of rectangles, but you will get close.
Related
Let's say we have a class/struct Point
class Point
{
int x;
int y;
}
and a class Polygon that contains list of Points
class Polygon
{
List<Point> points;
Path(List<Point> points)
{
//some implementation
}
}
I am interested in finding the Minimal bounding rectangle points of the Polygon(https://en.wikipedia.org/wiki/Minimum_bounding_rectangle). The found minimal bounding rectangle sides might not be parallel to both axis , so I am trying to find an algorithm written in Java,C#,C++ .Can anyone propose or link such a solution, thanks!
It is possible to construct minimal bounding box (both min-area and min-perimeter) using Rotating Calipers approach.
You can find description at this wayback archive page
The minimum area rectangle enclosing a convex polygon P has a side
collinear with an edge of the polygon.
The above result dramatically restricts the range of possible
rectangles. Not only is it not necessary to check all directions, but
only as many as the polygon's number of edges.
Illustrating the above result: the four lines of support (red), with
one coinciding with an edge, determine the enclosing rectangle (blue).
A simple algorithm would be to compute for each edge the corresponding
rectangle collinear with it. But the construction of this rectangle
would imply computing the polygon's extreme points for each edge, a
process that takes O(n) time (for n edges). The entire algorithm would
then have quadratic time complexity.
A much more efficient algorithm can be found. Instead of recomputing
the extreme points, it is possible to update them in constant time,
using the Rotating Calipers. Indeed, consider a convex polygon, with a
two pair of lines of support through all four usual extreme points in
the x and y directions. The four lines already determine an enclosing
rectangle for the polygon. But unless the polygon has a horizontal or
vertical edge, this rectangle is not a candidate for the minimum area.
However, the lines can be rotated until the above condition is
satisfied. This procedure is at the heart of the following algorithm.
The input is assumed to be a convex polygon with n vertices given in
clockwise order.
Compute all four extreme points for the polygon, and call them xminP,
xmaxP, yminP ymaxP.
Construct four lines of support for P through all four points. These
determine two sets of "calipers".
If one (or more) lines coincide with an edge, then compute the area of
the rectangle determined by the four lines, and keep as minimum.
Otherwise, consider the current minimum area to be infinite.
Rotate the lines clockwise until one of them coincides with an edge of
its polygon.
Compute the area of the new rectangle, and compare it to the current
minimum area. Update the minimum if necessary, keeping track of the
rectangle determining the minimum.
Repeat steps 4 and 5, until the lines have been rotated an angle
greater than 90 degrees. Output the minimum area enclosing rectangle.
Because two pairs of "calipers" determine an enclosing rectangle, this
algorithm considers all possible rectangles that could have the
minimum area. Furthermore, aside from the initialization, there are
only as many steps in the algorithm's main loop as there are vertices.
Thus the algorithm has linear time complexity.
You can do this as follows:
Find the convex hull of the polygon points. A popular method is the Graham scan.
For each edge of the convex hull, find the minimum bounding rectangle that must have one side overlapping with that edge, so that the convex hull's edge is a subsegment of that rectangle's side.
Find the two perpendicular sides of the rectangle by walking along the convex hull vertices, and projecting the vertex to the first side, retaining the two that have all other projections between them. The final opposite side can be found in a similar manner. The vertices that lie on the rectangle, should be the starting point for when this step is executed again for the next edge on the convex hull (step 2).
Calculate the size of these rectangles, and retain the minimal one.
The complexity of this algorithm is determined by the first step, which is O(nlogn). The second step is O(n), as you have a selection of one edge and 3 vertices that rotates around the convex hull, visiting each edge once, and each vertex 3 times.
Points from (0,0) to (R,C) in the cartesian plane are colored r, g or b. Make a triangle using these points such that-
a) All three vertices are of different colors.
b) At least one side of triangle is parallel to either of the axes.
c) Area of the triangle is maximum possible.
Output the maximum possible area.
Constraints : 1<=R<=1000 , 1<=C<=1000
Can someone please let me know the approach to this question?
The area of a triangle is 1/2 * base * height. So if one side of the triangle is parallel to the
x-axis, then the base of the triangle is formed by two colors on the same row (spread as far apart as possible), and the third color should be on the row that's farthest from the base. Hence, you can preprocess the data to find:
the top-most and bottom-most row for each color
the left-most and right-most column for each color on every row
Then for every row, you have twelve possibilities for forming a triangle, e.g.
left-most-red, right-most-blue, top-most green
left-most-red, right-most-blue, bottom-most green
left-most-red, right-most-green, top-most blue
...
And of course, there's the corresponding process for triangles with one edge parallel to the y-axis.
Thus, the problem can be solved in O(R*C) time, where most of the time is spent in the preprocessing.
Suppose you have a set of triangles, like the one shown in the image below, where black is a triangle edge, red is a triangle point, green is the polygon that needs to be found, and blue is the polygon's points.
The polygon described may or may not be concave. The triangles in it will always be adjacent (share all three points with the other triangles in the set).
What sort of algorithms exist to generate the polygon that such a set of triangles describes? The polygon should be in the form of a list of points in clockwise or counter-clockwise order.
How About Following A simple GrahamScan Algo... That's should Do the Trick.
Assume you have N distinct points Pi and M triangles. We define each triangle by 3 indices i, j and k to the points. Each triangle will have 3 edges defined as E(i,j), E(j,k) and E(i,k). The way to find the "polygon" is as follows:
1) Loop thru all triangles. For each triangle, add the 3 edges into a set. Edges with two identical point indices should be considered as the same edge. Namely, E(i,j) = E(j,i). Once encounter such case, remove both E(i,j) and E(j,i) from the set as these are the interior edges.
2) The remaining edges in the set should be the edges forming the polygon.
3) Sort the edges in the set by the point indices as follows:
(3a) Pick any edge from the set, say E(i,j).
(3b) Add indices i and j into a std::vector, then remove E(i,j) from the set.
(3c) Find the edge from the set that shares the last point index in the std::vector (which is j now). Denote this edge as E(j,k). Add index k into the std::vector and remove E(j,k) from the set.
(3d) Repeat step (3c) until the set contains no edges. The point indices in the std::vector will be the points order for the polygon.
If you only have M triangles and 3*M (x, y) values for the triangle vertices, then you will need to do some pre-processing to remove identical points and re-define the triangles in terms of the point indices as stated above.
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.
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)
.