0.12.0
Freundlich's C++ toolkit
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Classes | Functions
fcppt.container.grid
fcppt.container

Description

A simple n-dimensional array.

Introduction

fcppt::container::grid::object is a simple multi dimensional array similar to boost::multi_array. Let's first take a look at how to use a simple three dimensional grid of ints.

#include <fcppt/container/grid/object.hpp>
#include <fcppt/container/grid/interpolate.hpp>
#include <fcppt/math/interpolation/linear_functor.hpp>
#include <fcppt/io/cout.hpp>
#include <fcppt/text.hpp>
#include <iostream>
namespace
{
// typedef a three dimensional grid of ints
int,
3
> int3d_grid;
void
use_grid()
{
// Create a 5 by 10 by 20 grid.
// The initial values will be unspecified.
int3d_grid grid(
int3d_grid::dim(
5u,
10u,
20u
)
);
// Set the value on position (1,2,3) to 42
grid[
int3d_grid::dim(
1u,
2u,
3u
)
] = 42;
<< grid[
int3d_grid::dim(
1u,
2u,
3u
)
]
<< FCPPT_TEXT('\n');
}
}

Grid uses fcppt::math::dim::object to specify its size and to obtain an element.

Warning
Grid tries to be as efficient as possible and won't necessarily initialize its elements.

Iteration

Internally, the grid uses a std::vector or a fcppt::container::raw_vector to linearly represent the grid. The iterators returned by the grid are iterators over that internal storage array, so they're not special in any way (other than begin random-access). This also means that iteration is...

Here is an example of each iteration method:

namespace
{
int,
1
> int1d_grid;
int,
2
> int2d_grid;
int,
3
> int3d_grid;
}
int main()
{
int1d_grid one_dimensional(
int1d_grid::dim(3));
one_dimensional[int1d_grid::dim(0)] = 0;
one_dimensional[int1d_grid::dim(1)] = 1;
one_dimensional[int1d_grid::dim(2)] = 2;
// Outputs 0, 1, 2
for(int1d_grid::const_iterator it = one_dimensional.begin(); it != one_dimensional.end(); ++it)
fcppt::io::cout() << it << FCPPT_TEXT("\n");
int2d_grid two_dimensional(
int2d_grid::dim(3,2));
two_dimensional[int2d_grid::dim(0,0)] = 0;
two_dimensional[int2d_grid::dim(1,0)] = 1;
two_dimensional[int2d_grid::dim(2,0)] = 2;
two_dimensional[int2d_grid::dim(0,1)] = 3;
two_dimensional[int2d_grid::dim(1,1)] = 4;
two_dimensional[int2d_grid::dim(2,1)] = 5;
// Outputs 0, 1, 2, 3, 4, 5
for(int2d_grid::const_iterator it = two_dimensional.begin(); it != two_dimensional.end(); ++it)
fcppt::io::cout() << it << FCPPT_TEXT("\n");
int3d_grid three_dimensional(
int3d_grid::dim(3,2,2));
// First slice
three_dimensional[int3d_grid::dim(0,0,0)] = 0;
three_dimensional[int3d_grid::dim(1,0,0)] = 1;
three_dimensional[int3d_grid::dim(2,0,0)] = 2;
three_dimensional[int3d_grid::dim(0,1,0)] = 3;
three_dimensional[int3d_grid::dim(1,1,0)] = 4;
three_dimensional[int3d_grid::dim(2,1,0)] = 5;
// Second slice
three_dimensional[int3d_grid::dim(0,0,1)] = 6;
three_dimensional[int3d_grid::dim(1,0,1)] = 7;
three_dimensional[int3d_grid::dim(2,0,1)] = 8;
three_dimensional[int3d_grid::dim(0,1,1)] = 9;
three_dimensional[int3d_grid::dim(1,1,1)] = 10;
three_dimensional[int3d_grid::dim(2,1,1)] = 11;
// Outputs 0, 1, 2, 3, 4, 5, 6, ..., 11
for(int3d_grid::const_iterator it = three_dimensional.begin(); it != three_dimensional.end(); ++it)
fcppt::io::cout() << it << FCPPT_TEXT("\n");
}

To get the position of an iterator, use fcppt::container::grid::iterator_position.

Resizing

To resize a grid there are a couple of options. resize will resize the underlying container but leave the elements of the grid in an unspecific state.

There are two functions to preserve the current elements that will still fit into the grid after the resize: resize_preserve and resize_preserve_init .

resize_preserve only preserves the elements that still fit but doesn't initialize new elements. resize_preserve_init is like resize_preserve but will give all new elements a default value.

Here's an example:

#include <fcppt/container/grid/output.hpp>
#include <fcppt/container/grid/resize_preserve_init.hpp>
#include <fcppt/config/external_begin.hpp>
#include <boost/spirit/home/phoenix/core/reference.hpp>
#include <boost/spirit/home/phoenix/operator/arithmetic.hpp>
#include <algorithm>
#include <fcppt/config/external_end.hpp>
namespace
{
int,
2
> int2d_grid;
void
resize_grid()
{
int2d_grid grid(
int2d_grid::dim(
2u,
3u
)
);
{
int count = 0;
// Initialize the grid with numbers from 0 to 5.
// Note, that a grid will always be laid out in memory such that
// the lower dimensions are closer together.
std::generate(
grid.begin(),
grid.end(),
count
)++
);
}
<< grid
<< FCPPT_TEXT('\n');
// Give the grid one more row and column and initialize those with 42.
grid,
int2d_grid::dim(
3u,
4u
),
42
);
<< grid
<< FCPPT_TEXT('\n');
}
}

