Published
Edited
Dec 17, 2020
1 fork
1 star
Also listed in…
Math
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// A version of the Julia set appropriate to use as a texture.
texture = {
let n = 400;
let step = Math.PI / n;
let theta_min = -Math.PI;
let theta_max = Math.PI;
let phi_min = step;
let phi_max = Math.PI;

let w = 2 * n;
let h = n;
let bail = 100;

let canvas = d3
.create('canvas')
.attr('width', w)
.attr('height', h);
let context = canvas.node().getContext("2d");
let canvasData = context.createImageData(w, h);

let j = 0;
for (let theta = theta_min; theta < theta_max; theta = theta + step) {
let i = 0;
for (let phi = phi_min; phi < phi_max; phi = phi + step) {
let d = Math.tan(phi / 2);
let x = Math.cos(theta) / d;
let y = Math.sin(theta) / d;
let info = P_orbitInfo([x, y], bail);

let idx = (j + i * w) * 4;
let c = color(info, bail);
canvasData.data[idx + 0] = c[0];
canvasData.data[idx + 1] = c[1];
canvasData.data[idx + 2] = c[2];
canvasData.data[idx + 3] = 255;
i = i + 1;
}
j = j + 1;
}
context.putImageData(canvasData, 0, 0);
return canvas;
}
Insert cell
function color(info, bail) {
let v = 255 - (255 * info.cnt) / (bail + 1);
let lim = info.lim;
if (lim == 0) {
return [0, 0, v];
} else if (lim == 1) {
return [v, v, 0];
// } else if (lim == 2) {
// return [255 - v, 255 - v, 255 - v];
} else {
return [0, 0, 0];
}
}
Insert cell
function p_orbitInfo([x0, y0], bail) {
let cnt = 0;
let x = x0;
let y = y0;
let lim = p_classify([x, y]);
while (lim == 3 && cnt < bail) {
[x, y] = p([x, y]);
lim = p_classify([x, y]);
cnt = cnt + 1;
}
return { lim: lim, cnt: cnt };
}
Insert cell
function P_orbitInfo([x0, y0], bail) {
let cnt = 0;
let x = x0;
let y = y0;
let lim = P_classify([x, y]);
while (lim == 3 && cnt < bail) {
[x, y] = P([x, y]);
lim = P_classify([x, y]);
cnt = cnt + 1;
}
return { lim: lim, cnt: cnt };
}
Insert cell
function p_classify([x, y]) {
if ((x - 0.3) ** 2 + y ** 2 > 2) {
return 0;
} else if ((x - 1) ** 2 + y ** 2 < 0.01) {
return 1;
} else {
return 3;
}
}
Insert cell
function P_classify([x, y]) {
if (x ** 2 + y ** 2 < 0.25) {
return 0;
} else if ((x - 1) ** 2 + y ** 2 < 0.015625) {
return 1;
} else if (Math.abs(y) > 1.2) {
return 2;
} else {
return 3;
}
}
Insert cell
// The conjugate p(z)= 1/P(1/z) of the original function
// P(z) = P(x+iy) expressed in terms of x and y
function p([x, y]) {
let denominator =
4 -
8 * x +
12 * x ** 2 -
12 * x ** 3 +
8 * x ** 4 -
4 * x ** 5 +
x ** 6 -
4 * y ** 2 +
4 * x * y ** 2 +
8 * x ** 2 * y ** 2 -
8 * x ** 3 * y ** 2 +
3 * x ** 4 * y ** 2 -
4 * x * y ** 4 +
3 * x ** 2 * y ** 4 +
y ** 6;
let numerator_re =
4 * x -
8 * x ** 2 +
14 * x ** 3 -
16 * x ** 4 +
12 * x ** 5 -
7 * x ** 6 +
2 * x ** 7 -
10 * x * y ** 2 +
16 * x ** 2 * y ** 2 +
8 * x ** 3 * y ** 2 -
13 * x ** 4 * y ** 2 +
6 * x ** 5 * y ** 2 -
4 * x * y ** 4 -
5 * x ** 2 * y ** 4 +
6 * x ** 3 * y ** 4 +
y ** 6 +
2 * x * y ** 6;
let numerator_im =
4 * y -
8 * x * y +
18 * x ** 2 * y -
24 * x ** 3 * y +
16 * x ** 4 * y -
8 * x ** 5 * y +
2 * x ** 6 * y -
6 * y ** 3 +
8 * x * y ** 3 +
16 * x ** 2 * y ** 3 -
16 * x ** 3 * y ** 3 +
6 * x ** 4 * y ** 3 -
8 * x * y ** 5 +
6 * x ** 2 * y ** 5 +
2 * y ** 7;
return [numerator_re / denominator, numerator_im / denominator];
}
Insert cell
// The original function P(z) = P(x+iy)
// expressed in terms of x and y
function P([x, y]) {
let denominator =
4 -
12 * x +
17 * x ** 2 -
20 * x ** 3 +
16 * x ** 4 -
8 * x ** 5 +
4 * x ** 6 +
y ** 2 +
12 * x * y ** 2 +
8 * x ** 2 * y ** 2 -
16 * x ** 3 * y ** 2 +
12 * x ** 4 * y ** 2 -
8 * y ** 4 -
8 * x * y ** 4 +
12 * x ** 2 * y ** 4 +
4 * y ** 6;
let numerator_re =
2 * x -
7 * x ** 2 +
12 * x ** 3 -
16 * x ** 4 +
14 * x ** 5 -
8 * x ** 6 +
4 * x ** 7 +
y ** 2 -
4 * x * y ** 2 +
16 * x ** 2 * y ** 2 +
4 * x ** 3 * y ** 2 -
16 * x ** 4 * y ** 2 +
12 * x ** 5 * y ** 2 -
10 * x * y ** 4 -
8 * x ** 2 * y ** 4 +
12 * x ** 3 * y ** 4 +
4 * x * y ** 6;
let numerator_im =
2 * y -
8 * x * y +
16 * x ** 2 * y -
24 * x ** 3 * y +
18 * x ** 4 * y -
8 * x ** 5 * y +
4 * x ** 6 * y +
8 * x * y ** 3 +
12 * x ** 2 * y ** 3 -
16 * x ** 3 * y ** 3 +
12 * x ** 4 * y ** 3 -
6 * y ** 5 -
8 * x * y ** 5 +
12 * x ** 2 * y ** 5 +
4 * y ** 7;
return [numerator_re / denominator, numerator_im / denominator];
}
Insert cell
rotate = d3
.select(riemann_sphere)
.select('#rotation')
.attr('rotation', `0 1 0 ${rotation}`)
Insert cell
rotation_values = d3.range(0, 2 * Math.PI, Math.PI / 400)
Insert cell
import { Scrubber } from "@mbostock/scrubber"
Insert cell
d3 = require('d3@6')
Insert cell
x3dom = require('x3dom').catch(() => window['x3dom'])
Insert cell
html`
<style>
canvas {
outline: none
}
output {
display: none
}
</style>
`
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more