Creating rectangles from an array of coordinates / points

http://img853.imageshack.us/img853/2475/picture1eu.jpg

I have an ArrayList of points / coordinates, which is a Rectilinear Polygon. Now I want to split this shape into rectangles using the saved points in my ArrayList.

I started the algorithm, but I can’t finish it, and I feel that it will be easier:

ArrayList is called "allCoordinates".
ArrayList "xMatch" and "yMatch" are subsets of allCoordinates.

Algorithm:

ArrayList yMatch = All matching Coordinates in respect to 'y' 


So, in the case of this diagram above:
(Set 1 = [x1, y1] - [x8, y8],
Set2 = [x7, y7] - [x2, y2],
Set3 = [x4, y4] [x5, x5],
Set4 = [x3, y3] [x6, x6])

 ArrayList xMatch = All matching Coordinates in respect to 'x' 


So, in the case of this diagram above:
(Set 1 = [x1, y1] - [x2, y2],
Set2 = [x3, y3] - [x4, y4],
Set3 = [x5, y5] [x6, x6],
Set4 = [x7, y7] [x8, x8])



So now I have two arrays, all vertical edges and all horizontal edges. Now I need some way to check if they all connect together? As I said, this will be an easier way ...?

Edit:

Can I just make it clear that the rectangles should be formed using intersecting lines that start and end on existing coordinates. For example, you can draw a line from (x6, y6) horizontally and end along the edge (x1, y1) - (x8, y8). This line would start at the existing coordinate, but it would not end the existing coordinate. Therefore, the string is invalid.

+4
source share
4 answers

As you already noticed, I keep coming back to this problem. Partly because I like to solve these problems, but also because it annoyed me a bit, that I could not find an elegant algorithm for something that seems so easy.

Well, don't be fooled, this is not a trivial problem that you can solve with some simple dot manipulation, although it certainly does. This is partly due to the fact that although you think that you work only with points, you also secretly manipulate line segments and the areas covered by them, which also have their own limitations (i.e., segments should always form one or more closed chains and cannot intersect, except for the vertices that we define them c).

In addition, your algorithm should work on any input that you feed it. That is, it is not allowed to give an answer or an incorrect answer just because the polygon that you fed it is oriented in such a way that your algorithm is not like.
However, you can limit the type of input that your algorithm accepts. Therefore, the requirement that the input polygon contains only axes aligned along the axis is perfectly valid. (The difference between “incorrectly oriented” and “only axis-oriented segments” is that the first is vague criteria that cannot be determined without checking it on the algorithm, while the second may be).

To reproduce, we are looking for a way to horizontally split any rectangular polygon (i.e., consisting only of line segments along the axis) into rectangles.

Example of a rectilinear polygon Rectangular Polygon Example

Here's the plan:

  • Choose our building blocks
  • Allow Extra Peaks
  • Grid Alignment.
  • Work with grid cells with uneven size.
  • What cells are inside your polygon?
  • Building rectangles.

Choose our building blocks

Although these are implementation details, getting this clear background may help you better understand how the algorithm works.

In the code, we will use the following types of objects as the main building blocks to represent our polygon with:

  • Point consisting of x and y coordinates. (e.g. use Point2D.Double )
  • A segment consisting of a start and end point (e.g. use Line2D.Double )
  • A polygon consisting of a closed chain of segments (for example, use an ArrayList from Line2D.Double), where one segment ends at the same point as the starting point for the next segment.

In addition, we will use a grid that can be modeled as a two-dimensional array.

Allow extra vertices.

You stated that "rectangles should be formed using intersecting lines that begin and end on existing coordinates." However, note that most rectilinear polygons cannot be divided into rectangles using existing vertices only - see the Example above (as well as the caravan examples given earlier).

Therefore, this restriction will have to go - although we will not actually create new vertices explicitly.

Grid Alignment.

A thought experiment: what if your polygon existed only from (axis aligned) segments of length 10, 20, 30 or 40 ... i.e. multiples of 10? Then we could project our polygon onto a grid and use the grid cells that lie inside the polygon to compose the rectangles. Also, sizing these rectangles would be a breeze: just count the number of horizontally consecutive cells that lie inside the polygon and multiply by 10; what is your width.

Grid-aligned polygon Grid Aligned Polygon

Good idea besides:

  • A polygon does not consist of segments of the same or multiple lengths
  • How to determine which mesh cells lie inside a polygon?

We will consider each of the following issues.

Work with grid cells with uneven size.

If you think about it, there is no real reason that all grid cells have the same width and height. Therefore, we can create a grid located at a distance, so that our polygon coincides perfectly with it.

To get the width of the horizontal axes of the grid:

  • Collect all the x-coordinates of the vertices that make up the polygon.
  • Duplicate and sort them by increasing cost.
  • The difference between the two subsequent values ​​determines the width of this column.

Grid aligned to the polygon Polygon matched mesh

Obviously, the cell heights can be determined identically. You must define these widths and heights and store them in two arrays called gridWidths and gridHeights , respectively.

Now that we know the number of cells and their sizes, we can start modeling the contents of the grid.

What cells are inside your polygon?

Remember that our polygon is stored as a chain of line segments. To determine whether a grid cell is inside this polygon, we can use an even rule : construct a line segment outside * the polygon in the center of the cell we want to check, and count the number of intersections between this line segment and the polygon segments (i.e. use Line2D .Double intersectsLine () ). If the number is equal, it lies outside the polygon; if it is odd, it is inside the polygon.

