1
+ ( function ( ) {
2
+
3
+ /**
4
+ * Returns a Gaussian Random Number around a normal distribution defined by the mean
5
+ * and standard deviation parameters.
6
+ *
7
+ * Uses the algorithm used in Java's random class, which in turn comes from
8
+ * Donald Knuth's implementation of the BoxÐMuller transform.
9
+ *
10
+ * @param {Number } [mean = 0.0] The mean value, default 0.0
11
+ * @param {Number } [standardDeviation = 1.0] The standard deviation, default 1.0
12
+ * @return {Number } A random number
13
+ */
14
+ Math . randomGaussian = function ( mean , standardDeviation ) {
15
+
16
+ mean = defaultTo ( mean , 0.0 ) ;
17
+ standardDeviation = defaultTo ( standardDeviation , 1.0 ) ;
18
+
19
+ if ( Math . randomGaussian . nextGaussian !== undefined ) {
20
+ var nextGaussian = Math . randomGaussian . nextGaussian ;
21
+ delete Math . randomGaussian . nextGaussian ;
22
+ return ( nextGaussian * standardDeviation ) + mean ;
23
+ } else {
24
+ var v1 , v2 , s , multiplier ;
25
+ do {
26
+ v1 = 2 * Math . random ( ) - 1 ; // between -1 and 1
27
+ v2 = 2 * Math . random ( ) - 1 ; // between -1 and 1
28
+ s = v1 * v1 + v2 * v2 ;
29
+ } while ( s >= 1 || s == 0 ) ;
30
+ multiplier = Math . sqrt ( - 2 * Math . log ( s ) / s ) ;
31
+ Math . randomGaussian . nextGaussian = v2 * multiplier ;
32
+ return ( v1 * multiplier * standardDeviation ) + mean ;
33
+ }
34
+
35
+ } ;
36
+
37
+ /**
38
+ * Returns a normal probability density function for the given parameters.
39
+ * The function will return the probability for given values of X
40
+ *
41
+ * @param {Number } [mean = 0] The center of the peak, usually at X = 0
42
+ * @param {Number } [standardDeviation = 1.0] The width / standard deviation of the peak
43
+ * @param {Number } [maxHeight = 1.0] The maximum height of the peak, usually 1
44
+ * @returns {Function } A function that will return the value of the distribution at given values of X
45
+ */
46
+ Math . getGaussianFunction = function ( mean , standardDeviation , maxHeight ) {
47
+
48
+ mean = defaultTo ( mean , 0.0 ) ;
49
+ standardDeviation = defaultTo ( standardDeviation , 1.0 ) ;
50
+ maxHeight = defaultTo ( maxHeight , 1.0 ) ;
51
+
52
+ return function getNormal ( x ) {
53
+ return maxHeight * Math . pow ( Math . E , - Math . pow ( x - mean , 2 ) / ( 2 * ( standardDeviation * standardDeviation ) ) ) ;
54
+ }
55
+ } ;
56
+
57
+ function defaultTo ( value , defaultValue ) {
58
+ return isNaN ( value ) ? defaultValue : value ;
59
+ }
60
+
61
+ } ) ( ) ;
62
+
63
+ var math = {
64
+ radius : 1 ,
65
+ sqrt : Math . sqrt ,
66
+ cos : Math . cos ,
67
+ sin : Math . sin ,
68
+ acos : Math . acos ,
69
+ sum : function ( vector1 , vector2 ) {
70
+ return {
71
+ x : vector1 . x + vector2 . x ,
72
+ y : vector1 . y + vector2 . y ,
73
+ z : vector1 . z + vector2 . z
74
+ } ;
75
+ } ,
76
+ difference : function ( vector1 , vector2 ) {
77
+ return {
78
+ x : vector1 . x - vector2 . x ,
79
+ y : vector1 . y - vector2 . y ,
80
+ z : vector1 . z - vector2 . z
81
+ } ;
82
+ } ,
83
+ scale : function ( vector , scalar ) {
84
+ return {
85
+ x : vector . x * scalar ,
86
+ y : vector . y * scalar ,
87
+ z : vector . z * scalar
88
+ } ;
89
+ } ,
90
+ unit : function ( vector ) {
91
+ return math . scale ( vector , 1 / math . norm ( vector ) ) ;
92
+ } ,
93
+ inner : function ( vector1 , vector2 ) {
94
+ return vector1 . x * vector2 . x + vector1 . y * vector2 . y + vector1 . z * vector2 . z ;
95
+ } ,
96
+ norm : function ( vector ) {
97
+ return math . sqrt ( math . inner ( vector , vector ) )
98
+ } ,
99
+ angle : function ( vector1 , vector2 ) {
100
+ return math . acos ( math . inner ( vector1 , vector2 ) / ( math . norm ( vector1 ) * math . norm ( vector2 ) ) ) ;
101
+ } ,
102
+ scalar_projection : function ( vector1 , vector2 ) {
103
+ return math . inner ( vector1 , math . unit ( vector2 ) ) ;
104
+ } ,
105
+ vector_projection : function ( vector1 , vector2 ) {
106
+ return math . scale ( math . unit ( vector2 ) , math . scalar_projection ( vector1 , vector2 ) )
107
+ } ,
108
+ rejection : function ( vector1 , vector2 ) {
109
+ return math . difference ( vector1 , math . vector_projection ( vector1 , vector2 ) ) ;
110
+ } ,
111
+ exponential : function ( point , tangent ) {
112
+ var length = math . norm ( tangent ) ;
113
+ var angle = length / math . radius ;
114
+ var normal_component = math . radius * math . cos ( angle ) ;
115
+ var normal_vector = math . scale ( math . unit ( point ) , normal_component ) ;
116
+ var tangential_component = math . radius * math . sin ( angle ) ;
117
+ var tangential_vector = math . scale ( math . unit ( tangent ) , tangential_component ) ;
118
+ return math . sum ( normal_vector , tangential_vector ) ;
119
+ } ,
120
+ logarithm : function ( point1 , point2 ) {
121
+ var angle = math . angle ( point1 , point2 ) ;
122
+ var length = angle * math . radius ;
123
+ var direction = math . unit ( math . rejection ( point2 , point1 ) ) ;
124
+ return math . scale ( direction , length ) ;
125
+ } ,
126
+ extend : function ( vector , scalar ) {
127
+ var direction = math . unit ( vector ) ;
128
+ var magnitude = math . norm ( vector ) + scalar ;
129
+ return math . scale ( direction , magnitude ) ;
130
+ } ,
131
+ transport : function ( point , tangent , vector ) {
132
+ var length = math . norm ( tangent ) ;
133
+ var angle = length / math . radius ;
134
+ var normal_direction = math . unit ( point ) ;
135
+ var tangential_direction = math . unit ( tangent ) ;
136
+ var normal_component = math . inner ( vector , normal_direction ) ;
137
+ var tangential_component = math . inner ( vector , tangential_direction ) ;
138
+ var normal_vector = math . scale ( normal_direction , normal_component ) ;
139
+ var tangential_vector = math . scale ( tangential_direction , tangential_component ) ;
140
+ var rest = math . difference ( vector , math . sum ( normal_vector , tangential_vector ) ) ;
141
+ var normal_component2 = normal_component * math . cos ( angle ) - tangential_component * math . sin ( angle ) ;
142
+ var tangential_component2 = normal_component * math . sin ( angle ) + tangential_component * math . cos ( angle ) ;
143
+ var normal_vector2 = math . scale ( normal_direction , normal_component2 ) ;
144
+ var tangential_vector2 = math . scale ( tangential_direction , tangential_component2 ) ;
145
+ return math . sum ( rest , math . sum ( normal_vector2 , tangential_vector2 ) ) ;
146
+ } ,
147
+ coordinates : function ( azimuth , inclination ) {
148
+ return {
149
+ x : math . radius * math . cos ( inclination ) ,
150
+ y : math . radius * math . sin ( inclination ) * math . cos ( azimuth ) ,
151
+ z : math . radius * math . sin ( inclination ) * math . sin ( azimuth )
152
+ } ;
153
+ }
154
+ } ;
155
+
156
+ var frame = {
157
+ point : { x : 1 , y : 0 , z : 0 } ,
158
+ x : { x : 0 , y : 200 , z : 0 } ,
159
+ y : { x : 0 , y : 0 , z : 200 } ,
160
+ scale : 1
161
+ } ;
162
+
163
+ var speed = .00005 ;
164
+ var scaling = 1.002 ;
165
+ setInterval ( function ( ) {
166
+ for ( var n = 0 ; n < bullets . length ; ++ n ) {
167
+ var position = bullets [ n ] . position ;
168
+ var velocity = bullets [ n ] . velocity ;
169
+ bullets [ n ] . position = math . exponential ( position , velocity ) ;
170
+ bullets [ n ] . velocity = math . transport ( position , velocity , velocity ) ;
171
+ }
172
+
173
+ if ( keys [ 65 ] ) {
174
+ var tangent = math . scale ( frame . x , - speed ) ;
175
+ var frame_point = math . exponential ( frame . point , tangent ) ;
176
+ var frame_x = math . transport ( frame . point , tangent , frame . x ) ;
177
+ frame . point = frame_point ;
178
+ frame . x = frame_x ;
179
+ }
180
+ if ( keys [ 68 ] ) {
181
+ var tangent = math . scale ( frame . x , speed ) ;
182
+ var frame_point = math . exponential ( frame . point , tangent ) ;
183
+ var frame_x = math . transport ( frame . point , tangent , frame . x ) ;
184
+ frame . point = frame_point ;
185
+ frame . x = frame_x ;
186
+ }
187
+ if ( keys [ 83 ] ) {
188
+ var tangent = math . scale ( frame . y , speed ) ;
189
+ var frame_point = math . exponential ( frame . point , tangent ) ;
190
+ var frame_y = math . transport ( frame . point , tangent , frame . y ) ;
191
+ frame . point = frame_point ;
192
+ frame . y = frame_y ;
193
+ }
194
+ if ( keys [ 87 ] ) {
195
+ var tangent = math . scale ( frame . y , - speed ) ;
196
+ var frame_point = math . exponential ( frame . point , tangent ) ;
197
+ var frame_y = math . transport ( frame . point , tangent , frame . y ) ;
198
+ frame . point = frame_point ;
199
+ frame . y = frame_y ;
200
+ }
201
+ if ( keys [ 81 ] ) {
202
+ if ( frame . scale > .13 ) {
203
+ frame . scale /= scaling ;
204
+ }
205
+ }
206
+ if ( keys [ 69 ] ) {
207
+ frame . scale *= scaling ;
208
+ }
209
+ render ( ) ;
210
+ } , 1000 / 60 ) ;
211
+
212
+ var points = [ ] ;
213
+
214
+ var create_sprinkling ;
215
+ create_sprinkling = function ( number ) {
216
+ for ( var n = 0 ; n < number ; ++ n ) {
217
+ point = {
218
+ x : Math . randomGaussian ( ) ,
219
+ y : Math . randomGaussian ( ) ,
220
+ z : Math . randomGaussian ( )
221
+ }
222
+ point = math . unit ( point ) ;
223
+ point = math . scale ( point , math . radius ) ;
224
+ points . push ( point ) ;
225
+ }
226
+ } ;
227
+ create_sprinkling ( 1000 ) ;
228
+
229
+ var create_grid = function ( major , minor ) {
230
+ for ( var azimuth = 0 ; azimuth < 2 * Math . PI ; azimuth += 2 * Math . PI / major ) {
231
+ for ( var inclination = 0 ; inclination <= Math . PI ; inclination += Math . PI / minor ) {
232
+ points . push ( math . coordinates ( azimuth , inclination ) ) ;
233
+ }
234
+ }
235
+ for ( var azimuth = 0 ; azimuth < 2 * Math . PI ; azimuth += 2 * Math . PI / minor ) {
236
+ for ( var inclination = 0 ; inclination <= Math . PI ; inclination += Math . PI / major ) {
237
+ points . push ( math . coordinates ( azimuth , inclination ) ) ;
238
+ }
239
+ }
240
+ } ;
241
+ //create_grid(8, 64);
242
+
243
+ var bullets = [ ] ;
244
+ bullets . push ( {
245
+ position : {
246
+ x : 1 ,
247
+ y : 0 ,
248
+ z : 0
249
+ } ,
250
+ velocity : {
251
+ x : 0 ,
252
+ y : .01 ,
253
+ z : 0
254
+ }
255
+ } ) ;
256
+
257
+ var canvas = document . getElementById ( 'canvas' ) ;
258
+ var context = canvas . getContext ( '2d' ) ;
259
+
260
+ var render = function ( ) {
261
+ context . fillStyle = 'gray' ;
262
+ context . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
263
+ context . save ( ) ;
264
+ context . translate ( canvas . width / 2 , canvas . height / 2 ) ;
265
+ context . scale ( frame . scale , frame . scale ) ;
266
+
267
+ context . fillStyle = 'black' ;
268
+ context . beginPath ( ) ;
269
+ context . arc ( 0 , 0 , math . norm ( frame . x ) * Math . PI * math . radius * 5 , 0 , 2 * Math . PI ) ;
270
+ context . fill ( ) ;
271
+
272
+ context . fillStyle = 'white' ;
273
+ points . forEach ( function ( point ) {
274
+ var logarithm = math . logarithm ( frame . point , point ) ;
275
+ var x = math . inner ( logarithm , frame . x ) ;
276
+ var y = math . inner ( logarithm , frame . y ) ;
277
+ context . beginPath ( ) ;
278
+ context . arc ( x , y , 1 , 0 , 2 * Math . PI ) ;
279
+ context . fill ( ) ;
280
+ } ) ;
281
+ points . forEach ( function ( point ) {
282
+ var logarithm = math . extend ( math . logarithm ( frame . point , point ) , - 2 * Math . PI * math . radius ) ;
283
+ var x = math . inner ( logarithm , frame . x ) ;
284
+ var y = math . inner ( logarithm , frame . y ) ;
285
+ context . beginPath ( ) ;
286
+ context . arc ( x , y , 1 , 0 , 2 * Math . PI ) ;
287
+ context . fill ( ) ;
288
+ } ) ;
289
+ points . forEach ( function ( point ) {
290
+ var logarithm = math . extend ( math . logarithm ( frame . point , point ) , 2 * Math . PI * math . radius ) ;
291
+ var x = math . inner ( logarithm , frame . x ) ;
292
+ var y = math . inner ( logarithm , frame . y ) ;
293
+ context . beginPath ( ) ;
294
+ context . arc ( x , y , 1 , 0 , 2 * Math . PI ) ;
295
+ context . fill ( ) ;
296
+ } ) ;
297
+ points . forEach ( function ( point ) {
298
+ var logarithm = math . extend ( math . logarithm ( frame . point , point ) , - 4 * Math . PI * math . radius ) ;
299
+ var x = math . inner ( logarithm , frame . x ) ;
300
+ var y = math . inner ( logarithm , frame . y ) ;
301
+ context . beginPath ( ) ;
302
+ context . arc ( x , y , 1 , 0 , 2 * Math . PI ) ;
303
+ context . fill ( ) ;
304
+ } ) ;
305
+ points . forEach ( function ( point ) {
306
+ var logarithm = math . extend ( math . logarithm ( frame . point , point ) , 4 * Math . PI * math . radius ) ;
307
+ var x = math . inner ( logarithm , frame . x ) ;
308
+ var y = math . inner ( logarithm , frame . y ) ;
309
+ context . beginPath ( ) ;
310
+ context . arc ( x , y , 1 , 0 , 2 * Math . PI ) ;
311
+ context . fill ( ) ;
312
+ } ) ;
313
+
314
+ context . fillStyle = 'red' ;
315
+ bullets . forEach ( function ( bullet ) {
316
+ var logarithm = math . logarithm ( frame . point , bullet . position ) ;
317
+ var x = math . inner ( logarithm , frame . x ) ;
318
+ var y = math . inner ( logarithm , frame . y ) ;
319
+ context . beginPath ( ) ;
320
+ context . arc ( x , y , 5 , 0 , 2 * Math . PI ) ;
321
+ context . fill ( ) ;
322
+ } ) ;
323
+ bullets . forEach ( function ( bullet ) {
324
+ var logarithm = math . extend ( math . logarithm ( frame . point , bullet . position ) , - 2 * Math . PI * math . radius ) ;
325
+ var x = math . inner ( logarithm , frame . x ) ;
326
+ var y = math . inner ( logarithm , frame . y ) ;
327
+ context . beginPath ( ) ;
328
+ context . arc ( x , y , 5 , 0 , 2 * Math . PI ) ;
329
+ context . fill ( ) ;
330
+ } ) ;
331
+ bullets . forEach ( function ( bullet ) {
332
+ var logarithm = math . extend ( math . logarithm ( frame . point , bullet . position ) , 2 * Math . PI * math . radius ) ;
333
+ var x = math . inner ( logarithm , frame . x ) ;
334
+ var y = math . inner ( logarithm , frame . y ) ;
335
+ context . beginPath ( ) ;
336
+ context . arc ( x , y , 5 , 0 , 2 * Math . PI ) ;
337
+ context . fill ( ) ;
338
+ } ) ;
339
+ bullets . forEach ( function ( bullet ) {
340
+ var logarithm = math . extend ( math . logarithm ( frame . point , bullet . position ) , - 4 * Math . PI * math . radius ) ;
341
+ var x = math . inner ( logarithm , frame . x ) ;
342
+ var y = math . inner ( logarithm , frame . y ) ;
343
+ context . beginPath ( ) ;
344
+ context . arc ( x , y , 5 , 0 , 2 * Math . PI ) ;
345
+ context . fill ( ) ;
346
+ } ) ;
347
+ bullets . forEach ( function ( bullet ) {
348
+ var logarithm = math . extend ( math . logarithm ( frame . point , bullet . position ) , 4 * Math . PI * math . radius ) ;
349
+ var x = math . inner ( logarithm , frame . x ) ;
350
+ var y = math . inner ( logarithm , frame . y ) ;
351
+ context . beginPath ( ) ;
352
+ context . arc ( x , y , 5 , 0 , 2 * Math . PI ) ;
353
+ context . fill ( ) ;
354
+ } ) ;
355
+
356
+ context . restore ( ) ;
357
+ } ;
358
+
359
+ var keys = { } ;
360
+ addEventListener ( 'keydown' , function ( event ) {
361
+ keys [ event . which ] = true ;
362
+ } ) ;
363
+ addEventListener ( 'keyup' , function ( event ) {
364
+ keys [ event . which ] = false ;
365
+ } ) ;
0 commit comments