# Vertex, loop and draw along a vertex path

Hi,
I’m trying to adapt the code which has been written in java by Daniel Shiffman on his youtube channel into P5.js and I’ve met some problems. The loop which I used to draw the shape doesn’t work properly. In object which I created a vector values x,y and z are still 0 ( 0: Vector {vx: 0, vy: 0, vz: 0}
1: Vector {vx: 0, vy: 0, vz: 0} etc. etc). Where am I wrong?

This is a video which I mentioned -> https://www.youtube.com/watch?v=r6YMKr1X0VA&t=104s

This is my code:

``````let beta;
let arr =[];
function setup() {
createCanvas(400, 400, WEBGL);
}

function draw(){
beta = 0;
background(0);
translate(width/2, height/2);
let r = 250*(0.8 * 1.6 * sin(6 * beta));
let theta = 2 * beta;
let phi = 0.6 * PI * sin(12 * beta);

let x = r * cos(phi) * cos(theta);
let y = r * cos(phi) * sin(theta);
let z = r * sin(phi);

arr.push(new Vector(x,y,z));

beta += 0.01;
stroke(255);
strokeWeight(3);
noFill();
beginShape();
for(let v of arr) {
vertex(v.vx, v.vy, v.vz);
}

endShape();
}

class Vector {
constructor(vx, vy, vz) {
this.vx = vx;
this.vy = vy;
this.vz = vz;
}
}
``````
1 Like

Even though Java & JS share most of their syntaxes, there are still some important differences.

A peculiar 1 of them is which default value is assigned to a newly created variable or property.

Java assigns a different initial value to a newly field depending on its declared datatype:
Docs.Oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

But not JS (Python the same)! Default value is always `undefined` (`None` to Python).

So just after `let beta;`, variable beta is equal to `undefined`.
And any math operations w/ `undefined` result `NaN`!

2 Likes

I did some refactoring to the original Java Mode version. You can watch it running online here: OpenProcessing.org/sketch/608725

The online version got a bug though: strokeWeight() is completely ignored by vertex()! But it runs 100% correctly in the PDE (Processing’s IDE) though. ## “Knot3D.pde”:

``````/**
* 3D Knot (2017/Dec)
* Daniel Shiffman
* https://YouTu.be/r6YMKr1X0VA
*
* Mod GoToLoop (v1.0.3) (2018/Oct/16)
* https://OpenProcessing.org/sketch/608725 (pjs)
* https://OpenProcessing.org/sketch/608726 (p5js)
*
* https://Discourse.Processing.org/t/
* vertex-loop-and-draw-along-a-vertex-path/4545/3
*/

/**
* http://PaulBourke.net/geometry/knots/
* Knot 4 (1992/Oct):
*
* r(beta) = 0.8 + 1.6 * sin(6.0 * beta)
* theta(beta) = 2 * beta
* phi(beta) = 0.6 * pi * sin(12.0 * beta)
*
* x = r * cos(phi) * cos(theta)
* y = r * cos(phi) * sin(theta)
* z = r * sin(phi)
*/

import java.util.List;
final List<Knot> knots = new ArrayList<Knot>();

static final float
ANGLE_STEP = .02, BETA_STEP = .01,
MAG = 100.0, SEGS_LIMIT = PI + BETA_STEP,
PI_DOT_6 = PI * .6;

float angle, beta;
boolean paused;

void setup() {
size(600, 600, P3D);
smooth(8);

colorMode(HSB);
noFill();
strokeWeight(8.0);
}

void draw() {
background(0);
translate(width>>1, height>>1);
rotateY(angle += ANGLE_STEP);

beta += BETA_STEP;

beginShape();
for (final Knot k : knots) {
stroke(k.c);
vertex(k.v.x, k.v.y, k.v.z);
}
endShape();
}

void mousePressed() {
if (paused ^= true)  noLoop();
else                 loop();
}

void keyPressed() {
mousePressed();
}

final float
r = MAG * (.8 + 1.6 * sin(6.0 * beta)),
theta = 2.0 * beta,
phi = PI_DOT_6 * sin(12.0 * beta),
rCosPhi = r * cos(phi),

x = rCosPhi * cos(theta),
y = rCosPhi * sin(theta),
z = r * sin(phi);

final Knot knot = new Knot(x, y, z);
println(knots.size() + ": " + knot);
}

class Knot {
final PVector v;
final color c;

Knot(final float x, final float y, final float z) {
this(new PVector(x, y, z));
}

Knot(final PVector vec) {
c = color((v = vec).mag(), 255, 255);
}

String toString() {
return "Vec: " + v + "   \tHSB: " + c;
}
}
``````
1 Like

And while I was at it, I did a Python Mode version too: ## “Knot3D.pyde”:

