supercircles in JavaScript
Kragen Javier Sitaker
kragen at pobox.com
Sat Mar 3 03:37:01 EST 2007
This will also be online at http://pobox.com/~kragen/sw/lame.html for
easier viewing. Like everything else posted here without a notice
to the contrary, I dedicate this to the public domain.
<html><head><title>Curves of Lamé</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- about an hour of work, 2007-02-08 -->
<script type="text/javascript">//<![CDATA[
function $(id) { return document.getElementById(id) }
function drawCurve(ctx, points, x, y) {
ctx.beginPath()
ctx.moveTo(0, y)
for (var ii = 0; ii < points.length; ii++) {
ctx.lineTo(points[ii][0] * x, points[ii][1] * y)
}
ctx.stroke()
}
function redraw(canvas, exponent) {
var ctx = canvas.getContext('2d')
var w = canvas.width
var h = canvas.height
ctx.strokeStyle = 'grey'
// set coordinate system
ctx.save()
ctx.translate(w/2, h/2)
// the -1s are so that antialiased lines don't become half-width
// when they reach the edge:
ctx.scale(w/2-1, h/2-1)
ctx.lineWidth = 1/(w/2-1)
// draw axes
if ($('draw_axes').checked) {
ctx.moveTo(-1, 0)
ctx.lineTo(1, 0)
ctx.moveTo(0, -1)
ctx.lineTo(0, 1)
ctx.stroke()
}
// compute a point per pixel
var points = []
for (var xx = 0; xx <= 1; xx += 1/(w/2-1)) {
// x^n + y^n = 1; y = (1 - x^n)^(1/n)
var yy = Math.pow(1 - Math.pow(xx, exponent), 1/exponent)
points.push([xx, yy])
}
points.push([1, 0]) // ensure it's closed to take care of numerical error
// draw them
drawCurve(ctx, points, 1, 1)
drawCurve(ctx, points, 1, -1)
drawCurve(ctx, points, -1, 1)
drawCurve(ctx, points, -1, -1)
// restore coordinate system
ctx.restore()
}
function cls(canvas) {
canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height)
}
function draw() {
var ss = $('exponent')
redraw($('canvas'), ss.options[ss.selectedIndex].value)
}
function erase_old() {
cls($('canvas'))
draw()
}
// ]]>
</script>
</head>
<body onload="draw()">
<h1>Curves of Lamé</h1>
<div style="float:right; margin-left: 0.5em">
<div>
<label for="exponent">Exponent:
</label><select onchange="draw()" id="exponent">
<option>0.125</option>
<option>0.25</option>
<option>0.368</option>
<option>0.5</option>
<option>0.707</option>
<option>1</option>
<option>1.414</option>
<option>2</option>
<option selected="selected">2.718</option>
<option>3</option>
<option>4</option>
<option>8</option>
<option>50</option>
<option>500</option>
<option>5000</option>
</select>
<button onclick="erase_old()">Erase Old</button>
<input type="checkbox" id="draw_axes" checked="checked"
onchange="erase_old()" /><label for="draw_axes"> Draw Axes</label>
</div>
<canvas id="canvas" width="400" height="400" style="margin: 0.5em">
</canvas>
</div>
<p>These are curves of Lamé, generalizations of the circle given by
the formula <nobr><i>x<sup>n</sup> + y<sup>n</sup></i> = 1</nobr>.
When <i>n</i> = 2, you get a circle; when <i>n</i> is a bit greater
than 2, you get Piet Hein’s “supercircles”. He liked the effect you
got when <i>n</i> was roughly <i>e</i>, which is the default here, but
you can change the exponent in the drop-down box to see the different
kinds of curves you can get.</p>
</body></html>
More information about the Kragen-hacks
mailing list