* - It is best to build only horizontal line segments between the centers of the cells (as shown in the example), so that you do not run the risk of crossing the end points of the segment - this can be considered as 0 or 2 intersections, ruining your score.

So, we will model this grid as a grid , a two-dimensional array of Booleans. Treat each grid cell in this way and mark the corresponding spot in the grid as true (inside the polygon) or false (outer polygon).

Inside (T) or outside (F) based on the even-odd rule Inside (T) or outside (F) based on an even-odd rule

Building rectangles.

Now that we have a view of the polygon mesh, as well as the actual widths and heights of each cell, we can start building rectangles. I assume that you are only interested in the width and height of each rectangle, and not in the actual coordinates of the vertices that make up the rectangle (although this is now easy too).

 Foreach row in grid run_start = null Foreach cell C in row if C is marked as true and run_start = null //Found the start of a new run run_start = C else if C is marked as false and run_start != null //Found the end of a run The cells [run_start...C] form a horizontal rectangle. Use the gridWidths and gridHeights arrays to determine the dimensions, and report this rectangle as a result //Prepare for the next run run_start = null 

The polygon, partitioned into rectangles. A polygon divided into rectangles.

Please note that the two rectangles in the upper left corner have the same start and end x-coordinates and therefore can be considered as one rectangle. If you want, you can implement an extra pass that combines these types of rectangles.

Conclusion

Comparing a rectilinear polygon on a grid, we can easily divide it horizontally in rectangles without resorting to more complex geometric data structures. Please note that there are some optimization possibilities for this algorithm to work faster, but I don’t think it really matters for the current input sizes, and this will make implementation difficult.

+5
source

It is not simple:

I think that you will not successfully solve this yourself:

See details

Preparations, Chamos: computational geometry: chapter 8: Geometry Rectangles.

You should be familiar with sweep algorithms and spanning trees first.

If I find more, I will update. Found more:

The algorithm for finding the smallest rectangles to cover a set of rectangles without overlapping

+3
source

Note. I'm not going to theoretically optimal solution here, but only for an approach that gives the correct answer and works fast enough on the input polygon, for example, 100 vertices. In addition, special cases, such as an input polygon with holes in it, are no longer considered. In addition, polygons that are not x-monotonic * need preprocessing, which I will not talk about yet.
* Meaning: starting from any left position in P, you can reach any other position by moving up, down or to the right, but without leaving it.

Assumptions
As indicated in an earlier post , part of the question is in which direction to lay the decks (or “rectangles”) in order to minimize the number of decks used. I assume that your input polygon P will consist mainly of axial segments, so the choice in the direction decreases to horizontal or vertical. For the rest, I will assume that one flooring board is always oriented vertically (i.e. it goes from top to bottom). To calculate the result with horizontal boards, rotate P 90 degrees.

Description of the problem
We will try to cover P with terraces, each of which has unlimited length and maximum width W. In particular, we are looking for a coating that minimizes the total length of all used boards. Parts of used flooring that go beyond P (i.e. Losses) cannot be used to cover other parts of P. To minimize losses, it makes sense to align either the left or right border of the flooring with the vertex P, or place the floorboard next to another board.

Decision
The first step to this is to partition P into a set of vertical plates: take the different x-coordinates of all the vertices in P and sort them: each pair of consecutive x-coordinates then defines a plate S from P. Figure 1

Further, it should be recognized that for each plate S we have 4 possible ways to align (one or more) boards for boards: * (SL) Start left, i.e. Align the left side of the board with the left side of the board.
* (CL) Continue left, i.e. Continue drawing the decks defined by the slab to the left of it.
* (CR) Continue to the right, i.e. Continue the flooring pattern defined by the slab to the right of it.
* (SR) Start right, i.e. Align the right side of the board with the right side of the board.

Therefore, if we consider all possible combinations of 4 alignments for each of the S slabs, we have all possible flooring configurations. Note that not all alignment combinations are allowed; SL and SR can be used for any plate, but CL can only be used if the plate to its left is SL or CL, and CR can only be used if the plate to its right is SR or CR.

-Snip- The problem, apparently, is significantly different from what it is trying to solve here, so I will not end this post.

+1
source

I found a solution, but it is probably not the most optimal.


link

So, here we have our coordinates and the two ArrayList lists mentioned earlier - xMatch and yMatch.

xMatch = ArrayList coordinate pairs with corresponding x coordinates
yMatch = ArrayList coordinate pairs with corresponding y coordinates

I created a class called "Point2Point" that stores two batches of coordinates in a specific order. Both xMatch and yMatch are of type "Point2Point". Like any vector, order is important. I used the following order:


Point1 = starting point
Point2 = endpoint.

So now, using the for loop, I have mapped an element from xMatch to an element from yMatch with respect to Point1 (starting point). Comparing them, you get the following form:



Link2


Now it can be seen in this diagram that in order for these two vectors to be part of a rectangle, a coordinate (?,?) Must exist. Using the properties of a rectangular rectangle, I know that (?,?) Is equal to (yMatch.Point2.x, xMatch.Point2.y) or with respect to this diagram (x3, y2).


So now that I know what coordinates to look for, I can search in my ArrayList "allCoordinates" to see if these coordinates exist. If so, I have a right-angled nickname; if not, it's stupid!

0
source

All Articles