Compare commits
No commits in common. "feature-more-5-cells" and "main" have entirely different histories.
feature-mo
...
main
23
TODO.md
23
TODO.md
@ -1,13 +1,24 @@
|
|||||||
# FOURD-JS
|
# FOURD-JS
|
||||||
|
|
||||||
## 120-cell 5-cell
|
To-do:
|
||||||
|
|
||||||
We can label the 5-cells by using the 600-cell layers - might be more interesting
|
* render a basic wireframe (vertices and edges)
|
||||||
|
|
||||||
Try colouring the nodes according to the 120-cell standard way and the links
|
- cylinder and spheres
|
||||||
in a different set of 5 colours by the new mapping
|
- group these
|
||||||
|
|
||||||
For a subset of 24 5-cells, the vertices seem to be grouped in clusters on the 120-cells - each cluster has one of each of the 5 labels from the 120 cell
|
-- DONE
|
||||||
|
|
||||||
Write a script which checks this for each set
|
|
||||||
|
|
||||||
|
* algorithm for 4d -> 3d transform
|
||||||
|
|
||||||
|
--DONE
|
||||||
|
|
||||||
|
* 4D shape -> 3D projection -> wireframe -> three.js
|
||||||
|
|
||||||
|
--DONE
|
||||||
|
|
||||||
|
Next:
|
||||||
|
|
||||||
|
how to do this efficiently so that we can rotate the shape in 4d and have
|
||||||
|
this animate in 3d?
|
||||||
27
colours.js
27
colours.js
@ -1,14 +1,7 @@
|
|||||||
import ColorScheme from 'color-scheme';
|
import ColorScheme from 'color-scheme';
|
||||||
import Color from 'color';
|
import Color from 'color';
|
||||||
|
|
||||||
export const get_colours = (basis, n) => {
|
export const get_colours = (basis) => {
|
||||||
const colours = get_colours_spectrum(basis, n);
|
|
||||||
return colours;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const get_colours_tetrade = (basis, n) => {
|
|
||||||
// this always returns what the scheme has so it ignores n
|
|
||||||
const basis_c = Color(basis);
|
const basis_c = Color(basis);
|
||||||
const hslb = basis_c.hsl();
|
const hslb = basis_c.hsl();
|
||||||
const hue = hslb['color'][0];
|
const hue = hslb['color'][0];
|
||||||
@ -17,29 +10,13 @@ const get_colours_tetrade = (basis, n) => {
|
|||||||
const scheme = new ColorScheme;
|
const scheme = new ColorScheme;
|
||||||
scheme.from_hue(hue).scheme("tetrade").distance(0.75);
|
scheme.from_hue(hue).scheme("tetrade").distance(0.75);
|
||||||
const colours = scheme.colors();
|
const colours = scheme.colors();
|
||||||
//colours.reverse();
|
colours.reverse();
|
||||||
const hsl = colours.map((c) => Color("#" + c).hsl());
|
const hsl = colours.map((c) => Color("#" + c).hsl());
|
||||||
const resaturated = hsl.map((hslc) => hslc.saturationl(saturation).rgbNumber());
|
const resaturated = hsl.map((hslc) => hslc.saturationl(saturation).rgbNumber());
|
||||||
resaturated.unshift(basis);
|
resaturated.unshift(basis);
|
||||||
return resaturated;
|
return resaturated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const get_colours_spectrum = (basis, n) => {
|
|
||||||
// this returns n colours evenly spaced by hue
|
|
||||||
const basis_c = Color(basis);
|
|
||||||
const hslb = basis_c.hsl();
|
|
||||||
const hue = hslb['color'][0];
|
|
||||||
const saturation = hslb['color'][1];
|
|
||||||
const luminance = hslb['color'][2];
|
|
||||||
const hsl = [];
|
|
||||||
for( let i = 0; i < n; i++ ) {
|
|
||||||
const h = (hue + i * 360 / n) % 360;
|
|
||||||
hsl.push(Color.hsl(h, saturation, luminance));
|
|
||||||
}
|
|
||||||
return hsl.map((hslc) => hslc.rgbNumber());
|
|
||||||
}
|
|
||||||
|
|
||||||
// basic colours where 0 = blue
|
// basic colours where 0 = blue
|
||||||
// 1 - dark blue
|
// 1 - dark blue
|
||||||
// 2 - white
|
// 2 - white
|
||||||
|
|||||||
1
gui.js
1
gui.js
@ -13,7 +13,6 @@ const DEFAULTS = {
|
|||||||
inscribed: false,
|
inscribed: false,
|
||||||
inscribe_all: false,
|
inscribe_all: false,
|
||||||
colour: 0x3293a9,
|
colour: 0x3293a9,
|
||||||
colour_n: 5,
|
|
||||||
background: 0xd4d4d4,
|
background: 0xd4d4d4,
|
||||||
hyperplane: 0.93,
|
hyperplane: 0.93,
|
||||||
zoom: 1,
|
zoom: 1,
|
||||||
|
|||||||
24
main.js
24
main.js
@ -66,20 +66,9 @@ document.body.appendChild( renderer.domElement );
|
|||||||
// set up colours and materials for gui callbacks
|
// set up colours and materials for gui callbacks
|
||||||
|
|
||||||
scene.background = new THREE.Color(DEFAULTS.background);
|
scene.background = new THREE.Color(DEFAULTS.background);
|
||||||
|
const node_colours = get_colours(DEFAULTS.colour);
|
||||||
|
|
||||||
|
|
||||||
const STRUCTURES = POLYTOPES.build_all();
|
|
||||||
|
|
||||||
const STRUCTURES_BY_NAME = {};
|
|
||||||
|
|
||||||
STRUCTURES.map((s) => STRUCTURES_BY_NAME[s.name] = s);
|
|
||||||
|
|
||||||
const max_ms = Math.max(...STRUCTURES.map((s) => s.colour_n));
|
|
||||||
|
|
||||||
// make enough materials for the largest value of colour_n
|
|
||||||
|
|
||||||
const node_colours = get_colours(DEFAULTS.colour, max_ms);
|
|
||||||
|
|
||||||
const node_ms = node_colours.map((c) => new THREE.MeshStandardMaterial({color: c}));
|
const node_ms = node_colours.map((c) => new THREE.MeshStandardMaterial({color: c}));
|
||||||
const link_ms = node_colours.map((c) => new THREE.MeshStandardMaterial({color: c}));
|
const link_ms = node_colours.map((c) => new THREE.MeshStandardMaterial({color: c}));
|
||||||
|
|
||||||
@ -107,6 +96,12 @@ for( const face_m of face_ms ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const STRUCTURES = POLYTOPES.build_all();
|
||||||
|
|
||||||
|
const STRUCTURES_BY_NAME = {};
|
||||||
|
|
||||||
|
STRUCTURES.map((s) => STRUCTURES_BY_NAME[s.name] = s);
|
||||||
|
|
||||||
let shape = false;
|
let shape = false;
|
||||||
let structure = false;
|
let structure = false;
|
||||||
let node_show = [];
|
let node_show = [];
|
||||||
@ -167,8 +162,7 @@ relnotes.addEventListener('click', releaseNotes);
|
|||||||
// change the colors. Otherwise we just read stuff from gui.params.
|
// change the colors. Otherwise we just read stuff from gui.params.
|
||||||
|
|
||||||
function setColours(c) {
|
function setColours(c) {
|
||||||
if( structure ) {
|
const nc = get_colours(c);
|
||||||
const nc = get_colours(c, structure.colour_n);
|
|
||||||
for( let i = 0; i < node_ms.length; i++ ) {
|
for( let i = 0; i < node_ms.length; i++ ) {
|
||||||
node_ms[i].color = new THREE.Color(nc[i]);
|
node_ms[i].color = new THREE.Color(nc[i]);
|
||||||
link_ms[i].color = new THREE.Color(nc[i]);
|
link_ms[i].color = new THREE.Color(nc[i]);
|
||||||
@ -177,10 +171,8 @@ function setColours(c) {
|
|||||||
// taperedLink.set_color updates according to the link index
|
// taperedLink.set_color updates according to the link index
|
||||||
shape.links.map((l) => l.object.set_colour(nc));
|
shape.links.map((l) => l.object.set_colour(nc));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function setBackground(c) {
|
function setBackground(c) {
|
||||||
scene.background = new THREE.Color(c)
|
scene.background = new THREE.Color(c)
|
||||||
}
|
}
|
||||||
|
|||||||
75
polytopes.js
75
polytopes.js
@ -89,16 +89,16 @@ export const cell5 = () => {
|
|||||||
{id:5, label: 5, x: 0, y: 0, z: 0, w: 1 },
|
{id:5, label: 5, x: 0, y: 0, z: 0, w: 1 },
|
||||||
],
|
],
|
||||||
links: [
|
links: [
|
||||||
{ id:1, source:1, target: 2, label:0},
|
{ id:1, source:1, target: 2},
|
||||||
{ id:2, source:1, target: 3, label:0},
|
{ id:2, source:1, target: 3},
|
||||||
{ id:3, source:1, target: 4, label:0},
|
{ id:3, source:1, target: 4},
|
||||||
{ id:4, source:1, target: 5, label:0},
|
{ id:4, source:1, target: 5},
|
||||||
{ id:5, source:2, target: 3, label:0},
|
{ id:5, source:2, target: 3},
|
||||||
{ id:6, source:2, target: 4, label:0},
|
{ id:6, source:2, target: 4},
|
||||||
{ id:7, source:2, target: 5, label:0},
|
{ id:7, source:2, target: 5},
|
||||||
{ id:8, source:3, target: 4, label:0},
|
{ id:8, source:3, target: 4},
|
||||||
{ id:9, source:3, target: 5, label:0},
|
{ id:9, source:3, target: 5},
|
||||||
{ id:10, source:4, target: 5, label:0},
|
{ id:10, source:4, target: 5},
|
||||||
],
|
],
|
||||||
options: [ { name: '--' }],
|
options: [ { name: '--' }],
|
||||||
description: `Five tetrahedra joined at ten faces with three
|
description: `Five tetrahedra joined at ten faces with three
|
||||||
@ -126,7 +126,6 @@ export const cell16 = () => {
|
|||||||
index_nodes(nodes);
|
index_nodes(nodes);
|
||||||
scale_nodes(nodes, 0.5);
|
scale_nodes(nodes, 0.5);
|
||||||
const links = auto_detect_edges(nodes, 6);
|
const links = auto_detect_edges(nodes, 6);
|
||||||
links.map((l) => l.label = 0);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: '16-cell',
|
name: '16-cell',
|
||||||
@ -514,40 +513,29 @@ export const cell120_inscribed_cell5 = () => {
|
|||||||
const nodes = make_120cell_vertices();
|
const nodes = make_120cell_vertices();
|
||||||
const links = auto_detect_edges(nodes, 4);
|
const links = auto_detect_edges(nodes, 4);
|
||||||
|
|
||||||
for( const cstr in CELLINDEX.INDEX120 ) {
|
|
||||||
label_nodes(nodes, CELLINDEX.INDEX120[cstr], Number(cstr));
|
|
||||||
}
|
|
||||||
|
|
||||||
links.map((l) => l.label = 0);
|
links.map((l) => l.label = 0);
|
||||||
|
|
||||||
const CELL5S = CELLINDEX.CELL120_CELL5;
|
const CELL5S = CELLINDEX.CELL120_CELL5;
|
||||||
|
|
||||||
const nodesc5s = [];
|
|
||||||
const linksc5s = [];
|
|
||||||
const nids = [];
|
|
||||||
|
|
||||||
for( const c5 in CELL5S ) {
|
for( const c5 in CELL5S ) {
|
||||||
const nodes5 = nodes.filter((n) => CELL5S[c5].nodes.includes(n.id));
|
const nodes5 = nodes.filter((n) => CELL5S[c5].nodes.includes(n.id));
|
||||||
const links5 = auto_detect_edges(nodes5, 5);
|
const links5 = auto_detect_edges(nodes5, 5);
|
||||||
links5.map((l) => l.label = CELL5S[c5].label);
|
links5.map((l) => l.label = CELL5S[c5].label);
|
||||||
|
links.push(...links5);
|
||||||
nodes5.map((n) => n.label = CELL5S[c5].label);
|
nodes5.map((n) => n.label = CELL5S[c5].label);
|
||||||
linksc5s.push(...links5);
|
|
||||||
nodesc5s.push(...nodes5);
|
|
||||||
nids.push(...nodes5.map((n) => n.id));
|
|
||||||
}
|
}
|
||||||
const links120 = links.filter((l) => nids.includes(l.source) && nids.includes(l.target));
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: '120-cell with 5-cells',
|
name: '120-cell with 5-cells',
|
||||||
nodes: nodesc5s,
|
nodes: nodes,
|
||||||
links: [...linksc5s, ...links120],
|
links: links,
|
||||||
options: [
|
options: [
|
||||||
{ name: "all", links: [0, 1, 2, 3, 4, 5] },
|
{ name: "all", links: [0, 1, 2, 3, 4, 5] },
|
||||||
{ name: "24", links: [0, 3 ] },
|
{ name: "24", links: [0, 1 ] },
|
||||||
{ name: "48", links: [0, 1, 2 ] },
|
{ name: "48", links: [0, 1, 2 ] },
|
||||||
{ name: "72", links: [0, 1, 2, 3 ] },
|
{ name: "72", links: [0, 1, 2, 3 ] },
|
||||||
{ name: "96", links: [0, 1, 2, 3, 4 ] },
|
{ name: "96", links: [0, 1, 2, 3, 4 ] },
|
||||||
{ name: "hide 120-cell links", links: [ 1, 2, 3, 4, 5 ] },
|
{ name: "hide 1200-cell", links: [ 1, 2, 3, 4, 5 ] },
|
||||||
],
|
],
|
||||||
description: `The vertices of the 120-cell can also be partitioned
|
description: `The vertices of the 120-cell can also be partitioned
|
||||||
into 120 5-cells: each 5-cell has one vertex in each of the five
|
into 120 5-cells: each 5-cell has one vertex in each of the five
|
||||||
@ -818,6 +806,10 @@ export const cell600_layered = () => {
|
|||||||
|
|
||||||
// recolour nodes according to 24-cell partition
|
// recolour nodes according to 24-cell partition
|
||||||
|
|
||||||
|
nodes.map((n) => n.label = 8 + plabels[n.id]);
|
||||||
|
|
||||||
|
const node_c = [ 8, 9, 10, 11, 12, 13, 14, 15 ];
|
||||||
|
|
||||||
const options = [];
|
const options = [];
|
||||||
const layers = [];
|
const layers = [];
|
||||||
|
|
||||||
@ -826,7 +818,7 @@ export const cell600_layered = () => {
|
|||||||
options.push({
|
options.push({
|
||||||
name: CELLINDEX.LAYER_NAMES[i],
|
name: CELLINDEX.LAYER_NAMES[i],
|
||||||
links: [...layers],
|
links: [...layers],
|
||||||
nodes: [...layers]
|
nodes: [...node_c, ...layers]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -954,12 +946,12 @@ export const tetrahedron = () => {
|
|||||||
{id:4, label: 4, x: 0, y: 0, z: 1, w: 0 },
|
{id:4, label: 4, x: 0, y: 0, z: 1, w: 0 },
|
||||||
],
|
],
|
||||||
links: [
|
links: [
|
||||||
{ id:1, source:1, target: 2, label: 0},
|
{ id:1, source:1, target: 2},
|
||||||
{ id:2, source:1, target: 3, label: 0},
|
{ id:2, source:1, target: 3},
|
||||||
{ id:3, source:1, target: 4, label: 0},
|
{ id:3, source:1, target: 4},
|
||||||
{ id:4, source:2, target: 3, label: 0},
|
{ id:4, source:2, target: 3},
|
||||||
{ id:5, source:2, target: 4, label: 0},
|
{ id:5, source:2, target: 4},
|
||||||
{ id:6, source:3, target: 4, label: 0},
|
{ id:6, source:3, target: 4},
|
||||||
],
|
],
|
||||||
options: [ { name: '--' }],
|
options: [ { name: '--' }],
|
||||||
description: `The simplest three-dimensional polytope, consisting of four triangles joined at six edges. The 5-cell is its four-dimensional analogue.`,
|
description: `The simplest three-dimensional polytope, consisting of four triangles joined at six edges. The 5-cell is its four-dimensional analogue.`,
|
||||||
@ -1070,7 +1062,7 @@ export const icosahedron = () => {
|
|||||||
|
|
||||||
|
|
||||||
export const build_all = () => {
|
export const build_all = () => {
|
||||||
const shapes = [
|
return [
|
||||||
tetrahedron(),
|
tetrahedron(),
|
||||||
octahedron(),
|
octahedron(),
|
||||||
cube(),
|
cube(),
|
||||||
@ -1087,21 +1079,8 @@ export const build_all = () => {
|
|||||||
cell120_inscribed_cell5(),
|
cell120_inscribed_cell5(),
|
||||||
cell120_layered()
|
cell120_layered()
|
||||||
];
|
];
|
||||||
for( const shape of shapes ) {
|
|
||||||
shape.colour_n = count_labels(shape);
|
|
||||||
}
|
|
||||||
return shapes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const count_labels = (shape) => {
|
|
||||||
const labels = {};
|
|
||||||
shape.nodes.map((n) => labels[n.label] = true);
|
|
||||||
shape.links.map((n) => labels[n.label] = true);
|
|
||||||
return Object.keys(labels).length;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const radii = (shape) => {
|
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))
|
return shape.nodes.map(n => Math.sqrt(n.x * n.x + n.y * n.y + n.z * n.z + n.w * n.w))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -57,6 +57,7 @@ class TaperedLink extends THREE.Group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_colour(colours) {
|
set_colour(colours) {
|
||||||
|
console.log(`taperedLink.set_colour {this.colour_i} {colours[this.colour_i]}`);
|
||||||
this.material.color = new THREE.Color(colours[this.colour_i]);
|
this.material.color = new THREE.Color(colours[this.colour_i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user