Index to coordinates conversion, according the matrix shape

P

Paul A.

Hello,

I would like to converte an index (of a flatten array) to a
multi-dimensions coordinates (of the multi-dimensions version of the
previous flatten array).

Example:

Considering the following 2 dimensions array (3x3):

[ [ -, -, - ],
[ *, -, - ],
[ -, -, - ] ]

We can see that, the coordinates of the checked case is [0, 1].

Now, if we flat this array, it looks like:

[ -, -, -, *, -, -, -, -, - ]

Here, we can see the coordinate (or the index) of the checked case is 3.

But how can we do the opposite? I mean, a method looking like:

index_to_coordinates([3, 3], 3) # => [0, 1]

Thanks!
 
H

Hashmal

This is a perfect case for modulo (%). It gives the remainder of a division.

def index_to_coordinates arr_size, index
x = index % arr_size[0]
y = (index - x) / arr_size[0]
return x, y
end

coordinates [3, 3], 3 # => [0, 1]

You will notice that the "matrix height" (arr_size[1]) is not used for
the calculation. However, you might want to check that the index you ask
is not out of bounds.

PS: I usually make some stupid mistakes when doing math, so the code
above may be incorrect. However, the basic idea is here: modulo.
 
P

Paul A.

Hashmal wrote in post #997453:
This is a perfect case for modulo (%). It gives the remainder of a
division.

def index_to_coordinates arr_size, index
x = index % arr_size[0]
y = (index - x) / arr_size[0]
return x, y
end

coordinates [3, 3], 3 # => [0, 1]

Waw, thanks. But... is this okay with matrix of more then 2 dimensions?
:)

Such as this one:

NArray.object(2,3,2):
[ [ [ nil, nil ],
[ nil, nil ],
[ nil, nil ] ],
[ [ nil, nil ],
[ nil, nil ],
[ nil, nil ] ] ]
 
F

F. Senault

Le 9 mai 2011 à 00:14, Paul A. a écrit :
But how can we do the opposite? I mean, a method looking like:

index_to_coordinates([3, 3], 3) # => [0, 1]

A small example from a project of mine. Maybe you'll find things of
interest (the each method does that conversion, for instance).

class Grid
include Enumerable

attr_reader :width, :height, :depth
def initialize(width, height, depth)
@width = width
@height = height
@depth = depth
@tiles = Array.new(width * height * depth)
end

def include?(x, y, z)
(0..@width).include?(x) &&
(0..@height).include?(y) &&
(0..@depth).include?(z)
end

def [](x, y, z)
if include? x, y, z
@tiles[z * @width * @height + y * @width + x]
else
raise "Tile out of bound : (#{x}, #{y}, #{z}) - #{self}"
end
end

def []=(x, y, z, v)
if include? x, y, z
@tiles[z * @width * @height + y * @width + x] = v
else
raise "Tile out of bound : (#{x}, #{y}, #{z}) - #{self}"
end
end

def each
@tiles.each_with_index do |v, i|
yield v,
i % @width, # x
(i / @width) % @height, # y
i / (@height * @width) # z
end
end

def window(x, y, z, w, h, d)
z.upto(z + d - 1) do |sz|
y.upto(y + h - 1) do |sy|
x.upto(x + w - 1) do |sx|
yield self[sx, sy, sz], sx, sy, sz
end
end
end
end
end

Fred
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top