Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

An algorithm to solve a simple(?) array problem

For this problem speed is pretty crucial. I've drawn a nice image to explain the problem better. The algorithm needs to calculate if edges of a rectangle continue within the confines of the canvas, will the edge intersect another rectangle?

We know:

  1. The size of the canvas
  2. The size of each rectangle
  3. The position of each rectangle

The faster the solution is the better! I'm pretty stuck on this one and don't really know where to start.

alt text http://www.freeimagehosting.net/uploads/8a457f2925.gif

Cheers

like image 418
Tom Gullen Avatar asked Jul 08 '10 12:07

Tom Gullen


5 Answers

Just create the set of intervals for each of the X and the Y axis. Then for each new rectangle, see if there are intersecting intervals in the X or the Y axis. See here for one way of implementing the interval sets.

In your first example, the interval set on the horizontal axis would be { [0-8], [0-8], [9-10] }, and on the vertical: { [0-3], [4-6], [0-4] }

This is only a sketch, I abstracted many details here (e.g. usually one would ask an interval set/tree "which intervals overlap this one", instead of "intersect this one", but nothing not doable).

Edit

Please watch this related MIT lecture (it's a bit long, but absolutely worths it). Even if you find simpler solutions (than implementing an augmented red-black tree), it's good to know the ideas behind these things.

like image 70
Dimitris Andreou Avatar answered Oct 18 '22 14:10

Dimitris Andreou


Lines that are not parallel to each other are going to intersect at some point. Calculate the slopes of each line and then determine what lines they won't intersect with.

Start with that, and then let's see how to optimize it. I'm not sure how your data is represented and I can't see your image.

Using slopes is a simple equality check which probably means you can take advantage of sorting the data. In fact, you can probably just create a set of distinct slopes. You'll have to figure out how to represent the data such that the two slopes of the same rectangle are not counted as intersecting.

EDIT: Wait.. how can two rectangles whose edges go to infinity not intersect? Rectangles are basically two lines that are perpendicular to each other. shouldn't that mean it always intersects with another if those lines are extended to infinity?

like image 29
NG. Avatar answered Oct 18 '22 15:10

NG.


as long as you didn't mention the language you chose to solve the problem, i will use some kind of pseudo code

the idea is that if everything is ok, then a sorted collection of rectangle edges along one axis should be a sequence of non-overlapping intervals.

  1. number all your rectangles, assigning them individual ids
  2. create an empty binary tree collection (btc). this collection should have a method to insert an integer node with info btc::insert(key, value)
  3. for all rectangles, do:

foreach rect in rects do
    btc.insert(rect.top, rect.id)
    btc.insert(rect.bottom, rect.id)
  1. now iterate through the btc (this will give you a sorted order)

btc_item = btc.first()
do
    id = btc_item.id
    btc_item = btc.next()
    if(id != btc_item.id)
    then report_invalid_placement(id, btc_item.id)
    btc_item = btc.next()
while btc_item is valid

5,7,8 - repeat steps 2,3,4 for rect.left and rect.right coordinates

like image 21
ULysses Avatar answered Oct 18 '22 13:10

ULysses


I like this question. Here is my try to get on it:

If possible: Create a polygon from each rectangle. Treat each edge as an line of maximum length that must be clipped. Use a clipping algorithm to check weather or not a line intersects with another. For example this one: Line Clipping

But keep in mind: If you find an intersection which is at the vertex position, its a valid one.

like image 25
InsertNickHere Avatar answered Oct 18 '22 15:10

InsertNickHere


Here's an idea. Instead of creating each rectangle with (x, y, width, height), instantiate them with (x1, y1, x2, y2), or at least have it interpret these values given the width and height.

That way, you can check which rectangles have a similar x or y value and make sure the corresponding rectangle has the same secondary value.


Example:

The rectangles you have given have the following values:

  • Square 1: [0, 0, 8, 3]
  • Square 3: [0, 4, 8, 6]
  • Square 4: [9, 0, 10, 4]

First, we compare Square 1 to Square 3 (no collision):

  • Compare the x values
    • [0, 8] to [0, 8] These are exactly the same, so there's no crossover.
  • Compare the y values
    • [0, 4] to [3, 6] None of these numbers are similar, so they're not a factor

Next, we compare Square 3 to Square 4 (collision):

  • Compare the x values
    • [0, 8] to [9, 10] None of these numbers are similar, so they're not a factor
  • Compare the y values
    • [4, 6] to [0, 4] The rectangles have the number 4 in common, but 0 != 6, therefore, there is a collision

By know we know that a collision will occur, so the method will end, but lets evaluate Square 1 and Square 4 for some extra clarity.

  • Compare the x values
    • [0, 8] to [9, 10] None of these numbers are similar, so they're not a factor
  • Compare the y values
    • [0, 3] to [0, 4] The rectangles have the number 0 in common, but 3 != 4, therefore, there is a collision

Let me know if you need any extra details :)

like image 25
Justian Meyer Avatar answered Oct 18 '22 14:10

Justian Meyer