Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looping through a 3d-indexed 1d array in C++

Tags:

c++

arrays

I have created a class which imitates a 3D bool array by storing data in 1D array and overloading the () operator. I have already tried every approach I could find and think of and while, for example, this piece of code:

bool operator()(unsigned x, unsigned y, unsigned z) const { return _data[_zSize*_ySize*x + y*_ySize + z]; }

allows me to access every element I need (I am aware that (x,y,z) is here actually (z,y,x) but it's not up to me), I run into problems when I try to iterate through the array. Consider a 3D array of depth: 3, height: 4 and width 5 with every element initialized to false. When I try to invert all the values in the array (where sx() returns depth, sy() - height, sz() - width)

for (unsigned i = 0; i < x.sx(); ++i)
        for (unsigned j = 0; j < x.sy(); ++j)
            for (unsigned k = 0; k < x.sz(); ++k)
                x(i, j, k) = !x(i, j, k);

I get the following result (two remaining surfaces look the same):

11110
01110
01110
01111

So, obviously some elements are accessed and reversed twice. The pattern changes when I try different methods of indexing the array. What is the problem?

like image 762
Tinnuir Avatar asked Dec 05 '25 13:12

Tinnuir


2 Answers

The correct operator is

bool operator()(unsigned x, unsigned y, unsigned z) const { 
     return _data[_zSize*_ySize*x + y*_zSize + z]; 
}
like image 173
AnatolyS Avatar answered Dec 07 '25 03:12

AnatolyS


let me give a generalize approach with step size. Suppose you have a 3D array ,and accessing is done in (z,y,x)

By this indexing , i assume , Matrix dimensions as There are z number of Planes and Each plane is of size y,x , y width and y is height.

We first need to visualize the 3D structure and how we are going to access the element.

supposedly we wan to access ( 3,4,1)

Using zero based indexing

Here We z = 3 , y = 4 , x = 1 , Our Required Plane is 4th Plane , Our Required Row is 4th and Required Element is 1st .

Thus to go to the Required Plane : z * ( size of Plane ) = z * ( width * height )

To go to the Required Row , y * sizeo of Row = y * ( height) //or y * row_bytes

To go the Required Point , Just add x * sizeof( one Point) //Specific to multichannel data when there are 3 or 4 values per point e.g in Opencv 3 channel data.

Thus Final Equation will be

Considering 3 Channel Data ie 3 values per point of size uchar,

Value = z * (width * height) + y * ( height ) + x * (3 * sizeof(uchar) )

Thus once you get the Value , no you extract each pixel value one by one.

PS : 3 * sizeof(uchar) is replaced version of Vec3b used commonly in OpenCV to access 3 Channel uchar data.

like image 29
ATul Singh Avatar answered Dec 07 '25 03:12

ATul Singh



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!