Wednesday, September 4, 2013

Drawing circle and calculating sinus function without trigonometry, power, or root

The formula of a circle is quite straightforward (r=sqrt(x^2+y^2)) but it's not trivial how to draw a circle or calculate the trigonometric functions without advanced math. However, an interesting finding from 1972 makes it really easy.

Minsky discovered (by a mistake) that the following loop will draw an almost perfect circle on the screen:

    x = x - epsilon * y
    y = y + epsilon * x # NOTE: the x is the new x value here

Turns out that epsilon in the equation is practically the rotation angle in radians, so the above loop will gradually rotate the x and y coordinates in a circle.

Calculating sinus

If we can draw this circle, we can easily estimate the sinus values: for the current angle, which is basically the sum of epsilons so far,  we have a height (y), which just needs to be normalized to the 0-1 range to get the actual sinus for the angle.

The smaller the steps (epsilon) are, the more accurate the formula will be. However, because it's not a perfect circle, it can never be a very accurate estimation. If epsilon is large, the algorithm will draw a visible ellipsis instead of a circle (slightly tilted left).

The code in JavaScript

I've used a simple canvas object to draw on, so the core logic of the drawing looks like this:

for(var i = 0; i < steps; i++)
    x -= y/epsilon;
    y += x/epsilon;

    // Draws circle.
    context.fillRect(middleX+x, middleY+y, 1, 1);

    var deg = i / 2 / epsilon / Math.PI * 360; // Angle in degrees.
    var rad = i / epsilon; // Angle in radians.
    var sinVal = y / 100; // Normalising to 0-1

    // Draws sinus wave.
    context.fillRect(sinX+deg, sinY+y, 1, 1);

    if(i % parseInt(steps / sinMarkerCount) == 0)
        var text = "Sin(" + parseInt(deg) + ")=" + sinVal.toFixed(2);
        // Draws couple sinus values on sinus wave.
        context.fillText(text, sinX+deg, sinY+y);

And the result is this:

To grab the full source, go here. Or have a look at the live demo here

No comments:

Post a Comment