Added indexing for tesseract

experiments-120-cell
Mike Lynch 2023-08-06 18:54:32 +10:00
parent c3766b749b
commit 971a791339
4 changed files with 97 additions and 34 deletions

View File

@ -3,7 +3,7 @@ import ColorScheme from 'color-scheme';
export const get_colours = (basis) => { export const get_colours = (basis) => {
const scheme = new ColorScheme; const scheme = new ColorScheme;
const hexbasis = basis.toString(16).padStart(6, "0"); const hexbasis = basis.toString(16).padStart(6, "0");
scheme.from_hex(hexbasis).scheme("analogic").variation("hard").distance(0.5); scheme.from_hex(hexbasis).scheme("tetrade").variation("hard").distance(0.5);
return scheme.colors().map((cs) => parseInt('0x' + cs)); return scheme.colors().map((cs) => parseInt('0x' + cs));
} }

View File

@ -33,6 +33,8 @@ scene.background = new THREE.Color(0x808080);
const material = new THREE.MeshStandardMaterial({ color: 0x3293a9 }); const material = new THREE.MeshStandardMaterial({ color: 0x3293a9 });
const node_colours = get_colours(0x3293a9); const node_colours = get_colours(0x3293a9);
material.transparent = true;
material.opacity = 0.5;
const node_ms = node_colours.map((c) => new THREE.MeshStandardMaterial({color: c})); const node_ms = node_colours.map((c) => new THREE.MeshStandardMaterial({color: c}));

View File

@ -505,37 +505,41 @@ function make_120_partition(nodes, n) {
const pairs60 = neighbour_angles(chord3, n, "60.000"); const pairs60 = neighbour_angles(chord3, n, "60.000");
const icosas = partition_nodes(pairs60); const icosas = partition_nodes(pairs60);
n.label = 1;
const angles = icosa_nodes(nodes, icosas[0]); const angles = icosa_nodes(nodes, icosas[0]);
label_120_partition_r(nodes, chord3, 1, n, angles); label_120_partition_r(nodes, chord3, 1, n, angles);
} }
// recursive function to label a single 600-cell vertex partition of the // recursive function to label a single 600-cell vertex partition of the
// 120-cell by following icosahedral nets // 120-cell by following icosahedral nets
// this doesn't work! completely - labels only 108-112
function label_120_partition_r(nodes, chords, label, origin, neighbours) { function label_120_partition_r(nodes, chords, label, origin, neighbours) {
console.log(`label_120_partition_r`); console.log(`label_120_partition_r ${origin.id}`);
console.log(origin); console.log(neighbours.map((n) => n.id).join(', '));
console.log(neighbours.map((n) => n.id));
// first try to label everything
const unlabelled = [];
for( const n of neighbours ) { for( const n of neighbours ) {
if( n.label === 0 ) { if( n.label === 0 ) {
console.log(`Labelled ${n.id} ${label}`);
n.label = label; n.label = label;
console.log(`Added ${n.id} to group ${label}`); unlabelled.push(n);
} else if( n.label !== label ) {
console.log(`node ${n.id} is already in group ${n.label}`);
//return false;
}
}
for( const n of unlabelled ) {
// the angles represent two icosahedral pyramids - partition them and // the angles represent two icosahedral pyramids - partition them and
// pick the one which is at 60 to the edge we arrived on // pick the one which is at 60 to the edge we arrived on
console.log(`looking for more neighbors for ${n}`); //console.log(`looking for more neighbors for ${n}`);
const pairs60 = neighbour_angles(chords, n, "60.000"); const pairs60 = neighbour_angles(chords, n, "60.000");
const icosas = partition_nodes(pairs60); const icosas = partition_nodes(pairs60);
const icosa = choose_icosa(nodes, origin, n, icosas); const icosa = choose_icosa(nodes, origin, n, icosas);
const icosa_n = icosa_nodes(nodes, icosa); const icosa_n = icosa_nodes(nodes, icosa);
console.log(`recursing to ${nice_icosa(nodes,icosa)}`);
return label_120_partition_r(nodes, chords, label, n, icosa_n); return label_120_partition_r(nodes, chords, label, n, icosa_n);
} else {
if( n.label !== label ) {
console.log(`node ${n.id} is already in group ${n.label}`);
return false;
}
}
} }
} }
@ -558,7 +562,7 @@ function choose_icosa(nodes, origin, n1, icosas) {
} }
function icosa_nodes(nodes, icosa) { function icosa_nodes(nodes, icosa) {
return Array.from(icosa).map((nid) => node_by_id(nodes, nid)); return Array.from(icosa).map((nid) => node_by_id(nodes, nid)).sort((a, b) => a.id - b.id);
} }
function node_by_id(nodes, nid) { function node_by_id(nodes, nid) {
@ -567,13 +571,64 @@ function node_by_id(nodes, nid) {
} }
function enumerate_icosas(nodes) {
const chords = find_all_chords(nodes);
const chord3 = chords["1.74806"]; // these are edges of the 600-cells;
for( const n of nodes ) {
const pairs60 = neighbour_angles(chord3, n, "60.000");
const icosas = partition_nodes(pairs60);
for( const icosa of icosas ) {
const inodes = icosa_nodes(nodes, icosa);
console.log(icosa_to_csv(n.id, inodes).join(','));
}
}
}
function icosa_to_csv(nid, icosa) {
const cols = [ nid ];
const ia = icosa.map((n) => n.id);
for( let i = 1; i < 601; i++ ) {
if( ia.includes(i) ) {
cols.push(i);
} else {
cols.push('')
}
}
return cols;
}
function start_icosas(nodes, chords, origin) {
const pairs60 = neighbour_angles(chords, origin, "60.000");
return partition_nodes(pairs60).map((i) => nice_icosa(nodes, i));
}
function next_icosa(nodes, chords, origin, nid) {
const n = node_by_id(nodes, nid);
const pairs60 = neighbour_angles(chords, n, "60.000");
const icosas = partition_nodes(pairs60);
const icosa = choose_icosa(nodes, origin, n, icosas);
return nice_icosa(nodes, icosa);
}
function nice_icosa(nodes, icosa) {
return icosa_nodes(nodes, icosa).map((n) => n.id).join(', ');
}
const nodes = make_120cell_vertices(); const nodes = make_120cell_vertices();
// const chords = find_all_chords(nodes); // const chords = find_all_chords(nodes);
// const chord3 = chords["1.74806"]; // these are edges of the 600-cells; // const chord3 = chords["1.74806"]; // these are edges of the 600-cells;
// const pairs60 = neighbour_angles(chord3, nodes[0], "60.000");
// const icosas = partition_nodes(pairs60); //const pairs60 = neighbour_angles(chord3, nodes[0], "60.000");
//const icosas = partition_nodes(pairs60);
make_120_partition(nodes, nodes[0])

View File

@ -119,6 +119,13 @@ export const cell16 = () => {
export const tesseract = () => { export const tesseract = () => {
const nodes = PERMUTE.coordinates([1, 1, 1, 1], 0); const nodes = PERMUTE.coordinates([1, 1, 1, 1], 0);
index_nodes(nodes); index_nodes(nodes);
for( const n of nodes ) {
if( n.x * n.y * n.z * n.w > 0 ) {
n.label = 1;
}
}
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);
@ -168,6 +175,7 @@ export const cell24 = () => {
// see table in https://en.wikipedia.org/wiki/120-cell - maybe adapt the // see table in https://en.wikipedia.org/wiki/120-cell - maybe adapt the
// unit radius table // unit radius table
function make_120cell_vertices() { function make_120cell_vertices() {
const phi = 0.5 * (1 + Math.sqrt(5)); const phi = 0.5 * (1 + Math.sqrt(5));
const r5 = Math.sqrt(5); const r5 = Math.sqrt(5);
@ -177,23 +185,21 @@ function make_120cell_vertices() {
const nodes = [ const nodes = [
PERMUTE.coordinates([0, 0, 2, 2], 0), PERMUTE.coordinates([0, 0, 2, 2], 0),
PERMUTE.coordinates([1, 1, 1, r5], 0), PERMUTE.coordinates([1, 1, 1, r5], 1),
PERMUTE.coordinates([phi, phi, phi, phi2inv], 0), PERMUTE.coordinates([phi, phi, phi, phi2inv], 2),
PERMUTE.coordinates([phiinv, phiinv, phiinv, phi2], 0), PERMUTE.coordinates([phiinv, phiinv, phiinv, phi2], 3),
PERMUTE.coordinates([phi2, phi2inv, 1, 0], 0, true), PERMUTE.coordinates([phi2, phi2inv, 1, 0], 4, true),
PERMUTE.coordinates([r5, phiinv, phi, 0], 0, true), PERMUTE.coordinates([r5, phiinv, phi, 0], 5, true),
PERMUTE.coordinates([2, 1, phi, phiinv], 0, true), PERMUTE.coordinates([2, 1, phi, phiinv], 6, true),
].flat(); ].flat();
index_nodes(nodes); index_nodes(nodes);
label_nodes(nodes, [1], 1);
label_nodes(nodes, [25, 41, 97, 109, 157, 161, 173, 177, 113, 37, 53, 93 ], 2);
label_nodes(nodes, [29, 45, 101, 105, 153, 165, 169, 181, 117, 33, 49, 89], 4);
scale_nodes(nodes, 0.5); scale_nodes(nodes, 0.5);
return nodes; return nodes;
} }
function label_nodes(nodes, ids, label) { function label_nodes(nodes, ids, label) {
nodes.filter((n) => ids.includes(n.id)).map((n) => n.label = label); nodes.filter((n) => ids.includes(n.id)).map((n) => n.label = label);
} }