views:

307

answers:

2

This problem actually deals with roll-overs, I'll just generalized below as such:

I have a 2D view, and I have a number of rectangles within an area on the screen. How do I spread out those boxes such that they don't overlap each other, but only adjust them with minimal moving?

The rectangles' positions are dynamic and dependent on user's input, so their positions could be anywhere.

Attachedalt text images show the problem and desired solution

The real life problem deals with rollovers, actually.

Answers to the questions in the comments

  1. Size of rectangles is not fixed, and is dependent on the length of the text in the rollover

  2. About screen size, right now I think it's better to assume that the size of the screen is enough for the rectangles. If there is too many rectangles and the algo produces no solution, then I just have to tweak the content.

  3. The requirement to 'move minimally' is more for asethetics than an absolute engineering requirement. One could space out two rectangles by adding a vast distance between them, but it won't look good as part of the GUI. The idea is to get the rollover/rectangle as close as to its source (which I will then connect to the source with a black line). So either 'moving just one for x' or 'moving both for half x' is fine.

+4  A: 

Here's a guess.

Find the center C of the bounding box of your rectangles.

For each rectangle R that overlaps another.

  1. Define a movement vector v.
  2. Find all the rectangles R' that overlap R.
  3. Add a vector to v proportional to the vector between the center of R and R'.
  4. Add a vector to v proportional to the vector between C and the center of R.
  5. Move R by v.
  6. Repeat until nothing overlaps.

This incrementally moves the rectangles away from each other and the center of all the rectangles. This will terminate because the component of v from step 4 will eventually spread them out enough all by itself.

cape1232
Good idea finding the center and moving the rectangles about it. +1 The only problem is that finding the center is another problem all on its own, and one which is likely much more challenging for each rectangle that you add.
NickLarsen
Finding the center is easy. Just take the min and max of the corners of all the rectangles. And you only do it once, not once per iteration.
cape1232
This results in minimal moving as well, in the sense that it doesn't move a rectangle if nothing overlaps it. Oh, step 4 does, so you should skip step 4 if there are no overlaps. Finding the actual arrangement that requires minimal movement is probably much more difficult.
cape1232
For two rectangles located in a corner of the visible area the alg should be able to understand if the graph should be expanded or contracted. Just ranting. (I know that visibility is not on the scope yet, but I guess it is important not to solve the problem by just expanding the graph enough, because if not the solution is trivial: take the two nearest squares and "irradiate" all the graph from its center of mass enough to get those two rectangles apart). Your approach is better than this, of course. I am just saying that we should not expand unless it's necessary.
belisarius
@belisarius This doesn't expand if it is not necessary. Once nothing overlaps your rectangle, it stops moving. (It may start again, but only when it needs to.) With enough rectangles or ones big enough, it may not be possible to show them all on screen at full size. In that case, it is easy to find the bounding box of the respaced solution and scale everything the same amount so they fit on screen.
cape1232
I mean that your vector v should in some cases be -v, arghhhh ... too difficult to show the idea without a drawing !!
belisarius
Contracting is an interesting related problem, but one of the original requirements was "minimal movement". So if a rectangle isn't overlapping anything, it shouldn't move.
cape1232
+33  A: 
belisarius
+1 What an informative/meticulous answer!!!
Bragboy
Nice one. My friend and I are trying to implement it. *cross fingers* Thanks for the time to put this up!
Extrakun
@Extrakun Just ask if something is not clearly explained. English is not my first language!
belisarius
+1 for coördinates
Dave
Beska