Sign in to follow this  
ISDCaptain01

4D Arrays?

Recommended Posts

Im trying to make a 4D array class. But I dont know the equation that you need when you are locating a certain cell/index in the array.

For 2d arrays I know it is y(height)*width + x. I also know it for the 3d array but not on the top of my head. But what is it for a 4D array?

hmmm maybe its pointless since you cant even visualize a 4d array... Since what is considered the 4th dimension? I know the 3d has height width and depth but what is in 4d?

Share this post


Link to post
Share on other sites
height, widht, depth, and whatever. You can call it time, or monkeyballs, it doesn't really matter.
Or rather, it depends on what you want your fourth dimension to mean.

x + y*width + z*height*width + w*height*width*depth.

you can expand it to as many dimensions as you like.

Why do you need a 4D array anyway? sounds a bit exotic to me. Edited by Olof Hedman

Share this post


Link to post
Share on other sites
If you don't know what is in a 4D array, why do you bother to make a 4D array?
Also, when we come to a multiple dimension array, especially so high dimension 4D, we should consider better data structure rather than a plain array.
So if you want to store X, Y, Z, D in a 4D array, how about store them in a 1D array with a structure.
struct Item {
int X;
...
};
Item myArray[100];
Isn't that clearer?
If you are not using C/C++, just make Item a class. Edited by wqking

Share this post


Link to post
Share on other sites
4D "can" be visualized in 3D: [url="http://en.wikipedia.org/wiki/Tesseract"]http://en.wikipedia.org/wiki/Tesseract[/url]
The fourth dimension can called whatever you like, some people say it's time, some people say it's space and some say it's an object in itself.

Here is a nice link about how you project the 4D in 3D: [url="http://steve.hollasch.net/thesis/chapter4.html"]http://steve.hollasc...s/chapter4.html[/url]
Four-dimensional geometry: [url="http://steve.hollasch.net/thesis/chapter2.html"]http://steve.hollasc...s/chapter2.html[/url]

Share this post


Link to post
Share on other sites
The code in my post projects 4D into 1D

the first 3 dimensions doesn't have to be height, width, and depth either, thats only if you choose to represent space with it.

mathematically, they can be anything.

Share this post


Link to post
Share on other sites
Why aren't you just using
[code]
int array[3][4][5][6];
//or
std::vector< std::vector< std::vector< std::vector< /*your Type*/ > > > > array;
[/code]

Using a naked C++ array is usually bad for this and even if you have to if you use only one array you end up with a uniform grid like array only, jagged arrays wouldn't be possible you would need to use a "type****" for that and the just looks ugly. Edited by NightCreature83

Share this post


Link to post
Share on other sites
[quote name='ISDCaptain01' timestamp='1354871479' post='5008062']
im making it for learning purposes. The book goes up to making a 3d array class and I thought maybe making a 4d class myself would be good exercise
[/quote]
That makes sense.
Hope this Wiki helps you,
http://en.wikipedia.org/wiki/Array_data_structure#Multidimensional_arrays

Share this post


Link to post
Share on other sites
[quote name='EngineProgrammer' timestamp='1354869730' post='5008047']
4D "can" be visualized in 3D: [url="http://en.wikipedia.org/wiki/Tesseract"]http://en.wikipedia.org/wiki/Tesseract[/url]
[/quote]

A "funny" note on those pictures (wich I feel is often forgotten/omitted) is that it isn't just a 3D projection, but a 2D projection of a 3D projection of a 4D object :)
Might sound irrelevant, but I found that this realisation made me understand the 4D objects better. you have the same kind of information loss from 3D to 2D as you do in 4D to 3D, so in the same way an animation shows 3D objects better in 2D, you "see" the 4D objects better if you rotate it. (as is shown in the animated pictures) Edited by Olof Hedman

Share this post


Link to post
Share on other sites
[quote name='Olof Hedman' timestamp='1354872833' post='5008068']
[quote name='EngineProgrammer' timestamp='1354869730' post='5008047']
4D "can" be visualized in 3D: [url="http://en.wikipedia.org/wiki/Tesseract"]http://en.wikipedia.org/wiki/Tesseract[/url]
[/quote]

