Public
Edited
Dec 6, 2023
Insert cell
Insert cell
Insert cell
new QuadraticJuliaSet(0).draw_simple()
Insert cell
Insert cell
Insert cell
new QuadraticJuliaSet(-0.8).draw_simple({ depth })
Insert cell
Insert cell
new QuadraticJuliaSet(-0.8).draw()
Insert cell
Insert cell
QuadraticJuliaSet = {
let QuadraticJuliaSet = class QuadraticJuliaSet {
constructor(c) {
this.c = c;
}
};

QuadraticJuliaSet.prototype.draw_simple = function (
opts = {}
) {
let {
depth = 12,
width = 512,
height = 512,
extent = [
[-2, 2],
[-2, 2]
]
} = opts;

let c = this.c;
let xmin = extent[0][0];
let xmax = extent[0][1];
let ymin = extent[1][0];
let ymax = extent[1][1];
let pts = [math.complex(0.123, -0.0456)];
for (let i = 0; i < depth; i++) {
pts = pts
.map(function (z) {
let z1 = math.sqrt(math.add(z, math.multiply(c, -1)));
let z2 = math.multiply(z1, -1);
return [z1, z2];
})
.flat();
}
let canvas = d3
.create("canvas")
.attr("width", width)
.attr("height", height);

let ctx = canvas.node().getContext("2d");
ctx.fillStyle = "black";
pts = pts.map(function (z) {
let ij = complex_to_canvas(z, xmin, xmax, ymin, ymax, width, height);
let i = ij[0];
let j = ij[1];
ctx.fillRect(i, j, 1, 1);
});
return canvas.node();
};

QuadraticJuliaSet.prototype.generate_inverse_iterate_matrix = function (
opts = {}
) {
let {
bailout = 5,
extent = [
[-2, 2],
[-2, 2]
],
width = 512,
height = 512
} = opts;

let c = this.c;
let xmin = extent[0][0];
let xmax = extent[0][1];
let ymin = extent[1][0];
let ymax = extent[1][1];

let plot_record = new Array(height + 1);
for (let i = 0; i <= height; i++) {
plot_record[i] = new Array(width + 1);
}
for (let row = 0; row <= height; row++) {
for (let col = 0; col <= width; col++) {
plot_record[row][col] = 0;
}
}
let z0 = math.complex(0.123, -0.0456);
for (let i = 0; i < 5; i++) {
z0 = math.sqrt(math.add(z0, math.multiply(c, -1)));
z0 = math.multiply(math.sqrt(math.add(z0, math.multiply(c, -1))), -1);
}

let zNode = new JuliaNode(z0);
let queue = [zNode];
let cnt = 0;
while (queue.length > 0) {
zNode = queue.pop();
let z = zNode.z;
let ij = complex_to_canvas(z, xmin, xmax, ymin, ymax, width, height);
let i = ij[0];
let j = ij[1];
if (plot_record[i][j] < bailout) {
let z1 = math.sqrt(math.add(z, math.multiply(c, -1)));
let z2 = math.multiply(z1, -1);
let left = new JuliaNode(z1);
let right = new JuliaNode(z2);
zNode.left = left;
zNode.right = right;
queue.push(left);
queue.push(right);
plot_record[i][j] = plot_record[i][j] + 1;
}
}
return plot_record;
};

QuadraticJuliaSet.prototype.draw = function (opts = {}) {
let {
bailout = 5,
extent = [
[-2, 2],
[-2, 2]
],
width = 512,
height = 512
} = opts;
let all_opts = { bailout, extent, width, height };

let plot_record = this.generate_inverse_iterate_matrix(all_opts);
let canvas = d3
.create("canvas")
.attr("width", width)
.attr("height", height);

let ctx = canvas.node().getContext("2d");
ctx.fillStyle = "black";
let cnts = [];
for (let j = 0; j <= width; j++) {
for (let i = 0; i <= height; i++) {
if (plot_record[i][j] > 0) {
ctx.fillRect(i, j, 1, 1);
}
}
}
return canvas.node();
};

QuadraticJuliaSet.prototype.box_count = function () {
return box_count(
this.generate_inverse_iterate_matrix({
bailout: 5,
width: 2 ** 10,
height: 2 ** 10
})
);
};

return QuadraticJuliaSet;

function xy_to_canvas(x, y, xmin, xmax, ymin, ymax, width, height) {
return [
Math.min(Math.floor(((x - xmin) * width) / (xmax - xmin)), width - 1),
Math.min(Math.floor(((ymax - y) * height) / (ymax - ymin)), height - 1)
];
}
function complex_to_canvas(z, xmin, xmax, ymin, ymax, width, height) {
return xy_to_canvas(z.re, z.im, xmin, xmax, ymin, ymax, width, height);
}

function box_count(matrix) {
let w = matrix.length;
let cnts = [];
for (let s = 1; s <= w; s = 2 * s) {
let boxes = [];
let cnt = 0;
for (let i = 0; s * (i + 1) < w; i++) {
for (let j = 0; s * (j + 1) < w; j++) {
if (check_box(i, j, s)) {
cnt = cnt + 1;
boxes.push([i, j]);
}
}
}
cnts.push({ s: s, cnt: cnt, boxes: boxes });
}

function check_box(i, j, s) {
for (let i0 = i * s; i0 < (i + 1) * s; i0++) {
for (let j0 = j * s; j0 < (j + 1) * s; j0++) {
if (matrix[i0][j0] > 0) {
return true;
}
}
}
return false;
}

return cnts;
}
}
Insert cell
JuliaNode = class JuliaNode {
constructor(z) {
this.z = z;
}
}
Insert cell
math = require("mathjs")
Insert cell
// julia_dim2 = julia_dim
// .filter((a) => a.C < 0.2501)
// .concat([{ C: 0.2505, Dim: undefined }])
// .concat(julia_dim.filter((a) => a.C > 0.2505))
Insert cell
// julia_dim = FileAttachment("julia_dim.csv").csv({ typed: true })
Insert cell
// ss = require("simple-statistics")
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