``````"""
* 3D Knot (2017/Dec)
* Daniel Shiffman
* https://YouTu.be/r6YMKr1X0VA
*
* Mod GoToLoop (v1.0.3) (2018/Oct/16)
* https://OpenProcessing.org/sketch/608725 (pjs)
* https://OpenProcessing.org/sketch/608726 (p5js)
*
* https://Discourse.Processing.org/t/
* vertex-loop-and-draw-along-a-vertex-path/4545/4
"""

"""
* http://PaulBourke.net/geometry/knots/
* Knot 4 (1992/Oct):
*
* r(beta) = 0.8 + 1.6 * sin(6 * beta)
* theta(beta) = 2 * beta
* phi(beta) = 0.6 * pi * sin(12 * beta)
*
* x = r * cos(phi) * cos(theta)
* y = r * cos(phi) * sin(theta)
* z = r * sin(phi)
"""

ANGLE_STEP, BETA_STEP = .02, .01
MAG, SEGS_LIMIT = 100.0, PI + BETA_STEP
PI_DOT_6 = PI * .6

angle = beta = 0.0
paused = False

knots = []

def setup():
size(600, 600, P3D)
smooth(8)

colorMode(HSB)
noFill()
strokeWeight(8.0)

def draw():
global angle, beta

background(0)
translate(width>>1, height>>1)
rotateY(angle)
angle += ANGLE_STEP

beta += BETA_STEP

with beginShape():
for k in knots:
stroke(k.c)
vertex(k.v.x, k.v.y, k.v.z)

def mousePressed():
global paused
paused ^= True
noLoop() if paused else loop()

def keyPressed(): mousePressed()

r = MAG * (.8 + 1.6 * sin(6 * beta))
theta = 2 * beta
phi = PI_DOT_6 * sin(12 * beta)
rCosPhi = r * cos(phi)

x = rCosPhi * cos(theta)
y = rCosPhi * sin(theta)
z = r * sin(phi)

knot = Knot(x, y, z)
knots.append(knot)
print '%d: %s' % (len(knots), knot)

class Knot:
def __init__(k, *vec):
k.v = vec if len(vec) is 1 else PVector(*vec)
k.c = color(k.v.mag(), 255, 255)

def __str__(k): return 'Vec: %s   \tHSB: %d' % (k.v, k.c)
``````
3 Likes

And finally the “3D Knot” p5js version. Watch it online below: OpenProcessing.org/sketch/608726

However, there’s a worse bug in it: the last stroke() determines the color for all vertex()! ## “index.html”:

``````<!DOCTYPE html>

<meta charset=utf-8>
<meta name=viewport content=width=device-width,initial-scale=1>

<script async src=https://cdn.JsDelivr.net/npm/p5/lib/p5.js></script>
<script defer src=sketch.js></script>
``````

## “sketch.js”:

``````/**
* 3D Knot (2017/Dec)
* Daniel Shiffman
* https://YouTu.be/r6YMKr1X0VA
*
* Mod GoToLoop (v1.0.1) (2018/Oct/16)
* https://OpenProcessing.org/sketch/608725 (pjs)
* https://OpenProcessing.org/sketch/608726 (p5js)
*
* https://Discourse.Processing.org/t/
* vertex-loop-and-draw-along-a-vertex-path/4545/5
*/

/**
* http://PaulBourke.net/geometry/knots/
* Knot 4 (1992/Oct):
*
* r(beta) = 0.8 + 1.6 * sin(6 * beta)
* theta(beta) = 2 * beta
* phi(beta) = 0.6 * pi * sin(12 * beta)
*
* x = r * cos(phi) * cos(theta)
* y = r * cos(phi) * sin(theta)
* z = r * sin(phi)
*/

"use strict";

const π = Math.PI, ANGLE_STEP = .02, BETA_STEP = .01,
MAG = 100.0, SEGS_LIMIT = π + BETA_STEP,
PI_DOT_6 = π*.6,
knots = []

let α = 0.0, β = 0.0, paused = false, bg

function setup() {
createCanvas(600, 600, WEBGL).mousePressed(togglePause)
bg = color(0)
colorMode(HSB).strokeWeight(8.0).noFill()
}

function draw() {
background(bg).rotateY(α += ANGLE_STEP)

β += BETA_STEP

beginShape()
for (const { c, v } of knots)  stroke(c).vertex(v.x, v.y, v.z)
endShape()
}

function togglePause() {
(paused = !paused)? noLoop() : loop()
}

function keyPressed() {
togglePause()
}

const r = MAG * (.8 + sin(6*β)*1.6),
θ = 2*β, φ = PI_DOT_6 * sin(12*β),
rCosφ = r * cos(φ),
x = rCosφ * cos(θ), y = rCosφ * sin(θ), z = r * sin(φ),
knot = new Knot(x, y, z)

knots.push(knot)
console.log(knots.length + ':', knot)
}

class Knot {
constructor(...vec) {
this.v = vec.length === 1? vec : createVector(...vec)
this.c = color(this.v.mag(), 100, 100)
}
}
``````
2 Likes

Thanks. This is exactly what I am looking for.