skip to Main Content

I am trying to create a 2-dimensional array of vectors using p5.js
I generate the 2D vector array in setup() using nested For loops, and print the vector value to the console within the same nested loops.
Starting with a 2D array of 2×2 elements, I want the vectors to take their values from the array index (so, for example: vector[0][0] has value (0,0) and vector[1][1] has value (1,1).

This all works correctly in setup(), and the first line on the console is:

0 0 _class {x: 0, y: 0, z: 0, constructor: Object}

But when I access this 2D array in the draw() function and print the vectors to console, the first line is:

0 0 _class {x: 1, y: 0, z: 0, constructor: Object}

let xV = 2
let yV = 2
let vectorP = [2,2]

function setup() {
  for (var i = 0; i < xV; i++) {
   for (var j = 0; j < yV; j++) {
    vectorP[i,j] = new p5.Vector(i,j);
    console.log(i,j,vectorP[i,j]);
   }
  }
 }

function draw() {
 console.log ("draw")
  for (var i = 0; i < xV; i++) {
   for (var j = 0; j < yV; j++) {
    console.log(i,j,vectorP[i,j]) 
   }
  }
 }

I assume this is due to the way JavaScript deals with objects by reference rather than by value, but I cannot find a way to make it work. I have tried variations with createVector, push, etc. with the same result. The other possibility that occurred to me is that the next vector begins where the previous vector ended. I’m also not sure if my initial array declaration is correct.
*Edit: I have tried the declaration
let vectorP = new Array(2,2)
which makes no difference.

2

Answers


  1. Chosen as BEST ANSWER
    const xV = 2;
    const yV = 3;
    const zV = 4;
    
    let vectorP = [];
    
    function setup() {
     noLoop()
      
      for (let i = 0; i < xV; i++) {
        vectorP[i] = []
        
        for (let j = 0; j < yV; j++) {
          vectorP[i][j] = []
       
          for (var k = 0; k < zV; k++) {
            vectorP[i][j][k] = new p5.Vector(i, j, k);
          }
        }
      }
        
    }
    
    function draw() {
      for (let i = 0; i < xV; i++) {
        for (let j = 0; j < yV; j++) {
          for (var k = 0; k < zV; k++) {
            console.log(i,j,k,vectorP[i][j][k]);
          }
        }
      }
    }
    

  2. The following syntax is the problem:

    vectorP[i,j] = new p5.Vector(i,j);
    

    In particular, i,j does not do what you think it does (indexing into a 2d array). The expression i, j evaluates to only j and i is ignored:

    const a = [10, 11, 12, 13];
    const i = 2;
    const j = 1;
    console.log(a[i, j]); // => 11

    Similarly, let vectorP = [2,2] does not declare an empty 2×2 array. It declares a 1d array with 2 values: vectorP[0] = 2; vectorP[1] = 2:

    const vectorP = [2, 2];
    console.log(vectorP); // => [2, 2]
    console.log(vectorP[0]); // => 2
    vectorP[1] = 42;
    console.log(vectorP[1]); // => 42

    If you want a true 2d array, try:

    const xV = 2;
    const yV = 2;
    const vectorP = [];
    
    function setup() {
      noLoop();
    
      for (let i = 0; i < xV; i++) {
        vectorP.push([]);
      
        for (let j = 0; j < yV; j++) {
          vectorP[i][j] = new p5.Vector(i, j);
        }
      }
    }
    
    function draw() {
      for (let i = 0; i < xV; i++) {
        for (let j = 0; j < yV; j++) {
          console.log(i, j, vectorP[i][j]);
        }
      }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.js"></script>

    Or, more idiomatically, use the Array constructor and map to build the arrays and for ... of or .forEach to iterate:

    const xV = 2;
    const yV = 2;
    let vectorP = [];
    
    function setup() {
      noLoop();
      vectorP = [...Array(xV)].map((_, i) => 
        [...Array(yV)].map((_, j) => new p5.Vector(i, j))
      );
    }
    
    function draw() {
      vectorP.forEach((row, i) =>
        row.forEach((cell, j) =>
          console.log(i, j, cell)
        )
      );
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.js"></script>

    If you’re making many arrays, you can abstract away some of the messy syntax with:

    // ...
    const array = (len, fn) => [...Array(len)].map((_, i) => fn(i));
    
    function setup() {
      noLoop();
      vectorP = array(xV, i => array(yV, j => new p5.Vector(i, j)));
      // ...
    

    I prefer y to be rows (outer vertical axis) and x to be columns (inner horizontal axis). But I preserved your convention for this answer.

    When working with 2d arrays, it’s a good idea to test with different width/height values to ensure you don’t have row and column variables mixed up anywhere. In other words, try 3×2 instead of 2×2.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search