Jump to content
  • Advertisement
Sign in to follow this  
slynk

C++ 3D vector "resizing"

This topic is 2944 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The reason resizing is in quotes is because I'm not using vector.resize(), I'm trying to push_back on a vector but my codes not working.

I have a 3D vector for my tile map. (layer)(width)(height) In my tile map editor I want the ability to add rows and columns to the map by copying the row or column on the outside. I've successfully done this for the second dimension of the vector but I can't get it to work with the final dimension. My two functions are as follows (using C++):


void add(bool f)
{
if(f)//add Column this works
{
for(int i = 0; i < map.size(); i ++)
{map.at(i).push_back(map.at(i).back());}
}
else//add Row this doesn't
{
for(int i = 0; i < map.size(); i ++)
{
for(int j = 0; j <map.at(i).size(); j ++)
{
map.at(i).back().push_back(map.at(i).back().back());
}
}
}
}
void subtract(bool f)
{
if((f) && (map.at(0).size() != 1))//sub Column this works
{
for(int i = 0; i < map.size(); i ++)
{map.at(i).pop_back();}
}
else if((!f) &&(map.at(0).at(0).size() != 1))//sub Row this doesn't
{
for(int i = 0; i < map.size(); i ++)
{
for(int j = 0; j < map.at(i).size(); j--)
{
map.at(i).back().pop_back();
}
}
}
}


What am I doing wrong? Is the code correct and code else where is the reason it's not working?

Share this post


Link to post
Share on other sites
Advertisement
just noticed the j-- in the for loop, already fixed that. Still having problems.

