Compare commits
	
		
			No commits in common. "c281c4569a0960a5ea4753ff92c407a31217972d" and "bf8356b0a265c5894d372d599938670daf67850b" have entirely different histories.
		
	
	
		
			c281c4569a
			...
			bf8356b0a2
		
	
		
							
								
								
									
										93
									
								
								cellindex.js
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								cellindex.js
									
									
									
									
									
								
							@ -1,92 +1 @@
 | 
				
			|||||||
export const INDEX = {
 | 
					export const INDEX = {"1": [ 27,38,48,49,61,68,74,87,95,98,105,120, 126,131,140,149,156,165,174,179,185,200,207,210,218,223,226,231,234,239,241,248,252,253,258,263,265,272,274,279,284,285,289,296,300,301,306,311,313,320,324,325,331,334,339,342,347,350,356,357,362,367,369,376,378,383,388,389,393,400,403,406,413,414,419,420,425,427,438,440,444,448,449,453,458,460,469,471,473,474,487,488,490,494,499,503,511,512,513,514,525,527,530,532,539,543,546,550,555,558,563,566,572,573,580,581,585,592,593,600],"2":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,28,30,31,34,35,37,40,41,44,46,47,50,51,53,56,57,60,62,63,66,67,69,72,73,76,78,79,82,83,85,88,90,91,93,96,97,100,102,103,106,107,109,112,113,116,118,119,122,123,125,128,129,132,134,135,138,139,141,144,145,148,150,151,154,155,157,160,161,164,166,167,170,171,173,176,177,180,182,183,186,187,189,192,193,196,198,199,202,203,205,208,209,212,214,215],"3":[26,39,45,52,64,65,75,86,94,99,108,117,127,130,137,152,153,168,175,178,188,197,206,211,219,222,227,230,235,238,244,245,251,254,257,264,268,269,273,280,283,286,292,293,299,302,305,312,316,317,321,328,330,335,338,343,348,349,355,358,363,366,370,375,377,384,385,392,394,399,404,405,415,416,417,418,426,428,437,439,441,445,452,456,457,459,470,472,475,476,485,486,491,495,498,502,509,510,515,516,526,528,529,531,538,542,547,551,554,559,562,567,569,576,577,584,588,589,596,597],"4":[32,33,43,54,58,71,77,84,92,101,110,115,121,136,143,146,159,162,169,184,190,195,204,213,220,221,228,229,236,237,242,247,249,256,260,261,266,271,276,277,281,288,290,295,297,304,308,309,315,318,322,327,329,336,340,341,346,351,354,359,361,368,371,374,379,382,387,390,396,397,401,408,409,410,423,424,430,432,433,435,443,447,450,454,461,463,466,468,477,478,483,484,489,493,500,504,507,508,517,518,522,524,533,535,540,544,545,549,553,560,561,568,570,575,578,583,587,590,595,598],"5":[29,36,42,55,59,70,80,81,89,104,111,114,124,133,142,147,158,163,172,181,191,194,201,216,217,224,225,232,233,240,243,246,250,255,259,262,267,270,275,278,282,287,291,294,298,303,307,310,314,319,323,326,332,333,337,344,345,352,353,360,364,365,372,373,380,381,386,391,395,398,402,407,411,412,421,422,429,431,434,436,442,446,451,455,462,464,465,467,479,480,481,482,492,496,497,501,505,506,519,520,521,523,534,536,537,541,548,552,556,557,564,565,571,574,579,582,586,591,594,599]};
 | 
				
			||||||
	"1": [
 | 
					 | 
				
			||||||
		27,38,48,49,61,68,74,87,95,98,105,120, 126,131,140,149,156,165,174,
 | 
					 | 
				
			||||||
		179,185,200,207,210,218,223,226,231,234,239,241,248,252,253,258,263,
 | 
					 | 
				
			||||||
		265,272,274,279,284,285,289,296,300,301,306,311,313,320,324,325,331,
 | 
					 | 
				
			||||||
		334,339,342,347,350,356,357,362,367,369,376,378,383,388,389,393,400,
 | 
					 | 
				
			||||||
		403,406,413,414,419,420,425,427,438,440,444,448,449,453,458,460,469,
 | 
					 | 
				
			||||||
		471,473,474,487,488,490,494,499,503,511,512,513,514,525,527,530,532,
 | 
					 | 
				
			||||||
		539,543,546,550,555,558,563,566,572,573,580,581,585,592,593,600
 | 
					 | 
				
			||||||
	],
 | 
					 | 
				
			||||||
	"2":[
 | 
					 | 
				
			||||||
		1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,28,
 | 
					 | 
				
			||||||
		30,31,34,35,37,40,41,44,46,47,50,51,53,56,57,60,62,63,66,67,69,72,73,
 | 
					 | 
				
			||||||
		76,78,79,82,83,85,88,90,91,93,96,97,100,102,103,106,107,109,112,113,
 | 
					 | 
				
			||||||
		116,118,119,122,123,125,128,129,132,134,135,138,139,141,144,145,148,
 | 
					 | 
				
			||||||
		150,151,154,155,157,160,161,164,166,167,170,171,173,176,177,180,182,
 | 
					 | 
				
			||||||
		183,186,187,189,192,193,196,198,199,202,203,205,208,209,212,214,215
 | 
					 | 
				
			||||||
		],
 | 
					 | 
				
			||||||
	"3":[
 | 
					 | 
				
			||||||
		26,39,45,52,64,65,75,86,94,99,108,117,127,130,137,152,153,168,175,
 | 
					 | 
				
			||||||
		178,188,197,206,211,219,222,227,230,235,238,244,245,251,254,257,264,
 | 
					 | 
				
			||||||
		268,269,273,280,283,286,292,293,299,302,305,312,316,317,321,328,330,
 | 
					 | 
				
			||||||
		335,338,343,348,349,355,358,363,366,370,375,377,384,385,392,394,399,
 | 
					 | 
				
			||||||
		404,405,415,416,417,418,426,428,437,439,441,445,452,456,457,459,470,
 | 
					 | 
				
			||||||
		472,475,476,485,486,491,495,498,502,509,510,515,516,526,528,529,531,
 | 
					 | 
				
			||||||
		538,542,547,551,554,559,562,567,569,576,577,584,588,589,596,597
 | 
					 | 
				
			||||||
		],
 | 
					 | 
				
			||||||
	"4":[
 | 
					 | 
				
			||||||
		32,33,43,54,58,71,77,84,92,101,110,115,121,136,143,146,159,162,169,
 | 
					 | 
				
			||||||
		184,190,195,204,213,220,221,228,229,236,237,242,247,249,256,260,261,
 | 
					 | 
				
			||||||
		266,271,276,277,281,288,290,295,297,304,308,309,315,318,322,327,329,
 | 
					 | 
				
			||||||
		336,340,341,346,351,354,359,361,368,371,374,379,382,387,390,396,397,
 | 
					 | 
				
			||||||
		401,408,409,410,423,424,430,432,433,435,443,447,450,454,461,463,466,
 | 
					 | 
				
			||||||
		468,477,478,483,484,489,493,500,504,507,508,517,518,522,524,533,535,
 | 
					 | 
				
			||||||
		540,544,545,549,553,560,561,568,570,575,578,583,587,590,595,598
 | 
					 | 
				
			||||||
		],
 | 
					 | 
				
			||||||
	"5":[
 | 
					 | 
				
			||||||
		29,36,42,55,59,70,80,81,89,104,111,114,124,133,142,147,158,163,172,
 | 
					 | 
				
			||||||
		181,191,194,201,216,217,224,225,232,233,240,243,246,250,255,259,262,
 | 
					 | 
				
			||||||
		267,270,275,278,282,287,291,294,298,303,307,310,314,319,323,326,332,
 | 
					 | 
				
			||||||
		333,337,344,345,352,353,360,364,365,372,373,380,381,386,391,395,398,
 | 
					 | 
				
			||||||
		402,407,411,412,421,422,429,431,434,436,442,446,451,455,462,464,465,
 | 
					 | 
				
			||||||
		467,479,480,481,482,492,496,497,501,505,506,519,520,521,523,534,536,
 | 
					 | 
				
			||||||
		537,541,548,552,556,557,564,565,571,574,579,582,586,591,594,599
 | 
					 | 
				
			||||||
		]
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const LAYERS =  {
 | 
					 | 
				
			||||||
	"0": [154,266,158,222,218,250,254,162,268,156,160,252,256,166,270,272,
 | 
					 | 
				
			||||||
		164,220,224,168],
 | 
					 | 
				
			||||||
	"1": [2,318,314,30,414,510,362,26,506,410,338,458,462,110,
 | 
					 | 
				
			||||||
		 106,6,350,346,34,482,418,474,330,442,450,98,90,14,
 | 
					 | 
				
			||||||
		 364,28,508,476,394,570,572,124,122,478,348,32,480,
 | 
					 | 
				
			||||||
		 512,396,576,574,126,128,8,352,38,422,486,334,454,
 | 
					 | 
				
			||||||
		 446,94,102,514,366,518,342,470,466,114,118,16,368,
 | 
					 | 
				
			||||||
		 36,484,516,398,580,578,130,132,412,316,420,332,452,
 | 
					 | 
				
			||||||
		 444,92,100,4,320,416,340,464,460,108,112,40,488,424,
 | 
					 | 
				
			||||||
		 336,448,456,104,96,520,400,582,584,136,134,344,468,472,120,116],
 | 
					 | 
				
			||||||
	"2":[246,242,42,170,426,50,434,178,226,322,46,430,174,54,182,438,326,
 | 
					 | 
				
			||||||
		230,78,558,526,62,494,542,590,142,74,554,386,300,298,202,290,206,
 | 
					 | 
				
			||||||
		522,58,538,490,138,586,236,234,186,60,540,188,282,378,66,546,194,
 | 
					 | 
				
			||||||
		68,196,548,382,286,498,82,562,530,146,594,76,556,204,80,208,560,
 | 
					 | 
				
			||||||
		388,292,588,44,428,492,140,524,64,544,380,238,190,240,192,284,
 | 
					 | 
				
			||||||
		592,496,432,48,528,144,70,198,550,72,552,200,288,384,502,534,566,
 | 
					 | 
				
			||||||
		86,598,150,390,302,210,304,214,294,84,212,564,88,568,216,296,392,
 | 
					 | 
				
			||||||
		596,500,436,52,532,148,324,244,172,248,180,228,176,56,440,184,232,
 | 
					 | 
				
			||||||
		328,504,536,152,600],
 | 
					 | 
				
			||||||
	"3":[369,273,275,371,17,353,257,261,357,9,401,305,306,402,21,307,308,
 | 
					 | 
				
			||||||
		403,22,404,259,263,355,11,359,277,279,373,19,375,309,310,405,23,
 | 
					 | 
				
			||||||
		406,258,262,354,10,358,274,276,370,18,372,356,260,264,360,12,407,
 | 
					 | 
				
			||||||
		311,312,408,24,374,278,280,376,20],"4":[229,325,173,45,429,493,
 | 
					 | 
				
			||||||
		141,525,589,289,385,557,77,205,201,137,521,553,73,585,285,381,
 | 
					 | 
				
			||||||
		193,65,545,593,145,497,529,225,321,433,49,177,139,587,491,281,377,
 | 
					 | 
				
			||||||
		539,59,187,283,379,189,61,541,197,287,199,237,239,191,293,389,213,
 | 
					 | 
				
			||||||
		149,533,565,85,597,295,391,211,147,531,563,83,595,227,323,171,43,
 | 
					 | 
				
			||||||
		427,523,151,503,535,231,327,439,55,183,599,383,551,71,87,215,567,
 | 
					 | 
				
			||||||
		169,241,245,181,489,425,41,185,233,235,195,537,57,591,543,63,495,
 | 
					 | 
				
			||||||
		143,549,69,501,179,499,435,51,175,431,47,527,203,291,387,555,75,
 | 
					 | 
				
			||||||
		207,299,297,559,79,437,53,209,561,81,301,303,547,67,243,247],
 | 
					 | 
				
			||||||
	"5":[457,337,461,105,109,469,341,465,117,113,89,97,441,449,329,93,445,
 | 
					 | 
				
			||||||
		101,453,333,573,395,125,127,575,121,569,393,123,571,451,331,443,
 | 
					 | 
				
			||||||
		99,91,129,577,131,579,397,107,459,111,339,463,95,447,335,103,455,
 | 
					 | 
				
			||||||
		133,135,581,583,399,115,119,467,471,343
 | 
					 | 
				
			||||||
		],
 | 
					 | 
				
			||||||
	"6":[1,417,313,409,413,317,421,5,475,345,473,481,349,483,33,513,507,
 | 
					 | 
				
			||||||
		13,363,511,7,487,351,485,37,517,15,519,367,515,3,423,319,415,39,
 | 
					 | 
				
			||||||
		25,505,509,477,29,411,27,479,347,31,365,419,35,315,361
 | 
					 | 
				
			||||||
		],
 | 
					 | 
				
			||||||
	"7":[217,153,221,157,265,161,165,269,249,253,251,255,267,159,155,
 | 
					 | 
				
			||||||
		163,219,271,223,167]
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@ export const get_colours = (basis) => {
 | 
				
			|||||||
	const hexbasis = basis.toString(16).padStart(6, "0");
 | 
						const hexbasis = basis.toString(16).padStart(6, "0");
 | 
				
			||||||
	scheme.from_hex(hexbasis).scheme("tetrade").variation("hard").distance(0.5);
 | 
						scheme.from_hex(hexbasis).scheme("tetrade").variation("hard").distance(0.5);
 | 
				
			||||||
	const colours = scheme.colors().map((cs) => parseInt('0x' + cs));
 | 
						const colours = scheme.colors().map((cs) => parseInt('0x' + cs));
 | 
				
			||||||
	const set = colours.slice(1, 9);
 | 
						const set = colours.slice(1, 6);
 | 
				
			||||||
	set.reverse();
 | 
						set.reverse();
 | 
				
			||||||
	set.unshift(colours[0]);
 | 
						set.unshift(colours[0]);
 | 
				
			||||||
	return set;
 | 
						return set;
 | 
				
			||||||
 | 
				
			|||||||
@ -61,7 +61,7 @@ class FourDShape extends THREE.Group {
 | 
				
			|||||||
		return edge;
 | 
							return edge;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	updateLink(link, links_show) {
 | 
						updateLink(link) {
 | 
				
			||||||
		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);
 | 
				
			||||||
@ -71,7 +71,6 @@ 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;
 | 
				
			||||||
		link.object.visible = (!links_show || link.label in links_show); 
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -116,7 +115,6 @@ class FourDShape extends THREE.Group {
 | 
				
			|||||||
			const material = this.getMaterial(n, this.node_ms);
 | 
								const material = this.getMaterial(n, this.node_ms);
 | 
				
			||||||
			this.nodes3[n.id] = {
 | 
								this.nodes3[n.id] = {
 | 
				
			||||||
				v3: v3,
 | 
									v3: v3,
 | 
				
			||||||
				label: n.label,
 | 
					 | 
				
			||||||
				object: this.makeNode(material, v3)
 | 
									object: this.makeNode(material, v3)
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -131,17 +129,17 @@ class FourDShape extends THREE.Group {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	render3(rotations, nodes_show, links_show) {
 | 
						render3(rotations) {
 | 
				
			||||||
		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 = ( !nodes_show || n.label in nodes_show );
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for( const l of this.links ) {
 | 
							for( const l of this.links ) {
 | 
				
			||||||
			this.updateLink(l, links_show);
 | 
								this.updateLink(l);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for( const f of this.faces ) {
 | 
							for( const f of this.faces ) {
 | 
				
			||||||
@ -149,6 +147,7 @@ class FourDShape extends THREE.Group {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export { FourDShape };
 | 
					export { FourDShape };
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										46
									
								
								gui.js
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								gui.js
									
									
									
									
									
								
							@ -1,14 +1,13 @@
 | 
				
			|||||||
import { GUI } from 'lil-gui';
 | 
					import { GUI } from 'lil-gui';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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: '',
 | 
						shape: '120-cell',
 | 
				
			||||||
	option: '',
 | 
					 | 
				
			||||||
	visibility: 5,
 | 
					 | 
				
			||||||
	inscribed: false,
 | 
						inscribed: false,
 | 
				
			||||||
	inscribe_all: false,
 | 
						inscribe_all: false,
 | 
				
			||||||
	color: 0x3293a9,
 | 
						color: 0x3293a9,
 | 
				
			||||||
@ -23,25 +22,18 @@ const DEFAULTS = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class FourDGUI {
 | 
					class FourDGUI {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	constructor(shapes, changeShape, setColor, setBackground, setLinkOpacity, setVisibility) {
 | 
						constructor(changeShape, setColor, setBackground, setLinkOpacity) {
 | 
				
			||||||
		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'],
 | 
				
			||||||
			linkopacity: this.link['linkopacity'],
 | 
								linkopacity: this.link['linkopacity'],
 | 
				
			||||||
			link2opacity: this.link['linkopacity'],
 | 
								link2opacity: this.link['linkopacity'],
 | 
				
			||||||
			nodesize: this.link['nodesize'],
 | 
								nodesize: this.link['nodesize'],
 | 
				
			||||||
			depth: this.link['depth'],
 | 
					 | 
				
			||||||
			color: this.link['color'],
 | 
								color: this.link['color'],
 | 
				
			||||||
			background: this.link['background'],
 | 
								background: this.link['background'],
 | 
				
			||||||
			hyperplane: this.link['hyperplane'],
 | 
								hyperplane: this.link['hyperplane'],
 | 
				
			||||||
@ -51,19 +43,13 @@ class FourDGUI {
 | 
				
			|||||||
			dpsi: this.link['dpsi'],
 | 
								dpsi: this.link['dpsi'],
 | 
				
			||||||
			"copy link": function () { guiObj.copyUrl() }
 | 
								"copy link": function () { guiObj.copyUrl() }
 | 
				
			||||||
		};
 | 
							};
 | 
				
			||||||
		let options_ctrl;
 | 
					
 | 
				
			||||||
		this.gui.add(this.params, 'shape', SHAPE_NAMES).onChange((shape) => {
 | 
							this.gui.add(this.params, 'shape',
 | 
				
			||||||
			const options = this.getShapeOptions(shapes, shape);
 | 
								[ 'dodecahedron', '5-cell', '16-cell', 'tesseract',
 | 
				
			||||||
			options_ctrl = options_ctrl.options(options).onChange((option) => {
 | 
									'24-cell', '600-cell', '120-cell' ]
 | 
				
			||||||
				setVisibility(option)
 | 
							).onChange(changeShape)
 | 
				
			||||||
			});
 | 
							this.gui.add(this.params, 'inscribed').onChange(changeShape);
 | 
				
			||||||
			options_ctrl.setValue(options[0])
 | 
							this.gui.add(this.params, 'inscribe_all').onChange(changeShape);
 | 
				
			||||||
			changeShape(shape)
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		const options = this.getShapeOptions(shapes, this.params['shape']);
 | 
					 | 
				
			||||||
		options_ctrl = this.gui.add(this.params, 'option', options).onChange((option) => {
 | 
					 | 
				
			||||||
			setVisibility(option)
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
		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(
 | 
				
			||||||
@ -81,15 +67,6 @@ class FourDGUI {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	}	
 | 
						}	
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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) {
 | 
				
			||||||
		const value = this.urlParams.get(param);
 | 
							const value = this.urlParams.get(param);
 | 
				
			||||||
@ -118,7 +95,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", "option" ]) {
 | 
							for( const param of [ "shape", "rotation" ]) {
 | 
				
			||||||
			const value = this.urlParams.get(param);
 | 
								const value = this.urlParams.get(param);
 | 
				
			||||||
			if( value ) {
 | 
								if( value ) {
 | 
				
			||||||
				this.link[param] = value;
 | 
									this.link[param] = value;
 | 
				
			||||||
@ -144,7 +121,6 @@ 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());
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										79
									
								
								main.js
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								main.js
									
									
									
									
									
								
							@ -23,10 +23,7 @@ scene.add(light);
 | 
				
			|||||||
const amblight = new THREE.AmbientLight(0xffffff, 0.5);
 | 
					const amblight = new THREE.AmbientLight(0xffffff, 0.5);
 | 
				
			||||||
scene.add(amblight);
 | 
					scene.add(amblight);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
camera.position.set(0, 0, 4);
 | 
					camera.position.z = 4;
 | 
				
			||||||
 | 
					 | 
				
			||||||
camera.lookAt(0, 0, 0);
 | 
					 | 
				
			||||||
//camera.position.z = 4;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const renderer = new THREE.WebGLRenderer({antialias: true});
 | 
					const renderer = new THREE.WebGLRenderer({antialias: true});
 | 
				
			||||||
renderer.setSize( window.innerWidth, window.innerHeight );
 | 
					renderer.setSize( window.innerWidth, window.innerHeight );
 | 
				
			||||||
@ -62,26 +59,51 @@ for( const face_m of face_ms ) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const STRUCTURES = POLYTOPES.build_all();
 | 
					const STRUCTURES = {
 | 
				
			||||||
 | 
						'5-cell': POLYTOPES.cell5(),
 | 
				
			||||||
 | 
						'16-cell': POLYTOPES.cell16(),
 | 
				
			||||||
 | 
						'tesseract': POLYTOPES.tesseract(),
 | 
				
			||||||
 | 
						'24-cell': POLYTOPES.cell24(),
 | 
				
			||||||
 | 
						'dodecahedron': POLYTOPES.dodecahedron(),
 | 
				
			||||||
 | 
						'120-cell': POLYTOPES.cell120(),
 | 
				
			||||||
 | 
						'600-cell': POLYTOPES.cell600(),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const STRUCTURES_BY_NAME = {};
 | 
					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(),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
STRUCTURES.map((s) => STRUCTURES_BY_NAME[s.name] = s);
 | 
					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, option) {
 | 
					 | 
				
			||||||
	if( shape ) {
 | 
						if( shape ) {
 | 
				
			||||||
		scene.remove(shape);
 | 
							scene.remove(shape);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	structure = STRUCTURES_BY_NAME[name];
 | 
						let structure = STRUCTURES[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(option ? option : structure.options[0].name);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// initialise gui and read params from URL
 | 
					// initialise gui and read params from URL
 | 
				
			||||||
@ -114,31 +136,12 @@ function setLinkOpacity(o, primary) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let gui; // 
 | 
					let gui; // 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
function changeShape() {
 | 
					function changeShape() {
 | 
				
			||||||
	createShape(gui.params.shape);	
 | 
						console.log("change shape!")
 | 
				
			||||||
 | 
						createShape(gui.params.shape, gui.params.inscribed, gui.params.inscribe_all);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function setVisibility(option_name) {
 | 
					gui = new FourDGUI(changeShape, setColors, setBackground, setLinkOpacity);
 | 
				
			||||||
	const option = structure.options.filter((o) => o.name === option_name);
 | 
					 | 
				
			||||||
	if( option.length ) {
 | 
					 | 
				
			||||||
		node_show = option[0].nodes;
 | 
					 | 
				
			||||||
		link_show = option[0].links;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		console.log(`Error: option '${option_name}' not found`);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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);
 | 
				
			||||||
@ -181,7 +184,7 @@ renderer.domElement.addEventListener("pointerup", (event) => {
 | 
				
			|||||||
	dragging = false;
 | 
						dragging = false;
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
createShape(gui.params.shape, gui.params.option);
 | 
					createShape(gui.params.shape, gui.params.inscribed, gui.params.inscribe_all);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function animate() {
 | 
					function animate() {
 | 
				
			||||||
	requestAnimationFrame( animate );
 | 
						requestAnimationFrame( animate );
 | 
				
			||||||
@ -200,7 +203,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_show, link_show);
 | 
						shape.render3(rotations);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	renderer.render( scene, camera );
 | 
						renderer.render( scene, camera );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										278
									
								
								polytopes.js
									
									
									
									
									
								
							
							
						
						
									
										278
									
								
								polytopes.js
									
									
									
									
									
								
							@ -61,7 +61,6 @@ 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 },
 | 
				
			||||||
@ -84,8 +83,7 @@ export const cell5 = () => {
 | 
				
			|||||||
		geometry: {
 | 
							geometry: {
 | 
				
			||||||
			node_size: 0.02,
 | 
								node_size: 0.02,
 | 
				
			||||||
			link_size: 0.02
 | 
								link_size: 0.02
 | 
				
			||||||
		},
 | 
							}
 | 
				
			||||||
		options: [ { name: '--' }]
 | 
					 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -108,14 +106,12 @@ 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: {
 | 
				
			||||||
			node_size: 0.02,
 | 
								node_size: 0.02,
 | 
				
			||||||
			link_size: 0.02
 | 
								link_size: 0.02
 | 
				
			||||||
		},
 | 
							}
 | 
				
			||||||
		options: [ { name: '--' }]
 | 
					 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -135,33 +131,39 @@ 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',
 | 
					 | 
				
			||||||
		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: [
 | 
					 | 
				
			||||||
			{ name: 'none', links: [ 0 ] },
 | 
					 | 
				
			||||||
			{ 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 },
 | 
				
			||||||
@ -185,14 +187,7 @@ 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] ) {
 | 
				
			||||||
@ -203,23 +198,35 @@ export const cell24 = () => {
 | 
				
			|||||||
	// });
 | 
						// });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return {
 | 
						return {
 | 
				
			||||||
		name: '24-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: [
 | 
					 | 
				
			||||||
			{ name: 'none', links: [ 0 ] },
 | 
					 | 
				
			||||||
			{ 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]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -325,8 +332,6 @@ function make_120cell_vertices() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -334,8 +339,16 @@ function label_nodes(nodes, ids, label) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function label_faces_120cell(nodes, faces, cfaces, label) {
 | 
					function label_faces_120cell(nodes, faces, cfaces, label) {
 | 
				
			||||||
	const ns = new Set();
 | 
						const ns = new Set();
 | 
				
			||||||
 | 
						console.log(`label faces from ${cfaces}`);
 | 
				
			||||||
	for( const fid of cfaces ) {
 | 
						for( const fid of cfaces ) {
 | 
				
			||||||
		const face = faces.filter((f)=> f.id === fid );
 | 
							const face = faces.filter((f)=> f.id === fid );
 | 
				
			||||||
		if( face.length > 0 ) {
 | 
							if( face.length > 0 ) {
 | 
				
			||||||
@ -348,6 +361,33 @@ function label_faces_120cell(nodes, faces, cfaces, label) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function basic_auto_label_120cell(nodes, links) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						const faces = auto_120cell_faces(links);
 | 
				
			||||||
 | 
						const dodecas = DODECAHEDRA.DODECAHEDRA;
 | 
				
			||||||
 | 
						//const cfaces = [ 1, 2, 4, 145, 169 ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						let colour = 1;
 | 
				
			||||||
 | 
						for( const dd of dodecas ) {
 | 
				
			||||||
 | 
							label_faces_120cell(nodes, faces, dd, colour);
 | 
				
			||||||
 | 
							colour++;
 | 
				
			||||||
 | 
							if( colour > 8 ) {
 | 
				
			||||||
 | 
								colour = 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function label_120cell(nodes) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  	for( const cstr in CELL120.INDEX ) {
 | 
				
			||||||
 | 
								label_nodes(nodes, CELL120.INDEX[cstr], Number(cstr));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function link_labels(nodes, link) {
 | 
					function link_labels(nodes, link) {
 | 
				
			||||||
	const n1 = nodes.filter((n) => n.id === link.source);
 | 
						const n1 = nodes.filter((n) => n.id === link.source);
 | 
				
			||||||
	const n2 = nodes.filter((n) => n.id === link.target);
 | 
						const n2 = nodes.filter((n) => n.id === link.target);
 | 
				
			||||||
@ -355,88 +395,52 @@ function link_labels(nodes, link) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// version of the 120-cell where nodes are partitioned by 
 | 
					 | 
				
			||||||
// layer and the links follow that
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const cell120_layered = (max) => {
 | 
					export const cell120 = () => {
 | 
				
			||||||
	const nodes  = make_120cell_vertices();
 | 
						const nodes  = make_120cell_vertices();
 | 
				
			||||||
	const links = auto_detect_edges(nodes, 4);
 | 
						const links = auto_detect_edges(nodes, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nodes.map((n) => n.label = 9); // make all invisible by default
 | 
						label_120cell(nodes);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (const cstr in CELL120.LAYERS ) {
 | 
					 | 
				
			||||||
		label_nodes(nodes, CELL120.LAYERS[cstr], Number(cstr));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	links.map((l) => {
 | 
					 | 
				
			||||||
		const labels = link_labels(nodes, l);
 | 
					 | 
				
			||||||
		if( labels[0] >= labels[1] ) {
 | 
					 | 
				
			||||||
			l.label = labels[0];
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			l.label = labels[1];
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const options = [];
 | 
					 | 
				
			||||||
	const layers = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for( const i of [ 0, 1, 2, 3, 4, 5, 6, 7 ] ) {
 | 
					 | 
				
			||||||
		layers.push(i);
 | 
					 | 
				
			||||||
		options.unshift({
 | 
					 | 
				
			||||||
			name: "Layer " + String(i),
 | 
					 | 
				
			||||||
			links: [...layers],
 | 
					 | 
				
			||||||
			nodes: [...layers]
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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: 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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  	for( const cstr in CELL120.INDEX ) {
 | 
						label_120cell(nodes);
 | 
				
			||||||
		label_nodes(nodes, CELL120.INDEX[cstr], Number(cstr));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	links.map((l) => l.label = 0);
 | 
						const all_links = links;
 | 
				
			||||||
 | 
						all_links.map((l) => l.label = 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for( const p of [ 1, 2, 3, 4, 5 ]) {
 | 
						for( const p of ps) {
 | 
				
			||||||
		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);
 | 
				
			||||||
		links.push(...links600);
 | 
							all_links.push(...links600);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return {
 | 
						return {
 | 
				
			||||||
		name: '120-cell',
 | 
					 | 
				
			||||||
		nodes: nodes,
 | 
							nodes: nodes,
 | 
				
			||||||
		links: links,
 | 
							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 inscribed 600-cell", links: [ 0, 1 ] },
 | 
					 | 
				
			||||||
			{ 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
 | 
				
			||||||
@ -614,31 +618,48 @@ 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: {
 | 
							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 ] }
 | 
					 | 
				
			||||||
		]
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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: {
 | 
				
			||||||
 | 
								node_size: 0.02,
 | 
				
			||||||
 | 
								link_size: 0.02
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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;    
 | 
				
			||||||
@ -676,42 +697,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: {
 | 
							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 ] }
 | 
					 | 
				
			||||||
		]
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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: {
 | 
				
			||||||
 | 
								node_size: 0.02,
 | 
				
			||||||
 | 
								link_size: 0.02
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const build_all = () => {
 | 
					export const dodecahedron_inscribed = () => dodecahedron_some_inscribed([1]);
 | 
				
			||||||
	return [
 | 
					export const dodecahedron_all_inscribed = () => dodecahedron_some_inscribed([1,2,3,4,5]);
 | 
				
			||||||
	 	dodecahedron(),
 | 
					
 | 
				
			||||||
	 	cell5(),
 | 
					 | 
				
			||||||
		cell16(),
 | 
					 | 
				
			||||||
		tesseract(),
 | 
					 | 
				
			||||||
		cell24(),
 | 
					 | 
				
			||||||
		cell600(),
 | 
					 | 
				
			||||||
	 	cell120_inscribed(),
 | 
					 | 
				
			||||||
	 	cell120_layered()
 | 
					 | 
				
			||||||
	 	];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// code for generating the 120-cell labels
 | 
					//testbed for playing with stuff in node repl
 | 
				
			||||||
// has some overlap with permute - FIXME
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const THREE = require('three');
 | 
					const THREE =require('three');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function pandita(a) {
 | 
					function pandita(a) {
 | 
				
			||||||
	const n = a.length;
 | 
						const n = a.length;
 | 
				
			||||||
@ -134,7 +133,7 @@ function dist2(n1, n2) {
 | 
				
			|||||||
	return (n1.x - n2.x) ** 2 + (n1.y - n2.y) ** 2 + (n1.z - n2.z) ** 2 + (n1.w - n2.w) ** 2;
 | 
						return (n1.x - n2.x) ** 2 + (n1.y - n2.y) ** 2 + (n1.z - n2.z) ** 2 + (n1.w - n2.w) ** 2;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function auto_detect_edges(nodes, neighbours, debug=false) {
 | 
					function auto_detect_edges(nodes, neighbours, debug=false) {
 | 
				
			||||||
	const seen = {};
 | 
						const seen = {};
 | 
				
			||||||
	const nnodes = nodes.length;
 | 
						const nnodes = nodes.length;
 | 
				
			||||||
	const links = [];
 | 
						const links = [];
 | 
				
			||||||
@ -169,7 +168,7 @@ export function auto_detect_edges(nodes, neighbours, debug=false) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export 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);   
 | 
				
			||||||
	const phi2 = phi * phi;    
 | 
						const phi2 = phi * phi;    
 | 
				
			||||||
@ -231,7 +230,7 @@ function fingerprint(ids) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function auto_120cell_faces(links) {
 | 
					function auto_120cell_faces(links) {
 | 
				
			||||||
	const faces = [];
 | 
						const faces = [];
 | 
				
			||||||
	const seen = {};
 | 
						const seen = {};
 | 
				
			||||||
	let id = 1;
 | 
						let id = 1;
 | 
				
			||||||
@ -487,7 +486,7 @@ function colour_next_dodeca_maybe(nodes, links, faces, colours, dd, nextf, nextd
 | 
				
			|||||||
	const nextvs = dodecahedron_vertices(nextdd);
 | 
						const nextvs = dodecahedron_vertices(nextdd);
 | 
				
			||||||
	// get the initial colour permutations from the existing labels;
 | 
						// get the initial colour permutations from the existing labels;
 | 
				
			||||||
	const p = [];
 | 
						const p = [];
 | 
				
			||||||
	for( let i = 0; i < 5; i ++ ) {
 | 
						for( i = 0; i < 5; i ++ ) {
 | 
				
			||||||
		p[i] = colours[nextvs[i]];
 | 
							p[i] = colours[nextvs[i]];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	const nlabels = colour_dodecahedron_from_face(nextdd, p);
 | 
						const nlabels = colour_dodecahedron_from_face(nextdd, p);
 | 
				
			||||||
@ -530,33 +529,6 @@ function meridian(nodes, links, faces, startf, startn, dir=11, max=10) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function meridian_bump(nodes, links, faces, startf, startn, bumpdir=6) {
 | 
					 | 
				
			||||||
	const o =  face_plus_to_dodecahedron(faces, startf, startn);
 | 
					 | 
				
			||||||
	const dir = 11;
 | 
					 | 
				
			||||||
	const max = 10;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const colours = colour_dodecahedron_from_face(o, [ 1, 2, 3, 4, 5 ] );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const dds = follow_meridian(nodes, links, faces, colours, o, dir, max);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const dd4 = dds[4];
 | 
					 | 
				
			||||||
	const nextf = dd4[bumpdir];
 | 
					 | 
				
			||||||
	const bump = follow_face_to_dodeca(faces, dd4, nextf);
 | 
					 | 
				
			||||||
	const ncolours = colour_next_dodeca_maybe(nodes, links, faces, colours, dd4, nextf, bump);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	add_colours(colours, ncolours);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const labels = { 1: [], 2:[], 3:[], 4:[], 5:[] };
 | 
					 | 
				
			||||||
	for( const vstr in colours ) {
 | 
					 | 
				
			||||||
		labels[colours[vstr]].push(Number(vstr));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return { dodecahedra: dds, labels: labels };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function all_meridians(nodes, links, faces, startf, startn) {
 | 
					function all_meridians(nodes, links, faces, startf, startn) {
 | 
				
			||||||
	const o =  face_plus_to_dodecahedron(faces, startf, startn);
 | 
						const o =  face_plus_to_dodecahedron(faces, startf, startn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -696,9 +668,8 @@ function arctic(nodes, links, faces, startf, startn, max) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// this is the final one that works for the whole 120-cell
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function label_120cell(nodes, links, faces, startf, startn) {
 | 
					function arctic_two(nodes, links, faces, startf, startn) {
 | 
				
			||||||
	const pole = face_plus_to_dodecahedron(faces, startf, startn);
 | 
						const pole = face_plus_to_dodecahedron(faces, startf, startn);
 | 
				
			||||||
	const dds = [ pole ];
 | 
						const dds = [ pole ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -717,6 +688,10 @@ export function label_120cell(nodes, links, faces, startf, startn) {
 | 
				
			|||||||
		seen[dd_fingerprint(nextdd)] = true;
 | 
							seen[dd_fingerprint(nextdd)] = true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// go around all of the arctic circle and grow all faces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 1, 12, 20, 12, 30 = 75
 | 
				
			||||||
 | 
					    // 0  1   13, 33, 45
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for( const a of dds.slice(1, 13) ) {
 | 
						for( const a of dds.slice(1, 13) ) {
 | 
				
			||||||
		for( const i of [ 6, 7, 8, 9, 10 ] ) {
 | 
							for( const i of [ 6, 7, 8, 9, 10 ] ) {
 | 
				
			||||||
@ -747,8 +722,6 @@ export function label_120cell(nodes, links, faces, startf, startn) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// the 30 equatorials?
 | 
						// the 30 equatorials?
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for( const a of dds.slice(13, 46) ) {
 | 
						for( const a of dds.slice(13, 46) ) {
 | 
				
			||||||
		for( const i of [ 6, 7, 8, 9, 10 ] ) {
 | 
							for( const i of [ 6, 7, 8, 9, 10 ] ) {
 | 
				
			||||||
			const [ nextdd, ncolours ] = follow_and_colour(
 | 
								const [ nextdd, ncolours ] = follow_and_colour(
 | 
				
			||||||
@ -777,10 +750,7 @@ export function label_120cell(nodes, links, faces, startf, startn) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// this should get the rest or explode!
 | 
						// this should get the rest or explode!
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for( const a of dds ) {
 | 
						for( const a of dds ) {
 | 
				
			||||||
		for( const i of [ 6, 7, 8, 9, 10 ] ) {
 | 
							for( const i of [ 6, 7, 8, 9, 10 ] ) {
 | 
				
			||||||
			const [ nextdd, ncolours ] = follow_and_colour(
 | 
								const [ nextdd, ncolours ] = follow_and_colour(
 | 
				
			||||||
@ -808,124 +778,6 @@ export function label_120cell(nodes, links, faces, startf, startn) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function cell120_layers(nodes, links, faces, startf, startn, max_layer) {
 | 
					 | 
				
			||||||
	const pole = face_plus_to_dodecahedron(faces, startf, startn);
 | 
					 | 
				
			||||||
	const dds = [ pole ];
 | 
					 | 
				
			||||||
	const dd_families = { "0": [ pole ] }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const seen = {};
 | 
					 | 
				
			||||||
	seen[dd_fingerprint(pole)] = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const colours = colour_dodecahedron_from_face(dds[0], [ 1, 2, 3, 4, 5 ] );
 | 
					 | 
				
			||||||
	const vs = dodecahedron_vertices(dds[0]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// arctic
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if( max_layer > 0 ) {
 | 
					 | 
				
			||||||
		dd_families["1"] = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for( const face of pole ) {
 | 
					 | 
				
			||||||
			const [ nextdd, ncolours ] = follow_and_colour(
 | 
					 | 
				
			||||||
				nodes, links, faces, colours, pole, face
 | 
					 | 
				
			||||||
			);
 | 
					 | 
				
			||||||
				add_colours(colours, ncolours);
 | 
					 | 
				
			||||||
			dds.push(nextdd);
 | 
					 | 
				
			||||||
			dd_families["1"].push(nextdd);
 | 
					 | 
				
			||||||
			seen[dd_fingerprint(nextdd)] = true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// subarctic - interstitial
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if( max_layer > 1 ) {
 | 
					 | 
				
			||||||
		dd_families["2"] = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for( const a of dd_families["1"] ) {
 | 
					 | 
				
			||||||
			for( const i of [ 6, 7, 8, 9, 10 ] ) {
 | 
					 | 
				
			||||||
				const [ nextdd, ncolours ] = follow_and_colour(
 | 
					 | 
				
			||||||
					nodes, links, faces, colours, a, a[i]
 | 
					 | 
				
			||||||
				);
 | 
					 | 
				
			||||||
				const fp = dd_fingerprint(nextdd);
 | 
					 | 
				
			||||||
				if( !(fp in seen) ) {
 | 
					 | 
				
			||||||
					add_colours(colours, ncolours);
 | 
					 | 
				
			||||||
					dds.push(nextdd);
 | 
					 | 
				
			||||||
					dd_families["2"].push(nextdd);
 | 
					 | 
				
			||||||
					seen[fp] = true;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// tropic of cancer
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if( max_layer > 2 ) {
 | 
					 | 
				
			||||||
		dd_families["3"] = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for( const a of dd_families["1"] ) {
 | 
					 | 
				
			||||||
			const [ nextdd, ncolours ] = follow_and_colour(
 | 
					 | 
				
			||||||
				nodes, links, faces, colours, a, a[11]
 | 
					 | 
				
			||||||
			);
 | 
					 | 
				
			||||||
			const fp = dd_fingerprint(nextdd);
 | 
					 | 
				
			||||||
			if( !(fp in seen) ) {
 | 
					 | 
				
			||||||
				add_colours(colours, ncolours);
 | 
					 | 
				
			||||||
				dds.push(nextdd);
 | 
					 | 
				
			||||||
				dd_families["3"].push(nextdd);
 | 
					 | 
				
			||||||
				seen[fp] = true;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if( max_layer > 3 ) {
 | 
					 | 
				
			||||||
		// equator
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		dd_families["4"] = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for( const a of dds.slice(13, 46) ) {
 | 
					 | 
				
			||||||
			for( const i of [ 6, 7, 8, 9, 10 ] ) {
 | 
					 | 
				
			||||||
				const [ nextdd, ncolours ] = follow_and_colour(
 | 
					 | 
				
			||||||
					nodes, links, faces, colours, a, a[i]
 | 
					 | 
				
			||||||
				);
 | 
					 | 
				
			||||||
				const fp = dd_fingerprint(nextdd);
 | 
					 | 
				
			||||||
				if( !(fp in seen) ) {
 | 
					 | 
				
			||||||
					add_colours(colours, ncolours);
 | 
					 | 
				
			||||||
					dd_families["4"].push(nextdd);
 | 
					 | 
				
			||||||
					dds.push(nextdd);
 | 
					 | 
				
			||||||
					seen[fp] = true;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if( max_layer > 4 ) {
 | 
					 | 
				
			||||||
		dd_families["5"] = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for( const a of dd_families["4"] ) {
 | 
					 | 
				
			||||||
			for( const i of [ 6, 7, 8, 9, 10 ] ) {
 | 
					 | 
				
			||||||
				const [ nextdd, ncolours ] = follow_and_colour(
 | 
					 | 
				
			||||||
					nodes, links, faces, colours, a, a[i]
 | 
					 | 
				
			||||||
				);
 | 
					 | 
				
			||||||
				const fp = dd_fingerprint(nextdd);
 | 
					 | 
				
			||||||
				if( !(fp in seen) ) {
 | 
					 | 
				
			||||||
					add_colours(colours, ncolours);
 | 
					 | 
				
			||||||
					dds.push(nextdd);
 | 
					 | 
				
			||||||
					dd_families["5"].push(nextdd);
 | 
					 | 
				
			||||||
					seen[fp] = true;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const labels = { 1: [], 2:[], 3:[], 4:[], 5:[] };
 | 
					 | 
				
			||||||
	for( const vstr in colours ) {
 | 
					 | 
				
			||||||
		labels[colours[vstr]].push(Number(vstr));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return { dodecahedra: dds, labels: labels, families: dd_families };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// for a face, pick an edge, and then find the other two faces which
 | 
					// for a face, pick an edge, and then find the other two faces which
 | 
				
			||||||
// share this edge. These can be used as the starting points for the
 | 
					// share this edge. These can be used as the starting points for the
 | 
				
			||||||
// first face's two dodecahedra 
 | 
					// first face's two dodecahedra 
 | 
				
			||||||
@ -963,6 +815,7 @@ function make_120cell_cells(faces) {
 | 
				
			|||||||
		for( const dd of dds ) {
 | 
							for( const dd of dds ) {
 | 
				
			||||||
			const fp = dd_fingerprint(dd);
 | 
								const fp = dd_fingerprint(dd);
 | 
				
			||||||
			if( ! (fp in seen) ) {
 | 
								if( ! (fp in seen) ) {
 | 
				
			||||||
 | 
									//console.log(`added dodeca ${fp}`);
 | 
				
			||||||
				const d = {
 | 
									const d = {
 | 
				
			||||||
					id: i,
 | 
										id: i,
 | 
				
			||||||
					faces: dd,
 | 
										faces: dd,
 | 
				
			||||||
@ -1042,7 +895,7 @@ function meridian_label_120cell(nodes) {
 | 
				
			|||||||
		//label_nodes(nodes, [313], 6);
 | 
							//label_nodes(nodes, [313], 6);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1
 | 
					
 | 
				
			||||||
function check_120cell_nodes(nodes) {
 | 
					function check_120cell_nodes(nodes) {
 | 
				
			||||||
	nodes.map((n) => {
 | 
						nodes.map((n) => {
 | 
				
			||||||
		const vs = find_adjacent_labels(nodes, links, n.id);
 | 
							const vs = find_adjacent_labels(nodes, links, n.id);
 | 
				
			||||||
@ -1074,120 +927,9 @@ function make_dodecahedron_vertices() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// this one does the coherent indexing / partition into 600-cells
 | 
					// const nodes = make_120cell_vertices();
 | 
				
			||||||
 | 
					// const links = auto_detect_edges(nodes, 4);
 | 
				
			||||||
export function make_labelled_120cell() {
 | 
					// const faces = auto_120cell_faces(links);
 | 
				
			||||||
	const nodes = make_120cell_vertices();
 | 
					 | 
				
			||||||
	const links = auto_detect_edges(nodes, 4);
 | 
					 | 
				
			||||||
	const faces = auto_120cell_faces(links);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const labelled = label_120cell(nodes, links, faces, faces[0], 341);
 | 
					 | 
				
			||||||
	return labelled;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// calculate the w-distance of a dodecahedron's centroid
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function dd_w_distance(nodes, dd) {
 | 
					 | 
				
			||||||
	const vertices = new Set();
 | 
					 | 
				
			||||||
	dd.map((f) => f.nodes.map((n) => vertices.add(n)));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	let w = 0;
 | 
					 | 
				
			||||||
	for( const nid of vertices ) {
 | 
					 | 
				
			||||||
		const node = node_by_id(nodes, nid);
 | 
					 | 
				
			||||||
		w += node.w;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return w / 20;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function sort_dds_w(nodes, dds) {
 | 
					 | 
				
			||||||
	dds.sort((a, b) => {
 | 
					 | 
				
			||||||
		return dd_w_distance(nodes, a) - dd_w_distance(nodes, b)
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function find_antipode_dd(nodes, links, dd) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// notes because I'm too sick to continue working on this today
 | 
					 | 
				
			||||||
// the vertices which aren't counted by the layers are showing
 | 
					 | 
				
			||||||
// up in the visualisation because they are labelled "0" by default -
 | 
					 | 
				
			||||||
// for this to work better there needs to be a value which is never
 | 
					 | 
				
			||||||
// displayed.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// in the current layer algorithm, layer '5' (the one after the equator)
 | 
					 | 
				
			||||||
// is too greedy 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function make_layered_120cell(max_layer) {
 | 
					 | 
				
			||||||
	const nodes = make_120cell_vertices();
 | 
					 | 
				
			||||||
	const links = auto_detect_edges(nodes, 4);
 | 
					 | 
				
			||||||
	const faces = auto_120cell_faces(links);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const labelled = label_120cell(nodes, links, faces, faces[628], 250, max_layer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// get layers from sorted w-distance order
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const dds = labelled.dodecahedra;
 | 
					 | 
				
			||||||
	dds.sort((a, b) => dd_w_distance(nodes, b) - dd_w_distance(nodes, a));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const LAYERS = [
 | 
					 | 
				
			||||||
		[ "0", 1 ],
 | 
					 | 
				
			||||||
		[ "1", 12 ],
 | 
					 | 
				
			||||||
		[ "2", 20 ],
 | 
					 | 
				
			||||||
		[ "3", 12 ],
 | 
					 | 
				
			||||||
		[ "4", 30 ],
 | 
					 | 
				
			||||||
		[ "5", 12 ],
 | 
					 | 
				
			||||||
		[ "6", 20 ],
 | 
					 | 
				
			||||||
		[ "7", 12 ],
 | 
					 | 
				
			||||||
		[ "8", 1]
 | 
					 | 
				
			||||||
	];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const layer_dds = labelled["families"];
 | 
					 | 
				
			||||||
	const vertices_layers = {};
 | 
					 | 
				
			||||||
	const seen = {};
 | 
					 | 
				
			||||||
	let i = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for( const layer of LAYERS ) {
 | 
					 | 
				
			||||||
		const label = layer[0];
 | 
					 | 
				
			||||||
		const n = layer[1];
 | 
					 | 
				
			||||||
		vertices_layers[label] = [];
 | 
					 | 
				
			||||||
		console.log(`Layer ${label} starting at ${i}`);
 | 
					 | 
				
			||||||
		for( const dd of dds.slice(i, i + n) ) {
 | 
					 | 
				
			||||||
			console.log(dd_w_distance(nodes, dd));
 | 
					 | 
				
			||||||
			for( const face of dd ) {
 | 
					 | 
				
			||||||
				for( const n of face.nodes ) {
 | 
					 | 
				
			||||||
					if( !seen[n] ) {
 | 
					 | 
				
			||||||
						vertices_layers[label].push(n);
 | 
					 | 
				
			||||||
						seen[n] = true;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		i += n;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return JSON.stringify(vertices_layers);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export function make_meridians(bumpdir) {
 | 
					 | 
				
			||||||
	const nodes = make_120cell_vertices();
 | 
					 | 
				
			||||||
	const links = auto_detect_edges(nodes, 4);
 | 
					 | 
				
			||||||
	const faces = auto_120cell_faces(links);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	const mbs ={}
 | 
					 | 
				
			||||||
	for( const bumpdir of [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] ) {
 | 
					 | 
				
			||||||
		mbs[bumpdir] = meridian_bump(nodes, links, faces, faces[0], 341, bumpdir)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return mbs;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    // 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// console.log("Calculating 120-cell colours")
 | 
					// console.log("Calculating 120-cell colours")
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user