Compare commits
8 Commits
203850ba39
...
6d9610a1c6
Author | SHA1 | Date |
---|---|---|
Mike Lynch | 6d9610a1c6 | |
Mike Lynch | c481d24f3c | |
Mike Lynch | 029e6f3161 | |
Mike Lynch | 4bf38858ea | |
Mike Lynch | 50214adbe3 | |
Mike Lynch | 71c6aa62ac | |
Mike Lynch | 76f463ae03 | |
Mike Lynch | 42d1871a9e |
16
gui.js
16
gui.js
|
@ -6,7 +6,8 @@ const DEFAULTS = {
|
||||||
nodesize: 1.25,
|
nodesize: 1.25,
|
||||||
linkopacity: 0.5,
|
linkopacity: 0.5,
|
||||||
link2opacity: 0.5,
|
link2opacity: 0.5,
|
||||||
shape: '120-cell inscribed',
|
shape: '',
|
||||||
|
option: '',
|
||||||
visibility: 5,
|
visibility: 5,
|
||||||
inscribed: false,
|
inscribed: false,
|
||||||
inscribe_all: false,
|
inscribe_all: false,
|
||||||
|
@ -24,10 +25,16 @@ class FourDGUI {
|
||||||
|
|
||||||
constructor(shapes, changeShape, setColor, setBackground, setLinkOpacity, setVisibility) {
|
constructor(shapes, changeShape, setColor, setBackground, setLinkOpacity, setVisibility) {
|
||||||
this.gui = new GUI();
|
this.gui = new GUI();
|
||||||
|
const SHAPE_NAMES = shapes.map((s) => s.name);
|
||||||
|
// set default shape + option from the first shape
|
||||||
|
DEFAULTS.shape = shapes[0].name;
|
||||||
|
DEFAULTS.option = shapes[0].options[0].name;
|
||||||
|
|
||||||
this.parseLinkParams();
|
this.parseLinkParams();
|
||||||
const guiObj = this;
|
const guiObj = this;
|
||||||
this.params = {
|
this.params = {
|
||||||
shape: this.link['shape'],
|
shape: this.link['shape'],
|
||||||
|
option: this.link['option'],
|
||||||
inscribed: this.link['inscribed'],
|
inscribed: this.link['inscribed'],
|
||||||
inscribe_all: this.link['inscribe_all'],
|
inscribe_all: this.link['inscribe_all'],
|
||||||
thickness: this.link['thickness'],
|
thickness: this.link['thickness'],
|
||||||
|
@ -44,17 +51,17 @@ class FourDGUI {
|
||||||
dpsi: this.link['dpsi'],
|
dpsi: this.link['dpsi'],
|
||||||
"copy link": function () { guiObj.copyUrl() }
|
"copy link": function () { guiObj.copyUrl() }
|
||||||
};
|
};
|
||||||
const SHAPE_NAMES = shapes.map((s) => s.name);
|
|
||||||
let options_ctrl;
|
let options_ctrl;
|
||||||
this.gui.add(this.params, 'shape', SHAPE_NAMES).onChange((shape) => {
|
this.gui.add(this.params, 'shape', SHAPE_NAMES).onChange((shape) => {
|
||||||
const options = this.getShapeOptions(shapes, shape);
|
const options = this.getShapeOptions(shapes, shape);
|
||||||
options_ctrl = options_ctrl.options(options).onChange((option) => {
|
options_ctrl = options_ctrl.options(options).onChange((option) => {
|
||||||
setVisibility(option)
|
setVisibility(option)
|
||||||
});
|
});
|
||||||
|
options_ctrl.setValue(options[0])
|
||||||
changeShape(shape)
|
changeShape(shape)
|
||||||
});
|
});
|
||||||
const options = this.getShapeOptions(shapes, this.params['shape']);
|
const options = this.getShapeOptions(shapes, this.params['shape']);
|
||||||
options_ctrl = this.gui.add(this.params, 'options', options).onChange((option) => {
|
options_ctrl = this.gui.add(this.params, 'option', options).onChange((option) => {
|
||||||
setVisibility(option)
|
setVisibility(option)
|
||||||
});
|
});
|
||||||
this.gui.add(this.params, 'hyperplane', 1.5, 2.25);
|
this.gui.add(this.params, 'hyperplane', 1.5, 2.25);
|
||||||
|
@ -111,7 +118,7 @@ class FourDGUI {
|
||||||
const guiObj = this;
|
const guiObj = this;
|
||||||
|
|
||||||
this.urlParams = this.linkUrl.searchParams;
|
this.urlParams = this.linkUrl.searchParams;
|
||||||
for( const param of [ "shape", "rotation", "visiblity" ]) {
|
for( const param of [ "shape", "rotation", "option" ]) {
|
||||||
const value = this.urlParams.get(param);
|
const value = this.urlParams.get(param);
|
||||||
if( value ) {
|
if( value ) {
|
||||||
this.link[param] = value;
|
this.link[param] = value;
|
||||||
|
@ -137,6 +144,7 @@ class FourDGUI {
|
||||||
copyUrl() {
|
copyUrl() {
|
||||||
const url = new URL(this.linkUrl.origin + this.linkUrl.pathname);
|
const url = new URL(this.linkUrl.origin + this.linkUrl.pathname);
|
||||||
url.searchParams.append("shape", this.params.shape);
|
url.searchParams.append("shape", this.params.shape);
|
||||||
|
url.searchParams.append("option", this.params.option);
|
||||||
url.searchParams.append("inscribed", this.params.inscribed ? 'y': 'n');
|
url.searchParams.append("inscribed", this.params.inscribed ? 'y': 'n');
|
||||||
url.searchParams.append("inscribe_all", this.params.inscribe_all ? 'y': 'n');
|
url.searchParams.append("inscribe_all", this.params.inscribe_all ? 'y': 'n');
|
||||||
url.searchParams.append("thickness", this.params.thickness.toString());
|
url.searchParams.append("thickness", this.params.thickness.toString());
|
||||||
|
|
8
main.js
8
main.js
|
@ -62,7 +62,7 @@ for( const face_m of face_ms ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const STRUCTURES = [ POLYTOPES.cell120_inscribed() ];
|
const STRUCTURES = POLYTOPES.build_all();
|
||||||
|
|
||||||
const STRUCTURES_BY_NAME = {};
|
const STRUCTURES_BY_NAME = {};
|
||||||
|
|
||||||
|
@ -74,14 +74,14 @@ let node_show = [];
|
||||||
let link_show = [];
|
let link_show = [];
|
||||||
|
|
||||||
|
|
||||||
function createShape(name) {
|
function createShape(name, option) {
|
||||||
if( shape ) {
|
if( shape ) {
|
||||||
scene.remove(shape);
|
scene.remove(shape);
|
||||||
}
|
}
|
||||||
structure = STRUCTURES_BY_NAME[name];
|
structure = STRUCTURES_BY_NAME[name];
|
||||||
shape = new FourDShape(node_ms, link_ms, face_ms, structure);
|
shape = new FourDShape(node_ms, link_ms, face_ms, structure);
|
||||||
scene.add(shape);
|
scene.add(shape);
|
||||||
setVisibility(structure.options[0].name);
|
setVisibility(option ? option : structure.options[0].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialise gui and read params from URL
|
// initialise gui and read params from URL
|
||||||
|
@ -177,7 +177,7 @@ renderer.domElement.addEventListener("pointerup", (event) => {
|
||||||
dragging = false;
|
dragging = false;
|
||||||
})
|
})
|
||||||
|
|
||||||
createShape(gui.params.shape);
|
createShape(gui.params.shape, gui.params.option);
|
||||||
|
|
||||||
function animate() {
|
function animate() {
|
||||||
requestAnimationFrame( animate );
|
requestAnimationFrame( animate );
|
||||||
|
|
204
polytopes.js
204
polytopes.js
|
@ -84,7 +84,8 @@ export const cell5 = () => {
|
||||||
geometry: {
|
geometry: {
|
||||||
node_size: 0.02,
|
node_size: 0.02,
|
||||||
link_size: 0.02
|
link_size: 0.02
|
||||||
}
|
},
|
||||||
|
options: [ { name: '--' }]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,7 +114,8 @@ export const cell16 = () => {
|
||||||
geometry: {
|
geometry: {
|
||||||
node_size: 0.02,
|
node_size: 0.02,
|
||||||
link_size: 0.02
|
link_size: 0.02
|
||||||
}
|
},
|
||||||
|
options: [ { name: '--' }]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -133,6 +135,15 @@ export const tesseract = () => {
|
||||||
|
|
||||||
scale_nodes(nodes, Math.sqrt(2) / 2);
|
scale_nodes(nodes, Math.sqrt(2) / 2);
|
||||||
const links = auto_detect_edges(nodes, 4);
|
const links = auto_detect_edges(nodes, 4);
|
||||||
|
links.map((l) => { l.label = 0 });
|
||||||
|
|
||||||
|
for( const p of [ 1, 2 ] ) {
|
||||||
|
const nodes16 = nodes.filter((n) => n.label === p);
|
||||||
|
const links16 = auto_detect_edges(nodes16, 6);
|
||||||
|
links16.map((l) => l.label = p);
|
||||||
|
links.push(...links16);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: 'tesseract',
|
name: 'tesseract',
|
||||||
|
@ -142,36 +153,15 @@ export const tesseract = () => {
|
||||||
node_size: 0.02,
|
node_size: 0.02,
|
||||||
link_size: 0.02
|
link_size: 0.02
|
||||||
},
|
},
|
||||||
base: {},
|
|
||||||
options: [
|
options: [
|
||||||
[ 'One inscribed 16-cell', {} ],
|
{ name: 'none', links: [ 0 ] },
|
||||||
[ 'Both inscribed 16-cells', {} ],
|
{ name: 'one 16-cell', links: [ 0, 1 ] },
|
||||||
|
{ name: 'both 16-cells', links: [ 0, 1, 2 ] },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const tesseract_some_inscribed = (ps) => {
|
|
||||||
const t = tesseract();
|
|
||||||
|
|
||||||
const i_links = [];
|
|
||||||
|
|
||||||
for( const p of ps ) {
|
|
||||||
const nodes16 = t.nodes.filter((n) => n.label === p);
|
|
||||||
const links16 = auto_detect_edges(nodes16, 6);
|
|
||||||
links16.map((l) => l.label = p);
|
|
||||||
i_links.push(...links16);
|
|
||||||
}
|
|
||||||
|
|
||||||
t.links.push(...i_links);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const tesseract_inscribed = () => tesseract_some_inscribed([1]);
|
|
||||||
export const tesseract_all_inscribed = () => tesseract_some_inscribed([1,2]);
|
|
||||||
|
|
||||||
|
|
||||||
const CELL24_INDEXING = {
|
const CELL24_INDEXING = {
|
||||||
x: { y: 1, z: 3, w: 2 },
|
x: { y: 1, z: 3, w: 2 },
|
||||||
y: { z: 2, w: 3 },
|
y: { z: 2, w: 3 },
|
||||||
|
@ -195,7 +185,14 @@ export const cell24 = () => {
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
for( const p of [ 1, 2, 3 ] ) {
|
||||||
|
const nodes16 = nodes.filter((n) => n.label === p);
|
||||||
|
const links16 = auto_detect_edges(nodes16, 6);
|
||||||
|
links16.map((l) => l.label = p);
|
||||||
|
links.push(...links16);
|
||||||
|
}
|
||||||
// links.map((l) => {
|
// links.map((l) => {
|
||||||
// const ls = [ l.source, l.target ].map((nid) => node_by_id(nodes, nid).label);
|
// const ls = [ l.source, l.target ].map((nid) => node_by_id(nodes, nid).label);
|
||||||
// for ( const c of [1, 2, 3] ) {
|
// for ( const c of [1, 2, 3] ) {
|
||||||
|
@ -206,6 +203,7 @@ export const cell24 = () => {
|
||||||
// });
|
// });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
name: '24-cell',
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
geometry: {
|
geometry: {
|
||||||
|
@ -214,32 +212,14 @@ export const cell24 = () => {
|
||||||
},
|
},
|
||||||
base: {},
|
base: {},
|
||||||
options: [
|
options: [
|
||||||
[ 'One inscribed 16-cell', {} ],
|
{ name: 'none', links: [ 0 ] },
|
||||||
[ 'All inscribed 16-cells', {} ],
|
{ name: 'one 16-cell', links: [ 0, 1 ] },
|
||||||
|
{ name: 'three 16-cells', links: [ 0, 1, 2, 3 ] }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const cell24_some_inscribed = (ps) => {
|
|
||||||
const t = cell24();
|
|
||||||
|
|
||||||
const i_links = [];
|
|
||||||
|
|
||||||
for( const p of ps ) {
|
|
||||||
const nodes16 = t.nodes.filter((n) => n.label === p);
|
|
||||||
const links16 = auto_detect_edges(nodes16, 6);
|
|
||||||
links16.map((l) => l.label = p);
|
|
||||||
i_links.push(...links16);
|
|
||||||
}
|
|
||||||
|
|
||||||
t.links.push(...i_links);
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const cell24_inscribed = () => cell24_some_inscribed([1]);
|
|
||||||
export const cell24_all_inscribed = () => cell24_some_inscribed([1,2,3]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -413,28 +393,6 @@ function link_labels(nodes, link) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const cell120 = () => {
|
|
||||||
const nodes = make_120cell_vertices();
|
|
||||||
const links = auto_detect_edges(nodes, 4);
|
|
||||||
|
|
||||||
label_120cell(nodes);
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: '120-cell',
|
|
||||||
nodes: nodes,
|
|
||||||
links: links,
|
|
||||||
geometry: {
|
|
||||||
node_size: 0.02,
|
|
||||||
link_size: 0.02
|
|
||||||
},
|
|
||||||
base: {},
|
|
||||||
options: [
|
|
||||||
[ 'One inscribed 600-cell', {} ],
|
|
||||||
[ 'All inscribed 600-cells', {} ],
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const cell120_layered = (max) => {
|
export const cell120_layered = (max) => {
|
||||||
const nodes = make_120cell_vertices();
|
const nodes = make_120cell_vertices();
|
||||||
const links = auto_detect_edges(nodes, 4);
|
const links = auto_detect_edges(nodes, 4);
|
||||||
|
@ -473,7 +431,7 @@ export const cell120_inscribed = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: '120-cell inscribed',
|
name: '120-cell',
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
geometry: {
|
geometry: {
|
||||||
|
@ -482,14 +440,12 @@ export const cell120_inscribed = () => {
|
||||||
},
|
},
|
||||||
options: [
|
options: [
|
||||||
{ name: "none", links: [ 0 ]},
|
{ name: "none", links: [ 0 ]},
|
||||||
{ name: "one", links: [ 0, 1 ] },
|
{ name: "one inscribed 600-cell", links: [ 0, 1 ] },
|
||||||
{ name: "all", links: [ 0, 1, 2, 3, 4, 5 ] }
|
{ name: "five inscribed 600-cells", links: [ 0, 1, 2, 3, 4, 5 ] }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// export const cell120_inscribed = () => cell120_some_inscribed([1]);
|
|
||||||
// export const cell120_all_inscribed = () => cell120_some_inscribed([1,2,3,4,5]);
|
|
||||||
|
|
||||||
|
|
||||||
// Schoute's partition via https://arxiv.org/abs/1010.4353
|
// Schoute's partition via https://arxiv.org/abs/1010.4353
|
||||||
|
@ -667,48 +623,31 @@ export const cell600 = () => {
|
||||||
const nodes = make_600cell_vertices();
|
const nodes = make_600cell_vertices();
|
||||||
const links = auto_detect_edges(nodes, 12);
|
const links = auto_detect_edges(nodes, 12);
|
||||||
|
|
||||||
|
links.map((l) => l.label = 0);
|
||||||
|
|
||||||
|
for( const p of [1, 2, 3, 4, 5]) {
|
||||||
|
const nodes24 = nodes.filter((n) => n.label === p);
|
||||||
|
const links24 = auto_detect_edges(nodes24, 8);
|
||||||
|
links24.map((l) => l.label = p);
|
||||||
|
links.push(...links24);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
name: '600-cell',
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
geometry: {
|
|
||||||
node_size: 0.02,
|
|
||||||
link_size: 0.02
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const cell600_some_inscribed = (ps) => {
|
|
||||||
const nodes = make_600cell_vertices();
|
|
||||||
const links = auto_detect_edges(nodes, 12);
|
|
||||||
|
|
||||||
const all_links = links;
|
|
||||||
all_links.map((l) => l.label = 0);
|
|
||||||
|
|
||||||
for( const p of ps) {
|
|
||||||
const nodes24 = nodes.filter((n) => n.label === p);
|
|
||||||
const links24 = auto_detect_edges(nodes24, 8);
|
|
||||||
links24.map((l) => l.label = p);
|
|
||||||
all_links.push(...links24);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
nodes: nodes,
|
|
||||||
links: all_links,
|
|
||||||
geometry: {
|
geometry: {
|
||||||
node_size: 0.02,
|
node_size: 0.02,
|
||||||
link_size: 0.02
|
link_size: 0.02
|
||||||
},
|
},
|
||||||
|
options: [
|
||||||
|
{ name: "none", links: [ 0 ]},
|
||||||
|
{ name: "one 24-cell", links: [ 0, 1 ] },
|
||||||
|
{ name: "five 24-cells", links: [ 0, 1, 2, 3, 4, 5 ] }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const cell600_inscribed = () => cell600_some_inscribed([1]);
|
|
||||||
export const cell600_all_inscribed = () => cell600_some_inscribed([1,2,3,4,5]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function make_dodecahedron_vertices() {
|
function make_dodecahedron_vertices() {
|
||||||
const phi = 0.5 * (1 + Math.sqrt(5));
|
const phi = 0.5 * (1 + Math.sqrt(5));
|
||||||
const phiinv = 1 / phi;
|
const phiinv = 1 / phi;
|
||||||
|
@ -746,42 +685,41 @@ function make_dodecahedron_vertices() {
|
||||||
export const dodecahedron = () => {
|
export const dodecahedron = () => {
|
||||||
const nodes = make_dodecahedron_vertices();
|
const nodes = make_dodecahedron_vertices();
|
||||||
const links = auto_detect_edges(nodes, 3);
|
const links = auto_detect_edges(nodes, 3);
|
||||||
|
links.map((l) => l.label = 0);
|
||||||
|
|
||||||
|
for( const p of [ 1, 2, 3, 4, 5 ]) {
|
||||||
|
const tetran = nodes.filter((n) => n.label === p);
|
||||||
|
const tetral = auto_detect_edges(tetran, 3);
|
||||||
|
tetral.map((l) => l.label = p);
|
||||||
|
links.push(...tetral);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
name: 'dodecahedron',
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
geometry: {
|
|
||||||
node_size: 0.02,
|
|
||||||
link_size: 0.02
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const dodecahedron_some_inscribed = (ps) => {
|
|
||||||
const nodes = make_dodecahedron_vertices();
|
|
||||||
const links = auto_detect_edges(nodes, 3);
|
|
||||||
const all_links = links;
|
|
||||||
all_links.map((l) => l.label = 0);
|
|
||||||
|
|
||||||
for( const p of ps) {
|
|
||||||
const tetran = nodes.filter((n) => n.label === p);
|
|
||||||
const tetral = auto_detect_edges(tetran, 3);
|
|
||||||
tetral.map((l) => l.label = p);
|
|
||||||
all_links.push(...tetral);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
nodes: nodes,
|
|
||||||
links: all_links,
|
|
||||||
geometry: {
|
geometry: {
|
||||||
node_size: 0.02,
|
node_size: 0.02,
|
||||||
link_size: 0.02
|
link_size: 0.02
|
||||||
},
|
},
|
||||||
|
options: [
|
||||||
|
{ name: "none", links: [ 0 ]},
|
||||||
|
{ name: "one tetrahedron", links: [ 0, 1 ] },
|
||||||
|
{ name: "five tetrahedra", links: [ 0, 1, 2, 3, 4, 5 ] }
|
||||||
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export const dodecahedron_inscribed = () => dodecahedron_some_inscribed([1]);
|
export const build_all = () => {
|
||||||
export const dodecahedron_all_inscribed = () => dodecahedron_some_inscribed([1,2,3,4,5]);
|
return [
|
||||||
|
dodecahedron(),
|
||||||
|
cell5(),
|
||||||
|
cell16(),
|
||||||
|
tesseract(),
|
||||||
|
cell24(),
|
||||||
|
cell600(),
|
||||||
|
cell120_inscribed()
|
||||||
|
];
|
||||||
|
}
|
Loading…
Reference in New Issue