Classes

class  fcppt::container::grid::object< T, N, A >
 A simple n dimensional arraySee the module description for more information. More...
 

Functions

template<typename T , fcppt::container::grid::size_type N, typename A , typename Fn >
void fcppt::container::grid::fill (object< T, N, A > &g, Fn const &f)
 Fills a grid using a functor.
 
template<typename T , fcppt::container::grid::size_type N, typename A >
bool fcppt::container::grid::in_range (grid::object< T, N, A > const &_grid, typename grid::object< T, N, A >::dim const &_pos)
 Checks if the given position _pos is out of bounds.
 
template<typename Grid , typename Vector , typename Interpolator >
Grid::value_type const fcppt::container::grid::interpolate (Grid const &grid, Vector const &floating_point_position, Interpolator const &interpolator)
 Interpolates a value inside the grid cells.
 
template<typename T , grid::size_type N>
bool fcppt::container::grid::is_square (grid::object< T, N > const &g)
 Checks if a grid is a square or a rectangle.
 
template<typename Grid , typename Iterator >
Grid::dim const fcppt::container::grid::iterator_position (Grid const &grid, Iterator const it)
 Returns the position of an iterator.
 
template<typename Ch , typename Traits , typename T , fcppt::container::grid::size_type N, typename A >
std::basic_ostream< Ch, Traits > & fcppt::container::grid::operator<< (std::basic_ostream< Ch, Traits > &_stream, grid::object< T, N, A > const &_object)
 Outputs a grid.
 

Function Documentation

template<typename T , fcppt::container::grid::size_type N, typename A , typename Fn >
void fcppt::container::grid::fill ( object< T, N, A > &  g,
Fn const &  f 
)

Fills a grid using a functor.

Template Parameters
FnA functor with the signature: grid::value_type(grid::dim)
template<typename T , fcppt::container::grid::size_type N, typename A >
bool fcppt::container::grid::in_range ( grid::object< T, N, A > const &  _grid,
typename grid::object< T, N, A >::dim const &  _pos 
)

Checks if the given position _pos is out of bounds.

Returns
true if is not out of bounds, false otherwise.
template<typename Grid , typename Vector , typename Interpolator >
Grid::value_type const fcppt::container::grid::interpolate ( Grid const &  grid,
Vector const &  floating_point_position,
Interpolator const &  interpolator 
)

Interpolates a value inside the grid cells.

With grid::object alone, you can only access values at discrete points (since the object::dim type used to specify positions has an integral value_type).

Sometimes, however, you want to take a value in between the grid nodes. Think about a magnifying filter for textures, or drawing a line from one plot point to the next (in a one-dimensional grid). This is called interpolation, and it works in all dimensions.

To interpolate, you specify the grid, the floating_point_position and an interpolator. The latter will determine what kind of interpolation is used (linear, trigonometric, ...). You can choose one of the classes in fcppt::math::interpolation (the ones ending in _functor) or you can write your own interpolator class. It just needs an operator() looking like this:

Grid::value_type
operator()(
Vector::value_type,
Grid::value_type,
Grid::value_type) const
{
// ...
}

The Vector template parameter determines which floating point type is used for calculations. Here's an example:

float,
2
> float2d_grid;
void
interpolate_grid()
{
float2d_grid grid(
float2d_grid::dim(
2u,
2u
)
);
grid[float2d_grid::dim( 0u, 0u)] = 0.0f;
grid[float2d_grid::dim( 0u, 1u)] = 1.0f;
grid[float2d_grid::dim( 1u, 0u)] = 2.0f;
grid[float2d_grid::dim( 1u, 1u)] = 3.0f;
float const result =
grid,
float2d_vector(0.5f,0.5f),
// Will bilinearly interpolate ALL the grid points and return something
// inbetween (too lazy to calculate)
std::cout << result << '\n';
}
template<typename T , grid::size_type N>
bool fcppt::container::grid::is_square ( grid::object< T, N > const &  g)

Checks if a grid is a square or a rectangle.

Returns
true of the grid is square, false otherwise
template<typename Grid , typename Iterator >
Grid::dim const fcppt::container::grid::iterator_position ( Grid const &  grid,
Iterator const  it 
)

Returns the position of an iterator.

Warning
Behavior is undefined if the iterator doesn't belong to the given grid.
template<typename Ch , typename Traits , typename T , fcppt::container::grid::size_type N, typename A >
std::basic_ostream< Ch, Traits>& fcppt::container::grid::operator<< ( std::basic_ostream< Ch, Traits > &  _stream,
grid::object< T, N, A > const &  _object 
)

Outputs a grid.

Outputs the grid _object to _stream. Every level of the grid will be wrapped in parenthesis. So, for example, a two dimensional grid of size (n,m) will be written as ((x_0, y_0), (x_1, y_0), ..., (x_0, y_1), ..., (x_n, y_m)).

Template Parameters
TMust be a type that has an appropriate operator<<
Parameters
_streamThe stream to write to
_objectThe grid to write
Returns
_stream