4

I'm trying to bisect a circle with JavaScript and a <canvas> element. I used the formula given in the accepted answer to this question to find points on the edge of the circle, but for some reason when I give two opposite points on the circle (0 and 180, or 90 and 270, for example) I'm not getting a line that goes through the center of the circle.

My code, which you can see on JSFiddle, makes a nice Spirograph pattern, which is cool except that that's not what I'm trying to do.

How do I fix this so the lines go through the center?

(Ultimately I'm trying to draw a circle of fifths, but all I'm asking how to do now is get the lines to go through the center. Once that works I'll get on with the other steps to do the circle of fifths, which will obviously include drawing fewer lines and losing the Spirograph torus.)

Community
  • 1
  • 1
iconoclast
  • 21,213
  • 15
  • 102
  • 138

2 Answers2

4

Degrees in Javascript are specified in radians. Instead of checking for greater than or less than 180, and adding or subtracting 180, do the same with Math.PI radians.

http://jsfiddle.net/7w29h/1/

Plynx
  • 11,341
  • 3
  • 32
  • 33
  • 1
    Your lines are weird. You didn't pass the radian correctly to the function. – nhahtdh Feb 19 '13 at 04:53
  • @nhahtdh I wasn't trying to. This is all the OP needs to know to get the lines to pass through the center, that the trignometric functions are expecting radians. Your fiddle, which converts from degrees to radians as `sin` and `cos` are being called instead of using radians throughout, is also a valid solution. Personally, I'd want to use radians everywhere, based on tau (τ=2π). http://tauday.com/ – Plynx Feb 19 '13 at 05:01
2

Drawing function and trigonometry function in Math expects angle to be specified in radian, not degree.

Demo

Diff with your current code:

function bisect(context, degrees, radius, cx, cy) {
    // calculate the point on the edge of the circle
    var x1 = cx + radius * Math.cos(degrees / 180 * Math.PI);
    var y1 = cy + radius * Math.sin(degrees / 180 * Math.PI);

    /* Trimmed */    

    // and calculate the point on the opposite side
    var x2 = cx + radius * Math.cos(degrees2 / 180 * Math.PI);
    var y2 = cy + radius * Math.sin(degrees2 / 180 * Math.PI);

    /* Trimmed */
}

function draw(theCanvas) {

    /* Trimmed */
    // 2 * PI, which is 360 degree
    context.arc(250, 250, 220, 0, Math.PI * 2, false);

    /* Trimmed */

    context.arc(250, 250, 110, 0, Math.PI * 2, false);

    /* Trimmed */

    // No need to go up to 360 degree, unless the increment does
    // not divides 180
    for (j = 2; j < 180; j = j + 3) {
        bisect(context, j, 220, 250, 250);    
    }
    /* Trimmed */
}

Appendix

This is the full source code from JSFiddle, keep the full copy here just in case.

HTML

<canvas id="the_canvas" width="500" height="500"></canvas>

CSS

canvas {
    border:1px solid black;
}

JavaScript

function bisect(context, degrees, radius, cx, cy) {
    // calculate the point on the edge of the circle
    var x1 = cx + radius * Math.cos(degrees / 180 * Math.PI);
    var y1 = cy + radius * Math.sin(degrees / 180 * Math.PI);

    // get the point on the opposite side of the circle
    // e.g. if 90, get 270, and vice versa
    // (super verbose but easily readable)
    if (degrees > 180) {
        var degrees2 = degrees - 180;
    } else {
        var degrees2 = degrees + 180;
    }

    // and calculate the point on the opposite side
    var x2 = cx + radius * Math.cos(degrees2 / 180 * Math.PI);
    var y2 = cy + radius * Math.sin(degrees2 / 180 * Math.PI);

    // now actually draw the line
    context.beginPath();
    context.moveTo(x1, y1)
    context.lineTo(x2, y2)
    context.stroke();
}

function draw(theCanvas) {
    var context = theCanvas.getContext('2d');
    // draw the big outer circle
    context.beginPath();
    context.strokeStyle = "#222222";
    context.lineWidth = 2;
    context.arc(250, 250, 220, 0, Math.PI * 2, false);
    context.stroke();
    context.closePath();

    // smaller inner circle
    context.beginPath();
    context.strokeStyle = "#222222";
    context.lineWidth = 1;
    context.arc(250, 250, 110, 0, Math.PI * 2, false);
    context.stroke();
    context.closePath();

    for (j=2; j < 180; j = j + 3) {
        bisect(context, j, 220, 250, 250);    
    }

}
$(function () {
    var theCanvas = document.getElementById('the_canvas');
    console.log(theCanvas);
    draw(theCanvas, 50, 0, 270);
});
nhahtdh
  • 55,989
  • 15
  • 126
  • 162