spat v0.2.0 Spat

Functions for dealing with indexes.

Link to this section Summary

Functions

Get the index adjacent to the another index given a certain offset

Decode an encoded packed grid index

Encode a packed grid index

Pack a grid index into a bitstring

Get the bounds a grid index references

Unpack a grid index from a bitstring

Link to this section Types

Link to this type address_modes()
address_modes() :: :clamp | :wrap
Link to this type encoded_index()
encoded_index() :: String.t()
Link to this type grid_index()
grid_index() :: [non_neg_integer()]
Link to this type packed_grid_index()
packed_grid_index() :: bitstring()
Link to this type packing_options()
packing_options() :: [{:reverse, boolean()}]
Link to this type unpacking_options()
unpacking_options() :: packing_options()

Link to this section Functions

Link to this function adjacent(index, dimensions, subdivisions, offset, opts \\ [])

Get the index adjacent to the another index given a certain offset.

Addressing modes can be provided ([addressing: mode]) to specify the behaviour when referencing an index that is beyond the maximum bounds. The possible addressing modes are:

  • :clamp - Will clamp the bounds from min to max. (default)
  • :wrap - Will start from the opposing side.

iex> bounds = Spat.Bounds.new({ 10, 10 })
...> point = {2.6,0}
...> subdivisions = 2
...> [index] = Spat.Geometry.Point.index(point, bounds, subdivisions)
...> Spat.to_bounds(Spat.adjacent(index, Spat.Coord.dimension(point), subdivisions, { 1, 2 }), bounds)
Spat.Bounds.new([5.0, 5.0], [7.5, 7.5])

iex> Spat.adjacent([0, 0], 2, 2, { 4, 0 }, addressing: :clamp)
[1, 1]

iex> Spat.adjacent([0, 0], 2, 2, { 5, 0 }, addressing: :clamp)
[1, 1]

iex> Spat.adjacent([0, 0], 2, 2, { 4, 0 }, addressing: :wrap)
[0, 0]

iex> Spat.adjacent([0, 0], 2, 2, { 5, 0 }, addressing: :wrap)
[0, 1]

iex> Spat.adjacent([0, 0], 2, 2, { -1, 0 }, addressing: :clamp)
[0, 0]

iex> Spat.adjacent([0, 0], 2, 2, { -1, 0 }, addressing: :wrap)
[1, 1]

iex> Spat.adjacent(Spat.pack([0, 0], 2), 2, 2, { 5, 0 }, addressing: :clamp)
Spat.pack([1, 1], 2)

iex> Spat.adjacent(Spat.pack([0, 0], 2), 2, 2, { 5, 0 }, addressing: :wrap)
Spat.pack([0, 1], 2)

iex> Spat.adjacent(Spat.pack([0, 0], 2), 2, 2, { -1, 0 }, addressing: :wrap)
Spat.pack([1, 1], 2)

iex> Spat.adjacent(Spat.pack([0, 1], 2), 2, 2, { 0, 0 })
Spat.pack([0, 1], 2)

iex> Spat.adjacent(Spat.pack([0, 1], 2, reverse: true), 2, 2, { 0, 0 }, reverse: true)
Spat.pack([0, 1], 2, reverse: true)
Link to this function decode(hash, dimensions, subdivisions)

Decode an encoded packed grid index.

iex> Spat.decode("A", 2, 1)
<<0 :: 2>>

iex> Spat.decode("A", 3, 1)
<<0 :: 3>>

iex> Spat.decode("AA", 2, 4)
<<0 :: 8>>

iex> Spat.decode("BCD", 6, 3)
<<1 :: 6, 2 :: 6, 3 :: 6>>

Encode a packed grid index.

The encoding is a URL safe string. While the encoding is equivalent to the Base module's URL-safe base64 encoding (without padding), care should be taken if using those functions to encode/decode packed grid indexes. As packed grid indexes are bitstrings and not binaries, using the Base module variants (or other third party base64 functions) may result in losing information.

If you do have a workflow that requires it to be compatible with base64 implementations, then it is recommended you pad the packed grid index so it's now a binary.

iex> Spat.encode(<<0 :: 2>>)
"A"

iex> Spat.encode(<<0 :: 3>>)
"A"

