Public
Edited
Mar 26, 2024
1 fork
3 stars
A Julia set on the Riemann sphereThe Z-CurveBarnsley's fernA stochastic digraph IFS algorithmSelf-affine tilesThe TwindragonThe Eisenstein fractionsA self-affine tile with holesSelf-affine tiles via polygon mergeGolden rectangle fractalsBifurcation diagram with critical curvesThe tame twindragonIllustrations for the proof of Green's theoremNon-orientability of a Mobius stripExamples of parametric surfacesPenrose tilingThe extended unit circlePenrose three coloringNewtons's method on the Riemann sphereConic sectionsDivisor graphsThe dance of Earth and VenusIterating multiples of the sine functionBorderline fractalsSelf-similar intersectionsBox-counting dimension examplesMandelbrot by dimensionInverse iteration for quadratic Julia setsInteger Apollonian PackingsIllustrations of two-dimensonal heat flowThe logistic bifurcation locusThe eleven unfoldings of the cubeA unimodal function with fractal level curvesGreen's theorem and polygonal areaThe geometry and numerics of first order ODEsThe xxx^xxx-spindleAnimated beats
Rauzy Fractals
Hilbert's coordinate functionsPluckNot PiDrum strikeThe Koch snowflakeFractalized squareA Taylor series about π/4\pi/4π/4PlotX3D HyperboloidA PlotX3D animationModular arithmetic in 5th grade artSimple S-I-R ModelThe Poisson KernelPoly-gasketsClassification of 2D linear systems via trace and determinantJulia sets and the Mandelbrot setWater wavesFourier SeriesDisks for a solid of revolutionOrbit detection for the Mandelbrot setTracing a path on a spherePlot for mathematiciansFunctions of two variablesPartial derivativesDijkstra's algorithm on an RGGGradient ascentUnfolding polyhedraTangent plane to a level surfaceA strange discontinuityExamples of level surfacesMcMullen carpetsHills and valleysThe definition of ⇒Double and iterated integralsMST in an RGGTrees are bipartiteFractal typesettingd3.hierarchy and d3.treeK23 is PlanarPolar CoordinatesParametric region generatorParametric Plot 2DContour plotsGreedy graph coloringGraph6A few hundred interesting graphsThe Kings ProblemFirst order, autonomous systems of ODEsRunge-Kutta for systems of ODEs
Also listed in…
Fractals
PlotX3D
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Ultimately, everything depends on the substitution function sigma,
// which is denoted with an s in the code.
// s, though, is defined in the radio bitton at the top of the notebook.
// You can see how it's defined here:

