Why does my object keep getting NaN values? - javascript

I´ve been messing around with a library called p5.js and I encounter a problem while trying to modify the values of an object. After creating the array and pushing the objects I check for the object and it has many NaN values. This code can be run in editor.p5js.org for free in case you need it. Thanks in advance.
function setup() {
createCanvas(600, 600);
background(0);
p = [];
planetnum = 3; //Set one more
for (u = 0; u < planetnum; u++) {
p.push({
rx: 0,
ry: 0,
vx: 0,
vy: 0,
ax: 0,
ay: 0,
m: 10
});
}
for (u = 0; u < planetnum; u++) {
p[u].rx = 0;
p[u].ry = 0;
p[u].vx = 0;
p[u].vy = 0;
p[u].ax = 0;
p[u].ay = 0;
p[u].m = 10;
}
p[0].ry = 100;
p[1].rx = 100;
p[2].rx = -100;
console.log(p[1]);
}
function draw() {
background(0);
translate(width / 2, height / 2);
scale(1, -1);
console.log("Working");
color(255);
//Calculate next position
for (i = 0; i < planetnum; i++) {
p[i].ax = 0;
p[i].ay = 0;
console.log(p[i]);
for (o = 0; o < planetnum; o++) {
if (o != i) {
d = sqrt((p[i].ry - p[o].ry) ^ 2 + (p[i].rx - p[o].rx) ^ 2);
f = -0.001 / (d * d);
angle = Math.atan2((p[i].ry - p[o].ry), (p[i].rx - p[o].rx));
p[i].ax += f * d * Math.cos(angle) / p[i].m;
p[i].ay += f * d * Math.sin(angle) / p[i].m;
}
}
p[i].vx += p[i].ax;
p[i].ay += p[i].ay;
p[i].rx += p[i].vx;
p[i].ry += p[i].vy;
}
//Draw circles
for (i = 0; i < planetnum; i++) {
circle(p[i].rx, p[i].ry, 10);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

I'm guessing that when you wrote this code:
d = sqrt((p[i].ry - p[o].ry) ^ 2 + (p[i].rx - p[o].rx) ^ 2);
Your intention was to square each of those deltas. However, in JavaScript ^ is the bitwise XOR operator, not the exponent operator. This is probably resulting in your taking the square root of -1 which is NaN. This fixes the NaN problem:
d = sqrt((p[i].ry - p[o].ry) ** 2 + (p[i].rx - p[o].rx) ** 2);
Note: on certain defunct browsers you might need to use Math.pow(p[i].ry - p[o].ry, 2), also you could consider the p5.js dist function: dist(p[i].rx, p[i].ry, p[o].rx, p[o].ry).
function setup() {
createCanvas(600, 600);
background(0);
p = [];
planetnum = 3; //Set one more
for (u = 0; u < planetnum; u++) {
p.push({
rx: 0,
ry: 0,
vx: 0,
vy: 0,
ax: 0,
ay: 0,
m: 10
});
}
for (u = 0; u < planetnum; u++) {
p[u].rx = 0;
p[u].ry = 0;
p[u].vx = 0;
p[u].vy = 0;
p[u].ax = 0;
p[u].ay = 0;
p[u].m = 10;
}
p[0].ry = 100;
p[1].rx = 100;
p[2].rx = -100;
console.log(p[1]);
}
function mouseClicked() {
console.log("Debug:");
for (i = 0; i < planetnum; i++) {
console.log(p[i]);
}
}
function draw() {
background(0);
translate(width / 2, height / 2);
scale(1, -1);
color(255);
//Calculate next position
for (i = 0; i < planetnum; i++) {
p[i].ax = 0;
p[i].ay = 0;
for (o = 0; o < planetnum; o++) {
if (o != i) {
d = sqrt((p[i].ry - p[o].ry) ** 2 + (p[i].rx - p[o].rx) ** 2);
f = -0.001 / (d * d);
angle = Math.atan2((p[i].ry - p[o].ry), (p[i].rx - p[o].rx));
p[i].ax += f * d * Math.cos(angle) / p[i].m;
p[i].ay += f * d * Math.sin(angle) / p[i].m;
}
}
p[i].vx += p[i].ax;
p[i].ay += p[i].ay;
p[i].rx += p[i].vx;
p[i].ry += p[i].vy;
}
//Draw circles
for (i = 0; i < planetnum; i++) {
circle(p[i].rx, p[i].ry, 10);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

Related

How to make a grid of ellipses with subdivisions

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>

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>

Paper.js How can I make colorful strokeColor?

I have a problem. I can't make a colorful strokeColor. I tried to do like that
p.strokeColor = 'purple'; p.strokeColor = 'red'; and p.strokeColor=['purple','red'].
But nothing helps. Here's an example.
Here's a demo. https://codepen.io/aqua908/pen/rNvyyJj
You are doing fine, only choose different color every time, say according to y
if (y % 2 == 0) {
p.strokeColor = "purple";
} else {
p.strokeColor = "blue";
}
window.onload = function () {
var w = 800; //window.innerWidth
var h = 400; //window.innerHeight
var params = {
height: 0.3,
amplitude: 60,
speedX: 5,
speedY: 5,
speedZ: 5,
frequenceX: 2,
frequenceY: 2,
frequenceZ: 5
};
var gui = new dat.gui.GUI();
var f1 = gui.addFolder("Noise Waves");
f1.add(params, "height", 0.1, 1).step(0.1);
f1.add(params, "amplitude", 0, 150).step(1);
f1.add(params, "speedX", -10, 10).step(0.5);
f1.add(params, "speedY", -10, 10).step(0.5);
f1.add(params, "speedZ", -10, 10).step(0.5);
f1.add(params, "frequenceX", 1, 10);
f1.add(params, "frequenceY", 1, 10);
f1.add(params, "frequenceZ", 1, 10);
f1.open();
var simplex = new SimplexNoise();
var nx = 0;
var ny = 0;
var nz = 0;
var cols = 256;
var rows = 16;
var primitives = [];
paper.install(window);
paper.setup("myCanvas");
for (var y = 0; y < rows; y++) {
var p = new Path();
p.segments = [];
for (var x = 0; x < cols; x++) {
p.add(new Point(2, h / 2));
}
if (y % 2 == 0) {
p.strokeColor = "purple";
} else {
p.strokeColor = "blue";
}
p.strokeWidth = 2;
//p.smooth({ type: 'continuous' })
primitives.push(p);
}
view.onFrame = function (event) {
nx += params.speedX / 1000;
ny += params.speedY / 1000;
nz += params.speedZ / 100;
for (var y = 0; y < rows; y++) {
var p = primitives[y];
for (var x = 0; x < cols; x++) {
var Y =
(h * (1 - params.height)) / 2 +
((h * params.height) / rows) * y +
simplex.noise3D(
nx + (x * params.frequenceX) / 100,
ny + (y * params.frequenceY) / 100,
(nz * params.frequenceZ) / 100
) *
params.amplitude;
p.segments[x].point.x = (w / cols) * x;
p.segments[x].point.y += 0.1 * (Y - p.segments[x].point.y);
}
}
};
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/simplex-noise/2.3.0/simplex-noise.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.22/paper.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.0-0/dat.gui.js"></script>
<canvas id="myCanvas" width="400" height="200"></canvas>
Define an array containing the colors outside the for loop.
let colors = ['purple', 'red', 'blue', 'yellow']
In your for loop use the iteration index (in your case y) to pick a color from the array.
p.strokeColor = colors[y % colors.length];
use module % when the number of lines is greater than the length of the colors array.

This code runs for grid<=11 but gets stuck forever for grid>=12. Can anyone explain why this happens? (Using p5.js library of JavaScript)

Basically the title. I have read every line many times and still can't find my mistake.
I am just trying to put squares on a grid by calling a recursive function which creates the object and then calls itself again. I have checked that recursion is not infinite and there's a simple exit condition. Please help.
let grid = 11;
let sqr = [];
function setup() {
createCanvas(grid * grid, grid * grid);
noFill();
colorMode(HSB);
noLoop();
let maxs = floor(grid / 3);
let ratio = 2 * maxs * maxs;
makegrid(maxs, ratio);
}
function draw() {
background(0);
for (let sq of sqr) sq.show();
}
function makegrid(m, r) {
if (!m) return;
if (m == floor(grid / 3)) {
for (let i = 0; i < 2; i++) sqr.push(new sqrs(m, r));
m--;
makegrid(m, r);
} else {
let j = r / (m * m);
for (let k = 0; k < j; k++) sqr.push(new sqrs(m, r));
m--;
makegrid(m, r);
}
}
class sqrs {
constructor(m, r) {
let flag = true;
this.s = (m * width) / grid;
while (flag) {
flag = false;
this.x = (width / grid) * floor((grid + 1 - m) * random());
this.y = (height / grid) * floor((grid + 1 - m) * random());
if (!sqr.length) flag = false;
else {
for (let sq of sqr) {
let d = (this.x - sq.x) ** 2 + (this.y - sq.y) ** 2;
if (d < this.s ** 2 || d < sq.s ** 2) {
flag = true;
break;
}
}
}
}
}
show() {
stroke(random(340), 80, 80);
square(this.x, this.y, this.s);
}
}
As Jay pointed out in the comments, it's not the recursion that is the problem, but the while (flag) loop in your sqrs constructor that is the problem:
let grid = 12;
let sqr = [];
function setup() {
createCanvas(grid * grid, grid * grid);
noFill();
colorMode(HSB);
noLoop();
// maxs will be 4 if grid is 12
let maxs = floor(grid / 3);
// ratio will be 32
let ratio = 2 * maxs * maxs;
makegrid(maxs, ratio);
}
function draw() {
background(0);
for (let sq of sqr) sq.show();
}
function makegrid(m, r) {
if (m <= 0) return;
if (m == floor(grid / 3)) {
// Call 0: m == floor(grid / 3) == 4
for (let i = 0; i < 2; i++) sqr.push(new sqrs(m, r));
m--;
// Call 0: makegrid(3, 32);
makegrid(m, r);
} else {
// Call 1: j = 32 / (3 * 3) = 3.55555
// Call 2: j = 32 / (2 * 2) = 8
// Call 3: j = 32 / (1 * 1) = 32
let j = r / (m * m);
for (let k = 0; k < j; k++) sqr.push(new sqrs(m, r));
m--;
// Call 1: makegrid(2, 32)
// Call 2: makegrid(1, 32)
// Call 3: makegrid(0, 32)
makegrid(m, r);
}
}
class sqrs {
constructor(m, r) {
let flag = true;
this.s = (m * width) / grid;
// This code might end up repeating forever because every randomly generated
// position is too close to some existing square
let count = 0;
while (flag && ++count < 1000) {
flag = false;
this.x = (width / grid) * floor((grid + 1 - m) * random());
this.y = (height / grid) * floor((grid + 1 - m) * random());
if (sqr.length) {
// Check if the new square is too close to any existing squares
for (let sq of sqr) {
let d = (this.x - sq.x) ** 2 + (this.y - sq.y) ** 2;
if (d < this.s ** 2 || d < sq.s ** 2) {
flag = true;
break;
}
}
}
}
if (flag) {
this.s = 0;
print(`gave up after ${count} attempts to find a position for this square.`);
}
}
show() {
stroke(random(340), 80, 80);
square(this.x, this.y, this.s);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
The logic in that while loop doesn't make a whole lot of sense to me, so you're going to have to describe what you are actually trying to do if you want more advice.

Draw a border around an arbitrarily positioned set of shapes with RaphaelJS

I'm using RaphaelJS to draw a set of shapes at random positions on the paper, using this code:
http://jsbin.com/ixiqiy/2/edit
What I'm trying to do now is find the outermost set of positions, so that I can draw a border around the whole group. For example:
Can anyone help? Thanks.
OK, so using the Jarvis March algorithm and this python implementation I've managed to put together my own JS/RaphaelJS solution, which can be found here: http://jsbin.com/ixiqiy/12/edit.
Just in case that ever disappears, here's the code:
(function() {
function cmp(x, y) {
if (x > y) {
return 1;
} else if (x < y) {
return -1;
} else {
return 0;
}
}
function turn(p, q, r) {
return cmp((q[0] - p[0]) * (r[1] - p[1]) - (r[0] - p[0]) * (q[1] - p[1]), 0);
}
function dist(p, q) {
var dx = q[0] - p[0];
var dy = q[1] - p[1];
return dx * dx + dy * dy;
}
function next_hull_pt(points, p) {
var q = p,
r,
t;
for (var i = 0; i < points.length; i++) {
r = points[i];
t = turn(p, q, r);
if (t == -1 || t == 0 && dist(p, r) > dist(p, q)) {
q = r;
}
}
return q;
}
function convex_hull(points) {
var left,
point;
for (var i = 0; i < points.length; i++) {
point = points[i];
if (!left || point[0] < left[0]) {
left = point;
}
}
var hull = [left],
p,
q;
for (var i = 0; i < hull.length; i++) {
p = hull[i];
q = next_hull_pt(points, p);
if (q[0] != hull[0][0] || q[1] != hull[0][1]) {
hull.push(q);
}
}
hull.push(left);
return hull;
}
var paper = Raphael(0, 0, 800, 800),
set = paper.set(),
points = [],
point;
for (var i = 0; i < 20; i++) {
points[i] = [
Math.round(Math.random() * 500) + 100,
Math.round(Math.random() * 500) + 100
];
}
for (var i = 0; i < points.length; i++) {
point = points[i];
set.push(paper.circle(point[0], point[1], 5));
}
set.attr('fill', '#ff0000');
set.attr('stroke', '#ffffff');
var outline = convex_hull(points),
previous = [0, 0],
path = 'M';
for (var i = 0; i < outline.length; i++) {
point = outline[i];
path = path + (i == 0 ? 'M' : 'L') + point[0] + ',' + point[1] + ' ';
}
var path = paper.path(path);
path.attr('stroke', '#0000ff');
})();

Categories

Resources