Visualizing three dimensional arrays

edited September 2017 in Share Your Work

To a computer, arrays don't have any kind of a shape or dimension, they are just blocks of space where a value can be stored and retrieved. But most humans don't really think like this, it's usually easier to understand something if we can SEE it.

So, how do we "SEE" arrays?

Well, a regular, one dimensional array can be imagined like a numbered list of values stacked on top of eachother, and a two dimensional array might be seen as a chess board with numbered rows and numbered squares in each row...... but how do you imagine a three dimensional array? How about a four dimensional one?

This is a sketch I made to show how three dimensional arrays can be visualized in the real world. The idea is that there is a cube (which represents a three dimensional array) that has x layers, inside each layer are x rows, and in each row there are x values. In this particular sketch, I used a cube with four layers that have four rows and four values in those rows, so in all there are 64 unique values.

In this sketch, you use the number keys to choose a layer, row, or value, and you use BACKSPACE to go back a level:

Code:

// A three dimensional array (The cube)
// The fist "[]" represents the layer, while the second "[]" is the row in that layer and the 
// third is the value in that row
String[][][] dim = {

   {{"0a", "0b", "0c", "0d"}, 
    {"0e", "0f", "0g", "0h"}, // Layer 0
    {"0i", "0j", "0k", "0L"}, 
    {"0m", "0n", "0o", "0p"}}, 

   {{"1a", "1b", "1c", "1d"}, 
    {"1e", "1f", "1g", "1h"}, // Layer 1
    {"1i", "1j", "1k", "1L"}, 
    {"1m", "1n", "1o", "1p"}}, 

   {{"2a", "2b", "2c", "2d"}, 
    {"2e", "2f", "2g", "2h"}, // Layer 2
    {"2i", "2j", "2k", "2L"}, 
    {"2m", "2n", "2o", "2p"}}, 

   {{"3a", "3b", "3c", "3d"}, 
    {"3e", "3f", "3g", "3h"}, // Layer 3
    {"3i", "3j", "3k", "3L"}, 
    {"3m", "3n", "3o", "3p"}}

};

int lay = -1; // The layer of the cube (cube 0)
int row = -1; // The row in that layer             
int val = -1; // The value in that row            

boolean show_startScreen = true; 

void setup() {
  size(500, 500);
  rectMode(CENTER);
  textAlign(CENTER, CENTER);
  stroke(255);
  textSize(30);
  noFill();
  noLoop(); // I don't need the program to run more than once unless a key is pressed 
            //and something is changed (so redraw will be run in "void keyPressed()")
}

void draw() {
  background(0);

  if (show_startScreen) {   //if the start screen is still being shown, draw it!
    text("Multidimensional Array\nVisualization Tool", 250, 100);
    rect(250, 255, 350, 50);
    text("Press any key to begin", 250, 250);
    textSize(20);
    text("Cyber_Agent\n:)", 250, 400); //The totally awesome guy who made it
    textSize(30);
  } else {
    if (lay == -1) {  // if a layer has not been chosen
      text("Cube 0:", 250, 30);
      text("Choose a layer", 250, 460);
      rect(175, 175, 200, 200);
      text("0", 250, 95);
      rect(225, 225, 200, 200);
      text("1", 300, 145);
      rect(275, 275, 200, 200);
      text("2", 350, 195);
      rect(325, 325, 200, 200);
      text("3", 400, 245);
    } else if (row == -1) {  // if a row has not been chosen
      rect(250, 250, 400, 400);
      text("Layer " + lay + ":", 250, 20);
      text("Choose a row", 250, 475);
      rect(250, 105, 350, 50);
      text("0", 100, 100);
      rect(250, 200, 350, 50);
      text("1", 100, 195);
      rect(250, 300, 350, 50);
      text("2", 100, 295);
      rect(250, 400, 350, 50);
      text("3", 100, 395);
    } else if (val == -1) {  // if a value has not been chosen
      text("Row " + row + ":", 250, 100);
      text("Choose a value", 250, 400);
      rect(100, 250, 100, 100);
      text("0", 100, 250);
      rect(200, 250, 100, 100);
      text("1", 200, 250);
      rect(300, 250, 100, 100);
      text("2", 300, 250);
      rect(400, 250, 100, 100);
      text("3", 400, 250);
    } else {  //show a value                
      text("Value " + val + ":", 250, 100);
      rect(250, 250, 100, 100);
      text(dim[lay][row][val], 250, 250);  
      text("[" + lay + "]" + "[" + row + "]" + "[" + val + "]", 250, 400);  //show the actual location/ address of your chosen value
    }
  }
}

