Logo with initials

Arranging objects in 2D and 3D

──── 4 mins#Code

No matter how many (thousand) times you wrote a particular piece of code, you always have to it look up. I’ve been there so many times.

My brain forgets most snippets that involve lots of Math.sin and others. Anything like ((2 * i) / numItems) * PI. Unfortunately, that’s what a lot of “creative coding” is about. Fortunately, my brain can do association, like “I know I wrote this code in that project.”

I now have too many creative code algorithms across too many projects. So I’ve collected them in this article.

All snippets are language-agnostic, framework-agnostic and valid JavaScript.

2D

Arrange in a 2D grid

// arrange items in a horizontal grid from left to right
let gridSize = 3;
let itemSize = 60;
let numItems = 11;

for (let i = 0; i < numItems; i++) {
  // from left to right
  let gx = i % gridSize;
  let gy = Math.floor(i / gridSize);
  // swap gx and gy to arrange in a vertical grid from top to bottom
  // gx = Math.floor(i / gridSize);
  // gy = i % gridSize
  let x = gx * itemSize;
  let y = gy * itemSize;
  // 4px spacing
  rect(x, y, itemSize - 4, itemSize - 4);
}

Squares arranged in a grid

Arrange in a circle

let numItems = 8;
let radius = 100;
for (let i = 0; i <= numItems; i++) {
  // I love this line
  let angle = ((2 * i) / numItems) * Math.PI;
  let x = Math.cos(angle) * radius;
  let y = Math.sin(angle) * radius;
  ellipse(x, y, 20, 20);
}

./arrange-in-circle.svg

Arrange on a half circle

let numItems = 7;
let radius = 100;
// use this value to offset the angle and rotate your semicircle
let angleOffset = 0;
for (let i = 0; i < numItems; i++) {
  let t = i / Math.max(1, numItems - 1);
  let angle = Math.PI * t + angleOffset;
  let x = Math.cos(angle) * radius;
  let y = Math.sin(angle) * radius;
  ellipse(x, y, 20, 20);
}

./arrange-in-semicircle.svg

Make a spiral

let turns = 3; // How many revolutions
let radius = 100;
// How close we want the points to be, as an angle in radians, smaller is closer
let tightness = 0.2;
let full = Math.PI * 2 * turns;

for (let angle = 0; angle < full; angle += tightness) {
  let r = radius * (angle / full);
  let x = Math.cos(angle) * r;
  let y = Math.sin(angle) * r;
  ellipse(x, y, 4, 4);
}

./arrange-in-spiral.svg

3D

Random points on the surface of a sphere

let radius = 100;

for (let i = 0; i < 1000; i++) {
  // random θ and φ — spherical coordinate stuff 🤷‍♂️
  let theta = random(0, Math.PI * 2);
  let phi = random(-Math.PI / 2, Math.PI / 2);

  let x = radius * Math.sin(theta) * Math.cos(phi);
  let y = radius * Math.sin(theta) * Math.sin(phi);
  let z = radius * Math.cos(theta);
  point(x, y, z);
}

./arrange-around-sphere.svg

Random points in a sphere

for (let i = 0; i < 1000; i++) {
  let phi = Math.random() * (2 * Math.PI);
  let costheta = Math.random() * 2 - 1;
  let u = Math.random();

  let theta = Math.acos(costheta);
  // Math.cbrt is part of ES2015
  let r = radius * Math.cbrt(u);

  let x = r * Math.sin(theta) * Math.cos(phi);
  let y = r * Math.sin(theta) * Math.sin(phi);
  let z = r * Math.cos(theta);
  point(x, y, z);
}

./arrange-in-sphere.svg

Create a cube of cubes!

let xCount = 4;
let yCount = 4;
let zCount = 4;
let boxSize = 20;

for (let k = 0; k < zCount; k++) {
  for (let j = 0; j < yCount; j++) {
    for (let i = 0; i < xCount; i++) {
      let size = boxSize + 7; // add a bit of spacing around each cube
      let halfWayX = (size * xCount) / 2;
      let halfWayY = (size * yCount) / 2;
      let halfWayZ = (size * zCount) / 2;

      if (xCount % 2 != 0) halfWayX -= size / 2;
      if (yCount % 2 != 0) halfWayY -= size / 2;
      if (zCount % 2 != 0) halfWayZ -= size / 2;

      let x = size * i - halfWayX;
      let y = size * j - halfWayY;
      let z = size * k - halfWayZ;
      box(x, y, z, boxSize, boxSize, boxSize);
    }
  }
}

./cubes.png

If you’re curious how these images were generated, the code is available in this repository.

Suggestions welcome! I want to keep updating this post with cool visuals, and I would love your help. Please keep suggestions to spatial stuff though. We collectively wrote enough bubble sorts.