# Regular grid

Hello there,
I’m implementing Siddon’s algorithm for the calculation of the radiological path through an array of voxels. I was wondering what would be the most Juliesque way to define a regular grid? As an array of StepRange, for example? There is probably a package around there that already defines such a structure.
Sébastien

Depends on what functionality you need from the grid.
The most bare-bones rectangular grid is `Iterators.product(1:10, 1:100)`: it can be iterated or `map`ped over, but isn’t even an array.
More extensive grids can be created with the RectiGrids.jl package. They are arrays, and even more, KeyedArrays, providing convenient lookup methods. (disclaimer: I’m the package author)

3 Likes

one quick and dirty way is to do

``````ones(5)*transpose(range(-1, 5, length=4))

5×4 Matrix{Float64}:
-1.0  1.0  3.0  5.0
-1.0  1.0  3.0  5.0
-1.0  1.0  3.0  5.0
-1.0  1.0  3.0  5.0
-1.0  1.0  3.0  5.0
``````
``````range(-1, 5, length=4)*transpose(ones(5))

4×5 Matrix{Float64}:
-1.0  -1.0  -1.0  -1.0  -1.0
1.0   1.0   1.0   1.0   1.0
3.0   3.0   3.0   3.0   3.0
5.0   5.0   5.0   5.0   5.0
``````

(@aplavin reply is definitely more Juliasque, as it does not allocate memory in advance and it can map over multiple dimensions and different type of collections, the above would be analogous to Matlab’s `meshgrid`)

Shorter:

``````julia> ones(5) * (-1:2:5)'
5×4 Matrix{Float64}:
-1.0  1.0  3.0  5.0
-1.0  1.0  3.0  5.0
-1.0  1.0  3.0  5.0
-1.0  1.0  3.0  5.0
-1.0  1.0  3.0  5.0
``````
3 Likes

To be more precise, I need a `RegularGrid` type, that knows about the number of cells in each direction, the step in each direction, etc. A kind of multidimensional `range`.

This is what I’ve come up with for the time being

``````struct RegularGrid{NDIMS,T}
size::SVector{NDIMS,Int}
step::SVector{NDIMS,T}
center::SVector{NDIMS,T}
bb_min::SVector{NDIMS, T}
bb_max::SVector{NDIMS, T}
function RegularGrid{NDIMS, T}(size, step, center) where {NDIMS, T}
bb_min = center .- 0.5 * size .* step
bb_max = center .+ 0.5 * size .* step
new(size, step, center, bb_min, bb_max)
end
end

Base.ndims(::RegularGrid{NDIMS,T}) where {NDIMS,T} = NDIMS
Base.eltype(::RegularGrid{NDIMS,T}) where {NDIMS,T} = T
Base.ndims(::Type{RegularGrid{NDIMS,T}}) where {NDIMS,T} = NDIMS
Base.eltype(::Type{RegularGrid{NDIMS,T}}) where {NDIMS,T} = T

Base.size(grid::RegularGrid{NDIMS,T}, dim) where {NDIMS,T} = grid.size[dim]
Base.step(grid::RegularGrid{NDIMS,T}, dim) where {NDIMS,T} = grid.step[dim]
``````

This does the job, but I’d rather use a struct that has already been defined in another package.

Thanks, `RectiGrids.jl` looks promising. Does the grids thus defined know about the spacing of the cells?

2 Likes

Thank you! This is definitely what I’m looking for.

Of course!

``````julia> using RectiGrids

julia> G = grid(x=1:10, y=20:10:100);

julia> axiskeys(G, :x)
1:10

julia> step(axiskeys(G, :y))
10
``````

https://www.generic-mapping-tools.org/GMT.jl/dev/types/#Grid-type