Given a tiled, x- and y-aligned rectangle and (potentially) a starting set of other rectangles which may overlap, I'd like to find a set of rectangles so that:
- if no starting rectangle exists, one might be created; otherwise do not create additional rectangles
- each of the rectangles in the starting set are expanded as much as possible
- the overlap is minimal
- the whole tiled rectangle's area is covered.
This smells a lot like a set cover problem, but it still is... different.
The key is that each starting rectangle's area has to be maximized while still minimizing general overlap. A good solution keeps a balance between necessary overlaps and high initial rectangles sizes.
I'd propose a rating function such as that:
Higher is better.
Examples (assumes a rectangle tiled into a 4x4 grid; numbers in tiles denote starting rectangle "ID"):
easiest case: no starting rectangles provided, can just create one and expand it fully:
.---------------. .---------------. | | | | | | 1 | 1 | 1 | 1 | |---|---|---|---| |---|---|---|---| | | | | | | 1 | 1 | 1 | 1 | |---|---|---|---| => |---|---|---|---| | | | | | | 1 | 1 | 1 | 1 | |---|---|---|---| |---|---|---|---| | | | | | | 1 | 1 | 1 | 1 | ·---------------· ·---------------· rating: 16 * 1 - 0 = 16
more sophisticated:
.---------------. .---------------. .---------------. | 1 | 1 | | | | 1 | 1 | 1 | 1 | | 1 | 1 | 2 | 2 | |---|---|---|---| |---|---|---|---| |---|---|---|---| | 1 | 1 | | | | 1 | 1 | 1 | 1 | | 1 | 1 | 2 | 2 | |---|---|---|---| => |---|---|---|---| or |---|---|---|---| | | | 2 | 2 | | 2 | 2 | 2 | 2 | | 1 | 1 | 2 | 2 | |---|---|---|---| |---|---|---|---| |---|---|---|---| | | | 2 | 2 | | 2 | 2 | 2 | 2 | | 1 | 1 | 2 | 2 | ·---------------· ·---------------· ·---------------· ratings: (4 + 4) * 2 - 0 = 16 (4 + 4) * 2 - 0 = 16
pretty bad situation, with initial overlap:
.-----------------. .-----------------------. | 1 | | | | | 1 | 1 | 1 | 1 | |-----|---|---|---| |-----|-----|-----|-----| | 1,2 | 2 | | | | 1,2 | 1,2 | 1,2 | 1,2 | |-----|---|---|---| => |-----|-----|-----|-----| | | | | | | 2 | 2 | 2 | 2 | |-----|---|---|---| |-----|-----|-----|-----| | | | | | | 2 | 2 | 2 | 2 | ·-----------------· ·-----------------------· rating: (8 + 12) * 2 - (2 + 2 + 2 + 2) = 40 - 8 = 36 covering with 1 only: .-----------------------. | 1 | 1 | 1 | 1 | |-----|-----|-----|-----| | 1,2 | 1,2 | 1 | 1 | => |-----|-----|-----|-----| | 1 | 1 | 1 | 1 | |-----|-----|-----|-----| | 1 | 1 | 1 | 1 | ·-----------------------· rating: (16 + 2) * 1 - (2 + 2) = 18 - 4 = 16
more starting rectangles, also overlap:
.-----------------. .---------------------. | 1 | 1,2 | 2 | | | 1 | 1,2 | 1,2 | 1,2 | |---|-----|---|---| |---|-----|-----|-----| | 1 | 1 | | | | 1 | 1 | 1 | 1 | |---|-----|---|---| => |---|-----|-----|-----| | 3 | | | | | 3 | 3 | 3 | 3 | |---|-----|---|---| |---|-----|-----|-----| | | | | | | 3 | 3 | 3 | 3 | ·-----------------· ·---------------------· rating: (8 + 3 + 8) * 3 - (2 + 2 + 2) = 57 - 6 = 51
The starting rectangles may be located anywhere in the tiled rectangle and have any size (minimum bound 1 tile).
The starting grid might be as big as 33x33 currently, though potentially bigger in the future.
I haven't been able to reduce this problem instantiation to a well-problem, but this may only be my own inability.
My current approach to solve this in an efficient way would go like this:
if list of starting rects empty:
create starting rect in tile (0,0)
for each starting rect:
calculate the distances in x and y direction to the next object (or wall)
sort distances in ascending order
while free space:
pick rect with lowest distance
expand it in lowest distance direction
I'm unsure if this gives the optimal solution or really is the most efficient one... and naturally if there are edge cases this approach would fail on.
1
(or2
)? Similar for upper half of example 4. – jdehesa1
or2
would satisfy the minimum overlap requirement, but not the "maximize all starting rects" one. A balance of these two is the optimal solution. – Ionic1
, overlap 2, sizes 16 and 2 c) cover everything with1
and2
, overlap 16, sizes 16 and 16. Is there anyway to tell which one is the best trade-off, like a weighting or some additional rule? – jdehesa