Jump to content

  • Log In with Google      Sign In   
  • Create Account

4D Arrays?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
15 replies to this topic

#1 ISDCaptain01   Members   -  Reputation: 1397

Like
0Likes
Like

Posted 07 December 2012 - 02:09 AM

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?

Sponsor:

#2 Olof Hedman   Crossbones+   -  Reputation: 2852

Like
1Likes
Like

Posted 07 December 2012 - 02:12 AM

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, 07 December 2012 - 02:21 AM.


#3 wqking   Members   -  Reputation: 756

Like
2Likes
Like

Posted 07 December 2012 - 02:15 AM

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, 07 December 2012 - 02:16 AM.

http://www.cpgf.org/
cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.
v1.5.5 was released. Now supports tween and timeline for ease animation.


#4 EngineProgrammer   Members   -  Reputation: 295

Like
0Likes
Like

Posted 07 December 2012 - 02:42 AM

4D "can" be visualized in 3D: http://en.wikipedia.org/wiki/Tesseract
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: http://steve.hollasc...s/chapter4.html
Four-dimensional geometry: http://steve.hollasc...s/chapter2.html

#5 Olof Hedman   Crossbones+   -  Reputation: 2852

Like
0Likes
Like

Posted 07 December 2012 - 02:53 AM

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.

#6 ISDCaptain01   Members   -  Reputation: 1397

Like
0Likes
Like

Posted 07 December 2012 - 03:11 AM

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

#7 NightCreature83   Crossbones+   -  Reputation: 2857

Like
0Likes
Like

Posted 07 December 2012 - 03:14 AM

Why aren't you just using
int array[3][4][5][6];
//or
std::vector< std::vector< std::vector< std::vector< /*your Type*/ > > > > array;

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, 07 December 2012 - 03:17 AM.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#8 wqking   Members   -  Reputation: 756

Like
0Likes
Like

Posted 07 December 2012 - 03:18 AM

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

That makes sense.
Hope this Wiki helps you,
http://en.wikipedia.org/wiki/Array_data_structure#Multidimensional_arrays

http://www.cpgf.org/
cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.
v1.5.5 was released. Now supports tween and timeline for ease animation.


#9 Olof Hedman   Crossbones+   -  Reputation: 2852

Like
0Likes
Like

Posted 07 December 2012 - 03:33 AM

4D "can" be visualized in 3D: http://en.wikipedia.org/wiki/Tesseract


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, 07 December 2012 - 03:43 AM.


#10 NightCreature83   Crossbones+   -  Reputation: 2857

Like
0Likes
Like

Posted 07 December 2012 - 04:38 AM


4D "can" be visualized in 3D: http://en.wikipedia.org/wiki/Tesseract


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 Posted Image
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)

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.
Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#11 Olof Hedman   Crossbones+   -  Reputation: 2852

Like
0Likes
Like

Posted 07 December 2012 - 04:47 AM

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.

#12 Ryan_001   Prime Members   -  Reputation: 1410

Like
1Likes
Like

Posted 07 December 2012 - 06:47 AM

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.

#13 ISDCaptain01   Members   -  Reputation: 1397

Like
1Likes
Like

Posted 07 December 2012 - 11:43 PM

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://ConstructorArray4D(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 locationDatatype& 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 arrayint Width(){ return m_width;}//Height: Returns the height of the arrayint Height(){ return m_height;}//Depth: Returns the depth of the arrayint Depth(){ return m_depth;}//Time: Returns the time of the arrayint Time(){ return m_time;}//Resize: Resizes the arrayvoid 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 arrayint Size(){ return m_time * m_depth * m_height * m_width;}private://Private variablesDatatype *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, 07 December 2012 - 11:44 PM.


#14 Servant of the Lord   Crossbones+   -  Reputation: 19689

Like
1Likes
Like

Posted 08 December 2012 - 01:03 AM

Why aren't you just using

int array[3][4][5][6];
//or
std::vector< std::vector< std::vector< std::vector< /*your Type*/ > > > > array;

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.

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 would 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, 08 December 2012 - 01:04 AM.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#15 Servant of the Lord   Crossbones+   -  Reputation: 19689

Like
0Likes
Like

Posted 08 December 2012 - 01:17 AM

@ISDCaptain01: Nicely done! Your code looks very cleanly written too, which I approve of. Posted Image

A few notes:
  • 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 quite punishable by death, is often considered bad practice. Posted Image 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 does check range.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#16 Yrjö P.   Crossbones+   -  Reputation: 1412

Like
1Likes
Like

Posted 08 December 2012 - 06:35 AM

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.

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.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS