Pi with Matchsticks
by alancnet
HTML
<div ng-app ng-controller="Matchsticks as ctrl">
<a href="" ng-hide="showSettings" ng-click="showSettings=true">Show Settings</a>
<a href="" ng-show="showSettings" ng-click="showSettings=false">Hide Settings</a>
<table>
<tr>
<th>Presets</th>
<td>
<button ng-click="
ctrl.find = 'π';
">Find π</button>
<button ng-click="
ctrl.find = 'τ';
">Find τ</button>
<button ng-click="
ctrl.loops = 200;
ctrl.rate = 500;
">Slow</button>
<button ng-click="
ctrl.loops = 100000;
ctrl.rate = 1;
">Rapid</button>
<button ng-click="
ctrl.matchstickLength = 10;
ctrl.fieldSize = 16;
">Small</button>
<button ng-click="
ctrl.matchstickLength = 20;
ctrl.fieldSize = 12;
">Medium</button>
<button ng-click="
ctrl.matchstickLength = 80;
ctrl.fieldSize = 4;
">Large</button>
</td>
</tr>
<tr ng-show="showSettings">
<th>Visual Style</th>
<td>
<select ng-model="ctrl.visualStyle">
<option value="accumulate">Accumulate</option>
<option value="fade">Fade out</option>
<option value="clear">Clear every frame</option>
</select>
</td>
</tr>
<tr ng-show="showSettings">
<th>Find</th>
<td>
<select ng-model="ctrl.find">
<option value="π">π pi (3.14)</option>
<option value="τ">τ tau (6.28)</option>
</select>
...
CSS
canvas {
border: solid 1px black;
}
a, th {
font-family: sans-serif;
text-align: left;
font-size: 10pt;
}
JavaScript
function Matchsticks($scope) {
var ctrl = {
find: 'π',
matchstickLength: 20,
matchstickCount: 20,
fieldSize: 12, // In matchstick lengths
loops: 200,
rate: 500,
visualStyle: 'fade' // accumulate, clear, fade
}
$scope.$watch(function() {
run(
+ctrl.matchstickLength,
+ctrl.matchstickCount,
+ctrl.fieldSize,
+ctrl.loops,
+ctrl.rate,
ctrl.find,
ctrl.visualStyle
);
});
return ctrl;
}
function run(matchstickLength, matchstickCount, fieldSize, loops, rate, find, visualStyle) {
var canvas = run.canvas || (run.canvas = document.getElementById("canvas"));
var ctx = run.ctx || (run.ctx = canvas.getContext("2d"));
ctx.restore();
if (visualStyle == 'accumulate') ctx.globalCompositeOperation = "lighten";
else {
console.log('findme')
ctx.globalCompositeOperation = "source-over";
}
var totalCount = 0;
var totalCrossed = 0;
// Convert field size to pixels
fieldSize *= matchstickLength;
ctx.save();
ctx.saved = true;
// Clear
ctx.clearRect(0,0,canvas.width,canvas.height);
// Adjust for field
ctx.translate((canvas.width - fieldSize)/2, (canvas.height - fieldSize)/2);
var lines;
function drawField() {
// Fade out background
if (visualStyle != 'accumulate') {
if (visualStyle == 'fade') ctx.fillStyle = "rgba(255,255,255,.05)";
else if (visualStyle == 'clear') ctx.fillStyle = "rgba(255,255,255,1)";
ctx.fillRect(-canvas.width, -canvas.height, canvas.width * 4, canvas.height * 4);
}
// Draw field
ctx.strokeRect(0,0,fieldSize,fieldSize);
// Determine lines, Draw lines
ctx.strokeStyle = "green";
var columnWidth = matchstickLength;
// Pi or Tau?
if (find == 'π')...