Merge branch 'bugfix-colour-picker' into feature-120-cell-more-inscriptions
This commit is contained in:
commit
36b48b24e6
@ -1,7 +1,12 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
## v1.1 - 1/1/2025
|
## v1.2 - 18/1/2026
|
||||||
|
|
||||||
|
Added a second visualisation of the 120-cell's 5-cells without the 120-cell links
|
||||||
|
and with more colours added so you can get a sense of the individual 5-cells.
|
||||||
|
|
||||||
|
## v1.1 - 1/1/2026
|
||||||
|
|
||||||
The 120-cell now includes a visualisation of its inscribed 5-cells, which honestly
|
The 120-cell now includes a visualisation of its inscribed 5-cells, which honestly
|
||||||
looks like less of a mess than I expected it to.
|
looks like less of a mess than I expected it to.
|
||||||
|
|||||||
@ -9,12 +9,11 @@ export const get_colours = (basis) => {
|
|||||||
const luminance = hslb['color'][2];
|
const luminance = hslb['color'][2];
|
||||||
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().slice(1, 9);
|
const scolours = scheme.colors();
|
||||||
colours.reverse();
|
const colours = [ ...scolours, ...scolours, ...scolours, ...scolours, ...scolours, ...scolours, ...scolours, ...scolours ];
|
||||||
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);
|
||||||
console.log(resaturated);
|
|
||||||
return resaturated;
|
return resaturated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
gui.js
14
gui.js
@ -12,7 +12,7 @@ const DEFAULTS = {
|
|||||||
visibility: 5,
|
visibility: 5,
|
||||||
inscribed: false,
|
inscribed: false,
|
||||||
inscribe_all: false,
|
inscribe_all: false,
|
||||||
color: 0x3293a9,
|
colour: 0x3293a9,
|
||||||
background: 0xd4d4d4,
|
background: 0xd4d4d4,
|
||||||
hyperplane: 0.93,
|
hyperplane: 0.93,
|
||||||
zoom: 1,
|
zoom: 1,
|
||||||
@ -46,7 +46,7 @@ class FourDGUI {
|
|||||||
nodesize: this.link['nodesize'],
|
nodesize: this.link['nodesize'],
|
||||||
nodeopacity: this.link['nodeopacity'],
|
nodeopacity: this.link['nodeopacity'],
|
||||||
depth: this.link['depth'],
|
depth: this.link['depth'],
|
||||||
color: this.link['color'],
|
colour: this.link['colour'],
|
||||||
background: this.link['background'],
|
background: this.link['background'],
|
||||||
hyperplane: this.link['hyperplane'],
|
hyperplane: this.link['hyperplane'],
|
||||||
zoom: this.link['zoom'],
|
zoom: this.link['zoom'],
|
||||||
@ -60,8 +60,6 @@ class FourDGUI {
|
|||||||
};
|
};
|
||||||
if( funcs.extras ) {
|
if( funcs.extras ) {
|
||||||
for( const label in funcs.extras ) {
|
for( const label in funcs.extras ) {
|
||||||
console.log(label);
|
|
||||||
console.log(funcs.extras[label]);
|
|
||||||
this.params[label] = funcs.extras[label];
|
this.params[label] = funcs.extras[label];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,10 +81,9 @@ class FourDGUI {
|
|||||||
this.gui.add(this.params, 'nodesize', 0, 1.5);
|
this.gui.add(this.params, 'nodesize', 0, 1.5);
|
||||||
this.gui.add(this.params, 'nodeopacity', 0, 1).onChange(funcs.setNodeOpacity);
|
this.gui.add(this.params, 'nodeopacity', 0, 1).onChange(funcs.setNodeOpacity);
|
||||||
this.gui.add(this.params, 'linksize', 0, 2);
|
this.gui.add(this.params, 'linksize', 0, 2);
|
||||||
console.log(funcs.setLinkOpacity);
|
|
||||||
this.gui.add(this.params, 'linkopacity', 0, 1).onChange((v) => funcs.setLinkOpacity(v, true));
|
this.gui.add(this.params, 'linkopacity', 0, 1).onChange((v) => funcs.setLinkOpacity(v, true));
|
||||||
this.gui.add(this.params, 'link2opacity', 0, 1).onChange((v) => funcs.setLinkOpacity(v, false));
|
this.gui.add(this.params, 'link2opacity', 0, 1).onChange((v) => funcs.setLinkOpacity(v, false));
|
||||||
this.gui.addColor(this.params, 'color').onChange(funcs.setColor);
|
this.gui.addColor(this.params, 'colour').onChange(funcs.setColours);
|
||||||
this.gui.addColor(this.params, 'background').onChange(funcs.setBackground);
|
this.gui.addColor(this.params, 'background').onChange(funcs.setBackground);
|
||||||
this.gui.add(this.params, 'xRotate', [ 'YW', 'YZ', 'ZW' ]);
|
this.gui.add(this.params, 'xRotate', [ 'YW', 'YZ', 'ZW' ]);
|
||||||
this.gui.add(this.params, 'yRotate', [ 'XZ', 'XY', 'XW' ]);
|
this.gui.add(this.params, 'yRotate', [ 'XZ', 'XY', 'XW' ]);
|
||||||
@ -155,7 +152,7 @@ class FourDGUI {
|
|||||||
this.link['link2opacity'] = this.numParam('link2opacity', parseFloat);
|
this.link['link2opacity'] = this.numParam('link2opacity', parseFloat);
|
||||||
this.link['nodesize'] = this.numParam('nodesize', parseFloat);
|
this.link['nodesize'] = this.numParam('nodesize', parseFloat);
|
||||||
this.link['nodeopacity'] = this.numParam('nodeopacity', parseFloat);
|
this.link['nodeopacity'] = this.numParam('nodeopacity', parseFloat);
|
||||||
this.link['color'] = this.numParam('color', (s) => guiObj.stringToHex(s));
|
this.link['colour'] = this.numParam('colour', (s) => guiObj.stringToHex(s));
|
||||||
this.link['background'] = this.numParam('background', (s) => guiObj.stringToHex(s));
|
this.link['background'] = this.numParam('background', (s) => guiObj.stringToHex(s));
|
||||||
this.link['dpsi'] = this.numParam('dpsi', parseFloat);
|
this.link['dpsi'] = this.numParam('dpsi', parseFloat);
|
||||||
this.link['dtheta'] = this.numParam('dtheta', parseFloat);
|
this.link['dtheta'] = this.numParam('dtheta', parseFloat);
|
||||||
@ -172,7 +169,7 @@ class FourDGUI {
|
|||||||
url.searchParams.append("nodesize", this.params.nodesize.toString());
|
url.searchParams.append("nodesize", this.params.nodesize.toString());
|
||||||
url.searchParams.append("nodeopacity", this.params.nodesize.toString());
|
url.searchParams.append("nodeopacity", this.params.nodesize.toString());
|
||||||
url.searchParams.append("linkopacity", this.params.nodeopacity.toString());
|
url.searchParams.append("linkopacity", this.params.nodeopacity.toString());
|
||||||
url.searchParams.append("color", this.hexToString(this.params.color));
|
url.searchParams.append("colour", this.hexToString(this.params.colour));
|
||||||
url.searchParams.append("background", this.hexToString(this.params.background));
|
url.searchParams.append("background", this.hexToString(this.params.background));
|
||||||
url.searchParams.append("hyperplane", this.params.hyperplane.toString());
|
url.searchParams.append("hyperplane", this.params.hyperplane.toString());
|
||||||
url.searchParams.append("zoom", this.params.zoom.toString());
|
url.searchParams.append("zoom", this.params.zoom.toString());
|
||||||
@ -190,7 +187,6 @@ class FourDGUI {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
navigator.clipboard.writeText(text).then(function() {
|
navigator.clipboard.writeText(text).then(function() {
|
||||||
console.log('Async: Copying to clipboard was successful!');
|
|
||||||
}, function(err) {
|
}, function(err) {
|
||||||
console.error('Async: Could not copy text: ', err);
|
console.error('Async: Could not copy text: ', err);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -36,7 +36,7 @@
|
|||||||
<script type="module" src="/main.js"></script>
|
<script type="module" src="/main.js"></script>
|
||||||
<div id="description"></div>
|
<div id="description"></div>
|
||||||
<div id="release_notes"></div>
|
<div id="release_notes"></div>
|
||||||
<div id="info"><a href="#" id="show_notes">release 1.1</a> |
|
<div id="info"><a href="#" id="show_notes">release 1.2</a> |
|
||||||
|
|
||||||
by <a target="_blank" href="https://mikelynch.org/">Mike Lynch</a> |
|
by <a target="_blank" href="https://mikelynch.org/">Mike Lynch</a> |
|
||||||
<a target="_blank" href="https://git.tilde.town/bombinans/fourdjs">source</a></div>
|
<a target="_blank" href="https://git.tilde.town/bombinans/fourdjs">source</a></div>
|
||||||
|
|||||||
23
main.js
23
main.js
@ -1,6 +1,15 @@
|
|||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
|
|
||||||
const RELEASE_NOTES = `
|
const RELEASE_NOTES = `
|
||||||
|
<p><b>v1.2 - 18/1/2026</b></p>
|
||||||
|
|
||||||
|
<p>Added a second visualisation of the 120-cell's 5-cells without the 120-cell links and with more colours added so you can get a sense of the individual 5-cells.</p>
|
||||||
|
|
||||||
|
<p><b>v1.1 - 1/1/2026</b></p>
|
||||||
|
|
||||||
|
<p>The 120-cell now includes a visualisation of its inscribed 5-cells, which honestly
|
||||||
|
looks like less of a mess than I expected it to.</p>
|
||||||
|
|
||||||
<p><b>v1.0 - 16/11/2025</b></p>
|
<p><b>v1.0 - 16/11/2025</b></p>
|
||||||
|
|
||||||
<p>It's been <a target="_blank" href="https://mikelynch.org/2023/Sep/02/120-cell/">two years</a> since
|
<p>It's been <a target="_blank" href="https://mikelynch.org/2023/Sep/02/120-cell/">two years</a> since
|
||||||
@ -51,7 +60,8 @@ 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.color);
|
const node_colours = get_colours(DEFAULTS.colour);
|
||||||
|
|
||||||
|
|
||||||
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}));
|
||||||
@ -68,7 +78,6 @@ link_ms.map((m) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("link_ms", link_ms);
|
|
||||||
|
|
||||||
|
|
||||||
const face_ms = [
|
const face_ms = [
|
||||||
@ -146,7 +155,7 @@ relnotes.addEventListener('click', releaseNotes);
|
|||||||
// callbacks to do things which are triggered by controls: reset the shape,
|
// callbacks to do things which are triggered by controls: reset the shape,
|
||||||
// change the colors. Otherwise we just read stuff from gui.params.
|
// change the colors. Otherwise we just read stuff from gui.params.
|
||||||
|
|
||||||
function setColors(c) {
|
function setColours(c) {
|
||||||
const nc = get_colours(c);
|
const nc = get_colours(c);
|
||||||
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]);
|
||||||
@ -154,7 +163,7 @@ function setColors(c) {
|
|||||||
}
|
}
|
||||||
if( shape ) {
|
if( shape ) {
|
||||||
// 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_color(nc));
|
shape.links.map((l) => l.object.set_colour(nc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,8 +200,6 @@ function changeShape() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setVisibility(option_name) {
|
function setVisibility(option_name) {
|
||||||
console.log("setVisibility", option_name);
|
|
||||||
console.log(structure.options);
|
|
||||||
const option = structure.options.filter((o) => o.name === option_name);
|
const option = structure.options.filter((o) => o.name === option_name);
|
||||||
if( option.length ) {
|
if( option.length ) {
|
||||||
node_show = option[0].nodes;
|
node_show = option[0].nodes;
|
||||||
@ -207,7 +214,7 @@ gui = new FourDGUI(
|
|||||||
{
|
{
|
||||||
shapes: STRUCTURES,
|
shapes: STRUCTURES,
|
||||||
changeShape: changeShape,
|
changeShape: changeShape,
|
||||||
setColors: setColors,
|
setColours: setColours,
|
||||||
setBackground: setBackground,
|
setBackground: setBackground,
|
||||||
setNodeOpacity: setNodeOpacity,
|
setNodeOpacity: setNodeOpacity,
|
||||||
setLinkOpacity: setLinkOpacity,
|
setLinkOpacity: setLinkOpacity,
|
||||||
@ -217,7 +224,7 @@ gui = new FourDGUI(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// these are here to pick up colour settings from the URL params
|
// these are here to pick up colour settings from the URL params
|
||||||
setColors(gui.params.color);
|
setColours(gui.params.colour);
|
||||||
setBackground(gui.params.background);
|
setBackground(gui.params.background);
|
||||||
|
|
||||||
const dragK = 0.005;
|
const dragK = 0.005;
|
||||||
|
|||||||
18
polytopes.js
18
polytopes.js
@ -475,7 +475,7 @@ export const cell120_inscribed = () => {
|
|||||||
|
|
||||||
export const cell120_inscribed_cell5 = () => {
|
export const cell120_inscribed_cell5 = () => {
|
||||||
const nodes = make_120cell_vertices();
|
const nodes = make_120cell_vertices();
|
||||||
const links = auto_detect_edges(nodes, 4);
|
const links = [];
|
||||||
|
|
||||||
for( const cstr in CELLINDEX.INDEX120 ) {
|
for( const cstr in CELLINDEX.INDEX120 ) {
|
||||||
label_nodes(nodes, CELLINDEX.INDEX120[cstr], Number(cstr));
|
label_nodes(nodes, CELLINDEX.INDEX120[cstr], Number(cstr));
|
||||||
@ -483,17 +483,25 @@ export const cell120_inscribed_cell5 = () => {
|
|||||||
|
|
||||||
links.map((l) => l.label = 0);
|
links.map((l) => l.label = 0);
|
||||||
|
|
||||||
|
const CELL5S = CELLINDEX.CELL120_CELL5.cell5s;
|
||||||
|
|
||||||
|
for( const c5 in CELL5S ) {
|
||||||
|
const nodes5 = nodes.filter((n) => CELL5S[c5].includes(n.id));
|
||||||
|
const links5 = auto_detect_edges(nodes5, 5);
|
||||||
|
links5.map((l) => l.label = Number(c5));
|
||||||
|
links.push(...links5);
|
||||||
|
}
|
||||||
|
|
||||||
|
const show_links = Array.from({ length: 128 }, (_, i) => i);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: '120-cell-5-cell',
|
name: '120 5-cells',
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
options: [
|
options: [
|
||||||
{ name: "5-cells", links: [ 0, 1, 2, 3, 4, 5, 6, 7, 8 ] },
|
{ name: "none", links: show_links},
|
||||||
],
|
],
|
||||||
description: `The 120-cell with one of its 5-cells.`,
|
description: `The 120 5-cells from the 120-cell, without the latter's links. This colouring is pretty arbitrary, being based on the algorithm which partitioned the nodes: a later version will have something that's based on the symmetries of the 600-cells which each of the 5-cells has its nodes in.`,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,11 +4,11 @@ const EPSILON = 0.001;
|
|||||||
|
|
||||||
class TaperedLink extends THREE.Group {
|
class TaperedLink extends THREE.Group {
|
||||||
|
|
||||||
constructor(baseMaterial, color_i, n1, n2, r1, r2) {
|
constructor(baseMaterial, colour_i, n1, n2, r1, r2) {
|
||||||
super();
|
super();
|
||||||
const geometry = new THREE.ConeGeometry( 1, 1, 16, true );
|
const geometry = new THREE.ConeGeometry( 1, 1, 16, true );
|
||||||
const cplane = new THREE.Plane(new THREE.Vector3(0, -1, 0), 0.5);
|
const cplane = new THREE.Plane(new THREE.Vector3(0, -1, 0), 0.5);
|
||||||
this.color_i = color_i;
|
this.colour_i = colour_i;
|
||||||
this.material = baseMaterial.clone();
|
this.material = baseMaterial.clone();
|
||||||
this.material.clippingPlanes = [ cplane ];
|
this.material.clippingPlanes = [ cplane ];
|
||||||
this.object = new THREE.Mesh( geometry, this.material );
|
this.object = new THREE.Mesh( geometry, this.material );
|
||||||
@ -56,8 +56,9 @@ class TaperedLink extends THREE.Group {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_color(colors) {
|
set_colour(colours) {
|
||||||
this.material.color = new THREE.Color(colors[this.color_i]);
|
console.log(`taperedLink.set_colour {this.colour_i} {colours[this.colour_i]}`);
|
||||||
|
this.material.color = new THREE.Color(colours[this.colour_i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user