What is the correct coordinate parameter format/syntax to find the intersection of two rectangles

StackOverflow https://stackoverflow.com/questions/23473004

  •  15-07-2023
  •  | 
  •  

Question

I have this exercise:

Write a function, `rec_intersection(rect1, rect2)` and returns the
intersection of the two.

Rectangles are represented as a pair of coordinate-pairs: the
bottom-left and top-right coordinates (given in `[x, y]` notation).

I am trying to figure out how to call the method with puts and test out some value so I make sure I understand this problem. I've been struggling with this one for some reason.

This is the answer to the problem:

def rec_intersection(rect1, rect2)
  x_min = [rect1[0][0], rect2[0][0]].max
  x_max = [rect1[1][0], rect2[1][0]].min

  y_min = [rect1[0][1], rect2[0][1]].max
  y_max = [rect1[1][1], rect2[1][1]].min

  return nil if ((x_max < x_min) || (y_max < y_min))
  return [[x_min, y_min], [x_max, y_max]]
end

When I try to call the method using puts with code like this:

v = ([0,0][2,1])
w = ([1,0][3,1])
puts rec_intersection(v, w)

I get the following error:

calc.rb:2:in `rec_intersection': undefined method `[]' for nil:NilClass (NoMetho
dError)
        from calc.rb:14:in `<main>'

And when I try this:

v = [(0,0)(2,1)]
w = [(1,0)(3,1)]
puts rec_intersection(v, w)

I get this error:

calc.rb:12: syntax error, unexpected ',', expecting ')'
v = [(0,0)(2,1)]

What is the right format to pass the rectangle coordinate parameters to be able to call the functions with puts?

Was it helpful?

Solution 2

This two lines are wrong:

v = ([0,0][2,1])
w = ([1,0][3,1])

Your code defines an array [0,0] and than calls the [] method on that array (see) with the arguments 2 and 1. That means: start at the second position and take 1 element from the array. What leads to an empty array...

You need to define an array of arrays like this:

v = [ [0,0], [2,1] ]
w = [ [1,0], [3,1] ]

OTHER TIPS

Now that your question has been answered, I would like to suggest a way of doing this that I think is more Ruby-like, as it does not make use of indices. It also generalizes to dimensions higher than two (though that may be of no immediate interest).

Note that regardless of which method you use, you can generalize it to determining the intersection of any number of rectangles by first determining the intersection of the first two, then the intersection of that result with the third rectangle, and so on.

Code

def rec_intersection(rec1,rec2)
  rec1.zip(rec2, [:max, :min])
      .map { |*a,method| a.transpose.map { |b| b.send method } }
end

Examples

Suppose your overlapping rectangles looked like this.

Overlapping rectangles

The two rectangles are:

rec1 = [[0,0],[3,4]]
rec2 = [[2,2],[5,5]]

Therefore:

rec_intersection(rec1,rec2)
  #=> [[2, 2], [3, 4]]

One nice thing about this method is that it can be applied to overlapping boxes (orthotopes or hyperrectangles) in any number of dimensions. Suppose you have these two boxes in three dimensions:

enter image description here

The two rectangles are:

rec1 = [[0,0,0],[3,4,3]]
rec2 = [[2,3,1],[5,8,5]]

Therefore:

rec_intersection(rec1,rec2)
  #=> [[2, 3, 1], [3, 4, 3]]

Explanation

Consider the first example above:

rec1 = [[0,0],[3,4]]
rec2 = [[2,2],[5,5]]

We use Array#zip in order to compare the lower-left and upper-right coordinates of the two rectangles:

c = rec1.zip(rec2, [:max, :min])
  #=> [[[0, 0], [2, 2], :max], [[3, 4], [5, 5], :min]]

Notice that we also pass methods to each of these arrays: Enumerable#max for the first, Enumerable#min for the second.

Enumerable#map passes each element of c (of which there are two) into its block and assigns values to the block variables a and method. The first is:

a => [[0, 0], [2, 2]]
method => :max

Next we apply Array#transpose to a:

d = a.transpose
  #=> [[0, 2], [0, 2]]

and then map each of these arrays into the maximum of the elements by sending maxto the array:

d.map { |b| b.send method } #=> [2,2]

This gives us the maxima of the x and y coordinates, resulting in the first element of b being replaced with [2,2]. Next, map passes:

[[3, 4], [5, 5], #<Proc:0x00000101138498>]

into the block, assigning it to the block variables:

a  => [[3, 4], [5, 5]]
method => :min

Since :min computes the minimum of an array, we obtain:

d = a.transpose
  #=> [[3, 5], [4, 5]]
d.map { |b| b.send method } #=> [3,4]

The second element of b is therefore replaced with [3,4] and the method returns:

[[2, 2], [3, 4]]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top