Published
Edited
Oct 9, 2020
2 forks
25 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
renderer = {
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);
renderer.setPixelRatio(devicePixelRatio);
return renderer;
}
Insert cell
function breather(u_, v_, target) {
const a = 0.4;
const w = 20;
const u = -13.2 + u_ * 26.4;
const v = -37.4 + v_ * 2 * 37.4;

const r = 1 - a ** 2;
const l = Math.sqrt(r);
const d = a * ((l * Math.cosh(a * u)) ** 2 + (a * Math.sin(l * v)) ** 2);
const x = -u + (2 * r * Math.cosh(a * u) * Math.sinh(a * u)) / d;
const y =
(2 *
l *
Math.cosh(a * u) *
(-(l * Math.cos(v) * Math.cos(l * v)) - Math.sin(v) * Math.sin(l * v))) /
d;
const z =
(2 *
l *
Math.cosh(a * u) *
(-(l * Math.sin(v) * Math.cos(l * v)) + Math.cos(v) * Math.sin(l * v))) /
d;

target.set(x * w, z * w, y * w);
}
Insert cell
function bonanJeenerKlein(u_, v_, target) {
const u = 2 * Math.PI * u_;
const v = 2 * Math.PI * v_;

const w = 15;
const t = 2;

const k = Math.sin((a - 1) * u) + t;
const x =
a * Math.cos(u) -
Math.cos(a * u) -
((a - 1) / a) * k * Math.sin(((a + 1) * u) / 2) * Math.cos(v);
const y = k * Math.sin(v);
const z =
a * Math.sin(u) -
Math.sin(a * u) +
((a - 1) / a) * k * Math.cos(((a + 1) * u) / 2) * Math.cos(v);

target.set(x * w, y * w, z * w);
}
Insert cell
function triaxialHexatorus(u_, v_, target) {
const w = 100;
const u = 2 * Math.PI * u_;
const v = 2 * Math.PI * v_;

const x = Math.sin(u) / (Math.sqrt(2) + Math.cos(v));
const y =
Math.sin(u + (2 * Math.PI) / 3) /
(Math.sqrt(2) + Math.cos(v + (2 * Math.PI) / 3));
const z =
Math.cos(u - (2 * Math.PI) / 3) /
(Math.sqrt(2) + Math.cos(v - (2 * Math.PI) / 3));

target.set(x * w, y * w, z * w);
}
Insert cell
function kleinCycloid(u_, v_, target) {
const w = 10;
const c = 2;
const b = 5;
const u = u_ * 2 * b * c * Math.PI;
const v = v_ * 4 * Math.PI;

const x =
Math.cos(u / c) * Math.cos(u / b) * (a + Math.cos(v)) +
Math.sin(u / b) * Math.sin(v) * Math.cos(v);
const y =
Math.sin(u / c) * Math.cos(u / b) * (a + Math.cos(v)) +
Math.sin(u / b) * Math.sin(v) * Math.cos(v);
const z =
-Math.sin(u / b) * (a + Math.cos(v)) +
Math.cos(u / b) * Math.sin(v) * Math.cos(v);

target.set(x * w, z * w, y * w);
}
Insert cell
function braidedTorus(u_, v_, target) {
const w = 50;
const u = u_ * 8 * Math.PI;
const v = v_ * 2 * Math.PI;

const r = a / 50;
const R = b / 10;
const n = c / 10;

const x =
r * Math.cos(v) * Math.cos(u) +
R * Math.cos(u) * (1 + (1 / 2) * Math.cos(n * u));
const y = 2.5 * (r * Math.sin(v) + (1 / 2) * Math.sin(n * u));
const z =
r * Math.cos(v) * Math.sin(u) +
R * Math.sin(u) * (1 + (1 / 2) * Math.cos(n * u));

target.set(x * w, y * w, z * w);
}
Insert cell
function tranguloidTrefoil(u_, v_, target) {
const w = 30;
const u = -Math.PI + u_ * 2 * Math.PI;
const v = -Math.PI + v_ * 2 * Math.PI;

const x = (2 * Math.sin(3 * u)) / (2 + Math.cos(v));
const y =
(2 * (Math.sin(u) + 2 * Math.sin(2 * u))) /
(2 + Math.cos(v + (2 * Math.PI) / 3));
const z =
((Math.cos(u) - 2 * Math.cos(2 * u)) *
(2 + Math.cos(v)) *
(2 + Math.cos(v + (2 * Math.PI) / 3))) /
4;

target.set(x * w, z * w, y * w);
}
Insert cell
function hyperbolicHelicoid(u_, v_, target) {
const w = 150;
const u = -4 + u_ * 8;
const v = -4 + v_ * 8;
const k = 3 + a / 20;

const x =
(Math.sinh(v) * Math.cos(k * u)) / (1 + Math.cosh(u) * Math.cosh(v));
const y =
(Math.sinh(v) * Math.sin(k * u)) / (1 + Math.cosh(u) * Math.cosh(v));
const z = (Math.cosh(v) * Math.sinh(u)) / (1 + Math.cosh(u) * Math.cosh(v));

target.set(x * w, z * w, y * w);
}
Insert cell
function monkeySaddle(u_, v_, target) {
const w = 150;
const u = -1 + u_ * 2;
const v = -1 + v_ * 2;

const x = u;
const y = v;
const z = u ** 3 - 3 * u * v ** 2;

target.set(x * w, z * w, y * w);
}
Insert cell
function snail(u_, v_, target) {
const w = 10;
const u = u_ * 6 * Math.PI;
const v = v_ * 2 * Math.PI;

const d = b / 15;

const h = Math.E ** (u / (6 * Math.PI));
const x =
a * (1 - h) * Math.cos(u) * Math.cos((1 / 2) * v) * Math.cos((1 / 2) * v);
const y = 1 - Math.E ** (u / (d * Math.PI) - Math.sin(v) + h * Math.sin(v));
const z =
a * (h - 1) * Math.sin(u) * Math.cos((1 / 2) * v) * Math.cos((1 / 2) * v);

target.set(x * w, -200 - y * w, z * w);
}
Insert cell
function sievert(u_, v_, target) {
const w = 60;
const u = -Math.PI / 2 + u_ * (Math.PI / (100 - a * 2));
const v = 0.105 + v_ * 1;
const k = 0.5;

const p = -u / Math.sqrt(k + 1) + Math.atan(tan(u) * Math.sqrt(k + 1));
const l = 2 / (k + 1 - k * sin(v) * sin(v) * cos(u) * cos(u));
const r =
(l * Math.sqrt((k + 1) * (1 + k * sin(u) * sin(u))) * sin(v)) /
Math.sqrt(k);

const x = r * cos(p);
const y = r * sin(p);
const z = (Math.log(tan(v / 2)) + l * (k + 1) * cos(v)) / Math.sqrt(k);

target.set(x * w, z * w, y * w);
}
Insert cell
function roman(u, v, target) {
const a = 20
const x = (a ** 2 / 4) * sin(2 * u) * cos(v) ** 2;
const y = (a ** 2 / 4) * sin(u) * sin(2 * v);
const z = (a ** 2 / 4) * cos(u) * sin(2 * v);

target.set(x, z, y);
}
Insert cell
function richmond(u, v, target) {
const w = 500;
const r = u;
const theta = v * 2 * Math.PI;

const n = a;
const t = b;

const x =
-Math.cos(t + theta) / (2 * r) -
(r ** (2 * n + 1) * Math.cos(t - (2 * n + 1) * theta)) / (4 * n + 2);
const y =
-Math.sin(t + theta) / (2 * r) +
(r ** (2 * n + 1) * Math.sin(b - (2 * n + 1) * theta)) / (4 * n + 2);
const z = (r ** n * Math.cos(b - n * theta)) / n;

target.set(x * w, z * w, y * w);
}
Insert cell
function pseudosphere(u, v, target) {
const w = 10;

const x = a * cos(u) * sin(v) * w;
const y = a * sin(u) * sin(v) * w;
const z = a * (cos(v) + Math.log(tan(v / 2))) * w;

target.set(x, z, y);
}
Insert cell
function helicoid(u, v, target) {
const w = 50;
const x = (a / 5) * v * cos(u) * w;
const y = (a / 5) * v * sin(u) * w;
const z = (b / 2) * (-w / 2 + u * w);

target.set(x, z, y);
}
Insert cell
function plucker(u, v, target) {
const w = 150;
const x = u * cos(v) * w;
const y = u * sin(v) * w;
const z = sin((a / 5) * v) * w;

target.set(x, z, y);
}
Insert cell
function heart(u, v, target) {
const w = 3;
const x = a * cos(u) * (1.2 + cos(v)) * sin(v) * w;
const y = a * (1 + cos(v)) * sin(u) * sin(v) * w;
const z = 50 + -a * cos(v) * (1 / 2 + cos(v)) * w;

target.set(x, z, y);
}
Insert cell
function experiment(u, v, target) {
const w = 5;
const x = 2 * a * cos(u) * (1 + cos(v)) * sin(v) * w;
const y = 2 * a * (1 + cos(v)) * sin(u) * sin(v) * w;
const z = -2 * a * cos(v) * (1 + cos(2 * v)) * w;

target.set(x, z, y);
}
Insert cell
function octahedron(u, v, target) {
const w = n ** (n / 10) * 10;
const x =
a * cos(u) * cos(v) * Math.sqrt(cos(u) ** 2 * cos(v) ** 2) ** (n - 1) * w;
const y =
a * sin(u) * cos(v) * Math.sqrt(sin(u) ** 2 * cos(v) ** 2) ** (n - 1) * w;
const z = a * sin(v) * Math.sqrt(sin(v) ** 2) ** (n - 1) * w;

target.set(x, z, y);
}
Insert cell
function hyperbolicParaboloid(u_, v_, target) {
const w = 20;
const u = -w + u_ * 2 * w;
const v = -w + v_ * 2 * w;

const x = a * u;
const y = b * v;
// scaled down
const z = (1 / 3) * (u ** 2 - 2 * u * v);

target.set(x, z, y);
}
Insert cell
function enneper(u_, v_, target) {
const w = 15;
const u = u_ * 2 * Math.PI;
const v = v_ * 2.5;

const s = v * Math.cos(u);
const t = v * Math.sin(u);

const x = s * (1 - (1 / 3) * s ** 2 + t ** 2) * w;
const y = t * (1 - (1 / 3) * t ** 2 + s ** 2) * w;
const z = (s ** 2 - t ** 2) * w;

target.set(x, z, y);
}
Insert cell
function cyclideOfDupin(u, v, target) {
if (a === b) return;

const w = 8;
const k = c / Math.PI;
const x =
((b * (k - b * cos(u)) + a * cos(u) * (a - k * cos(v))) /
(a - b * cos(u) * cos(v))) *
w;
const y =
((Math.sqrt(a ** 2 - b ** 2) * (a - k * cos(v)) * sin(u)) /
(a - b * cos(u) * cos(v))) *
w;
const z =
((Math.sqrt(a ** 2 - b ** 2) * (k - b * cos(u)) * sin(v)) /
(a - b * cos(u) * cos(v))) *
w;

target.set(x, z, y);
}
Insert cell
function eight(u, v_, target) {
const v = -Math.PI / 2 + v_ * Math.PI;
const w = 150;
const x = cos(u) * Math.sin(2 * v) * w;
const y = sin(u) * Math.sin(2 * v) * w;
const z = Math.sin(v) * w;

target.set(x, z, y);
}
Insert cell
function dinit(u_, v_, target) {
const u = u_ * Math.PI * 4;
const v = v_ * 1;
const w = 10;

const x = w * a * Math.cos(u) * Math.sin(v);
const y = w * a * Math.sin(u) * Math.sin(v);
const z = w * a * (Math.cos(u) + Math.log(Math.tan(v / 2))) + b * u;

target.set(x, z, y);
}
Insert cell
function catenoid(u, v, target) {
const r = 250;
const t = -40 + v * 80;
const x = a * Math.cos(-Math.PI + u * 2 * Math.PI) * Math.cosh(t / a);
const y = a * Math.sin(-Math.PI + u * 2 * Math.PI) * Math.cosh(t / a);
const z = -r / 2 + v * r;

target.set(x, z, y);
}
Insert cell
function catalan(u_, v_, target) {
const w = 10;
const u = -2 * Math.PI + u_ * 4 * Math.PI;
const v = -3 + v_ * 6;

const x = 4 * u - Math.cosh(v) * Math.sin(u);
const y = 10 - Math.cos(u) * Math.cosh(v);
const z = -6 * Math.sin(u / 2) * Math.sinh(v / 2);

target.set(x * w, z * w, y * w);
}
Insert cell
function boy(u, v, target) {
const r = 110;
const c = new Complex(u * cos(v), u * sin(v));

const g1 =
-(3 / 2) *
new Complex(
c.mul(new Complex(1, 0).sub(c.pow(4))).mul(
c
.pow(6)
.add(c.pow(3).mul(Math.sqrt(5)))
.sub(1)
.inverse()
)
).im;

const g2 =
-(3 / 2) *
new Complex(
c.mul(new Complex(1, 0).add(c.pow(4))).mul(
c
.pow(6)
.add(c.pow(3).mul(Math.sqrt(5)))
.sub(1)
.inverse()
)
).re;

const g3 =
-1 / 2 +
new Complex(
new Complex(1, 0).add(c.pow(6)).mul(
c
.pow(6)
.add(c.pow(3).mul(Math.sqrt(5)))
.sub(1)
.inverse()
)
).im;

const x = (1 / (g1 ** 2 + g2 ** 2 + g3 ** 2)) * g1 * r;
const y = (1 / (g1 ** 2 + g2 ** 2 + g3 ** 2)) * g2 * r;
const z = (1 / (g1 ** 2 + g2 ** 2 + g3 ** 2)) * g3 * r;

target.set(x, z, y);
}
Insert cell
function bour(u, v, target) {
const r = u * 15;
const theta = 4 * Math.PI * v;

const x = r * Math.cos(theta) - (1 / 2) * r ** 2 * Math.cos(2 * theta);
const y = -r * Math.sin(theta) * (r * Math.cos(theta) + 1);
const z = (4 / 3) * r ** (3 / 2) * Math.cos((3 * theta) / 2);

target.set(x, z, y);
}
Insert cell
function bohdom(u, v, target) {
const w = 10;
const x = a * cos(u) * w;
const y = (a * sin(u) + b * cos(v)) * w;
const z = c * sin(v) * w;

target.set(x, z, y);
}
Insert cell
function astell(u, v, target) {
const w = 5;
const x = a * cos(u) * cos(v) * w;
const y = b * sin(u) * cos(v) * w;
const z = c * sin(v) ** 3 * w;

target.set(x, z, y);
}
Insert cell
function agnesirev(u, v, target) {
const w = 4;
const x = -2 * a * cos(u) * cos(v) ** 2 * w;
const y = -2 * a * cos(v) ** 2 * sin(u) * w;
const z = 2 * a * tan(v) * w;

target.set(x, z, y);
}
Insert cell
function hyperboloid(u, v, target) {
const x = a * cosh(-1 / 2 + v) * cos(-1 / 2 + u);
const y = a * cosh(-1 / 2 + v) * sin(-1 / 2 + u);
const z = b * sinh(-1 / 2 + v);

target.set(x, z, y);
}
Insert cell
parametricObj = {
const geometry = new THREE.ParametricBufferGeometry(
equations[parseInt(eq)],
slices,
slices
);
const material = new THREE.MeshNormalMaterial({
side: THREE.DoubleSide,
wireframe
// color: 0x000
});
return new THREE.Mesh(geometry, material);
}
Insert cell
scene = {
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(parametricObj);
axis(scene);
return scene;
}
Insert cell
function line([x1, y1, z1], [x2, y2, z2], color = 0x000000) {
const geometry = new THREE.Geometry();
geometry.vertices.push(new THREE.Vector3(x1, y1, z1));
geometry.vertices.push(new THREE.Vector3(x2, y2, z2));
const material = new THREE.LineBasicMaterial({ color });
return new THREE.Line(geometry, material);
}
Insert cell
function arrow([x, y, z], [rx, ry, rz]) {
const geometry = new THREE.ConeBufferGeometry(5, 25, 25);
const material = new THREE.MeshBasicMaterial({ color: 0x000000 });
const cone = new THREE.Mesh(geometry, material);
cone.position.set(x, y, z);
cone.rotation.set(rx,ry,rz)
return cone;
}
Insert cell
function axis(scene) {
const w = 300;
const axis = [
[
[-w, 0, 0],
[w, 0, 0],
[(1 / 2) * Math.PI, 0, (1 / 2) * Math.PI],
[-(1 / 2) * Math.PI, 0, -(1 / 2) * Math.PI]
],
[[0, -w, 0], [0, w, 0], [Math.PI, 0, 0], [0, -Math.PI, 0]],
[
[0, 0, -w],
[0, 0, w],
[(1 / 2) * Math.PI, 0, Math.PI],
[-(1 / 2) * Math.PI, 0, Math.PI]
]
].map(([from, to, rotFrom, rotTo]) => {
scene.add(arrow(from, rotFrom));
scene.add(arrow(to, rotTo));
scene.add(line(from, to));
});
}
Insert cell
eqData = [
{ name: "hyperbolicHelicoid", params: [26] },
{ name: "tranguloidTrefoil", params: [] },
{ name: "breather", params: [] },
{ name: "kleinCycloid", params: [21] },
{ name: "trialxialHexatorus", params: [] },
{ name: "monkeySaddle", params: [] },
{ name: "boy", params: [] },
{ name: "braidedTorus", params: [11, 22, 15] },
{ name: "roman", params: [] },
{ name: "bonanJeenerKlein", params: [6] },
{ name: "snail", params: [14, 13] },
{ name: "helicoid", params: [21, 21] },
{ name: "hyperboloid", params: [17, 21] },
{ name: "cyclideOfDupin", params: [15, 4, 15] },
{ name: "eight", params: [] },
{ name: "dinit", params: [7, 21] },
{ name: "catenoid", params: [12] },
{ name: "richmond", params: [7, 10] },
{ name: "bour", params: [] },
{ name: "bohdom", params: [5, 10, 7] },
{ name: "astell", params: [21, 21, 21] },
{ name: "agnesirev", params: [13] },
{ name: "enneper", params: [] },
{ name: "hyperbolicParaboloid", params: [8, 8] },
{ name: "octahedron", params: [16, 15, 12, 3] },
{ name: "experiment", params: [13] },
{ name: "sievert", params: [40] },
{ name: "heart", params: [21] },
{ name: "plucker", params: [20] },
{ name: "pseudosphere", params: [11] },
{ name: "catalan", params: [] }
]
Insert cell
equations = [
hyperbolicHelicoid,
tranguloidTrefoil,
breather,
kleinCycloid,
triaxialHexatorus,
monkeySaddle,
boy,
braidedTorus,
roman,
bonanJeenerKlein,
snail,
helicoid,
hyperboloid,
cyclideOfDupin,
eight,
dinit,
catenoid,
richmond,
bour,
bohdom,
astell,
agnesirev,
enneper,
hyperbolicParaboloid,
octahedron,
experiment,
sievert,
heart,
plucker,
pseudosphere,
catalan
]
Insert cell
camera = {
const fov = 45;
const aspect = width / height;
const near = 0.01;
const far = 100000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
camera.lookAt(scene.position);
camera.position.set(200, 400, -700);
return camera;
}
Insert cell
height = width
Insert cell
cos = t => Math.cos(2 * Math.PI * t)
Insert cell
cosh = t => Math.cosh(2 * Math.PI * t)
Insert cell
sin = t => Math.sin(2 * Math.PI * t)
Insert cell
sinh = t => Math.sinh(2 * Math.PI * t)
Insert cell
tan = t => Math.tan(2 * Math.PI * t)
Insert cell
tanh = t => Math.tanh(2 * Math.PI * t)
Insert cell
a = values[0].length > 0 && values[0][0]
Insert cell
b = values[0].length > 1 && values[0][1]
Insert cell
c = values[0].length > 2 && values[0][2]
Insert cell
n = values[0].length > 3 && values[0][3]
Insert cell
Insert cell
import { slider } from '@jashkenas/inputs'
Insert cell
import { inputsGroup } from '@bumbeishvili/input-groups'
Insert cell
Complex = require('complex.js@2.0.11/complex.js')
Insert cell
THREE = {
const THREE = (window.THREE = await require("three@0.99.0/build/three.min.js"));
await require("three@0.99.0/examples/js/controls/OrbitControls.js").catch(
() => {}
);
return THREE;
}
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