-1

I am given an array of 2D points and the task is to generate a minimal list of rectangles, where all rectangles have the same size and orientation, which cover all 2D point positions and can overlap.

So far, I have a rather unsatisfying solution, where the first point in the array is selected as center for the first rectangle and then move the rectangle so the nearest point is going to fit in. That process is repeated until an already covered point would be lost, if the rectangle is to be moved again. After that the process is repeated starting with the next uncovered point until no point is left. Not very satisfying.

The target is to figure out an optimal algorithm. It does not have to be the absolute minimal number of rectangles, but as few as possible.

Shridhar R Kulkarni
  • 6,653
  • 3
  • 37
  • 57
Aeonos
  • 365
  • 1
  • 13

2 Answers2

1

As only a heuristic solution can do, I would try as follows:

  • find the global bounding box of the points;

  • cover the bounding box with a regular grid of rectangles, with no overlaps nor gaps.

  • if a rectangle happens to be empty, discard it.

You can add a post-processing step, trying to improve:

  • select pairs of neighboring rectangles and find the bounding box of the points they cover; if that box fits in a single rectangle, merge the two rectangles.

enter image description here

Note that as the rectangles have the same size and orientation, you can rescale the data so that the rectangles become unit squares. (Also said by trincot.)

0

First of all, the coordinates can be translated/projected in such a way that the rectangle size is 1x1 and the orientation is 0° (aligned with the X/Y axis). So I will assume that situation.

Then you could proceed as follows:

  1. Sort the points by their x-coordinate
  2. Create a directed graph as follows:
    • For each point a, take the points in the x-interval [ax, ax+1], excluding a itself
    • Exclude from this list those points whose y-coordinate is not in the range [ay-1, ay+1]
    • Sort these points by y-coordinate
    • Put these points in the adjacency list for point a.
  3. Mark all points as unvisited
  4. If there are no unvisited points, return 0 to indicate that no (more) rectangles were needed.
  5. Take the next unvisited point a from the sorted list of points: mark a as visited.
  6. If a has no neighbors, then increase the rectangle count and repeat from step 4
  7. Slide a rectangle, with its left x-coordinate always equal to ax, over the neighbors, such that:
    • the first chosen rectangle has its low-y-coordinate common with the first unvisited neighbor point
    • maintain a list L of neighbors that get visited (only if they were not already marked as visited) by getting covered by this rectangle
    • all next rectangle positions each gain one unvisited point at their high-y-coordinate end.
    • The points in L that get uncovered at the low-y side of the sliding rectangle, are removed from L and marked unvisited again
    • Each time a new rectangle position is identified, a recursive (DFS) call is made that starts at step 4.
    • The DFS call will return the number of rectangles that were still needed to cover all the remaining, unvisited points
    • Keep the minimum value returned from all these recursive calls, and add 1 (for the current rectangle)
    • NB: The recursion tree can be pruned by passing the current minimum result as cut-off point, so to avoid searches that increase the number of rectangles too much.
  8. When all rectangle positions have been processed, mark any points still in L as unvisited.
  9. Return the minimum count of rectangles found.

This could still be a very expensive algorithm, as the search tree can easily become very wide.

A potential improvement could be the use of BFS instead of DFS, using a priority queue (e.g. Min Heap). The number to minimise would be the number of rectangles already used (i.e. the cost so far) plus the x-coordinate difference between the right most (unvisited) point and left-most unvisited point, rounded upwards (i.e. a lower bound of the cost still ahead). This is an A* algorithm, so you can stop the search as soon as you get a situation where all points were covered (visited).

The downside of this BFS method is the memory use and management, since each state (in the priority queue) includes a set of visited points.

trincot
  • 317,000
  • 35
  • 244
  • 286