Skip to content

Commit fae47a2

Browse files
author
Carlos
committed
Added agarsphere demo
1 parent cbb42bc commit fae47a2

File tree

2 files changed

+378
-0
lines changed

2 files changed

+378
-0
lines changed

agarsphere/agarsphere.html

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>
5+
Agarsphere
6+
</title>
7+
<script defer src="agarsphere.js"></script>
8+
</head>
9+
<body>
10+
<canvas id="canvas" width="640" height="480">
11+
</canvas>
12+
</body>
13+
</html>

agarsphere/agarsphere.js

+365
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
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

Comments
 (0)