[0, 1, 2].map((i) => s(i).toString().replace(/,/g, ""))
Insert cell
// W is supposed to be an infinite word.
// This is just a real long approximation.
// It's obtained by iteration of s
W = {
let i = [0];
while (i.length < 40000) {
i = s(i);
}
return i;
}
Insert cell
// Use the word W to define the stair case.
staircase = {
let basis = [
[1, 0, 0],
[0, 1, 0],
[0, 0, 1]
];
let accumulated = [basis[W[0]]];
for (let i = 1; i < W.length; i++) {
let last = accumulated.slice(-1)[0];
let next = basis[W[i]];
accumulated.push([last[0] + next[0], last[1] + next[1], last[2] + next[2]]);
}
return accumulated;
}
Insert cell
Insert cell
// Use the substitution s to define M.
M = {
let M = math.zeros(3, 3);
for (let j = 0; j < 3; j++) {
let counts = _.countBy(s(j));
for (let i = 0; i < 3; i++) {
M.set([i, j], counts[i] || 0);
}
}
return M;
}
Insert cell
// Here's what M looks like
M.toArray()
Insert cell
// Compute the eigenvalues and eigenvectors of M
eigenInfo = math.eigs(M)
Insert cell
// Convert the eigenvectors to a change of basis matrix.
eigen_basis = {
let real_evec = math.column(eigenInfo.vectors, real_pos);
let leading_term = real_evec.get([0, 0]);
real_evec = math.re(math.divide(real_evec, leading_term));
let complex_pos = eigenInfo.values
.toArray()
.map((x) => typeof x)
.indexOf("object");
let complex_evec = eigenInfo.vectors.columns()[complex_pos].toArray();
leading_term = complex_evec[0][0];
complex_evec = math.divide(complex_evec, leading_term);

let eigen_basis = math.identity(3);
eigen_basis.subset(math.index([0, 1, 2], 0), real_evec);
eigen_basis.subset(math.index([0, 1, 2], 1), math.re(complex_evec));
eigen_basis.subset(math.index([0, 1, 2], 2), math.im(complex_evec));

return eigen_basis;
}
Insert cell
// Find the position of the real eigenvalue.
// Used to help construct the eigen_basis, as well as for
// the display of the eigenvalues in the exposition
real_pos = eigenInfo.values
.toArray()
.map((x) => typeof x)
.indexOf("number")
Insert cell
// Compute the projection matrix.
P = math.multiply(
eigen_basis,
[
[0, 0, 0],
[0, 1, 0],
[0, 0, 1]
],
math.inv(eigen_basis)
)
Insert cell
Insert cell
// Project the points in the long staircase and gather them according to
// the last step taken. These points are used to generate the 3D fractal.
gatheredProjectedPoints = {
let pts = staircase.map((pt) => math.multiply(P, pt).toArray());
let gatheredPoints = [[], [], []];
W.forEach((address, idx) => gatheredPoints[address].push(pts[idx]));
return gatheredPoints;
}
Insert cell
// Gather just a few points to display the staircase.
gatheredPoints55 = {
let gatheredPoints = [[], [], []];
W.slice(0, 55).forEach((address, idx) =>
gatheredPoints[address].push(staircase[idx])
);
return gatheredPoints;
}
Insert cell
// Compute an orthogonal viewpoint for the Rauzy fractal in 3D. Based on
// https://observablehq.com/@mcmcclur/understanding-x3d-viewpoints#orientation_string
// Code is a bit of mess since it combines mathjs and ml-matrix.
viewpoint = {
// Set up look, right, and up vectors.
let v1 = math.column(eigen_basis, 1);
let v2 = math.column(eigen_basis, 2);
let u = normalize(math.cross(v1, v2).toArray().flat());
let look = normalize(u.flat());
let right = normalize(cross(look, [0, 0, 1]));
let up = cross(right, look);

// Build a matrix with those vectors as columns
let M = new mlm.Matrix([right, up, look.map((x) => -x)]).transpose();

// Compute the eigenvalue decomposition of the matrix
let eig = new mlm.EigenvalueDecomposition(M);

// Find the position of the 1 in the list of eigenvalues
let tolerance = 10 ** -8;
let b1 = eig.realEigenvalues.map((e) => Math.abs(e - 1) < tolerance);
let b2 = eig.imaginaryEigenvalues.map((e) => Math.abs(e) < tolerance);
let one_position = (b1 && b2).indexOf(true);

// The corresponding eigenvector forms the first three entries of our
// orientation vector.
let v = eig.eigenvectorMatrix.transpose().to2DArray()[one_position];

// Find the position of eigenvalue with positive imaginary part.
let rot_position = eig.imaginaryEigenvalues
.map((y) => y > 10 ** -8)
.indexOf(true);

// The argument of that eigenvalue should be the rotation we need.
let rot = Math.atan2(
eig.imaginaryEigenvalues[rot_position],
eig.realEigenvalues[rot_position]
);

// Push that final value on to our vector and return.
v.push(rot);

return {
position: math
.column(
u.map((x) => [-4 * x]),
0
)
.flat(), //.toArray().flat(),
orientation: v
};
}
Insert cell
Insert cell
// This regular expression is used to identify strings that look like
// real numbers for formatting in the exposition.
real_regexp = /([0-9]*\.?[0-9]+)/g
Insert cell
delay = 0
Insert cell
Insert cell
plotx3d_canvas_style
Insert cell
import {
show_x3d,
create_pointSet,
create_indexedLineSet,
create_sphere,
create_arrow,
style as plotx3d_canvas_style
} from "@mcmcclur/plotx3d"
Insert cell
import { AffineFunction, DigraphIFS } from "@mcmcclur/digraphifs-class"
Insert cell
import { cross, normalize, rotation_matrix } from "@mcmcclur/x3dom-utilities"
Insert cell
math = require("mathjs@11")
Insert cell
mlm = require("ml-matrix@6")
Insert cell
pics = Promise.all([
FileAttachment("rauzy0.png").image(),
FileAttachment("rauzy1.png").image(),
FileAttachment("rauzy2.png").image(),
FileAttachment("rauzy3.png").image(),
FileAttachment("rauzy4.png").image()
// "blank"
])
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more