2

I have a 3 dimensioned boost::multi_array representing layers of 2d tilemaps. I would like to be able to clear a layer - aka iterate through all tiles on one layer and set its value to 0, but I can't figure out how to do this - I believe I have to use views but the documentation doesn't make much sense to me. For example, when looking at this example code:

// myarray = 2 x 3 x 4

//
// array_view dims: [base,bound) (dimension striding default = 1)
// dim 0: [0,2) 
// dim 1: [1,3) 
// dim 2: [0,4) (strided by 2), 
// 

typedef boost::multi_array_types::index_range range;
// OR typedef array_type::index_range range;
array_type::array_view<3>::type myview = myarray[ boost::indices[range(0,2)][range(1,3)][range(0,4,2)] ];

for (array_type::index i = 0; i != 2; ++i)
    for (array_type::index j = 0; j != 2; ++j)
        for (array_type::index k = 0; k != 2; ++k) 
            assert(myview[i][j][k] == myarray[i][j+1][k*2]);

How does boost::indices work? what do those ranges even represent? Sorry if this is obvious to some, I just can't get the hang of it.

Thanks in advance, ell.

1 Answer 1

7

That example creates a 3D view which accesses a part of a larger 3D array, and it's a little bit complicated because they are showing off strided views at the same time as bounded.

It'd be easier to understand if they used [range(0,2)][range(1,3)][range(0,4)], which would cut out a solid 3D block (0..2 along the first dimension, 1..3 along the second, 0..4 along the third)

Your goal is a 2D view (slice), so let's look at that, I'll make it simple:

you have a 3x3x3 array, and you want to zero out a plane that goes through its center. There are three such planes, so let's create a 2D view for each of the three:

#include <iostream>
#include <iomanip>
#include <boost/multi_array.hpp>

int main()
{
    typedef boost::multi_array<int, 3> array_t;

    array_t a(boost::extents[3][3][3]); // 3D array of 3x3x3

    int values = 0;
    for(array_t::index i = 0; i != 3; ++i)
        for(array_t::index j = 0; j != 3; ++j)
            for(array_t::index k = 0; k != 3; ++k)
                a[i][j][k] = values++;

    for(array_t::index i = 0; i != 3; ++i) {
        for(array_t::index j = 0; j != 3; ++j) {
            for(array_t::index k = 0; k != 3; ++k)
                std::cout << std::setw(2) << a[i][j][k] << ' ';
            std::cout << '\n';
        }
        std::cout << '\n';
    }

so far so good.. now let's cut some 2D planes out:

typedef boost::multi_array_types::index_range range_t;
array_t::index_gen indices;

// 2D plane that's constant in the 1st dimension
array_t::array_view<2>::type plane =
    a[ indices[1][range_t(0,3)][range_t(0,3)] ];

for (array_t::index i = 0; i != 3; ++i)
    for (array_t::index j = 0; j != 3; ++j)
        plane[i][j] = 0;

try printing this cube now, you'll see that one of the three planes is zeroed.

Then replace the initializer for plane with

a[ indices[range_t(0,3)][1][range_t(0,3)] ];

and with

a[ indices[range_t(0,3)][range_t(0,3)][1] ];

and print the cubes now.. You'll get it!

Sign up to request clarification or add additional context in comments.

1 Comment

Is there a built in way to extract a copy of a sub-array? That is, instead of using a View of the same data, actually copy the data without manually iterating over corresponding indices of the view and a new multi_array?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.