A "funny" note on those pictures (wich I feel is often forgotten/omitted) is that it isn't just a 3D projection, but a 2D projection of a 3D projection of a 4D object [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]
Might sound irrelevant, but I found that this realisation made me understand the 4D objects better. you have the same kind of information loss from 3D to 2D as you do in 4D to 3D, so in the same way an animation shows 3D objects better in 2D, you "see" the 4D objects better if you rotate it. (as is shown in the animated pictures)
[/quote]
The real problem with 4D is that you can't imagine it so you have no idea what the real representation looks like, our brains are wired for a 3D world. So to us even a 2D image of a 3D object will actually still look 3D because our brain will try an interpret the depth in the image anyways.

Share this post


Link to post
Share on other sites
Yes, thats why you "forget" to mention the 2D projection, but understanding projections and realizing this image is really a double projection, at least gives me a better "feeling" of what the 4D object is, even though any "visualisation" has to be in 3D at most.

For a 2D projection of a 3D projection to feel 3D, you either need shading, animation, or an easily recognizable object. All of these are extra hints of the third dimension. Just a straight static 2D projection of a 3D object gives little hints of the objects 3Dness, and makes it seem flat.

In the same way, shading, and animations, can give you more hints of the objects 4Dness in the 3D projection, and give you a better understanding of it, even if you still can't visualize it in your head.

Share this post


Link to post
Share on other sites
I found myself using 4D arrays before. What I did was pass a 'stride' vector around. So say u have a 40x30x20x10 4D array, the 4D stride vector would be: { 1, 40, 40*30, 40*30*20 }. Sometimes you want to pad to align rows or what-have-you and that can easily be adjusted for in the stride. You can even use the stride to convert from indices to byte offsets, if you're working with raw data. Then to convert a 4D index and a stride to a 1D offset you simple do the dot product, something like dot(index,stride). Obviously this could easily be extrapolated to N dimensions, under the hood there's nothing special or tricky going on, but by pairing a stride vector with all the arrays it makes it very easy to work with.

Share this post


Link to post
Share on other sites
Well here it is. My 4D array resize algorithm:

[source lang="cpp"]#pragma once

#include <iostream>
using namespace std;

template <class Datatype>

class Array4D
{

public:

//Constructor
Array4D(int p_time, int p_depth, int p_height, int p_width)
{
m_array = new Datatype[ p_time * p_depth * p_height * p_width];
m_time = p_time;
m_depth = p_depth;
m_height = p_height;
m_width = p_width;
}

//Destructor
~Array4D()
{
if(m_array != 0)
{
delete[] m_array;
}

m_array = 0;
}

//Get: Retrieves the value from passed in location
Datatype& Get(int p_t, int p_z, int p_y, int p_x)
{
return m_array[ ( (p_t * m_depth * m_height * m_width) + (p_z * m_height * m_width) + (p_y * m_width) + (p_x) ) ];
}


//Width: Returns the width of the array
int Width()
{
return m_width;
}

//Height: Returns the height of the array
int Height()
{
return m_height;
}

//Depth: Returns the depth of the array
int Depth()
{
return m_depth;
}

//Time: Returns the time of the array
int Time()
{
return m_time;

}

//Resize: Resizes the array
void Resize(int p_time, int p_depth, int p_height, int p_width)
{
//Declare a pointer to a new array and allocate enouh memory
Datatype *newarray = new [p_time * p_depth * p_height * p_width];

//Determine the minimum of all four dimensions
int minx = (p_width < m_width ? p_width : m_width);
int miny = (p_height < m_height ? p_height : m_height);
int minz = (p_depth < m_depth ? p_depth : m_depth);
int mint = (p_time < m_time ? p_time : m_time);

//Declare four dimensional coordinates
int x;
int y;
int x;
int t;

//Declare temporary variables
int t1;
int t2;
int t3;
int t4;
int t5;
int t6;

//Now loop through each cell and paste the values from the old array into the new array
for(t = 0; t < mint; t++)
{
t1 = t * p_depth * m_height * m_width
t2 = t * m_depth * m_height * m_width

for(z = 0; z < minz; z++)
{
t3 = z * p_width * m_height;
t4 = z * m_width * m_height;

for(y = 0; y < miny; y++)
{
t5 = y * p_width;
t6 = y * m_width;

for(x = 0; x < minx ; x++)
{
newarray[t1 + t3 + t5 + x] = m_array[t2 + t4 + t6 + x];
}
}
}
}

//Deallocate the old array
if(m_array != 0)
{
delete[] m_array;
}
m_array = newarray;

//set the new dimesions
m_width = p_width;
m_height = p_height;
m_depth = p_depth;
m_time = p_time;
}


//Size: Returns the total size of the array
int Size()
{
return m_time * m_depth * m_height * m_width;
}

private:

//Private variables
Datatype *m_array;
int m_width;
int m_height;
int m_depth;
int m_time;
};