void keyPressed() {
  if (!show_startScreen) {  // If the start screen has been passed
    if (keyCode == BACKSPACE) {  // go back a level
      if (val != -1) {
        val = -1;
      } else if (row != -1) {
        row = -1;
      } else if (lay != -1) {
        lay = -1;
      }
    } else if (key == '0' || key == '1'|| key == '2'|| key == '3') { //make sure that the pressed key was a 0, 1, 2, or 3
      if (lay == -1) { // if layer has not been set, set it!
        lay = Integer.parseInt(str(key)); //covert the pressed key to an int, and store it
      } else if (row == -1) {  // if layer has not been set, set it!
        row = Integer.parseInt(str(key)); //covert the pressed key to an int, and store it
      } else if (val == -1) {  // if layer has not been set, set it!
        val = Integer.parseInt(str(key)); //covert the pressed key to an int, and store it
      }
    }
  } else {
    show_startScreen = false;
  }
  key = 'q'; // This gets rid of some loopholes
  redraw(); // Run the code in "draw()" once more
}

end of code

Honestly, this is so random and I don't think that this has any practical uses, but I am going to keep it handy just in case I suddenly forget how to wrap my head around three dimensional arrays.

P.S. A four dimensional array could be imagined as x cubes, each with x layers, and x rows in those layers, and x values in those rows. Perhaps a five dimensional array would be x groups of x cubes with x layers with x rows with x values. And so on....

