Compare commits
3 Commits
1e59b55f5e
...
0e1d8df7b5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e1d8df7b5 | ||
|
|
137f7db066 | ||
|
|
0ae1d66669 |
14
cellindex.js
14
cellindex.js
@ -104,16 +104,12 @@ export const LAYERS120 = {
|
||||
163,219,271,223,167]
|
||||
};
|
||||
|
||||
// just one for now
|
||||
|
||||
export const CELL120_CELL5 = {
|
||||
"1": [ 1, 258, 304, 431, 510 ],
|
||||
"2": [ 1, 260, 302, 427, 506 ],
|
||||
"3": [1, 264, 298, 435, 514],
|
||||
"4": [1, 330, 334, 387, 391],
|
||||
"5": [1, 491, 503, 574, 578],
|
||||
"6": [1, 495, 499, 570, 582 ],
|
||||
};
|
||||
"1": [ 258, 1, 510, 304, 431 ],
|
||||
"2": [ 185, 93, 222, 295, 372 ],
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Schoute's partition via https://arxiv.org/abs/1010.4353
|
||||
|
||||
|
||||
@ -1,10 +1,24 @@
|
||||
|
||||
// TODO - try visualising the 5-cells from a vertex on the layered 120-cell
|
||||
// and get an intuition for how they work with the dodecahedral structure
|
||||
|
||||
// Another new approach -
|
||||
// pick a starting 5-cell
|
||||
// look at the neighbours on the 120-cell of all of its 5 vertices
|
||||
// try to find abother 5-cell with these neighbours
|
||||
// if there's only one, add that to the list and keep going
|
||||
// if there's more than one, are they disjoint with each other?
|
||||
|
||||
import * as POLYTOPES from './polytopes.js';
|
||||
|
||||
// exploring more inscriptions of the 120-cell
|
||||
|
||||
|
||||
function choice(a) {
|
||||
const r = Math.floor(Math.random() * a.length);
|
||||
return a[r];
|
||||
}
|
||||
|
||||
export function nodes_links(links, nodeid) {
|
||||
return links.filter((l) => l.source === nodeid || l.target === nodeid);
|
||||
}
|
||||
@ -100,11 +114,6 @@ export function chord_survey() {
|
||||
}
|
||||
}
|
||||
|
||||
// how to proceed: start with the 120-cell that has five 600-cells inscribed
|
||||
// in it. Take the 120 nodes from one of those 600-cells, and construct a 5-cell
|
||||
// from each such that all of the vertices are on different 600-cells.
|
||||
|
||||
// collect them and output by label because every 5-cell is on all 5 600-cells
|
||||
|
||||
function overlap(c1, c2) {
|
||||
for( const l in c1 ) {
|
||||
@ -116,13 +125,13 @@ function overlap(c1, c2) {
|
||||
}
|
||||
|
||||
|
||||
export function gather_5cells() {
|
||||
const cell120 = POLYTOPES.cell120_inscribed();
|
||||
export function gather_5cells(cell120) {
|
||||
const CHORD5 = round_dist(Math.sqrt(2.5));
|
||||
const bins = [];
|
||||
const all = [];
|
||||
cell120.nodes.filter((n) => n.label === 1).map((n) => {
|
||||
const g = distance_group(cell120, n, CHORD5);
|
||||
const cells = [ ];
|
||||
const g = distance_group(cell120, n, CHORD5);
|
||||
for( const pair of g ) {
|
||||
let seen = false;
|
||||
for( const cell of cells ) {
|
||||
@ -146,26 +155,163 @@ export function gather_5cells() {
|
||||
cells.push(cell);
|
||||
}
|
||||
}
|
||||
//console.log(`From ${n.id}`);
|
||||
//console.log(cells);
|
||||
for( const cell of cells ) {
|
||||
let binned = false;
|
||||
for( const bin of bins ) {
|
||||
const overlaps = bin.filter((b) => overlap(b, cell));
|
||||
if( overlaps.length === 0 ) {
|
||||
bin.push(cell);
|
||||
binned = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( !binned ) {
|
||||
console.log(`new bin for ${JSON.stringify(cell)}`);
|
||||
bins.push([ cell ]);
|
||||
}
|
||||
}
|
||||
//console.log(bins);
|
||||
})
|
||||
;
|
||||
all.push(...cells);
|
||||
});
|
||||
return all;
|
||||
}
|
||||
|
||||
gather_5cells();
|
||||
function audit_5cells(cells) {
|
||||
// this verifies that for each label (a 600-cell set), each of its
|
||||
// vertices is in exactly 7 5-cells. It checks out.
|
||||
|
||||
['1','2','3','4','5'].map((l) => {
|
||||
const sets = {};
|
||||
for( const cell of cells ) {
|
||||
const lv = cell[l];
|
||||
if( !(lv in sets) ) {
|
||||
sets[lv] = [];
|
||||
}
|
||||
sets[lv].push(cell);
|
||||
}
|
||||
for( const lv in sets ) {
|
||||
const ok = ( sets[lv].length === 7 ) ? 'ok' : 'miss';
|
||||
console.log(`${l},${lv},${sets[lv].length},${ok}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function try_120_5_cells_fails(cell120, cells, l) {
|
||||
// iterate over every vertex in the 600-cell defined by label l,
|
||||
// get all 7 5-cells including that vertex, and add them if they are
|
||||
// disjoint with what we already have
|
||||
|
||||
// this always runs out of disjoint nodes early
|
||||
|
||||
const vertices = cell120.nodes.filter((n) => n.label === l);
|
||||
|
||||
const cellset = [];
|
||||
for( const v of vertices ) {
|
||||
console.log(`Vertex ${v.id}`);
|
||||
const vcells = cells.filter((c) => c[l] === v.id);
|
||||
const overlap_any = (cs, c) => {
|
||||
for( const seen of cs ) {
|
||||
if( overlap(seen, c) ) {
|
||||
console.log("overlap");
|
||||
console.log(c);
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const disjoint = vcells.filter((c) => ! overlap_any(cellset, c));
|
||||
console.log(`Found ${disjoint.length} disjoint cells`);
|
||||
if( disjoint.length > 0 ) {
|
||||
cellset.push(choice(disjoint));
|
||||
}
|
||||
}
|
||||
console.log(`Found total of ${cellset.length} disjoint cells`);
|
||||
//console.log(cellset);
|
||||
}
|
||||
|
||||
function overlap_any(cs, c) {
|
||||
for( const seen of cs ) {
|
||||
if( overlap(seen, c) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
function explore_disjoint(cell120, all5, l) {
|
||||
const a = all5[0];
|
||||
|
||||
const overlaps = all5.filter((c) => overlap(c, a));
|
||||
|
||||
console.log(a);
|
||||
|
||||
console.log(overlaps.length);
|
||||
console.log(overlaps);
|
||||
}
|
||||
|
||||
// select a five-cell from a starting vertex v
|
||||
// find a neighbor of v vn on its 600 cell, find all of the 5-cells which include
|
||||
// vn. Then see if we can find any from that set which are similiar neighbours to
|
||||
// the other four vertices in the first 5-cell
|
||||
|
||||
// the idea is that the 600-cells are a guide to finding the right subset of
|
||||
// 5-cells
|
||||
|
||||
function neighbours600(cell120, vid) {
|
||||
const v = cell120.nodes.filter((node) => node.id === vid)[0];
|
||||
const label = v.label;
|
||||
const links = cell120.links.filter((l) => {
|
||||
return l.label === v.label && (l.source === v.id || l.target == v.id );
|
||||
});
|
||||
const nodes = links.map((l) => {
|
||||
if( l.source === v.id ) {
|
||||
return l.target;
|
||||
} else {
|
||||
return l.source;
|
||||
}
|
||||
});
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function cell120node(cell120, nid) {
|
||||
return cell120.nodes.filter((n) => n.id === nid)[0];
|
||||
}
|
||||
|
||||
function node_dist(cell120, aid, bid) {
|
||||
const a = cell120node(cell120, aid);
|
||||
const b = cell120node(cell120, bid);
|
||||
return dist(a, b);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function follow_600(cell120, all5) {
|
||||
const v = cell120.nodes[0];
|
||||
console.log("Start vertex:");
|
||||
console.log(v);
|
||||
const v5s = all5.filter((c5) => c5[v.label] === v.id);
|
||||
console.log(`Vertex ${v.id} belongs to these 5-cells:`);
|
||||
console.log(v5s);
|
||||
const n600s = neighbours600(cell120, v.id);
|
||||
const n600id = n600s[0];
|
||||
const n600 = cell120node(cell120, n600id);
|
||||
console.log("One 600-cell neighbour:");
|
||||
console.log(n600);
|
||||
const DIST600 = round_dist(node_dist(cell120, v.id, n600id));
|
||||
const nv5s = all5.filter((c5) => c5[v.label] === n600id);
|
||||
console.log(`Vertex ${n600id} belongs to these 5-cells:`);
|
||||
console.log(nv5s);
|
||||
console.log("Distances for each pair of 5-cells from the two sets:");
|
||||
for( const v5a of v5s ) {
|
||||
for( const v5b of nv5s ) {
|
||||
let match = true;
|
||||
const d = {};
|
||||
for( const label in v5a ) {
|
||||
d[label] = round_dist(node_dist(cell120, v5a[label], v5b[label]));
|
||||
if( d[label] != DIST600 ) {
|
||||
match = false;
|
||||
}
|
||||
}
|
||||
if( match ) {
|
||||
console.log("--- pair ---");
|
||||
console.log(v5a);
|
||||
console.log(v5b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const cell120 = POLYTOPES.cell120_inscribed();
|
||||
const all5 = gather_5cells(cell120);
|
||||
|
||||
follow_600(cell120, all5);
|
||||
|
||||
|
||||
48
gui.js
48
gui.js
@ -28,9 +28,10 @@ const DEFAULTS = {
|
||||
|
||||
class FourDGUI {
|
||||
|
||||
constructor(shapes, changeShape, setColor, setBackground, setNodeOpacity,setLinkOpacity, setVisibility, showDocs) {
|
||||
constructor(funcs) {
|
||||
this.shapes = funcs.shapes;
|
||||
this.gui = new GUI();
|
||||
const SHAPE_NAMES = shapes.map((s) => s.name);
|
||||
const SHAPE_NAMES = this.shapes.map((s) => s.name);
|
||||
|
||||
this.parseLinkParams();
|
||||
const guiObj = this;
|
||||
@ -55,41 +56,52 @@ class FourDGUI {
|
||||
captions: true,
|
||||
dtheta: this.link['dtheta'],
|
||||
dpsi: this.link['dpsi'],
|
||||
"copy link": function () { guiObj.copyUrl() }
|
||||
"copy link": function () { guiObj.copyUrl() },
|
||||
};
|
||||
if( funcs.extras ) {
|
||||
for( const label in funcs.extras ) {
|
||||
console.log(label);
|
||||
console.log(funcs.extras[label]);
|
||||
this.params[label] = funcs.extras[label];
|
||||
}
|
||||
}
|
||||
let options_ctrl;
|
||||
this.gui.add(this.params, 'shape', SHAPE_NAMES).onChange((shape) => {
|
||||
const options = this.getShapeOptions(shapes, shape);
|
||||
const options = this.getShapeOptions(shape);
|
||||
options_ctrl = options_ctrl.options(options).onChange((option) => {
|
||||
setVisibility(option)
|
||||
funcs.setVisibility(option)
|
||||
});
|
||||
options_ctrl.setValue(options[0])
|
||||
changeShape(shape)
|
||||
funcs.changeShape(shape)
|
||||
});
|
||||
const options = this.getShapeOptions(shapes, this.params['shape']);
|
||||
const options = this.getShapeOptions(this.params['shape']);
|
||||
options_ctrl = this.gui.add(this.params, 'option').options(options).onChange((option) => {
|
||||
setVisibility(option)
|
||||
funcs.setVisibility(option)
|
||||
});
|
||||
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, 'nodesize', 0, 1.5);
|
||||
this.gui.add(this.params, 'nodeopacity', 0, 1).onChange(setNodeOpacity);
|
||||
this.gui.add(this.params, 'nodeopacity', 0, 1).onChange(funcs.setNodeOpacity);
|
||||
this.gui.add(this.params, 'linksize', 0, 2);
|
||||
console.log(setLinkOpacity);
|
||||
this.gui.add(this.params, 'linkopacity', 0, 1).onChange((v) => setLinkOpacity(v, true));
|
||||
this.gui.add(this.params, 'link2opacity', 0, 1).onChange((v) => setLinkOpacity(v, false));
|
||||
this.gui.addColor(this.params, 'color').onChange(setColor);
|
||||
this.gui.addColor(this.params, 'background').onChange(setBackground);
|
||||
console.log(funcs.setLinkOpacity);
|
||||
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.addColor(this.params, 'color').onChange(funcs.setColor);
|
||||
this.gui.addColor(this.params, 'background').onChange(funcs.setBackground);
|
||||
this.gui.add(this.params, 'xRotate', [ 'YW', 'YZ', 'ZW' ]);
|
||||
this.gui.add(this.params, 'yRotate', [ 'XZ', 'XY', 'XW' ]);
|
||||
this.gui.add(this.params, 'captions').onChange(showDocs);
|
||||
this.gui.add(this.params, 'captions').onChange(this.showDocs);
|
||||
this.gui.add(this.params, 'damping');
|
||||
this.gui.add(this.params, 'copy link');
|
||||
|
||||
if( funcs.extras ) {
|
||||
for( const label in funcs.extras ) {
|
||||
this.gui.add(this.params, label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getShapeOptions(shapes, shape) {
|
||||
const spec = shapes.filter((s) => s.name === shape);
|
||||
getShapeOptions(shape) {
|
||||
const spec = this.shapes.filter((s) => s.name === shape);
|
||||
if( spec && spec[0].options ) {
|
||||
return spec[0].options.map((o) => o.name);
|
||||
} else {
|
||||
|
||||
22
main.js
22
main.js
@ -200,14 +200,20 @@ function setVisibility(option_name) {
|
||||
|
||||
|
||||
gui = new FourDGUI(
|
||||
STRUCTURES,
|
||||
changeShape,
|
||||
setColors,
|
||||
setBackground,
|
||||
setNodeOpacity,
|
||||
setLinkOpacity,
|
||||
setVisibility,
|
||||
showDocs
|
||||
{
|
||||
shapes: STRUCTURES,
|
||||
changeShape: changeShape,
|
||||
setColors: setColors,
|
||||
setBackground: setBackground,
|
||||
setNodeOpacity: setNodeOpacity,
|
||||
setLinkOpacity: setLinkOpacity,
|
||||
setVisibility: setVisibility,
|
||||
showDocs: showDocs,
|
||||
extras: {
|
||||
"Show an alert": function() { alert("hi there") },
|
||||
"Show a different one": function() { alert('yowza')},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// these are here to pick up colour settings from the URL params
|
||||
|
||||
19
polytopes.js
19
polytopes.js
@ -463,19 +463,27 @@ export const cell120_inscribed = () => {
|
||||
|
||||
export const cell120_inscribed_cell5 = () => {
|
||||
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 links = [];
|
||||
|
||||
for( const p of [ 1, 2 ]) {
|
||||
const nodes600 = nodes.filter((n) => n.label === p);
|
||||
const links600 = auto_detect_edges(nodes600, 12);
|
||||
links600.map((l) => l.label = p);
|
||||
links.push(...links600);
|
||||
}
|
||||
|
||||
for( const c5 in CELLINDEX.CELL120_CELL5 ) {
|
||||
const nodes5 = nodes.filter((n) => CELLINDEX.CELL120_CELL5[c5].includes(n.id));
|
||||
console.log(`node5 = ${nodes5}`);
|
||||
const links5 = auto_detect_edges(nodes5, 4);
|
||||
links5.map((l) => l.label = c5);
|
||||
links5.map((l) => l.label = 0);
|
||||
links.push(...links5);
|
||||
}
|
||||
|
||||
@ -484,8 +492,7 @@ export const cell120_inscribed_cell5 = () => {
|
||||
nodes: nodes,
|
||||
links: links,
|
||||
options: [
|
||||
{ name: "none", links: [ 0 ]},
|
||||
{ name: "one inscribed 5-cell", links: [ 0, 1 ] },
|
||||
{ name: "5-cells", links: [ 0, 1, 2, 3, 4, 5, 6 ] },
|
||||
],
|
||||
description: `The 120-cell with one of its 5-cells.`,
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user