First draft of refactored optional / visible nodes and links
parent
06c1b074b3
commit
203850ba39
|
@ -20,8 +20,6 @@ class FourDShape extends THREE.Group {
|
||||||
this.node_scale = 1;
|
this.node_scale = 1;
|
||||||
this.link_scale = 1;
|
this.link_scale = 1;
|
||||||
this.hyperplane = HYPERPLANE;
|
this.hyperplane = HYPERPLANE;
|
||||||
this.node_f = () => true;
|
|
||||||
this.link_f = () => true;
|
|
||||||
this.initShapes();
|
this.initShapes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +61,7 @@ class FourDShape extends THREE.Group {
|
||||||
return edge;
|
return edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateLink(link) {
|
updateLink(link, links_show) {
|
||||||
const n1 = this.nodes3[link.source].v3;
|
const n1 = this.nodes3[link.source].v3;
|
||||||
const n2 = this.nodes3[link.target].v3;
|
const n2 = this.nodes3[link.target].v3;
|
||||||
const length = n1.distanceTo(n2);
|
const length = n1.distanceTo(n2);
|
||||||
|
@ -73,9 +71,7 @@ class FourDShape extends THREE.Group {
|
||||||
link.object.position.copy(centre);
|
link.object.position.copy(centre);
|
||||||
link.object.lookAt(n2);
|
link.object.lookAt(n2);
|
||||||
link.object.children[0].rotation.x = Math.PI / 2.0;
|
link.object.children[0].rotation.x = Math.PI / 2.0;
|
||||||
const l1 = this.nodes3[link.source].label;
|
link.object.visible = (!links_show || link.label in links_show);
|
||||||
const l2 = this.nodes3[link.target].label;
|
|
||||||
link.object.visible = this.link_f(link.label);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,18 +131,17 @@ class FourDShape extends THREE.Group {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
render3(rotations, node_f, link_f) {
|
render3(rotations, nodes_show, links_show) {
|
||||||
this.scalev3 = new THREE.Vector3(this.node_scale, this.node_scale, this.node_scale);
|
this.scalev3 = new THREE.Vector3(this.node_scale, this.node_scale, this.node_scale);
|
||||||
for( const n of this.nodes4 ) {
|
for( const n of this.nodes4 ) {
|
||||||
const v3 = this.fourDtoV3(n.x, n.y, n.z, n.w, rotations);
|
const v3 = this.fourDtoV3(n.x, n.y, n.z, n.w, rotations);
|
||||||
this.nodes3[n.id].v3 = v3;
|
this.nodes3[n.id].v3 = v3;
|
||||||
this.nodes3[n.id].object.position.copy(v3);
|
this.nodes3[n.id].object.position.copy(v3);
|
||||||
this.nodes3[n.id].object.scale.copy(this.scalev3);
|
this.nodes3[n.id].object.scale.copy(this.scalev3);
|
||||||
this.nodes3[n.id].object.visible = node_f(n.label);
|
this.nodes3[n.id].object.visible = ( !nodes_show || n.label in nodes_show );
|
||||||
}
|
}
|
||||||
this.link_f = link_f;
|
|
||||||
for( const l of this.links ) {
|
for( const l of this.links ) {
|
||||||
this.updateLink(l);
|
this.updateLink(l, links_show);
|
||||||
}
|
}
|
||||||
|
|
||||||
for( const f of this.faces ) {
|
for( const f of this.faces ) {
|
||||||
|
|
50
gui.js
50
gui.js
|
@ -1,28 +1,12 @@
|
||||||
import { GUI } from 'lil-gui';
|
import { GUI } from 'lil-gui';
|
||||||
|
|
||||||
const SHAPES = [
|
|
||||||
'dodecahedron', '5-cell', '16-cell', 'tesseract',
|
|
||||||
'24-cell', '600-cell', '120-cell',
|
|
||||||
'120-cell-layers', '120-cell-all-inscribed'
|
|
||||||
];
|
|
||||||
|
|
||||||
const SHAPE_OPTIONS = {
|
|
||||||
'dodecahedron': [ 'inscribed', 'all_inscribed'],
|
|
||||||
'tesseract': [ 'inscribed', 'all_inscribed'],
|
|
||||||
'16-cell': [ 'inscribed', 'all_inscribed'],
|
|
||||||
'24-cell': [ 'inscribed', 'all_inscribed'],
|
|
||||||
'600-cell': [ 'inscribed', 'all_inscribed'],
|
|
||||||
'120-cell': [ 'inscribed', 'all_inscribed'],
|
|
||||||
'120-cell-layers': [ '0', '1', '2', '3' ,'4', '5', '6' ]
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const DEFAULTS = {
|
const DEFAULTS = {
|
||||||
thickness: 0.25,
|
thickness: 0.25,
|
||||||
nodesize: 1.25,
|
nodesize: 1.25,
|
||||||
linkopacity: 0.5,
|
linkopacity: 0.5,
|
||||||
link2opacity: 0.5,
|
link2opacity: 0.5,
|
||||||
shape: '120-cell',
|
shape: '120-cell inscribed',
|
||||||
visibility: 5,
|
visibility: 5,
|
||||||
inscribed: false,
|
inscribed: false,
|
||||||
inscribe_all: false,
|
inscribe_all: false,
|
||||||
|
@ -38,7 +22,7 @@ const DEFAULTS = {
|
||||||
|
|
||||||
class FourDGUI {
|
class FourDGUI {
|
||||||
|
|
||||||
constructor(changeShape, setColor, setBackground, setLinkOpacity, setVisibility) {
|
constructor(shapes, changeShape, setColor, setBackground, setLinkOpacity, setVisibility) {
|
||||||
this.gui = new GUI();
|
this.gui = new GUI();
|
||||||
this.parseLinkParams();
|
this.parseLinkParams();
|
||||||
const guiObj = this;
|
const guiObj = this;
|
||||||
|
@ -60,16 +44,19 @@ 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', SHAPES).onChange((v) => {
|
this.gui.add(this.params, 'shape', SHAPE_NAMES).onChange((shape) => {
|
||||||
if( SHAPE_OPTIONS[v] ) {
|
const options = this.getShapeOptions(shapes, shape);
|
||||||
options_ctrl = options_ctrl.options(SHAPE_OPTIONS[v]);
|
options_ctrl = options_ctrl.options(options).onChange((option) => {
|
||||||
} else {
|
setVisibility(option)
|
||||||
options_ctrl = options_ctrl.options([])
|
});
|
||||||
}
|
changeShape(shape)
|
||||||
changeShape(v)
|
});
|
||||||
|
const options = this.getShapeOptions(shapes, this.params['shape']);
|
||||||
|
options_ctrl = this.gui.add(this.params, 'options', options).onChange((option) => {
|
||||||
|
setVisibility(option)
|
||||||
});
|
});
|
||||||
options_ctrl = this.gui.add(this.params, 'options', []);
|
|
||||||
this.gui.add(this.params, 'hyperplane', 1.5, 2.25);
|
this.gui.add(this.params, 'hyperplane', 1.5, 2.25);
|
||||||
this.gui.add(this.params, 'thickness', 0.1, 2);
|
this.gui.add(this.params, 'thickness', 0.1, 2);
|
||||||
this.gui.add(this.params, 'linkopacity', 0, 1).onChange(
|
this.gui.add(this.params, 'linkopacity', 0, 1).onChange(
|
||||||
|
@ -85,7 +72,16 @@ class FourDGUI {
|
||||||
this.gui.add(this.params, 'damping');
|
this.gui.add(this.params, 'damping');
|
||||||
this.gui.add(this.params, 'copy link');
|
this.gui.add(this.params, 'copy link');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getShapeOptions(shapes, shape) {
|
||||||
|
const spec = shapes.filter((s) => s.name === shape);
|
||||||
|
if( spec && spec[0].options ) {
|
||||||
|
return spec[0].options.map((o) => o.name);
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
numParam(param, parser) {
|
numParam(param, parser) {
|
||||||
|
|
77
main.js
77
main.js
|
@ -61,59 +61,27 @@ for( const face_m of face_ms ) {
|
||||||
face_m.opacity = FACE_OPACITY;
|
face_m.opacity = FACE_OPACITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// generalisation of the inscription stuff
|
|
||||||
|
|
||||||
// structure - with labels on nodes and links
|
const STRUCTURES = [ POLYTOPES.cell120_inscribed() ];
|
||||||
// options - a set of menu items, each one has a node and link filter
|
|
||||||
|
|
||||||
|
const STRUCTURES_BY_NAME = {};
|
||||||
|
|
||||||
const STRUCTURES = {
|
STRUCTURES.map((s) => STRUCTURES_BY_NAME[s.name] = s);
|
||||||
'5-cell': POLYTOPES.cell5(),
|
|
||||||
'16-cell': POLYTOPES.cell16(),
|
|
||||||
'tesseract': POLYTOPES.tesseract(),
|
|
||||||
'24-cell': POLYTOPES.cell24(),
|
|
||||||
'dodecahedron': POLYTOPES.dodecahedron(),
|
|
||||||
'120-cell': POLYTOPES.cell120(),
|
|
||||||
'120-cell-layers': POLYTOPES.cell120_layered(),
|
|
||||||
'120-cell-all-inscribed': POLYTOPES.cell120_all_inscribed(),
|
|
||||||
'600-cell': POLYTOPES.cell600(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const INSCRIBED = {
|
|
||||||
'tesseract': POLYTOPES.tesseract_inscribed(),
|
|
||||||
'24-cell': POLYTOPES.cell24_inscribed(),
|
|
||||||
'120-cell': POLYTOPES.cell120_inscribed(),
|
|
||||||
'600-cell': POLYTOPES.cell600_inscribed(),
|
|
||||||
'dodecahedron': POLYTOPES.dodecahedron_inscribed(),
|
|
||||||
};
|
|
||||||
|
|
||||||
const ALL_INSCRIBED = {
|
|
||||||
'tesseract': POLYTOPES.tesseract_all_inscribed(),
|
|
||||||
'24-cell': POLYTOPES.cell24_all_inscribed(),
|
|
||||||
'120-cell': POLYTOPES.cell120_all_inscribed(),
|
|
||||||
'600-cell': POLYTOPES.cell600_all_inscribed(),
|
|
||||||
'dodecahedron': POLYTOPES.dodecahedron_all_inscribed(),
|
|
||||||
}
|
|
||||||
|
|
||||||
let shape = false;
|
let shape = false;
|
||||||
|
let structure = false;
|
||||||
|
let node_show = [];
|
||||||
|
let link_show = [];
|
||||||
|
|
||||||
function createShape(name, inscribed, all) {
|
|
||||||
|
function createShape(name) {
|
||||||
if( shape ) {
|
if( shape ) {
|
||||||
scene.remove(shape);
|
scene.remove(shape);
|
||||||
}
|
}
|
||||||
let structure = STRUCTURES[name];
|
structure = STRUCTURES_BY_NAME[name];
|
||||||
if( inscribed ) {
|
|
||||||
if( name in INSCRIBED ) {
|
|
||||||
if( all ) {
|
|
||||||
structure = ALL_INSCRIBED[name];
|
|
||||||
} else {
|
|
||||||
structure = INSCRIBED[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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialise gui and read params from URL
|
// initialise gui and read params from URL
|
||||||
|
@ -145,23 +113,28 @@ function setLinkOpacity(o, primary) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let gui; //
|
let gui; //
|
||||||
let visible_labels = 6;
|
|
||||||
|
|
||||||
let node_prune = () => true;
|
|
||||||
let link_prune = () => true;
|
|
||||||
|
|
||||||
function changeShape() {
|
function changeShape() {
|
||||||
createShape(gui.params.shape, gui.params.inscribed, gui.params.inscribe_all);
|
createShape(gui.params.shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setVisibility(v) {
|
function setVisibility(option_name) {
|
||||||
console.log("setVisibility");
|
const option = structure.options.filter((o) => o.name === option_name);
|
||||||
visible_labels = v;
|
node_show = option[0].nodes;
|
||||||
|
link_show = option[0].links;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gui = new FourDGUI(changeShape, setColors, setBackground, setLinkOpacity, setVisibility);
|
gui = new FourDGUI(
|
||||||
|
STRUCTURES,
|
||||||
|
changeShape,
|
||||||
|
setColors,
|
||||||
|
setBackground,
|
||||||
|
setLinkOpacity,
|
||||||
|
setVisibility
|
||||||
|
);
|
||||||
|
|
||||||
// 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);
|
setColors(gui.params.color);
|
||||||
|
@ -204,7 +177,7 @@ renderer.domElement.addEventListener("pointerup", (event) => {
|
||||||
dragging = false;
|
dragging = false;
|
||||||
})
|
})
|
||||||
|
|
||||||
createShape(gui.params.shape, gui.params.inscribed, gui.params.inscribe_all);
|
createShape(gui.params.shape);
|
||||||
|
|
||||||
function animate() {
|
function animate() {
|
||||||
requestAnimationFrame( animate );
|
requestAnimationFrame( animate );
|
||||||
|
@ -223,7 +196,7 @@ function animate() {
|
||||||
shape.hyperplane = gui.params.hyperplane;
|
shape.hyperplane = 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;
|
||||||
shape.render3(rotations, node_prune, link_prune);
|
shape.render3(rotations, node_show, link_show);
|
||||||
|
|
||||||
renderer.render( scene, camera );
|
renderer.render( scene, camera );
|
||||||
}
|
}
|
||||||
|
|
48
polytopes.js
48
polytopes.js
|
@ -61,6 +61,7 @@ export const cell5 = () => {
|
||||||
const r5 = Math.sqrt(5);
|
const r5 = Math.sqrt(5);
|
||||||
const r2 = Math.sqrt(2) / 2;
|
const r2 = Math.sqrt(2) / 2;
|
||||||
return {
|
return {
|
||||||
|
name: '5-cell',
|
||||||
nodes: [
|
nodes: [
|
||||||
{id:1, label: 1, x: r2, y: r2, z: r2, w: -r2 / r5 },
|
{id:1, label: 1, x: r2, y: r2, z: r2, w: -r2 / r5 },
|
||||||
{id:2, label: 2, x: r2, y: -r2, z: -r2, w: -r2 / r5 },
|
{id:2, label: 2, x: r2, y: -r2, z: -r2, w: -r2 / r5 },
|
||||||
|
@ -106,6 +107,7 @@ export const cell16 = () => {
|
||||||
const links = auto_detect_edges(nodes, 6);
|
const links = auto_detect_edges(nodes, 6);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
name: '16-cell',
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
geometry: {
|
geometry: {
|
||||||
|
@ -133,12 +135,18 @@ export const tesseract = () => {
|
||||||
const links = auto_detect_edges(nodes, 4);
|
const links = auto_detect_edges(nodes, 4);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
name: 'tesseract',
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
geometry: {
|
geometry: {
|
||||||
node_size: 0.02,
|
node_size: 0.02,
|
||||||
link_size: 0.02
|
link_size: 0.02
|
||||||
}
|
},
|
||||||
|
base: {},
|
||||||
|
options: [
|
||||||
|
[ 'One inscribed 16-cell', {} ],
|
||||||
|
[ 'Both inscribed 16-cells', {} ],
|
||||||
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +211,12 @@ export const cell24 = () => {
|
||||||
geometry: {
|
geometry: {
|
||||||
node_size: 0.02,
|
node_size: 0.02,
|
||||||
link_size: 0.02
|
link_size: 0.02
|
||||||
}
|
},
|
||||||
|
base: {},
|
||||||
|
options: [
|
||||||
|
[ 'One inscribed 16-cell', {} ],
|
||||||
|
[ 'All inscribed 16-cells', {} ],
|
||||||
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,12 +420,18 @@ export const cell120 = () => {
|
||||||
label_120cell(nodes);
|
label_120cell(nodes);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
name: '120-cell',
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
geometry: {
|
geometry: {
|
||||||
node_size: 0.02,
|
node_size: 0.02,
|
||||||
link_size: 0.02
|
link_size: 0.02
|
||||||
},
|
},
|
||||||
|
base: {},
|
||||||
|
options: [
|
||||||
|
[ 'One inscribed 600-cell', {} ],
|
||||||
|
[ 'All inscribed 600-cells', {} ],
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,46 +442,54 @@ export const cell120_layered = (max) => {
|
||||||
layered_120cell(nodes);
|
layered_120cell(nodes);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
name: '120-cell layered',
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: links,
|
links: links,
|
||||||
geometry: {
|
geometry: {
|
||||||
node_size: 0.02,
|
node_size: 0.02,
|
||||||
link_size: 0.02
|
link_size: 0.02
|
||||||
},
|
},
|
||||||
|
options: [
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const cell120_some_inscribed = (ps) => {
|
export const cell120_inscribed = () => {
|
||||||
const nodes = make_120cell_vertices();
|
const nodes = make_120cell_vertices();
|
||||||
const links = auto_detect_edges(nodes, 4);
|
const links = auto_detect_edges(nodes, 4);
|
||||||
|
|
||||||
label_120cell(nodes);
|
label_120cell(nodes);
|
||||||
|
|
||||||
const all_links = links;
|
links.map((l) => l.label = 0);
|
||||||
all_links.map((l) => l.label = 0);
|
|
||||||
|
|
||||||
for( const p of ps) {
|
for( const p of [ 1, 2, 3, 4, 5 ]) {
|
||||||
const nodes600 = nodes.filter((n) => n.label === p);
|
const nodes600 = nodes.filter((n) => n.label === p);
|
||||||
const links600 = auto_detect_edges(nodes600, 12);
|
const links600 = auto_detect_edges(nodes600, 12);
|
||||||
links600.map((l) => l.label = p);
|
links600.map((l) => l.label = p);
|
||||||
all_links.push(...links600);
|
links.push(...links600);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
name: '120-cell inscribed',
|
||||||
nodes: nodes,
|
nodes: nodes,
|
||||||
links: all_links,
|
links: 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", links: [ 0, 1 ] },
|
||||||
|
{ name: "all", links: [ 0, 1, 2, 3, 4, 5 ] }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const cell120_inscribed = () => cell120_some_inscribed([1]);
|
// export const cell120_inscribed = () => cell120_some_inscribed([1]);
|
||||||
export const cell120_all_inscribed = () => cell120_some_inscribed([1,2,3,4,5]);
|
// 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
|
||||||
|
@ -757,3 +784,4 @@ const dodecahedron_some_inscribed = (ps) => {
|
||||||
export const dodecahedron_inscribed = () => dodecahedron_some_inscribed([1]);
|
export const dodecahedron_inscribed = () => dodecahedron_some_inscribed([1]);
|
||||||
export const dodecahedron_all_inscribed = () => dodecahedron_some_inscribed([1,2,3,4,5]);
|
export const dodecahedron_all_inscribed = () => dodecahedron_some_inscribed([1,2,3,4,5]);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue