From 19c73d0f8053113c8b7a4eb8c8f78f8aa369f55b Mon Sep 17 00:00:00 2001 From: Mike Lynch Date: Fri, 28 Jul 2023 17:06:42 +1000 Subject: [PATCH 1/2] More shape experiments --- fourDShape.js | 38 +++++++++++++++++++++++- main.js | 15 +++++++++- polytopes.js | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 130 insertions(+), 3 deletions(-) diff --git a/fourDShape.js b/fourDShape.js index 03aa60b..8ac36cc 100644 --- a/fourDShape.js +++ b/fourDShape.js @@ -10,13 +10,15 @@ const LINK_SIZE = 0.01; class FourDShape extends THREE.Group { - constructor(node_ms, link_ms, structure) { + constructor(node_ms, link_ms, face_ms, structure) { super(); this.node_ms = node_ms; this.link_ms = link_ms; + this.face_ms = face_ms; this.nodes4 = structure.nodes; this.nodes3 = {}; this.links = structure.links; + this.faces = ( "faces" in structure ) ? structure.faces : []; this.hyperplane = HYPERPLANE; this.initShapes(); } @@ -71,6 +73,32 @@ class FourDShape extends THREE.Group { link.object.children[0].rotation.x = Math.PI / 2.0; } + + setFaceGeometry(face, geometry) { + const values = []; + for( const f of face.nodes ) { + const v3 = this.nodes3[f].v3; + values.push(v3.x); + values.push(v3.y); + values.push(v3.z); + } + const v3 = this.nodes3[face.nodes[0]].v3; + values.push(v3.x); + values.push(v3.y); + values.push(v3.z); + const vertices = new Float32Array(values); + geometry.setAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) ); + } + + makeFace(material, face) { + const geometry = new THREE.BufferGeometry(); + this.setFaceGeometry(face, geometry) + const mesh = new THREE.Mesh( geometry, material ); + this.add(mesh); + return mesh; + } + + fourDtoV3(x, y, z, w, rotations) { const v4 = new THREE.Vector4(x, y, z, w); for ( const m4 of rotations ) { @@ -94,6 +122,10 @@ class FourDShape extends THREE.Group { const material = this.getMaterial(l, this.link_ms); l.object = this.makeLink(material, l); } + // for( const f of this.faces ) { + // const material = this.getMaterial(f, this.face_ms); + // f.object = this.makeFace(material, f); + // } } @@ -108,6 +140,10 @@ class FourDShape extends THREE.Group { for( const l of this.links ) { this.updateLink(l); } + + // for( const f of this.faces ) { + // this.setFaceGeometry(f, f.object.geometry); + // } } diff --git a/main.js b/main.js index 31171d5..c553ded 100644 --- a/main.js +++ b/main.js @@ -112,6 +112,7 @@ document.body.appendChild( renderer.domElement ); const NODE_OPACITY = 1.0; const LINK_OPACITY = 1.0; +const FACE_OPACITY = 0.2; const node_ms = [ new THREE.MeshStandardMaterial( { color: 0x90ebff } ) @@ -140,6 +141,17 @@ for( const link_m of link_ms ) { } } + +const face_ms = [ + new THREE.MeshLambertMaterial( { color: 0x44ff44 } ) + ]; + +for( const face_m of face_ms ) { + face_m.transparent = true; + face_m.opacity = FACE_OPACITY; +} + + const STRUCTURES = { '5-cell': POLYTOPES.cell5(), '16-cell': POLYTOPES.cell16(), @@ -156,7 +168,8 @@ function createShape(name) { if( shape ) { scene.remove(shape); } - shape = new FourDShape(node_ms, link_ms, STRUCTURES[name]); + console.log(STRUCTURES[name]); + shape = new FourDShape(node_ms, link_ms, face_ms, STRUCTURES[name]); scene.add(shape); } diff --git a/polytopes.js b/polytopes.js index d00b6ea..bf61373 100644 --- a/polytopes.js +++ b/polytopes.js @@ -112,6 +112,82 @@ export const cell24 = () => { } +// face detection for the 120-cell + +// NOTE: all of these return node ids, not nodes + +// return all the links which connect to a node + +function nodes_links(links, nodeid) { + return links.filter((l) => l.source === nodeid || l.target === nodeid); +} + +// filter to remove a link to a given id from a set of links + +function not_to_this(link, nodeid) { + return !(link.source === nodeid || link.target === nodeid); +} + +// given nodes n1, n2, return all neighbours of n2 which are not n1 + +function unmutuals(links, n1id, n2id) { + const nlinks = nodes_links(links, n2id).filter((l) => not_to_this(l, n1id)); + return nlinks.map((l) => { + if( l.source === n2id ) { + return l.target; + } else { + return l.source; + } + }) +} + + +function fingerprint(ids) { + const sids = [...ids]; + sids.sort(); + return sids.join(','); +} + + + +function auto_120cell_faces(links) { + const faces = []; + const seen = {}; + let id = 1; + for( const edge of links ) { + const v1 = edge.source; + const v2 = edge.target; + const n1 = unmutuals(links, v2, v1); + const n2 = unmutuals(links, v1, v2); + const shared = []; + for( const a of n1 ) { + const an = unmutuals(links, v1, a); + for( const d of n2 ) { + const dn = unmutuals(links, v2, d); + for( const x of an ) { + for( const y of dn ) { + if( x == y ) { + shared.push([v1, a, x, d, v2]) + } + } + } + } + } + if( shared.length !== 3 ) { + console.log(`Bad shared faces for ${edge.id} ${v1} ${v2}`); + } + for( const face of shared ) { + const fp = fingerprint(face); + if( !seen[fp] ) { + faces.push({ id: id, nodes: face }); + id++; + seen[fp] = true; + } + } + } + return faces; +} + function make_120cell_vertices() { @@ -138,9 +214,11 @@ function make_120cell_vertices() { export const cell120 = () => { const nodes = make_120cell_vertices(); const links = auto_detect_edges(nodes, 4); + const faces = auto_120cell_faces(links); return { nodes: nodes, - links: links + links: links, + faces: faces } } From 3f95a17f456bbd18c9af25b4788528f2558a47b6 Mon Sep 17 00:00:00 2001 From: Mike Lynch Date: Mon, 31 Jul 2023 17:37:19 +1000 Subject: [PATCH 2/2] Reinstated 120-cell faces --- fourDShape.js | 14 +++++++------- main.js | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/fourDShape.js b/fourDShape.js index 429a9ad..29d7f64 100644 --- a/fourDShape.js +++ b/fourDShape.js @@ -121,10 +121,10 @@ class FourDShape extends THREE.Group { const material = this.getMaterial(l, this.link_ms); l.object = this.makeLink(material, l); } - // for( const f of this.faces ) { - // const material = this.getMaterial(f, this.face_ms); - // f.object = this.makeFace(material, f); - // } + for( const f of this.faces ) { + const material = this.getMaterial(f, this.face_ms); + f.object = this.makeFace(material, f); + } } @@ -141,9 +141,9 @@ class FourDShape extends THREE.Group { this.updateLink(l); } - // for( const f of this.faces ) { - // this.setFaceGeometry(f, f.object.geometry); - // } + for( const f of this.faces ) { + this.setFaceGeometry(f, f.object.geometry); + } } diff --git a/main.js b/main.js index 6915a81..7faabbe 100644 --- a/main.js +++ b/main.js @@ -7,6 +7,8 @@ import { rotfn } from './rotation.js'; import { FourDGUI } from './gui.js'; import { FourDShape } from './fourDShape.js'; +const FACE_OPACITY = 0.3; + // scene, lights and camera const scene = new THREE.Scene();