How to make a grid of ellipses with subdivisions - javascript

I have created a circle with subdivisions (function CircleSubDivs) in p5.js and now want to generate a grid filled with those. Ideally the ellipse would also be disproportionate if the width and height of a tile is not the same, or if the amount of tiles were to be controlled by the mouse position the ellipse would move flexibly.
This was my inspiration
This is my code so far:
// let colors = [
// "#F48668 ",
// "#5D2E8C",
// "#F7F7F7"
// ];
function CircleSubDivs(x, y, size) {
let amount = 13;
let r = 360 / amount;
for (let j = 0; j < 10; j++) {
for (let i = 0; i < amount; i++) {
fill(random(255));
let s = map(j, 0, 8, width, 100);
arc(width / 2, height / 2, s, s, radians(r * i), radians(r * (i + 1)));
}
}
}
function setup() {
createCanvas(500, 500);
frameRate(1);
}
function draw() {
background("#0F0F0F");
noStroke();
let tilesX = 3;
let tilesY = 2;
let tileW = width / tilesX;
let tileH = height / tilesY;
for (let x = 0; x < tilesX; x++) {
for (let y = 0; y < tilesY; y++) {
CircleSubDivs(x * tileW, y * tileH, tileW, tileH);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
As you can see I have created a grid and tried to store my function for the ellipse with divisions in there, but it just shows me one single ellipse when I run it. I would really appreciate some help :)

Your parameters to your function are unused, so the function does the same thing every time.
You might try something like:
function drawSubdividedCircle(x, y, size, segments=13, layers=10) {
const r = 360 / segments;
for (let i = 0; i < segments; i++) {
for (let j = 0; j < layers; j++) {
fill(random(255));
const s = map(j, 0, layers, size, 0);
arc(
x + size / 2,
y + size / 2,
s,
s,
radians(r * i),
radians(r * (i + 1))
);
}
}
}
function setup() {
createCanvas(500, 500);
frameRate(1);
}
function draw() {
background("#0F0F0F");
noStroke();
const tilesX = 3;
const tilesY = 2;
const tileSize = width / tilesX;
for (let x = 0; x < tilesX; x++) {
for (let y = 0; y < tilesY; y++) {
drawSubdividedCircle(x * tileSize, y * tileSize, tileSize);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>

Related

How to make a grid with one bigger tile

I'm working on this program for a grid that generates geometric shapes and I want the function drawSubdividedCircle to always appear only once at a random position on the grid and take up the with and height of two rows/columns. I think the main problem is stacking because when i run it now the objects overlap. This is basically my goal:
And this is the code:
let colors = [
"#F7F7F7",
"#141414",
"#f07f45",
"#bcaad6",
"#60388e",
"#00afc6",
"#aae3ea"
];
let tilesX = 5;
let tilesY = 5;
let tileW;
let tileH;
let tileSize;
function drawSubdividedCircle (x, y, size, segments, layers) {
segments = random (1,13);
layers = random (1,13);
const r = 360 / segments;
for (let i = 0; i < segments; i++)
{
for (let j = 0; j < layers; j++)
{
fill(random(colors));
const s = map(j, 0, layers, size, 0);
arc(
x + size / 2,
y + size / 2,
s,
s,
radians(r * i),
radians(r * (i + 1)));
}
}
}
function setup() {
createCanvas(500, 500, SVG);
tileW = width / tilesX;
tileH = height / tilesY;
tileSize = (tileW, tileH);
}
function draw() {
noStroke();
frameRate(2);
for (let x = 0; x < tilesX; x++)
{
for (let y = 0; y < tilesY; y++)
{
let r = random(1);
if (r < 0.5)
{
ellipse((x - 0.5) * tileSize, (y - 0.5) * tileSize, tileSize, tileSize);
fill(random(colors));
}
else
{
rect(x * tileSize, y * tileSize, tileSize, tileSize);
fill(random(colors));
}{ drawSubdividedCircle(x * tileSize, y * tileSize, tileSize*2);
fill(random(colors));
}
}
}
//save("sketch1.6.5.svg");
//print("saved svg");
//noLoop();
}
Added an array to keep track of the state of each individual tile. Could be optimized for sure, but this works just fine.
https://editor.p5js.org/Kroepniek/sketches/MsFlcY3kl
let colors = [
"#F7F7F7",
"#141414",
"#f07f45",
"#bcaad6",
"#60388e",
"#00afc6",
"#aae3ea"
];
let tilesX = 5;
let tilesY = 5;
let tileW;
let tileH;
let tileSize;
let tileIsFree;
let subdividedCirclesCount = 0;
const subdividedCirclesLimit = 1;
function reinitTileStateArray()
{
tileIsFree = [];
for (let x = 0; x < tilesX; x++)
{
for (let y = 0; y < tilesY; y++)
{
tileIsFree[y * tilesX + x] = true;
}
}
subdividedCirclesCount = 0;
}
function drawSubdividedCircle (x, y, size, segments, layers) {
subdividedCirclesCount++;
segments = random (1,13);
layers = random (1,13);
const r = 360 / segments;
for (let j = 0; j < layers; j++)
{
for (let i = 0; i < segments; i++)
{
fill(random(colors));
const s = map(j, 0, layers, size, 0);
arc(
x + size / 2,
y + size / 2,
s,
s,
radians(r * i),
radians(r * (i + 1)));
}
}
}
function setup() {
createCanvas(500, 500);
frameRate(2);
tileW = width / tilesX;
tileH = height / tilesY;
tileSize = (tileW, tileH);
}
function draw() {
background(0);
noStroke();
reinitTileStateArray();
let randomChance = 0.5;
for (let y = 0; y < tilesY; y++)
{
for (let x = 0; x < tilesX; x++)
{
let r = random();
if (tileIsFree[y * tilesX + x])
{
fill(random(colors));
rect(x * tileSize, y * tileSize, tileSize, tileSize);
if (r < randomChance)
{
fill(random(colors));
ellipse((x + 0.5) * tileSize, (y + 0.5) * tileSize, tileSize, tileSize);
}
else if (subdividedCirclesCount < subdividedCirclesLimit && tileIsFree[y * tilesX + x + 1])
{
drawSubdividedCircle(x * tileSize, y * tileSize, tileSize * 2);
tileIsFree[y * tilesX + x] = false;
tileIsFree[y * tilesX + x + 1] = false;
tileIsFree[(y + 1) * tilesX + x] = false;
tileIsFree[(y + 1) * tilesX + x + 1] = false;
randomChance = 0.75;
}
}
}
}
//save("sketch1.6.5.svg");
//print("saved svg");
//noLoop();
}

How to change the rows or columns of a grid without messing up the content

I want to be able to implement more rows or columns to the grid depending on the format. (For example if i want to use the sketch on a horizontal 16x9 screen, there would have to be more rows than columns) Right now it only works if the format/canvas is square.
As soon as I change the number of tiles or the size of the canvas, the elements jump around.
Here is my sketch:
let colors = [
"#F7F7F7",
"#141414",
"#FB2576",
"#F48668",
"#67339E",
"#00A6A6",
"#78FFD6"
];
function drawSubdividedCircle(x, y, size, segments, layers) {
segments = random (1,13);
layers = random (1,13);
const r = 360 / segments;
for (let i = 0; i < segments; i++) {
for (let j = 0; j < layers; j++) {
fill(random(colors));
const s = map(j, 0, layers, size, 0);
arc(
x + size / 2,
y + size / 2,
s,
s,
radians(r * i),
radians(r * (i + 1)));
}
}
}
function setup() {
createCanvas(500, 500);
frameRate(2);
}
function draw() {
noStroke();
let tilesX = 5;
let tilesY = 5;
let tileW = width / tilesX;
let tileH = height / tilesY;
const tileSize = width / tilesX;
for (let x = 0; x < tilesX; x++) {
for (let y = 0; y < tilesY; y++) {
rect(x*tileW, y*tileH, tileW, tileH);
fill(random(colors));
push();
for (let x = 0; x < tilesX; x++) {
for (let y = 0; y < tilesY; y++) {
let r = random(1);
if (r < 0.5) {
ellipseMode(CORNER);
ellipse(x*tileW, y*tileH, tileW, tileH);
fill(random(colors));
} else {
ellipseMode(CENTER);
drawSubdividedCircle(x * tileSize, y * tileSize, tileSize);
fill(random(colors));
pop();
}
}
}
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
I changed your code a little.. Removed two redundant for-loops, it is much faster now.
When you want to make your program responsive, you have to make a choice. Do you want the circles to scale when you change the resolution or maybe do you want the amount of rows/columns to change when the resolution changes? There are several possibilities, I made it now to keep the amount of tiles, and use the smaller value of the 'tileW' and 'tileH' to remain the circle shape.
let colors = [
"#F7F7F7",
"#141414",
"#FB2576",
"#F48668",
"#67339E",
"#00A6A6",
"#78FFD6"
];
var tilesX = 5;
var tilesY = 5;
var tileW;
var tileH;
var tileSize;
function drawSubdividedCircle(x, y, size, segments, layers)
{
segments = random (1,13);
layers = random (1,13);
const r = 360 / segments;
for (let i = 0; i < segments; i++)
{
for (let j = 0; j < layers; j++)
{
fill(random(colors));
const s = map(j, 0, layers, size, 0);
arc(
x + size / 2,
y + size / 2,
s,
s,
radians(r * i),
radians(r * (i + 1)));
}
}
}
function setup()
{
createCanvas(550, 500);
ellipseMode(CENTER);
//frameRate(2);
tileW = width / tilesX;
tileH = height / tilesY;
tileSize = min(tileW, tileH);
}
function draw()
{
background(0);
noStroke();
for (let x = 0; x < tilesX; x++)
{
for (let y = 0; y < tilesY; y++)
{
rect(x * tileSize, y * tileSize, tileSize, tileSize);
fill(random(colors));
let r = random(1);
if (r < 0.5)
{
ellipse((x - 0.5) * tileSize, (y - 0.5) * tileSize, tileSize, tileSize);
fill(random(colors));
}
else
{
drawSubdividedCircle(x * tileSize, y * tileSize, tileSize);
fill(random(colors));
}
}
}
}

Weird pattern of Heat Equation Simulation on 2D Canvas

I'm playing with a Heat Equation on 2D Canvas with additional heat source in a form of a donut. The result I got some "acidic" pattern around this donut.
const width = 200; // width of the grid
const height = 200; // height of the grid
const dt = 0.25; // time step
const dx = 1; // space step in the x-direction
const dy = 1; // space step in the y-direction
const alpha = 0.25; // thermal diffusivity
const Q = [];
// Heat of the heat source
const Q0 = 80;
const r1 = 8;
const r2 = 12;
for (let i = 0; i < width - 1; i++) {
Q[i] = [];
for (let j = 0; j < height - 1; j++) {
// Calculate the distance from the center of the region
const r = Math.sqrt((i - width / 2) ** 2 + (j - height / 2) ** 2);
Q[i][j] = (r1 < r && r < r2) ? Q0 : 0;
}
}
let grid = []; // array to store the grid
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Initialize the grid with random temperatures
for (let i = 0; i < width; i++) {
grid[i] = [];
for (let j = 0; j < height; j++) {
grid[i][j] = 50
}
}
function updateGrid() {
// Update the temperature of each cell based on the heat equation
for (let i = 1; i < width - 1; i++) {
for (let j = 1; j < height - 1; j++) {
const d2Tdx2 = (grid[i + 1][j] - 2 * grid[i][j] + grid[i - 1][j]) / (dx ** 2);
const d2Tdy2 = (grid[i][j + 1] - 2 * grid[i][j] + grid[i][j - 1]) / (dy ** 2);
grid[i][j] = grid[i][j] + alpha * dt * (d2Tdx2 + d2Tdy2) + (Q[i][j] * dt);
}
}
}
// This function is called repeatedly to update the grid and render it
function main() {
updateGrid();
renderGrid();
requestAnimationFrame(main);
}
// This function render the grid
function renderGrid() {
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Iterate over the grid and draw each cell
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
let hue = ((100 - grid[i][j]) / 100) * 240;
//ctx.fillStyle = `rgb(${temp}, ${temp}, ${temp})`;
ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
ctx.fillRect(i * dx, j * dy, dx, dy);
}
}
}
// Start the simulation
main();
Tried different approaches, like playing with hsl colors, initial parameters but something definitely missing there.
What I aslo noticed is that during debuging, some values seems to be blowing up and I think that's the root of the problem but can't find the source of it, I have tried to found more information about this behaviour of differential equiations and why this can happen but couldn't apply it to the source code.
during calculation values in grid can go over 100, thus making formula ((100 - grid[i][j]) / 100) * 240; produce negative values
the simples way to fix is to limit values:
grid[i][j] = Math.min(100, grid[i][j] + alpha * dt * (d2Tdx2 + d2Tdy2) + (Q[i][j] * dt));
const width = 200; // width of the grid
const height = 200; // height of the grid
const dt = 0.25; // time step
const dx = 1; // space step in the x-direction
const dy = 1; // space step in the y-direction
const alpha = 0.25; // thermal diffusivity
const Q = [];
// Heat of the heat source
const Q0 = 80;
const r1 = 8;
const r2 = 12;
for (let i = 0; i < width - 1; i++) {
Q[i] = [];
for (let j = 0; j < height - 1; j++) {
// Calculate the distance from the center of the region
const r = Math.sqrt((i - width / 2) ** 2 + (j - height / 2) ** 2);
Q[i][j] = (r1 < r && r < r2) ? Q0 : 0;
}
}
let grid = []; // array to store the grid
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Initialize the grid with random temperatures
for (let i = 0; i < width; i++) {
grid[i] = [];
for (let j = 0; j < height; j++) {
grid[i][j] = 50
}
}
function updateGrid() {
// Update the temperature of each cell based on the heat equation
for (let i = 1; i < width - 1; i++) {
for (let j = 1; j < height - 1; j++) {
const d2Tdx2 = (grid[i + 1][j] - 2 * grid[i][j] + grid[i - 1][j]) / (dx ** 2);
const d2Tdy2 = (grid[i][j + 1] - 2 * grid[i][j] + grid[i][j - 1]) / (dy ** 2);
grid[i][j] = Math.min(100, grid[i][j] + alpha * dt * (d2Tdx2 + d2Tdy2) + (Q[i][j] * dt));
}
}
}
// This function is called repeatedly to update the grid and render it
function main() {
updateGrid();
renderGrid();
requestAnimationFrame(main);
}
// This function render the grid
function renderGrid() {
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Iterate over the grid and draw each cell
for (let i = 0; i < width; i++) {
for (let j = 0; j < height; j++) {
let hue = (100 - grid[i][j]) / 100 * 240;
//ctx.fillStyle = `rgb(${temp}, ${temp}, ${temp})`;
ctx.fillStyle = `hsl(${hue}, 100%, 50%)`;
ctx.fillRect(i * dx, j * dy, dx, dy);
}
}
}
// Start the simulation
main();
<canvas width="500" height="500" id="canvas"></canvas>

How to make a grid of moiré circles in p5.js?

I'm attempting to make a grid where every tile is filled with a single "moire-style" ellipse (a circle with circles inside).
function setup() {
createCanvas(500, 500);
ellipseMode(CENTER);
}
function draw() {
background(255);
noFill();
strokeWeight(3);
stroke(0);
let tilesX = 3;
let tilesY = tilesX;
let tileW = width / tilesX;
let tileH = height / tilesY;
for (let x = 0; x < tilesX; x++) {
for (let y = 0; y < tilesY; y++) {
moire(tilesX, tilesY, tileW);
}
}
function moire(x, y, size) {
for (var i = 1; i <= tileW; i = i + 8) {
ellipse(width / 2, height / 2, 2 * i, 2 * i);
translate(tilesX, tilesY);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>
This is what I have in my p5.js sketch but the moire elements don't align to the tiles.
The following demo will create a grid of moire circles:
let _numRows = 3;
let _numCols = 3;
let _colGap = 30;
let _rowGap = 30;
function moire(x, y, size) {
for (var i = 1; i <= size; i = i + 8) {
ellipse(x, y, 2 * i, 2 * i);
translate(3, 3);
}
}
function setup() {
createCanvas(500, 500);
ellipseMode(CENTER);
}
function draw() {
background(255);
noFill();
strokeWeight(3);
stroke(0);
let _xOffset = width/5;
let _yOffset = height/5;
for (let j = 0; j < _numCols; j++) {
for (let k = 0; k < _numRows; k++) {
push();
moire(_xOffset + j * (100 + _colGap), _yOffset + k * (100 + _rowGap), 50);
pop();
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>

Unable to set 2D Javascript array inside nested loop [duplicate]

This question already has answers here:
Array.prototype.fill() with object passes reference and not new instance
(7 answers)
Closed 5 months ago.
I am trying to convert a 2D grid of (x, y) points to a sphere in space. I loop through all of the points in the grid and set the value to an object {x: someX, y: someY, z: someZ}. But for some reason, the value I get inside the loop is different from the value outside. Do I have a typo or is this something about JS I don't understand yet? Here is the exact section causing issues:
for (let y = 0; y < GRID_WIDTH; y++) {
for (let x = 0; x < GRID_WIDTH; x++) {
points[y][x] = grid2Sphere(x, y); //returns {x: someX, y: someY, z: someZ}. This works.
console.log(points[y][x]); // This logs the correct values
}
console.log(points[y]); // This is always equal to the row where y = 0. It's as if everything that happened in the inner loop did not get set.
}
For those interested, here is the entire file. I am using p5.js:
let R;
let points;
const GRID_WIDTH = 20;
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
stroke("#000");
R = 100;
angleMode(RADIANS);
points = new Array(GRID_WIDTH).fill(new Array(GRID_WIDTH).fill({}));
// Calculate and draw each point.
for (let y = 0; y < GRID_WIDTH; y++) {
for (let x = 0; x < GRID_WIDTH; x++) {
points[y][x] = Object.assign({}, grid2Sphere(x, y));
console.log(points[y][x]);
}
console.log(points[y]);
}
drawPoints(points);
}
function draw() {
noLoop();
}
function drawPoints(pArray) {
for (let y = 0; y < GRID_WIDTH; y++) {
for (let x = 0; x < GRID_WIDTH; x++) {
let p = pArray[y][x];
point(p.x, p.y, p.z);
}
}
}
function grid2Sphere(x, y) {
var radX = map(x, 0, GRID_WIDTH - 1, -1 * PI * R, PI * R);
var radY = map(y, 0, GRID_WIDTH - 1, -1 * PI / 2 * R, PI / 2 * R);
var lon = radX / R;
var lat = 2 * atan(exp(radY / R)) - PI / 2;
var x_ = R * cos(lat) * cos(lon);
var y_ = R * cos(lat) * sin(lon);
var z_ = R * sin(lat);
return {x: x_, y: y_, z: z_};
}
I think you're on the right track, the confusion stems from here actually:
points = new Array(GRID_WIDTH).fill(new Array(GRID_WIDTH).fill({}));
to break it down:
new Array(GRID_WIDTH).fill({}) creates an array of empty objects
new Array(GRID_WIDTH).fill(new Array(GRID_WIDTH).fill({})); makes a new array that is filled with references (not copies) of the first array (e.g. if the first array of {},{},... was called myData, the nested array would contain: myData,myData,... 20 times)
You could assign/allocate a new array on each y loop:
// Calculate and draw each point.
for (let y = 0; y < GRID_WIDTH; y++) {
// ensure this is a new array (and not the same reference)
points[y] = [];
for (let x = 0; x < GRID_WIDTH; x++) {
points[y][x] = grid2Sphere(x, y);
console.log(x, y, points[y][x]);
}
console.log(y, points[y]);
}
Here's a modified version of your code:
let R;
let points;
const GRID_WIDTH = 20;
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
background(255);
stroke("#000");
R = 100;
points = new Array(GRID_WIDTH).fill(new Array(GRID_WIDTH).fill({}));
// Calculate and draw each point.
for (let y = 0; y < GRID_WIDTH; y++) {
// ensure this is a new array (and not the same reference)
points[y] = [];
for (let x = 0; x < GRID_WIDTH; x++) {
points[y][x] = grid2Sphere(x, y);
console.log(x, y, points[y][x]);
}
console.log(y, points[y]);
}
// move camera for visual debugging purposes only
camera(300, -100, 0, 0, 0, 0, 0, 1, 0);
drawPoints(points);
}
function drawPoints(pArray) {
for (let y = 0; y < GRID_WIDTH; y++) {
for (let x = 0; x < GRID_WIDTH; x++) {
let p = pArray[y][x];
point(p.x, p.y, p.z);
}
}
}
function grid2Sphere(x, y) {
var radX = map(x, 0, GRID_WIDTH - 1, -1 * PI * R, PI * R);
var radY = map(y, 0, GRID_WIDTH - 1, -1 * PI / 2 * R, PI / 2 * R);
var lon = radX / R;
var lat = 2 * atan(exp(radY / R)) - PI / 2;
var x_ = R * cos(lat) * cos(lon);
var y_ = R * cos(lat) * sin(lon);
var z_ = R * sin(lat);
return {x: x_, y: y_, z: z_};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js"></script>
You could simplify further by just using an empty array that gets populated later (without worrying about filling it ahead of time):
let R = 100;
let points;
const GRID_WIDTH = 20;
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
background(255);
stroke("#000");
points = [];
// Calculate and draw each point.
for (let y = 0; y < GRID_WIDTH; y++) {
points[y] = [];
for (let x = 0; x < GRID_WIDTH; x++) {
points[y][x] = grid2Sphere(x, y);
console.log(x, y, points[y][x]);
}
console.log(y, points[y]);
}
}
function draw(){
background(255);
orbitControl();
drawPoints(points);
}
function drawPoints(pArray) {
beginShape(POINTS);
for (let y = 0; y < GRID_WIDTH; y++) {
for (let x = 0; x < GRID_WIDTH; x++) {
let p = pArray[y][x];
vertex(p.x, p.y, p.z);
}
}
endShape();
}
function grid2Sphere(x, y) {
var radX = map(x, 0, GRID_WIDTH - 1, -PI * R, PI * R);
var radY = map(y, 0, GRID_WIDTH - 1, -HALF_PI * R, HALF_PI * R);
var lon = radX / R;
var lat = 2 * atan(exp(radY / R)) - PI / 2;
return {
x: R * cos(lat) * cos(lon),
y: R * cos(lat) * sin(lon),
z: R * sin(lat)
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js"></script>
You can simplify even further by using a flat (1D) array (which you can easily set the size of if you need to):
let R = 100;
const GRID_WIDTH = 20;
const NUM_POINTS = GRID_WIDTH * GRID_WIDTH;
let points = new Array(NUM_POINTS);
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
for(let i = 0; i < NUM_POINTS; i++){
let x = i % GRID_WIDTH;
let y = i / GRID_WIDTH; // this is a float (ok for now, but with image indices floor() it)
points[i] = p5.Vector.fromAngles(map(x, 0, GRID_WIDTH - 1, 0, PI),
map(y, 0, GRID_WIDTH - 1, 0, TWO_PI),
R);
}
}
function draw(){
background(255);
orbitControl();
drawPoints(points);
}
function drawPoints(pArray) {
beginShape(POINTS);
pArray.forEach(p => vertex(p.x, p.y, p.z));
endShape();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.min.js"></script>
Here, I'm also using beginShape() / endShape() / vertex() which should be more efficient than point() (though for your static image won't make a difference) and using p5.Vector which on top of providing x,y,z properties has a bunch of nice linear algebra utilities (e.g. computing angles between vectors, perpendiculars to vectors, etc.) as well as p5.Vector.fromAngles() which does the spherical to cartesian coordinate conversion for you.
An even shorter version of the above (though less readible):
let R = 100;
const GRID_WIDTH = 20;
let points = new Array(GRID_WIDTH * GRID_WIDTH).fill();
function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
points.forEach((p,i) => points[i] = p5.Vector.fromAngles((i % GRID_WIDTH) / GRID_WIDTH * PI,
(i / GRID_WIDTH) / GRID_WIDTH * TWO_PI, R));
}
function draw(){
background(255);
orbitControl();
drawPoints(points);
}
function drawPoints(pArray) {
beginShape(POINTS);
pArray.forEach(p => vertex(p.x, p.y, p.z));
endShape();
}

Categories

Resources