[/source]

and heres an example implementation file to test it:

[source lang="cpp"]#include <iostream>
#include "Array4D.h"
using namespace std;



int main()
{
//Create two different 4-Dimensional arrays
Array4D<int> iarray(5, 5, 5, 5);
Array4D<float> farray(7, 7, 7, 7);

//Create some variables to show output
int i;
int f;

//Insert 10 into an array
iarray.Get(2, 1, 3, 0) = 10;
i = iarray.Get(2, 1, 3, 0);
cout << "The value at time 2, depth 1, height 3, and width 0 is: " << i << endl;

farray.Get(2, 1, 3, 0) = 25.0f;
f = farray.Get(2, 1, 3, 0);
cout << "The value at time 2, depth 1, height 3, and width 0 is: " << f << endl;

//Display the size of the arrays
cout << "The size of iarray is: " << iarray.Size() << endl;
cout << "The size of farray is: " << farray.Size() << endl;


cin.get();
return 0;
}[/source] Edited by ISDCaptain01

Share this post


Link to post
Share on other sites
[quote name='NightCreature83' timestamp='1354871645' post='5008063']
Why aren't you just using
[code]
int array[3][4][5][6];
//or
std::vector< std::vector< std::vector< std::vector< /*your Type*/ > > > > array;
[/code]

Using a naked C++ array is usually bad for this and even if you have to if you use only one array you end up with a uniform grid like array only, jagged arrays wouldn't be possible you would need to use a "type****" for that and the just looks ugly.
[/quote]
Your first example and second example aren't equivalent.

While I agree with using an std::vector, I disagree with stacking them four deep.
A vector of a vector of a vector of a vector is not the same as a 4D array, in the same way that a vector of a vector is not the same as a 2D array, since each vector within the first vector aren't constrained to the same size (a so called 'jagged array' is an array of an array, not a 2D array).
If you have access to C++11, a std::array [i]would[/i] constrain it to the same size.

When I want a multi-dimensional array, I use a single std::vector, and resize it to (width * height) or (width * height * depth), and index into it as Olof Hedman shows. Edited by Servant of the Lord

Share this post


Link to post
Share on other sites
@ISDCaptain01: Nicely done! Your code looks very cleanly written too, which I approve of. [img]http://public.gamedev.net//public/style_emoticons/default/biggrin.png[/img]

A few notes:[list]
[*]Typically, people put the dimensions in the order (x,y,z,t) (width, height, depth, time). You seem to have them backward - which is fine, but unusual.
[*]You also declare alot of your temporary variables before their use in your Resize() function. This, while not [i]quite[/i] punishable by death, is often considered bad practice. [img]http://public.gamedev.net//public/style_emoticons/default/wink.png[/img] Variables shouldn't be declared until the last moment they are needed, unless you have a reason for doing otherwise. And if you do declare them in advance, they should at least be initialized. Where you declare temporary x,y,z,t in your Resize() function you accidentally declare 'x' twice instead of 'z'.
[*]Your 'Get()' function doesn't check to make sure the parameters are within range - that may be intentional though. The standard library typically provides two accessing methods - the subscript operator [], which doesn't check for range (used for extra speed when you are iterating and are confident you don't go over), and a 'at()' function that [i]does [/i]check range.
[/list]

Share this post


Link to post
Share on other sites
[quote name='Servant of the Lord' timestamp='1354950198' post='5008410']
When I want a multi-dimensional array, I use a single std::vector, and resize it to (width * height) or (width * height * depth), and index into it as Olof Hedman shows.
[/quote]Yep. Also, when you do that, a small indexing function can be very helpful. Easy to get variations of "x + y*width + "z*height*width + w*height*width*depth" wrong in individual accesses, much clearer when you have "array[idx(0, 0, arg, time)]" and so on.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this