Compare commits
8 Commits
1ec7955861
...
f79a90e0d9
Author | SHA1 | Date |
---|---|---|
Mike Lynch | f79a90e0d9 | |
Mike Lynch | 78ebb381ee | |
Mike Lynch | f99901f1b0 | |
Mike Lynch | 39fe6e5e40 | |
Mike Lynch | 836e0d5ab6 | |
Mike Lynch | 0be8c47608 | |
Mike Lynch | 5e31403420 | |
Mike Lynch | aba20124db |
12
gui.js
12
gui.js
|
@ -2,8 +2,8 @@ import { GUI } from 'lil-gui';
|
||||||
|
|
||||||
|
|
||||||
const DEFAULTS = {
|
const DEFAULTS = {
|
||||||
thickness: 1.0,
|
thickness: 0.5,
|
||||||
nodesize: 2.0,
|
nodesize: 1.5,
|
||||||
linkopacity: 0.5,
|
linkopacity: 0.5,
|
||||||
link2opacity: 0.5,
|
link2opacity: 0.5,
|
||||||
shape: '120-cell',
|
shape: '120-cell',
|
||||||
|
@ -13,10 +13,10 @@ const DEFAULTS = {
|
||||||
inscribe_all: false,
|
inscribe_all: false,
|
||||||
color: 0x3293a9,
|
color: 0x3293a9,
|
||||||
background: 0xd4d4d4,
|
background: 0xd4d4d4,
|
||||||
hyperplane: 1.5,
|
hyperplane: 0.93,
|
||||||
zoom: 1,
|
zoom: 1,
|
||||||
xRotate: 'YW',
|
xRotate: 'YW',
|
||||||
yRotate: 'XZ',
|
yRotate: 'XW',
|
||||||
dtheta: 0,
|
dtheta: 0,
|
||||||
dpsi: 0,
|
dpsi: 0,
|
||||||
}
|
}
|
||||||
|
@ -65,9 +65,9 @@ class FourDGUI {
|
||||||
options_ctrl = this.gui.add(this.params, 'option').options(options).onChange((option) => {
|
options_ctrl = this.gui.add(this.params, 'option').options(options).onChange((option) => {
|
||||||
setVisibility(option)
|
setVisibility(option)
|
||||||
});
|
});
|
||||||
this.gui.add(this.params, 'hyperplane', 1.4, 2.0);
|
this.gui.add(this.params, 'hyperplane', 0.5, 1 / 0.8);
|
||||||
this.gui.add(this.params, 'zoom', 0.1, 2.0);
|
this.gui.add(this.params, 'zoom', 0.1, 2.0);
|
||||||
this.gui.add(this.params, 'thickness', 0, 2);
|
this.gui.add(this.params, 'thickness', 0, 1);
|
||||||
this.gui.add(this.params, 'linkopacity', 0, 1).onChange(
|
this.gui.add(this.params, 'linkopacity', 0, 1).onChange(
|
||||||
(v) => setLinkOpacity(v, true)
|
(v) => setLinkOpacity(v, true)
|
||||||
);
|
);
|
||||||
|
|
6
main.js
6
main.js
|
@ -9,7 +9,7 @@ import { FourDShape } from './fourDShape.js';
|
||||||
import { get_colours } from './colours.js';
|
import { get_colours } from './colours.js';
|
||||||
|
|
||||||
const FACE_OPACITY = 0.3;
|
const FACE_OPACITY = 0.3;
|
||||||
const CAMERA_K = 10;
|
const CAMERA_K = 5;
|
||||||
|
|
||||||
// scene, lights and camera
|
// scene, lights and camera
|
||||||
|
|
||||||
|
@ -213,8 +213,8 @@ function animate() {
|
||||||
rotfn[gui.params.xRotate](theta),
|
rotfn[gui.params.xRotate](theta),
|
||||||
rotfn[gui.params.yRotate](psi)
|
rotfn[gui.params.yRotate](psi)
|
||||||
];
|
];
|
||||||
shape.hyperplane = gui.params.hyperplane;
|
shape.hyperplane = 1 / gui.params.hyperplane;
|
||||||
camera.position.set(0, 0, gui.params.zoom * CAMERA_K / gui.params.hyperplane);
|
camera.position.set(0, 0, gui.params.zoom * CAMERA_K * gui.params.hyperplane);
|
||||||
|
|
||||||
shape.link_scale = gui.params.thickness;
|
shape.link_scale = gui.params.thickness;
|
||||||
shape.node_scale = gui.params.nodesize;
|
shape.node_scale = gui.params.nodesize;
|
||||||
|
|
174
polytopes.js
174
polytopes.js
|
@ -58,16 +58,15 @@ export function auto_detect_edges(nodes, neighbours, debug=false) {
|
||||||
// too small and simple to calculate
|
// too small and simple to calculate
|
||||||
|
|
||||||
export const cell5 = () => {
|
export const cell5 = () => {
|
||||||
const r5 = Math.sqrt(5);
|
const c1 = Math.sqrt(5) / 4;
|
||||||
const r2 = Math.sqrt(2) / 2;
|
|
||||||
return {
|
return {
|
||||||
name: '5-cell',
|
name: '5-cell',
|
||||||
nodes: [
|
nodes: [
|
||||||
{id:1, label: 1, x: r2, y: r2, z: r2, w: -r2 / r5 },
|
{id:1, label: 1, x: c1, y: c1, z: c1, w: -0.25 },
|
||||||
{id:2, label: 2, x: r2, y: -r2, z: -r2, w: -r2 / r5 },
|
{id:2, label: 2, x: c1, y: -c1, z: -c1, w: -0.25 },
|
||||||
{id:3, label: 3, x: -r2, y: r2, z: -r2, w: -r2 / r5 },
|
{id:3, label: 3, x: -c1, y: c1, z: -c1, w: -0.25 },
|
||||||
{id:4, label: 4, x: -r2, y: -r2, z: r2, w: -r2 / r5 },
|
{id:4, label: 4, x: -c1, y: -c1, z: c1, w: -0.25 },
|
||||||
{id:5, label: 5, x: 0, y: 0, z: 0, w: 4 * r2 / r5 },
|
{id:5, label: 5, x: 0, y: 0, z: 0, w: 1 },
|
||||||
],
|
],
|
||||||
links: [
|
links: [
|
||||||
{ id:1, source:1, target: 2},
|
{ id:1, source:1, target: 2},
|
||||||
|
@ -109,7 +108,7 @@ export const cell16 = () => {
|
||||||
nodes[1].label = 4;
|
nodes[1].label = 4;
|
||||||
|
|
||||||
index_nodes(nodes);
|
index_nodes(nodes);
|
||||||
scale_nodes(nodes, 0.75);
|
scale_nodes(nodes, 0.5);
|
||||||
const links = auto_detect_edges(nodes, 6);
|
const links = auto_detect_edges(nodes, 6);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -142,7 +141,7 @@ export const tesseract = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scale_nodes(nodes, Math.sqrt(2) / 2);
|
scale_nodes(nodes, 0.5);
|
||||||
const links = auto_detect_edges(nodes, 4);
|
const links = auto_detect_edges(nodes, 4);
|
||||||
links.map((l) => { l.label = 0 });
|
links.map((l) => { l.label = 0 });
|
||||||
|
|
||||||
|
@ -198,6 +197,7 @@ export const cell24 = () => {
|
||||||
n.label = CELL24_INDEXING[axes[0]][axes[1]];
|
n.label = CELL24_INDEXING[axes[0]][axes[1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scale_nodes(nodes, Math.sqrt(2) / 2);
|
||||||
index_nodes(nodes);
|
index_nodes(nodes);
|
||||||
const links = auto_detect_edges(nodes, 8);
|
const links = auto_detect_edges(nodes, 8);
|
||||||
links.map((l) => l.label = 0);
|
links.map((l) => l.label = 0);
|
||||||
|
@ -338,7 +338,7 @@ export function make_120cell_vertices() {
|
||||||
PERMUTE.coordinates([2, 1, phi, phiinv], 0, true),
|
PERMUTE.coordinates([2, 1, phi, phiinv], 0, true),
|
||||||
].flat();
|
].flat();
|
||||||
index_nodes(nodes);
|
index_nodes(nodes);
|
||||||
scale_nodes(nodes, 0.5);
|
scale_nodes(nodes, 0.25 * Math.sqrt(2));
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,7 +540,7 @@ export function make_600cell_vertices() {
|
||||||
|
|
||||||
|
|
||||||
index_nodes(nodes);
|
index_nodes(nodes);
|
||||||
scale_nodes(nodes, 0.75);
|
scale_nodes(nodes, 0.5);
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -715,6 +715,7 @@ function make_dodecahedron_vertices() {
|
||||||
{ x: -phi, y: phiinv, z:0, w: 0 , label: 4},
|
{ x: -phi, y: phiinv, z:0, w: 0 , label: 4},
|
||||||
{ x: -phi, y: -phiinv, z:0, w: 0 , label: 2},
|
{ x: -phi, y: -phiinv, z:0, w: 0 , label: 2},
|
||||||
];
|
];
|
||||||
|
scale_nodes(nodes, 1 / Math.sqrt(3));
|
||||||
index_nodes(nodes);
|
index_nodes(nodes);
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
@ -754,8 +755,155 @@ export const dodecahedron = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const tetrahedron = () => {
|
||||||
|
const r2 = Math.sqrt(2);
|
||||||
|
const r3 = Math.sqrt(3);
|
||||||
|
return {
|
||||||
|
name: 'Tetrahedron',
|
||||||
|
nodes: [
|
||||||
|
{id:1, label: 1, x: 2 * r2 / 3, y: 0, z: -1/3, w: 0 },
|
||||||
|
{id:2, label: 2, x: -r2 / 3, y: r2 / r3, z: -1/3, w: 0 },
|
||||||
|
{id:3, label: 3, x: -r2 / 3, y: -r2 / r3, z: -1/3, w: 0 },
|
||||||
|
{id:4, label: 4, x: 0, y: 0, z: 1, w: 0 },
|
||||||
|
],
|
||||||
|
links: [
|
||||||
|
{ id:1, source:1, target: 2},
|
||||||
|
{ id:2, source:1, target: 3},
|
||||||
|
{ id:3, source:1, target: 4},
|
||||||
|
{ id:4, source:2, target: 3},
|
||||||
|
{ id:5, source:2, target: 4},
|
||||||
|
{ id:6, source:3, target: 4},
|
||||||
|
],
|
||||||
|
geometry: {
|
||||||
|
node_size: 0.02,
|
||||||
|
link_size: 0.02
|
||||||
|
},
|
||||||
|
options: [ { name: '--' }],
|
||||||
|
description: `The simplest three-dimensional polytope, consisting of four triangles joined at six edges. The 5-cell is its four-dimensional analogue.`,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const octahedron = () => {
|
||||||
|
const nodes = [
|
||||||
|
{id: 1, label: 1, x: 1, y: 0, z: 0, w: 0},
|
||||||
|
{id: 2, label: 1, x: -1, y: 0, z: 0, w: 0},
|
||||||
|
{id: 3, label: 2, x: 0, y: 1, z: 0, w: 0},
|
||||||
|
{id: 4, label: 2, x: 0, y: -1, z: 0, w: 0},
|
||||||
|
{id: 5, label: 3, x: 0, y: 0, z: 1, w: 0},
|
||||||
|
{id: 6, label: 3, x: 0, y: 0, z: -1, w: 0},
|
||||||
|
];
|
||||||
|
const links = [
|
||||||
|
{id:1, source: 1, target: 3},
|
||||||
|
{id:2, source: 1, target: 4},
|
||||||
|
{id:3, source: 1, target: 5},
|
||||||
|
{id:4, source: 1, target: 6},
|
||||||
|
{id:5, source: 2, target: 3},
|
||||||
|
{id:6, source: 2, target: 4},
|
||||||
|
{id:7, source: 2, target: 5},
|
||||||
|
{id:8, source: 2, target: 6},
|
||||||
|
{id:9, source: 3, target: 5},
|
||||||
|
{id:10, source: 3, target: 6},
|
||||||
|
{id:11, source: 4, target: 5},
|
||||||
|
{id:12, source: 4, target: 6},
|
||||||
|
]
|
||||||
|
links.map((l) => { l.label = 0 });
|
||||||
|
return {
|
||||||
|
name: 'Octahedron',
|
||||||
|
nodes: nodes,
|
||||||
|
links: links,
|
||||||
|
geometry: {
|
||||||
|
node_size: 0.02,
|
||||||
|
link_size: 0.02
|
||||||
|
},
|
||||||
|
options: [ { name: '--' }],
|
||||||
|
description: `The three-dimensional cross-polytope, the 16-cell is its four-dimensional analogue.`,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export const cube = () => {
|
||||||
|
const nodes = [
|
||||||
|
{id: 1, label: 1, x: 1, y: 1, z: 1, w: 0},
|
||||||
|
{id: 2, label: 2, x: -1, y: 1, z: 1, w: 0},
|
||||||
|
{id: 3, label: 2, x: 1, y: -1, z: 1, w: 0},
|
||||||
|
{id: 4, label: 1, x: -1, y: -1, z: 1, w: 0},
|
||||||
|
{id: 5, label: 2, x: 1, y: 1, z: -1, w: 0},
|
||||||
|
{id: 6, label: 1, x: -1, y: 1, z: -1, w: 0},
|
||||||
|
{id: 7, label: 1, x: 1, y: -1, z: -1, w: 0},
|
||||||
|
{id: 8, label: 2, x: -1, y: -1, z: -1, w: 0},
|
||||||
|
];
|
||||||
|
scale_nodes(nodes, 1/Math.sqrt(3));
|
||||||
|
const links = auto_detect_edges(nodes, 3);
|
||||||
|
links.map((l) => { l.label = 0 });
|
||||||
|
return {
|
||||||
|
name: 'Cube',
|
||||||
|
nodes: nodes,
|
||||||
|
links: links,
|
||||||
|
geometry: {
|
||||||
|
node_size: 0.02,
|
||||||
|
link_size: 0.02
|
||||||
|
},
|
||||||
|
options: [ { name: '--' }],
|
||||||
|
description: `The three-dimensional measure polytope, the tesseract is its four-dimensional analogue.`,
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function make_icosahedron_vertices() {
|
||||||
|
const phi = 0.5 * (1 + Math.sqrt(5));
|
||||||
|
|
||||||
|
const nodes = [
|
||||||
|
{ x: 0, y: 1, z: phi, w: 0, label: 1 },
|
||||||
|
{ x: 0, y: -1, z: phi, w: 0, label: 1 },
|
||||||
|
{ x: 0, y: 1, z: -phi, w: 0, label: 1 },
|
||||||
|
{ x: 0, y: -1, z: -phi, w: 0, label: 1 },
|
||||||
|
{ x: 1, y: phi, z: 0, w: 0, label: 2 },
|
||||||
|
{ x: -1, y: phi, z: 0, w: 0, label: 2 },
|
||||||
|
{ x: 1, y: -phi, z: 0, w: 0, label: 2 },
|
||||||
|
{ x: -1, y: -phi, z: 0, w: 0, label: 2 },
|
||||||
|
{ x: phi, y: 0, z: 1, w: 0, label: 3},
|
||||||
|
{ x: phi, y: 0, z: -1, w: 0, label: 3},
|
||||||
|
{ x: -phi, y: 0, z: 1, w: 0, label: 3},
|
||||||
|
{ x: -phi, y: 0, z: -1, w: 0, label: 3},
|
||||||
|
];
|
||||||
|
|
||||||
|
scale_nodes(nodes, 1/Math.sqrt((5 + Math.sqrt(5)) / 2));
|
||||||
|
index_nodes(nodes);
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const icosahedron = () => {
|
||||||
|
const nodes = make_icosahedron_vertices();
|
||||||
|
const links = auto_detect_edges(nodes, 5);
|
||||||
|
links.map((l) => l.label = 0);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'Icosahedron',
|
||||||
|
nodes: nodes,
|
||||||
|
links: links,
|
||||||
|
geometry: {
|
||||||
|
node_size: 0.02,
|
||||||
|
link_size: 0.02
|
||||||
|
},
|
||||||
|
options: [
|
||||||
|
{ name: "--"},
|
||||||
|
],
|
||||||
|
description: `The icosahedron is a twenty-sided polyhedron and is dual to the dodecahedron. Its four-dimensional analogue is the 600-cell.`
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export const build_all = () => {
|
export const build_all = () => {
|
||||||
return [
|
return [
|
||||||
|
tetrahedron(),
|
||||||
|
octahedron(),
|
||||||
|
cube(),
|
||||||
|
icosahedron(),
|
||||||
dodecahedron(),
|
dodecahedron(),
|
||||||
cell5(),
|
cell5(),
|
||||||
cell16(),
|
cell16(),
|
||||||
|
@ -768,3 +916,7 @@ export const build_all = () => {
|
||||||
cell120_layered()
|
cell120_layered()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const radii = (shape) => {
|
||||||
|
return shape.nodes.map(n => Math.sqrt(n.x * n.x + n.y * n.y + n.z * n.z + n.w * n.w))
|
||||||
|
}
|
Loading…
Reference in New Issue