EDIT: Fixed it. Sorry for the wasted post :(

For anyone who happens upon this similar issue, I fixed it with :


void add(bool f)
{
if(f)//add Column
{
for(int i = 0; i < map.size(); i ++)
{map.at(i).push_back(map.at(i).back());}
}
else//add Row
{
for(int i = 0; i < map.size(); i ++)
{
for(int j = 0; j <map.at(0).size(); j ++)
{
map.at(i).at(j).push_back(map.at(i).back().back());
}
}
}
}
void subtract(bool f)
{
if((f) && (map.at(0).size() != 1))//sub Column
{
for(int i = 0; i < map.size(); i ++)
{map.at(i).pop_back();}
}
else if((!f) &&(map.at(0).at(0).size() != 1))//sub Row
{
for(int i = 0; i < map.size(); i ++)
{
for(int j = 0; j < map.at(0).size(); j++)
{
map.at(i).at(j).pop_back();
}
}
}
}

Share this post


Link to post
Share on other sites
Seeing nested std::vector's makes me cringe, so let me just point out boost::multi_array. You may have reasons for doing it this way, so I'll just stop there.

Share this post


Link to post
Share on other sites
The term 3D vector is misleading. You're actually trying to implenent a multidimensional array, here, a 3-dimensional array. The notions of row and column are only meaningful in 2-dimensional arrays. Unless, this is what you mean by row i, column j:


std::vector< std::vector< std::vector< Tile > > > map;
//map initialisation
int i = 0; //row index
int j = 0; //colum index
int k = 0; //tile index in vector of tiles

//we access the kth element (tile) of the jth colum of the ith row
map[j][k] = Tile(...);


You probably want to be able to add tiles to your map at run time. Now, I wonder why would you want to be able to do that?

Nevertheless, here is how it could be done:

//10 is the number of std::vector< std::vector< Tile > >s
std::vector< std::vector< std::vector< Tile > > > map( 10 );
//we want the fourth std::vector< std::vector< Tile > > to contain 3 elements
//that is to say 3 std::vector< Tile >s
map[3].resize( 3 );
//we want to add a tile to the second element of map[3]
map[3][1].push_back( Tile(...) );


After reading what you're trying to achieve:
-instead of using a boolean to either add what you call a column or a "row", write two functions, one for adding a "column", the other, for adding a "row"
-What you do when you add a "row", could be done this way:


std::vector< std::vector< std::vector< Tile > > > map;
//map initialization

for( int unsigned i = 0; i < map.size(); ++i )
{
map.push_back( std::vector< Tile >() );
}

-What you do when you add a "column", could be done this way


for( size_t i = 0; i < map.size(); ++i )
{
for( size_t j = 0; j < map.size(); ++j )
{
map[j].push_back( Tile() );
}
}


[Edited by - johnstanp on August 28, 2010 5:41:41 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by incin
Seeing nested std::vector's makes me cringe, so let me just point out boost::multi_array. You may have reasons for doing it this way, so I'll just stop there.


I'm using vectors because when I was using 2d arrays and 3d arrays, the size of the array had to be hard coded to pass it to a function. ex:


int tile[][];

function(tile);




produced errors because in the function definition, I would have to say


void function(int tile[][size]);




to pass it. I want the size to be dynamic. I could be completely wrong on how multi dimensional arrays work but that's what I saw in the googles so I switched to vectors.

Quote:
Original post by incin The term 3D vector is misleading. You're actually trying to implenent a multidimensional array, here, a 3-dimensional array. The notions of row and column are only meaningful in 2-dimensional arrays. Unless, this is what you mean by row i, column j


i = layer, j = row.

I have a 3d vector for my tile map because I wanted a layered map. (Layer 0 is for grass and stuff, layer 1 is for buildings and sign posts, etc.) So it's a vector of 2d vectors. The 2d vectors are rows and columns, holding the index of the tile to be placed (or -1 for no tile). I figured loading up the tile set into memory and holding a few ints is better than holding copies of the same tile over and over again. (Bitmaps are bigger than ints I'm almost certain.)

Also the code you provided does add rows and columns, however it doesn't copy the outer row or column and make it the new one. I could fill it with -1 for my set up but I thought if the ground is covered in grass, the user of the tile editor probably wants the rest of the map to be as such and if not, they can delete it.

Thank you for your responses, if you still believe I'm going about this the wrong way, please inform me. I want my code to be as slim as possible. I'm at the point in programming where I can do anything, it will just probably look scary as code.

Share this post


Link to post
Share on other sites
Quote:
Original post by slynk
What am I doing wrong?


What you are doing wrong is that you are not using boost::multi_array for storage.

Share this post


Link to post
Share on other sites
Do you have a link or a list to what the benefits are to using boost::multi_array over vectors? I'm willing to try them if I'm given a concrete reason as to why they are better. If they are just more user friendly, I think I'd prefer not to convert all my functions and classes to use them.

Share this post


Link to post
Share on other sites
Quote:
Original post by slynk
Do you have a link or a list to what the benefits are to using boost::multi_array over vectors? I'm willing to try them if I'm given a concrete reason as to why they are better. If they are just more user friendly, I think I'd prefer not to convert all my functions and classes to use them.
Typically, using multi_array (or a similar array wrapper) rather than nested vectors for non-jagged multi-dimensional arrays will make your code more clear and more expressive of its intent, which, IMO, is reason enough to do so.

Although this may or may not matter in your case, using a wrapper such as multi_array that stores the data in a contiguous block can be better for performance, due to increased cache coherency and (possibly) decreased fragmentation.

Also, nested vectors are just messy and inelegant :|

If you're going to be inserting and removing rows and columns frequently, that will require a little work regardless of what method you're using for storage. Granted, using nested vectors does make the special case of adding or removing rows or columns (one or the other, depending) relatively straightforward to handle, but it's still not going to be particularly efficient. IMO, using multi_array would still be preferable in this case.

Share this post


Link to post
Share on other sites
Quote:
Original post by slynk
Do you have a link or a list to what the benefits are to using boost::multi_array over vectors? I'm willing to try them if I'm given a concrete reason as to why they are better. If they are just more user friendly, I think I'd prefer not to convert all my functions and classes to use them.


Here's why. (Not tested, but should be fairly close.)


typedef boost::multi_array<Element, 3> Map; // indexed as [layer][column][row]
typedef Map::array_view<2>::type Slice;
typedef boost::gen_type<3, 2>::type Slicer;
const boost::index_range all;
using boost::indices;
using boost::extents;

void adjust_size(Map& m, size_type x, size_type y, size_type z) {
m.resize(extents[m.shape()[0] + x][m.shape()[1] + y][m.shape()[2] + z]);
}

void copy_slice(Map& m, const Slicer& src, const Slicer& dest) {
Slice src_slice = m[src];
Slice dest_slice = m[dest];
std::copy(src_slice.begin(), src_slice.end(), dest_slice.begin());
}

void duplicate_last_layer(Map& m) {
adjust_size(m, 1, 0, 0);
int size = m.shape()[0];
copy_slice(indices[size - 2][all][all], indices[size - 1][all][all]);
}

void duplicate_last_column(Map& m) {
adjust_size(m, 0, 1, 0);
int size = m.shape()[1];
copy_slice(indices[all][size - 2][all], indices[all][size - 1][all]);
}

void duplicate_last_row(Map& m) {
adjust_size(m, 0, 0, 1);
int size = m.shape()[2];
copy_slice(indices[all][all][size - 2], indices[all][all][size - 1]);
}

void remove_last_layer(Map& m) {
adjust_size(m, -1, 0, 0);
}

void remove_last_column(Map& m) {
adjust_size(m, 0, -1, 0);
}

void remove_last_row(Map& m) {
adjust_size(m, 0, 0, -1);
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!