Comments

  • Man, the code looked fine when I pasted it in, but it got all compressed after I posted it..... anyone know how I can fix that?

  • Edit post, highlight code, press ctrl-o

  • Oh! Thanks so much!

  • edited September 2017
    void setup() {
      String a[][][][];
      a = new String[][][][]{{{
    {"This"}, 
    {"is", "a"}, 
    {"four", "dimensional", "array"}}, 
    {{",even", "though"}, 
    {"it's", "not"}, 
    {"a"}}}, 
    {{{"cube."}}}};
      for (int w=0; w   <a.length; w++) {
        for (int z=0; z<a[w].length; z++) {
          for (int y=0; y<a[w][z].length; y++) {
            for (int x=0; x<a[w][z][y].length; x++) {
              print( a[w][z][y][x] + " ");
            }
          }
        }
      }
    }
    
  • The fourth component can also be time.

    E.g. the different moves in a 3D chess cube

  • here is a 3D cube with letters

    // States:
    // consts / numbers must be unique
    final int HELP   = 0; // help 
    final int GAME   = 1; // standard: selecting Cells with the mouse
    int state = GAME;   // current 
    
    // Cells 
    CellClass[][][] Cells = new CellClass[6][6][6];
    
    // rotation and Scale  
    float currentAngle1;      
    float zoomScale1=1.7;         
    boolean rotateFlag=true; 
    
    // Misc 
    PFont font1;
    
    // --------------------------------------------------------
    // main funcs 
    
    void setup() {
      size(1400, 800, P3D);
      background(111);
    
      defineCells();
    
      font1 = createFont("Arial", 32);
      textFont(font1); 
      textAlign(CENTER, CENTER); 
    
      currentAngle1=0;
    } // func ---
    
    void draw() {
      switch (state) {
    
      case HELP:
        // to do  
        background(111);
        text("Help\n\nThis is the help..."
          +"\n\npress any key.", 
          32, 344);
        break;
    
      case GAME:
        playTheGame();   
        break;
      } // switch
    } // func draw()
    
    // ----------------------------------------------------
    
    void playTheGame() {
    
      background(111);
      lights();
    
      camera(0, 0, 510, 
        0, 0, 0, 
        0, 1, 0);
    
      pushMatrix(); 
      scale (zoomScale1);
      rotateY(radians(currentAngle1));
    
      showTheGrid();
    
      popMatrix();
    
      strokeWeight(1);
    
      //stroke(255, 0, 0); 
      //line (0, -100, 0, 
      //  0, height+100, 0); 
      //line (width/2, -100, 
      //  width/2, height+100 ); 
    
      // rotation  
      if (keyPressed&&key=='r')
        currentAngle1++;
      if (keyPressed&&key=='l')
        currentAngle1--;
    
      if (rotateFlag)
        currentAngle1++;
    
      // 2D part / HUD  ---------------------------------------------
      camera();
      //  hint(DISABLE_DEPTH_MASK);
      //  hint(DISABLE_DEPTH_TEST);
      noLights();
      // textMode(MODEL);
      // textMode(SHAPE);
      textSize(14);
      fill(0); 
      text("Use r and l to rotate. Mouse wheel to zoom. Space to stop/start rotation. "
        +"\n", 
        310, 20 );
    
      //stroke(255, 0, 0); 
      //line (width/2, -100, 
      //  width/2, height+100 );
    }
    
    // ------------------------------------------------------------------
    
    void showTheGrid() {
      // show Cells : all
      for (int i = 0; i < Cells.length; i++) {
        for (int j = 0; j < Cells[i].length; j++) {
          for (int k = 0; k < Cells[i][j].length; k++) {
            //
            Cells[i][ j][k].show();
            //
          }// for
        }// for
      }// for
    } // func 
    
    // ----------------------------------------------------
    // input funcs
    
    void keyPressed () {
    
      switch (state) {
    
      case HELP : 
        // reset 
        state = GAME; 
        break; 
    
      case GAME : 
        if (key!=CODED) {
    
          // not CODED -----------------------------------
    
          if (key=='x'||key=='X') {
            // reset  
            defineCells();
          } else if (key == 'h' ) {
            //
            // F1 
            state = HELP; 
            println("1");
          } else if (key == ' ' ) {
            //
            // F1 
            rotateFlag = !rotateFlag; 
            println("1");
          }
        } else {
    
          // if (key==CODED) { --------------------------------------------
          //
          switch (keyCode) {
    
          case java.awt.event.KeyEvent.VK_PAGE_UP : 
            zoomScale1-=.01; 
            break; 
    
          case java.awt.event.KeyEvent.VK_PAGE_DOWN : 
            zoomScale1+=.01; 
            break; 
    
          default : 
            // do nothing 
            break;
          } // switch
        } // else
        break;
    
        //
      } // switch (state) { 
      //
    } // func 
    
    // ----------------------------------------------------
    // misc funcs
    
    void defineCells() {
      // define Cells
    
      float widthOverAll = 6*(height/10);
      float posX = (width/2) - (widthOverAll/2);
      println (posX);
    
      for (int i = 0; i < Cells.length; i++) {
        for (int j = 0; j < Cells[i].length; j++) {
          for (int k = 0; k < Cells[i][j].length; k++) {
    
            // prepare values 
            color currentCol = color (111);
            String randomWord="";
            randomWord+=""+char(int(random(65, 95)));
            randomWord+=""+char(int(random(65, 95)));
            randomWord+=""+char(int(random(65, 95)));
            randomWord+=""+char(int(random(65, 95)));
    
            // create a Cell        
            Cells[i][ j][k] = new CellClass( 
              -230 + i*(height/10), 
              -185 + j*(height/10), 
              -230 + k*(height/10), 
              currentCol, 
              randomWord);
          }
        }
      } // for
    } // func 
    
    // ----------------------------------------
    
    void mousePressed() {
    
      switch (state) {
    
      case HELP :
        // go back 
        state = GAME; 
        break; 
    
      case GAME : 
        //
        break;
      } // switch
    }//func
    
    void mouseWheel(MouseEvent event) {
    
      //This method controls zoomScale1 variable
    
      if (event.getCount()==-1)
        zoomScale1 += 0.1;
      else if (event.getCount()==1) {
        if (zoomScale1>=.1)
          zoomScale1 -= 0.1;
      }
    
      // check lower boundary 
      if (zoomScale1<.1)
        zoomScale1 = .1;
    } 
    
    // ========================================================
    // classes
    
    class CellClass {
    
      // this class represents one Box / Cell
    
      float x; 
      float y; 
      float z; 
    
      float scX, scY; 
    
      color col; 
      color defaultCol; 
    
      String textCell=""; 
    
      // constr
      CellClass(float x_, float y_, float z_, 
        color col_, 
        String word_) {
        x = x_; 
        y = y_; 
        z = z_; 
        col = col_;
        defaultCol = col; 
    
        textCell=word_;
      } // constr
    
      void show() {
        pushMatrix(); 
    
        translate(x, y, z);
        //rotateY ( currentAngle1 );
    
        noFill();
        stroke(255); 
        rect(-33, -16, 66, 32);
    
        fill(0, 0, 255);//blue 
    
        noStroke(); 
        // Cell(7);
    
        text(textCell, 0, 0); 
        col = defaultCol;
    
        // the Cell / box was drawn at (0, 0, 0), store that location
        scX = screenX(0, 0, 0); 
        scY = screenY(0, 0, 0);
    
        popMatrix();
      } // method
    } // class 
    // ==============================================================
    
Sign In or Register to comment.