iex> Spat.encode(<<0 :: 8>>)
"AA"

iex> Spat.encode(<<1 :: 6, 2 :: 6, 3 :: 6>>)
"BCD"
Link to this function pack(index, dimensions, opts \\ [])

Pack a grid index into a bitstring.

iex> Spat.pack([0], 2)
<<0 :: 2>>

iex> Spat.pack([0], 3)
<<0 :: 3>>

iex> Spat.pack([], 2)
<<>>

iex> Spat.pack([0, 0, 0, 0], 2)
<<0 :: 8>>

iex> Spat.pack([1, 2, 3, 4], 2)
<<1 :: 2, 2 :: 2, 3 :: 2, 0 :: 2>>

iex> Spat.pack([1, 2, 3, 4], 2, reverse: true)
<<0 :: 2, 3 :: 2, 2 :: 2, 1 :: 2>>

iex> Spat.pack([1, 2, 3, 4], 3, reverse: true)
<<4 :: 3, 3 :: 3, 2 :: 3, 1 :: 3>>

iex> Spat.pack([1, 2, 3, 4000], 12, reverse: true)
<<4000 :: 12, 3 :: 12, 2 :: 12, 1 :: 12>>
Link to this function to_bounds(index, bounds, opts \\ [])

Get the bounds a grid index references.

iex> bounds = Spat.Bounds.new({ 10, 10 })
...> point = {2.6,0}
...> subdivisions = 2
...> indexes = Spat.Geometry.Point.index(point, bounds, subdivisions)
...> Enum.map(indexes, &Spat.to_bounds(&1, bounds))
[Spat.Bounds.new([2.5, 0], [5.0, 2.5])]

iex> Spat.to_bounds([0], Spat.Bounds.new({ 10, 10 }))
Spat.Bounds.new([0, 0], [5.0, 5.0])

iex> Spat.to_bounds([1], Spat.Bounds.new({ 10, 10 }))
Spat.Bounds.new([5.0, 0], [10.0, 5.0])

iex> Spat.to_bounds([2], Spat.Bounds.new({ 10, 10 }))
Spat.Bounds.new([0, 5.0], [5.0, 10.0])

iex> Spat.to_bounds([3], Spat.Bounds.new({ 10, 10 }))
Spat.Bounds.new([5.0, 5.0], [10.0, 10.0])

iex> Spat.to_bounds([0, 0, 0], Spat.Bounds.new({ 10, 10 }))
Spat.Bounds.new([0, 0], [1.25, 1.25])

iex> Spat.to_bounds(Spat.pack([3], 2), Spat.Bounds.new({ 10, 10 }))
Spat.Bounds.new([5.0, 5.0], [10.0, 10.0])

iex> Spat.to_bounds(Spat.pack([0, 0, 0], 2), Spat.Bounds.new({ 10, 10 }))
Spat.Bounds.new([0, 0], [1.25, 1.25])

iex> Spat.to_bounds(Spat.pack([0, 0, 1], 2), Spat.Bounds.new({ 10, 10 }))
Spat.Bounds.new([1.25, 0], [2.5, 1.25])

iex> Spat.to_bounds(Spat.pack([0, 0, 1], 2, reverse: true), Spat.Bounds.new({ 10, 10 }), reverse: true)
Spat.Bounds.new([1.25, 0], [2.5, 1.25])
Link to this function unpack(index, dimensions, opts \\ [])

Unpack a grid index from a bitstring.

iex> Spat.unpack(<<0 :: 2>>, 2)
[0]

iex> Spat.unpack(<<0 :: 3>>, 3)
[0]

iex> Spat.unpack(<<>>, 2)
[]

iex> Spat.unpack(<<0 :: 8>>, 2)
[0, 0, 0, 0]

iex> Spat.unpack(<<1 :: 2, 2 :: 2, 3 :: 2, 0 :: 2>>, 2)
[1, 2, 3, 0]

iex> Spat.unpack(<<0 :: 2, 3 :: 2, 2 :: 2, 1 :: 2>>, 2, reverse: true)
[1, 2, 3, 0]

iex> Spat.unpack(<<4000 :: 12, 3 :: 12, 2 :: 12, 1 :: 12>>, 12, reverse: true)
[1, 2, 3, 4000]