-
Notifications
You must be signed in to change notification settings - Fork 0
/
kleinohedron.js
297 lines (269 loc) · 34 KB
/
kleinohedron.js
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
"use strict";
const KLEINOHEDRON_POINTS = [[1.198880187289056, 0, 0.6612969858348382], [1.198880187289056, -0.5170228027868913, 0.41231192666794103], [1.198880187289056, -0.6447168897320918, -0.14715242291046376], [1.198880187289056, -0.2869260088811906, -0.5958079966748963], [1.198880187289056, 0.28692600888119035, -0.5958079966748964], [1.198880187289056, 0.6447168897320918, -0.14715242291046401], [1.198880187289056, 0.5170228027868915, 0.41231192666794086], [2.529536805958039, 1.4486657014001736, 1.8165693320881382], [2.8581818503209298, 1.1617396925189833, 2.412377328763035], [2.52953680595804, 0.5170228027868915, 2.2652249058525715], [1.7910780944118034, 1.1102230246251565e-16, 1.4859208391707202], [1.7910780944118025, 1.1617396925189827, 0.9264564895923144], [2.52953680595804, -1.4486657014001731, 1.8165693320881395], [1.7910780944118034, -1.1617396925189831, 0.9264564895923155], [2.8581818503209298, -1.1617396925189822, 2.4123773287630357], [2.529536805958039, -0.5170228027868902, 2.2652249058525715], [2.529536805958039, -2.0933825911322645, 1.0081199233428382], [2.8581818503209298, -2.610405393919156, 0.5958079966748971], [1.7910780944118034, -1.4486657014001738, -0.33064849291741893], [2.52953680595804, -2.3234793850379662, 6.661338147750939e-16], [2.529536805958039, -2.093382591132266, -1.008119923342836], [2.8581818503209298, -2.093382591132266, -1.6694169091776745], [1.7910780944118034, -0.6447168897320923, -1.3387684162602564], [2.52953680595804, -1.4486657014001743, -1.8165693320881389], [2.8581818503209298, -1.1102230246251565e-15, -2.677536832520513], [2.52953680595804, 0.5170228027868905, -2.2652249058525724], [1.7910780944118034, 0.6447168897320915, -1.3387684162602569], [2.529536805958039, -0.5170228027868927, -2.2652249058525715], [2.8581818503209298, 2.0933825911322645, -1.6694169091776767], [2.529536805958039, 1.4486657014001725, -1.8165693320881404], [2.52953680595804, 2.0933825911322654, -1.0081199233428384], [1.7910780944118034, 1.448665701400174, -0.3306484929174197], [2.8581818503209298, 2.6104053939191574, 0.5958079966748948], [2.52953680595804, 2.0933825911322663, 1.0081199233428366], [2.529536805958039, 2.3234793850379662, -1.5543122344752192e-15], [7.917255462237005, 4.416861976170232, 6.49417156670374], [6.586598843568021, 4.05907109531933, 5.089914161283542], [7.917255462237009, 2.3234793850379676, 7.50229149004658], [6.5865988435680265, 1.4486657014001747, 6.347019143793282], [4.188838468989913, 2.7380994808643573, 3.0081853254379296], [5.519495087658895, 4.059071095319329, 3.6039933221128235], [4.188838468989915, 0.6447168897320924, 4.016305248780769], [4.18883846898991, 3.5420482925324364, 2.000065402095089], [4.927297180536151, 2.093382591132266, 4.3469537416981865], [7.17879675069077, 2.610405393919158, 6.612178647550756], [5.519495087658899, -0.2869260088811896, 5.420562654200967], [5.519495087658898, 0.2869260088811916, 5.420562654200966], [5.5194950876588935, 4.41686197617023, 3.1553377483483898], [4.188838468989915, -0.6447168897320914, 4.016305248780769], [7.178796750690772, 3.54204829253244, 6.163523073786324], [4.188838468989915, -2.738099480864357, 3.0081853254379327], [6.5865988435680265, -4.059071095319329, 5.0899141612835495], [7.17879675069077, -3.542048292532435, 6.163523073786327], [7.917255462237009, -4.416861976170227, 6.494171566703746], [7.917255462237005, -2.3234793850379605, 7.50229149004658], [6.586598843568021, -1.4486657014001687, 6.347019143793279], [7.178796750690772, -2.6104053939191534, 6.612178647550759], [4.927297180536151, -2.093382591132263, 4.346953741698188], [5.519495087658898, -4.059071095319328, 3.603993322112828], [4.188838468989915, -3.5420482925324386, 2.000065402095095], [5.519495087658899, -4.41686197617023, 3.155337748348396], [4.188838468989915, -4.0590710953193305, -0.2651595037574761], [5.519495087658898, -5.348504874783512, -0.9264564895923133], [4.188838468989915, -3.7721450864381403, -1.522264486267211], [5.519495087658899, -5.220810787838312, -1.4859208391707186], [7.178796750690772, -6.797170576183684, 2.0817288358456185], [7.917255462237005, -7.314193378970572, 2.8610329025274703], [6.5865988435680265, -6.510244567302497, 2.220446049250313e-15], [4.927297180536151, -4.70378798505142, 1.0736089125027815], [7.17879675069077, -7.027267370089385, 1.0736089125027823], [7.917255462237009, -7.831216181757466, 0.5958079966748997], [6.586598843568021, -5.865527677570399, 2.824689255430979], [4.188838468989915, -1.161739692518984, -3.8982981679337563], [7.17879675069077, -5.220810787838314, -4.824754657526067], [7.917255462237009, -5.348504874783514, -5.751211147118382], [4.927297180536151, -3.7721450864381407, -3.008185325437929], [6.5865988435680265, -4.059071095319332, -5.089914161283547], [4.188838468989915, -2.323479385037967, -3.3388338183553508], [5.519495087658898, -2.610405393919158, -4.759265668366127], [7.917255462237005, -6.797170576183685, -3.9346418150302402], [6.586598843568021, -5.8655276775704035, -2.824689255430971], [5.519495087658899, -2.093382591132266, -5.008250727533024], [7.178796750690772, -5.865527677570405, -4.016305248780765], [5.519495087658899, 2.6104053939191543, -4.759265668366129], [5.519495087658898, 2.0933825911322628, -5.008250727533026], [7.17879675069077, 0.5170228027868871, -7.089979563378641], [7.917255462237009, 1.1617396925189785, -7.767450993804059], [6.5865988435680265, 1.4486657014001705, -6.347019143793284], [4.188838468989915, 1.1617396925189822, -3.8982981679337567], [4.927297180536151, -3.1086244689504383e-15, -4.8247546575260705], [6.586598843568021, -1.4486657014001771, -6.347019143793279], [7.178796750690772, -0.517022802786895, -7.089979563378641], [7.917255462237005, -1.1617396925189878, -7.767450993804055], [4.188838468989915, 2.323479385037966, -3.3388338183553525], [4.188838468989915, 3.77214508643814, -1.5222644862672134], [4.927297180536151, 3.772145086438137, -3.008185325437934], [7.178796750690772, 5.220810787838309, -4.824754657526073], [6.5865988435680265, 5.865527677570404, -2.82468925543098], [5.519495087658899, 5.3485048747835116, -0.9264564895923173], [5.519495087658898, 5.220810787838311, -1.4859208391707222], [6.586598843568021, 4.059071095319324, -5.0899141612835495], [7.917255462237005, 5.348504874783506, -5.751211147118387], [7.17879675069077, 5.865527677570401, -4.016305248780772], [7.917255462237009, 6.7971705761836825, -3.9346418150302496], [4.188838468989915, 4.059071095319331, -0.26515950375747854], [4.927297180536151, 4.703787985051422, 1.0736089125027755], [6.586598843568021, 6.510244567302495, -5.773159728050814e-15], [7.917255462237005, 7.8312161817574655, 0.5958079966748895], [7.17879675069077, 6.797170576183687, 2.081728835845611], [7.917255462237009, 7.314193378970578, 2.861032902527463], [7.178796750690772, 7.027267370089388, 1.0736089125027748], [6.5865988435680265, 5.865527677570408, 2.8246892554309735], [13.897172025638726, -2.0933825911322597, 13.702158210929401], [10.907213743937874, -2.093382591132263, 10.657629238394984], [10.90721374393787, 2.0933825911322677, 10.657629238394978], [13.304974118515979, -1.4486657014001691, 13.188013648005025], [13.897172025638719, 9.40757597010284, 10.179828322567086], [13.30497411851597, 9.407575970102839, 9.355204469231204], [14.635630737184947, 11.731055355140802, 8.693907483396357], [16.887130307339568, 13.179721056540973, 10.510476815484498], [12.23787036260685, 5.865527677570406, 10.693972885491466], [13.89717202563872, 7.83121618175747, 11.43693330507682], [20.02334939346392, 11.731055355140805, 16.19619897344294], [19.28489068191769, 9.637672764008546, 16.67399988927083], [16.294932400216833, 6.797170576183688, 14.775767123432171], [16.29493240021683, 7.314193378970577, 14.526782064265273], [14.635630737184957, 11.086338465408716, 9.502356892141666], [9.57655712526888, 7.027267370089387, 6.428682577543799], [10.907213743937865, 7.027267370089388, 8.28159555672843], [17.6255890188858, 11.086338465408712, 13.665814563832889], [9.576557125268875, 7.831216181757465, 5.420562654200957], [21.682651056495782, 13.179721056540975, 17.18814445219519], [20.615547300586663, 11.214032552353915, 17.269807885945717], [23.013307675164775, 12.017981364021997, 19.600521780958232], [10.90721374393785, 9.637672764008533, 5.008250727533008], [13.897172025638726, 4.059071095319333, 13.253502637164964], [19.28489068191768, 7.027267370089389, 17.93110487178056], [23.013307675164775, 7.831216181757471, 21.616761627643903], [13.304974118515979, 1.4486657014001767, 13.188013648005024], [13.897172025638724, 2.0933825911322685, 13.702158210929397], [20.023349393463924, 5.348504874783515, 19.26987328804082], [21.6826510564958, 5.2208107878383165, 21.020953630969018], [20.615547300586673, 6.5102445673024985, 19.535032791798297], [13.304974118515965, 11.21403255235391, 7.089979563378628], [13.897172025638707, 12.017981364021985, 6.906483493371668], [9.576557125268886, 0.6447168897320932, 9.502356892141679], [9.576557125268888, -0.6447168897320883, 9.50235689214168], [12.237870362606852, 4.703787985051424, 11.253437235069875], [14.635630737184957, 0.5170228027868955, 14.59227105342522], [16.88713030733958, 6.217248937900877e-15, 16.857495959277788], [14.635630737184963, -0.5170228027868871, 14.592271053425224], [17.625589018885822, 3.772145086438144, 17.188144452195214], [16.88713030733958, -13.179721056540972, 10.510476815484516], [14.635630737184963, -11.731055355140805, 8.693907483396378], [9.576557125268888, -7.831216181757469, 5.420562654200972], [12.23787036260685, -4.703787985051416, 11.253437235069875], [16.29493240021683, -6.797170576183678, 14.775767123432175], [20.02334939346392, -5.3485048747835, 19.26987328804082], [21.682651056495782, -5.220810787838294, 21.02095363096901], [16.294932400216833, -7.314193378970568, 14.52678206426528], [13.304974118515979, -11.214032552353913, 7.0899795633786455], [19.28489068191768, -9.637672764008528, 16.67399988927083], [23.013307675164775, -12.017981364021981, 19.60052178095824], [12.237870362606852, -5.865527677570402, 10.693972885491473], [20.615547300586673, -11.214032552353906, 17.269807885945735], [13.897172025638726, -7.831216181757462, 11.436933305076831], [10.90721374393787, -7.027267370089387, 8.281595556728437], [17.625589018885822, -11.086338465408712, 13.665814563832914], [20.023349393463924, -11.731055355140796, 16.196198973442954], [21.6826510564958, -13.17972105654097, 17.188144452195214], [10.907213743937874, -9.637672764008547, 5.0082507275330315], [13.304974118515979, -9.407575970102837, 9.355204469231214], [13.897172025638724, -9.407575970102837, 10.179828322567095], [19.28489068191769, -7.027267370089378, 17.931104871780573], [13.89717202563872, -4.059071095319322, 13.253502637164964], [20.615547300586663, -6.510244567302481, 19.535032791798294], [13.897172025638726, -12.017981364021995, 6.9064834933716925], [9.576557125268886, -7.027267370089387, 6.428682577543807], [23.013307675164775, -7.831216181757454, 21.61676162764391], [14.635630737184957, -11.08633846540871, 9.502356892141679], [17.6255890188858, -3.772145086438126, 17.1881444521952], [9.576557125268886, -9.407575970102844, -1.485920839170718], [13.304974118515979, -13.179721056540979, -1.522264486267206], [13.897172025638726, -12.892795047659796, -5.089914161283541], [10.907213743937874, -9.924598772889741, -4.412442730858128], [13.304974118515979, -12.535004166808891, -4.346953741698182], [9.576557125268888, -9.120649961221657, -2.7430258216804506], [20.02334939346392, -18.400531844379277, 7.832939982964007], [13.89717202563872, -12.892795047659781, 5.089914161283552], [16.88713030733958, -16.434843340192224, -3.7511457450232815], [14.635630737184963, -14.111363955154264, -3.751145745023287], [13.897172025638726, -13.82443794627307, 1.0081199233428446], [21.6826510564958, -21.655654128030534, 0.412311926667952], [17.625589018885822, -17.596583032711216, -0.14715242291045705], [12.237870362606852, -12.017981364022, 2.0817288358456203], [16.29493240021683, -15.790126450460129, 3.898298167933759], [16.294932400216833, -15.91782053740533, 3.338833818355357], [23.013307675164775, -21.78334821497572, 7.355139067136123], [20.615547300586663, -19.332174742992557, 7.089979563378645], [23.013307675164775, -22.817393820549505, 2.824689255430984], [20.615547300586673, -20.493914435511552, 2.0000654020951014], [19.28489068191768, -19.045248734111368, 2.8610329025274757], [14.635630737184957, -14.341460749059962, -2.7430258216804475], [19.28489068191769, -18.400531844379287, 5.68572215795845], [20.023349393463924, -19.97689163272466, 0.9264564895923222], [12.23787036260685, -11.731055355140805, 3.3388338183553556], [17.6255890188858, -15.790126450460118, 7.767450993804062], [21.682651056495782, -19.689965623843452, 9.024555976313799], [10.90721374393787, -10.856241671503017, -0.33064849291741716], [13.897172025638724, -13.82443794627307, -1.0081199233428322], [10.907213743937874, -2.738099480864363, -10.51047681548452], [13.897172025638726, -4.0590710953193385, -13.253502637164967], [20.615547300586673, -14.341460749059967, -14.77576712343217], [23.013307675164775, -16.434843340192224, -16.078191892595925], [10.90721374393787, -6.510244567302499, -8.693907483396377], [13.897172025638724, -7.831216181757472, -11.436933305076824], [16.29493240021683, -12.892795047659789, -9.91466881880961], [16.294932400216833, -12.53500416680889, -10.36332439257404], [14.635630737184957, -6.7971705761836905, -12.922854144247543], [9.576557125268886, -4.703787985051424, -8.281595556728433], [20.02334939346392, -17.59658303271121, -9.50235689214166], [13.89717202563872, -12.017981364021997, -6.9064834933716766], [17.625589018885822, -10.856241671503025, -13.849310633839863], [19.28489068191769, -15.91782053740534, -10.841125308401924], [12.23787036260685, -9.924598772889736, -7.089979563378637], [21.6826510564958, -13.824437946273079, -16.673999889270828], [13.304974118515979, -4.416861976170237, -12.510542217579607], [12.237870362606852, -9.120649961221657, -8.098099486721479], [20.615547300586663, -17.596583032711205, -10.693972885491451], [17.6255890188858, -15.91782053740533, -7.502291490046565], [21.682651056495782, -19.332174742992564, -9.767516395899131], [16.88713030733958, -7.314193378970582, -15.18807905010011], [14.635630737184963, -5.865527677570409, -13.37150971801198], [13.304974118515979, -7.02726737008939, -11.253437235069867], [20.023349393463924, -13.179721056540982, -15.040926627189647], [9.576557125268888, -3.5420482925324452, -8.84105990630684], [19.28489068191768, -14.11136395515426, -13.106350214254485], [13.897172025638726, -9.407575970102847, -10.179828322567088], [23.013307675164775, -19.332174742992567, -12.445053228419646], [21.6826510564958, 4.416861976170216, -21.204449700975978], [17.625589018885822, 4.0590710953193225, -17.12265546303528], [12.237870362606852, 0.6447168897320879, -12.179893724662193], [10.90721374393787, 2.7380994808643546, -10.51047681548452], [13.897172025638724, 4.0590710953193225, -13.253502637164969], [20.023349393463924, 3.5420482925324297, -19.682185214708767], [13.897172025638726, 2.093382591132256, -13.702158210929401], [16.294932400216833, 0.28692600888118136, -16.261687962602892], [16.29493240021683, -0.28692600888119735, -16.261687962602892], [20.615547300586663, -2.6104053939191676, -20.425145634294115], [23.013307675164775, -2.3234793850379774, -22.87386661015364], [14.635630737184957, 5.8655276775703955, -13.371509718011982], [9.576557125268886, 3.5420482925324355, -8.84105990630684], [17.6255890188858, -4.0590710953193385, -17.122655463035255], [21.682651056495782, -4.416861976170242, -21.20444970097596], [13.304974118515979, 7.027267370089381, -11.253437235069878], [9.576557125268888, 4.703787985051418, -8.28159555672844], [10.907213743937874, 6.510244567302496, -8.693907483396384], [13.897172025638726, 7.831216181757462, -11.436933305076836], [13.89717202563872, -2.093382591132272, -13.702158210929394], [20.615547300586673, 2.6104053939191463, -20.42514563429413], [23.013307675164775, 2.3234793850379543, -22.87386661015364], [14.635630737184963, 6.797170576183681, -12.922854144247554], [16.88713030733958, 7.314193378970566, -15.188079050100118], [19.28489068191768, 1.4486657014001594, -19.204384298880875], [19.28489068191769, -1.4486657014001825, -19.204384298880885], [12.23787036260685, -0.6447168897320976, -12.17989372466219], [13.304974118515979, 4.416861976170223, -12.510542217579609], [20.02334939346392, -3.54204829253245, -19.68218521470876], [12.237870362606852, 9.924598772889734, -7.089979563378648], [16.294932400216833, 12.892795047659778, -9.91466881880962], [13.897172025638726, 12.017981364021992, -6.906483493371695], [9.576557125268886, 9.120649961221652, -2.743025821680458], [17.625589018885822, 15.91782053740534, -7.502291490046593], [21.6826510564958, 19.332174742992564, -9.767516395899163], [10.90721374393787, 9.924598772889738, -4.412442730858135], [13.897172025638724, 12.892795047659789, -5.089914161283554], [16.29493240021683, 12.535004166808879, -10.363324392574052], [13.89717202563872, 9.407575970102831, -10.179828322567097], [14.635630737184963, 14.341460749059966, -2.7430258216804626], [9.576557125268888, 9.407575970102846, -1.4859208391707268], [19.28489068191769, 14.111363955154255, -13.106350214254512], [12.23787036260685, 9.120649961221648, -8.098099486721484], [14.635630737184957, 14.111363955154259, -3.7511457450232992], [20.615547300586663, 14.341460749059944, -14.775767123432178], [23.013307675164775, 16.43484334019221, -16.078191892595942], [17.6255890188858, 10.856241671502996, -13.849310633839861], [21.682651056495782, 13.824437946273049, -16.673999889270835], [10.907213743937874, 10.856241671503023, -0.33064849291742515], [13.304974118515979, 13.17972105654098, -1.52226448626722], [13.304974118515979, 12.535004166808886, -4.3469537416981945], [16.88713030733958, 16.43484334019222, -3.7511457450233], [23.013307675164775, 19.332174742992557, -12.445053228419665], [19.28489068191768, 15.91782053740532, -10.841125308401937], [13.897172025638726, 13.824437946273076, -1.0081199233428473], [20.023349393463924, 17.5965830327112, -9.50235689214168], [20.615547300586673, 17.5965830327112, -10.693972885491476], [20.02334939346392, 13.179721056540965, -15.04092662718966], [20.02334939346392, 19.97689163272466, 0.9264564895922991], [13.89717202563872, 13.824437946273068, 1.0081199233428269], [20.615547300586663, 20.493914435511545, 2.00006540209508], [23.013307675164775, 22.817393820549512, 2.8246892554309593], [21.682651056495782, 21.65565412803052, 0.4123119266679236], [16.29493240021683, 15.917820537405333, 3.33883381835534], [16.294932400216833, 15.790126450460132, 3.898298167933743], [19.28489068191769, 19.04524873411139, 2.8610329025274552], [13.897172025638726, 12.892795047659796, 5.089914161283537], [20.615547300586673, 19.332174742992578, 7.089979563378628], [12.237870362606852, 11.731055355140814, 3.3388338183553463], [19.28489068191768, 18.400531844379287, 5.685722157958425], [12.23787036260685, 12.017981364022, 2.0817288358456096], [17.6255890188858, 17.596583032711198, -0.14715242291047836], [20.023349393463924, 18.40053184437929, 7.83293998296399], [17.625589018885822, 15.790126450460148, 7.767450993804055], [21.6826510564958, 19.689965623843477, 9.024555976313778], [23.013307675164775, 21.78334821497573, 7.355139067136104]];
const KLEINOHEDRON_FACES = [[0, 1, 2, 3, 4, 5, 6], [0, 6, 11, 7, 8, 9, 10], [0, 10, 15, 14, 12, 13, 1], [1, 13, 16, 17, 19, 18, 2], [2, 18, 20, 21, 23, 22, 3], [3, 22, 27, 24, 25, 26, 4], [4, 26, 29, 28, 30, 31, 5], [5, 31, 34, 32, 33, 11, 6], [7, 11, 33, 42, 47, 40, 39], [7, 39, 36, 35, 49, 43, 8], [8, 43, 44, 37, 38, 41, 9], [9, 41, 46, 45, 48, 15, 10], [12, 14, 57, 52, 53, 51, 50], [12, 50, 58, 60, 59, 16, 13], [14, 15, 48, 55, 54, 56, 57], [16, 59, 71, 66, 65, 68, 17], [17, 68, 69, 70, 67, 61, 19], [18, 19, 61, 62, 64, 63, 20], [20, 63, 80, 79, 82, 75, 21], [21, 75, 73, 74, 76, 77, 23], [22, 23, 77, 78, 81, 72, 27], [24, 27, 72, 90, 92, 91, 89], [24, 89, 85, 86, 87, 88, 25], [25, 88, 84, 83, 93, 29, 26], [28, 29, 93, 100, 101, 96, 95], [28, 95, 102, 103, 97, 94, 30], [30, 94, 99, 98, 104, 34, 31], [32, 34, 104, 106, 107, 110, 105], [32, 105, 108, 109, 111, 42, 33], [35, 36, 128, 129, 131, 122, 121], [35, 121, 132, 133, 123, 120, 49], [36, 39, 40, 127, 117, 116, 128], [37, 44, 147, 136, 137, 142, 135], [37, 135, 140, 141, 151, 114, 38], [38, 114, 139, 138, 145, 46, 41], [40, 47, 130, 118, 119, 126, 127], [42, 111, 134, 144, 143, 130, 47], [43, 49, 120, 125, 124, 147, 44], [45, 46, 145, 148, 149, 150, 146], [45, 146, 115, 112, 113, 55, 48], [50, 51, 166, 172, 171, 177, 58], [51, 53, 165, 168, 169, 167, 166], [52, 57, 56, 155, 156, 159, 163], [52, 163, 161, 162, 164, 165, 53], [54, 55, 113, 180, 158, 157, 174], [54, 174, 175, 178, 173, 155, 56], [58, 177, 179, 152, 153, 154, 60], [59, 60, 154, 160, 176, 170, 71], [61, 67, 208, 209, 182, 181, 62], [62, 181, 202, 189, 190, 186, 64], [63, 64, 186, 185, 183, 184, 80], [65, 66, 188, 198, 197, 203, 205], [65, 205, 195, 196, 194, 69, 68], [66, 71, 170, 206, 207, 187, 188], [67, 70, 191, 204, 192, 193, 208], [69, 194, 201, 199, 200, 191, 70], [72, 81, 235, 226, 211, 210, 90], [73, 75, 82, 224, 216, 217, 227], [73, 227, 236, 213, 212, 237, 74], [74, 237, 234, 225, 222, 214, 76], [76, 214, 215, 233, 219, 78, 77], [78, 219, 218, 231, 232, 235, 81], [79, 80, 184, 229, 230, 220, 221], [79, 221, 228, 238, 223, 224, 82], [83, 84, 251, 250, 262, 261, 255], [83, 255, 254, 257, 256, 100, 93], [84, 88, 87, 242, 243, 266, 251], [85, 89, 91, 265, 247, 246, 241], [85, 241, 263, 260, 259, 245, 86], [86, 245, 244, 239, 240, 242, 87], [90, 210, 252, 253, 267, 258, 92], [91, 92, 258, 248, 249, 264, 265], [94, 97, 274, 275, 289, 271, 99], [95, 96, 281, 276, 269, 268, 102], [96, 101, 277, 283, 284, 280, 281], [97, 103, 270, 294, 273, 272, 274], [98, 99, 271, 282, 290, 278, 279], [98, 279, 288, 293, 287, 106, 104], [100, 256, 285, 286, 296, 277, 101], [102, 268, 292, 291, 295, 270, 103], [105, 110, 309, 302, 303, 307, 108], [106, 287, 310, 301, 297, 298, 107], [107, 298, 299, 300, 304, 309, 110], [108, 307, 308, 314, 306, 305, 109], [109, 305, 311, 313, 312, 134, 111]];
const KLEINOHEDRON_NEIGHBORS = [[22, 23, 5, 6, 17, 1, 21], [3, 19, 20, 21, 0, 17, 2], [7, 3, 1, 17, 16, 11, 10], [4, 15, 19, 1, 2, 7, 5], [15, 3, 5, 12, 11, 21, 14], [7, 6, 0, 23, 12, 4, 3], [17, 0, 5, 7, 8, 14, 13], [6, 5, 3, 2, 10, 9, 8], [7, 9, 22, 16, 15, 14, 6], [23, 22, 8, 7, 10, 20, 19], [7, 2, 11, 12, 13, 20, 9], [4, 12, 10, 2, 16, 22, 21], [13, 10, 11, 4, 5, 23, 18], [12, 18, 17, 6, 14, 20, 10], [8, 15, 4, 21, 20, 13, 6], [18, 19, 3, 4, 14, 8, 16], [18, 15, 8, 22, 11, 2, 17], [6, 13, 18, 16, 2, 1, 0], [13, 12, 23, 19, 15, 16, 17], [1, 3, 15, 18, 23, 9, 20], [13, 14, 21, 1, 19, 9, 10], [22, 0, 1, 20, 14, 4, 11], [23, 0, 21, 11, 16, 8, 9], [22, 9, 19, 18, 12, 5, 0]];
function kleinohedron_set(elt, value) {
if (!elt.querySelector('.kleinohedron')) {
const pixels = Math.max(window.screen.availWidth, window.screen.availHeight) * window.devicePixelRatio * 0.3;
elt.innerHTML = `<canvas class="kleinohedron" width="${pixels}" height="${pixels}"></canvas>`;
kleinohedron_update_faces(elt, value);
} else {
const current_value = parseInt(elt.querySelector('.kleinohedron').getAttribute('value'));
if (value === current_value) {
// do nothing
} else if (value === (current_value + 1) % 168) {
kleinohedron_animate(elt, value);
} else {
kleinohedron_update_faces(elt, value);
}
}
}
function kleinohedron_update_faces(elt, value) {
const [numbers, offsets] = kleinohedron_calc_orientation(value);
elt.querySelector('.kleinohedron').setAttribute('value', value);
klienohedron_draw(elt, numbers, offsets, value, 0, [0, 0, 0]);
}
function kleinohedron_calc_orientation(value) {
const numbers = Array(KLEINOHEDRON_FACES.length).fill(-1);
const offsets = Array(KLEINOHEDRON_FACES.length).fill(0);
// the i-th neighbor is between vertices (i+offset) and (i+offset+1) of the face
// the edge between vertices 0,1 says "sun", between vertices 1,2 says "mon" etc
const visited = Array(KLEINOHEDRON_FACES.length).fill(false);
const queue = [];
numbers[0] = value % 24;
offsets[0] = (10 - Math.trunc(value / 24)) % 7;
visited[0] = true;
queue.push(0);
while (queue.length) {
const known = queue.pop();
const offset = offsets[known];
for (let i = 0; i < 7; i++) {
const u = KLEINOHEDRON_FACES[known][(i + offset) % 7],
v = KLEINOHEDRON_FACES[known][(i + offset + 1) % 7];
for (let other = 0; other < KLEINOHEDRON_FACES.length; other++) {
if (visited[other])
continue;
for (let j = 0; j < 7; j++) {
if ((KLEINOHEDRON_FACES[other][j] == v) && (KLEINOHEDRON_FACES[other][(j+1)%7] == u)) {
const other_hour = KLEINOHEDRON_NEIGHBORS[numbers[known]][i];
numbers[other] = other_hour;
offsets[other] = (j + 7 - KLEINOHEDRON_NEIGHBORS[other_hour].indexOf(numbers[known])) % 7;
visited[other] = true;
queue.push(other);
}
}
}
}
}
return [numbers, offsets];
}
function klienohedron_draw(elt, numbers, offsets, value, frac, transformation) {
const size = elt.querySelector('.kleinohedron').width;
const half_size = 0.5 * size;
const matrix = exp_ISO_2_1(transformation.map(function(coef) {return frac * coef;}));
const DAYS_OF_THE_WEEK = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
function project_point(pt) {
const [w, x, y] = apply_matrix(matrix, KLEINOHEDRON_POINTS[pt]);
return [
half_size + half_size * x / w,
half_size - half_size * y / w
];
};
const buffer = document.createElement('canvas');
buffer.width = size;
buffer.height = size;
const ctx = buffer.getContext('2d');
ctx.beginPath();
ctx.strokeStyle = '#e0e0e0';
ctx.lineWidth = 2;
ctx.font = `${Math.trunc(half_size)}px Verdana`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
for (let i = 0; i < KLEINOHEDRON_FACES.length; i++) {
const vertices = KLEINOHEDRON_FACES[i].map(project_point);
ctx.moveTo(vertices[0][0], vertices[0][1]);
for (let j = 0; j < vertices.length; j++) {
const vertex = vertices[(j+1) % vertices.length];
ctx.lineTo(vertex[0], vertex[1]);
}
const center_x = vertices.reduce(function(tot, pt) {return tot + pt[0]}, 0) / 7,
center_y = vertices.reduce(function(tot, pt) {return tot + pt[1]}, 0) / 7;
const r = Math.sqrt(Math.pow(center_x / half_size - 1, 2) + Math.pow(center_y / half_size - 1, 2));
if (r < 0.97) {
const font_size = 0.11 * size * (1 - 0.42 * r - 0.5 * r * r);
ctx.fillStyle = 'lightgray';
if (numbers[i] === value % 24) {
const brightness = 211 + 44 * Math.sqrt(1 - frac);
ctx.fillStyle = `rgb(${brightness}, ${brightness}, ${brightness})`;
} else if ((frac > 0) && (numbers[i] === (value + 1) % 24)) {
const brightness = 211 + 44 * Math.sqrt(frac);
ctx.fillStyle = `rgb(${brightness}, ${brightness}, ${brightness})`;
}
ctx.save();
ctx.translate(center_x, center_y);
ctx.scale(font_size / half_size, font_size / half_size);
ctx.fillText(numbers[i].toString(), 0, 0);
ctx.restore();
}
const offset = offsets[i];
for (let j = 0; j < 7; j++) {
const [x1, y1] = vertices[(j + offset) % 7],
[x2, y2] = vertices[(j + offset + 1) % 7];
const x = 0.41 * x1 + 0.41 * x2 + 0.18 * center_x,
y = 0.41 * y1 + 0.41 * y2 + 0.18 * center_y;
const r = Math.sqrt(Math.pow(x / half_size - 1, 2) + Math.pow(y / half_size - 1, 2));
if (r < 0.97) {
let font_size = 0.065 * size * (1 - 0.42 * r - 0.5 * r * r);
ctx.fillStyle = 'rgba(211, 211, 211, 0.6)';
if ((numbers[i] === value % 24) && (j === Math.trunc(value / 24))) {
font_size *= 1 + 0.5 * Math.sqrt(1 - frac);
const brightness = 211 + 44 * Math.sqrt(1 - frac);
const alpha = 0.6 + 0.4 * Math.sqrt(1 - frac);
ctx.fillStyle = `rgba(${brightness}, ${brightness}, ${brightness}, ${alpha})`;
} else if ((frac > 0) && (numbers[i] === (value + 1) % 24) && (j === Math.trunc((value + 1) / 24))) {
font_size *= 1 + 0.5 * Math.sqrt(frac);
const brightness = 211 + 44 * Math.sqrt(frac);
const alpha = 0.6 + 0.4 * Math.sqrt(frac);
ctx.fillStyle = `rgba(${brightness}, ${brightness}, ${brightness}, ${alpha})`;
}
ctx.save();
ctx.translate(x, y);
ctx.rotate(Math.atan2(y2 - y1, x2 - x1));
ctx.scale(font_size / half_size, font_size / half_size);
ctx.fillText(DAYS_OF_THE_WEEK[j], 0, 0);
ctx.restore();
}
}
}
ctx.closePath();
ctx.stroke();
const real_ctx = elt.querySelector('.kleinohedron').getContext('2d');
const mask = real_ctx.createRadialGradient(half_size, half_size, 0.85 * half_size, half_size, half_size, 0.985 * half_size);
mask.addColorStop(0, 'black');
mask.addColorStop(1, 'transparent');
real_ctx.fillStyle = mask;
real_ctx.globalCompositeOperation = 'copy';
real_ctx.fillRect(0, 0, size, size);
real_ctx.globalCompositeOperation = 'source-in';
real_ctx.drawImage(buffer, 0, 0);
}
function hyperboloid_rotation_matrix(angle) {
const c = Math.cos(angle), s = Math.sin(angle);
return [[1, 0, 0], [0, c, -s], [0, s, c]];
}
function hyperboloid_translation_matrix(distance) {
const c = Math.cosh(distance), s = Math.sinh(distance);
return [[c, s, 0], [s, c, 0], [0, 0, 1]];
}
function multiply_matrices(matrices) {
const multiply_two_matrices = function(mat1, mat2) {
return [0, 1, 2].map(function(i) {
return [0, 1, 2].map(function(j) {
return mat1[i][0] * mat2[0][j] + mat1[i][1] * mat2[1][j] + mat1[i][2] * mat2[2][j];
});
});
};
let matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
for (const mat of matrices) {
matrix = multiply_two_matrices(matrix, mat);
}
return matrix;
}
function apply_matrix(matrix, point) {
return matrix.map(function(row) {
return row[0] * point[0] + row[1] * point[1] + row[2] * point[2];
});
}
function log_ISO_2_1(m) {
let half_inv_k2;
const cosh_sqrt_D = 0.5 * (m[0][0] + m[1][1] + m[2][2] - 1);
if (cosh_sqrt_D > 1 + 1e-9) {
const sqrt_D = Math.acosh(cosh_sqrt_D);
half_inv_k2 = sqrt_D*sqrt_D / (Math.expm1(sqrt_D) + Math.expm1(-sqrt_D));
} else if (cosh_sqrt_D < 1 - 1e-9) {
const i_sqrt_D = Math.acos(Math.max(-1, cosh_sqrt_D));
const haversine_angle = 0.5 * i_sqrt_D;
half_inv_k2 = Math.pow(haversine_angle / Math.sin(haversine_angle), 2);
} else {
half_inv_k2 = 1 - (cosh_sqrt_D - 1) / 6;
}
const twice_k2_a2 = m[0][0] + m[1][1] - m[2][2] - 1,
twice_k2_b2 = m[0][0] - m[1][1] + m[2][2] - 1,
twice_k2_c2 = m[0][0] - m[1][1] - m[2][2] + 1;
let a = Math.sqrt(Math.max(0, half_inv_k2 * twice_k2_a2)),
b = Math.sqrt(Math.max(0, half_inv_k2 * twice_k2_b2)),
c = Math.sqrt(Math.max(0, half_inv_k2 * twice_k2_c2));
const sign_scores = [
m[0][2] + m[1][0] + m[1][2],
m[0][1] + m[2][0] + m[2][1],
m[0][1] - m[2][0] - m[2][1],
-m[0][2] + m[1][0] - m[1][2],
-m[0][1] + m[2][0] - m[2][1],
m[0][2] - m[1][0] - m[1][2],
-m[0][2] - m[1][0] + m[1][2],
-m[0][1] - m[2][0] + m[2][1]
];
const signs = sign_scores.indexOf(Math.max(...sign_scores));
if (signs & 4) a = -a;
if (signs & 2) b = -b;
if (signs & 1) c = -c;
return [a, b, c];
}
function exp_ISO_2_1([a, b, c]) {
const D = a*a + b*b - c*c;
let k1, k2;
if (D > 1e-9) {
const sqrt_D = Math.sqrt(D);
k1 = Math.sinh(sqrt_D) / sqrt_D;
k2 = (Math.cosh(sqrt_D) - 1) / D;
} else if (D < -1e-9) {
const sqrt_D = Math.sqrt(-D);
k1 = Math.sin(sqrt_D) / sqrt_D;
k2 = (Math.cos(sqrt_D) - 1) / D;
} else {
k1 = 1 + D / 6;
k2 = 0.5 + D / 24;
}
return [
[1 + k2 * (a*a + b*b), k1 * a - k2 * b*c, k1 * b + k2 * a*c],
[k1 * a + k2 * b*c, 1 + k2 * (a*a - c*c), k1 * c + k2 * a*b],
[k1 * b - k2 * a*c, -k1 * c + k2 * a*b, 1 + k2 * (b*b - c*c)]
];
}
function kleinohedron_animate(elt, value) {
const current_value = parseInt(elt.querySelector('.kleinohedron').getAttribute('value'));
const [numbers, offsets] = kleinohedron_calc_orientation(current_value);
elt.querySelector('.kleinohedron').setAttribute('value', value);
const TAU = Math.PI * 2;
const HEPTAGON_DISTANCE = 1.090549663507086;
const neighbor_index = Math.trunc(current_value / 24) - KLEINOHEDRON_NEIGHBORS[current_value % 24].indexOf(value % 24);
const new_face_rotation = KLEINOHEDRON_NEIGHBORS[value % 24].indexOf(current_value % 24) + 2 - Math.trunc(value / 24);
const transformation = log_ISO_2_1(multiply_matrices([
hyperboloid_rotation_matrix(TAU * (new_face_rotation - 0.25) / 7),
hyperboloid_translation_matrix(-HEPTAGON_DISTANCE),
hyperboloid_rotation_matrix(TAU * (0.25 + neighbor_index / 7))
]));
let start_ts, previous_ts;
function draw_frame(timestamp) {
if (start_ts === undefined) {
start_ts = timestamp;
}
if (timestamp === previous_ts) {
window.requestAnimationFrame(draw_frame);
return;
}
previous_ts = timestamp;
const frac = (timestamp - start_ts - 600) / 1200;
if (frac < 0) {
window.requestAnimationFrame(draw_frame);
return;
}
if (frac >= 1) {
kleinohedron_update_faces(elt, value);
return;
}
klienohedron_draw(elt, numbers, offsets, current_value, frac, transformation)
window.requestAnimationFrame(draw_frame);
}
window.requestAnimationFrame(draw_frame);
}