Algorithm for drawing a 5 point star

24,762

Solution 1

I made some changes to the code that Chris posted so it would work for me:

var alpha = (2 * Math.PI) / 10; 
var radius = 12;
var starXY = [100,100]

canvasCtx.beginPath();

for(var i = 11; i != 0; i--)
{
    var r = radius*(i % 2 + 1)/2;
    var omega = alpha * i;
    canvasCtx.lineTo((r * Math.sin(omega)) + starXY[0], (r * Math.cos(omega)) + starXY[1]);
}
canvasCtx.closePath();
canvasCtx.fillStyle = "#000";
canvasCtx.fill();

Hope it helps...

Solution 2

n point star, points are distributed evenly around a circle. Assume the first point is at 0,r (top), with the circle centred on 0,0, and that we can construct it from a series of triangles rotated by 2π/(2n+1):

5 point star

Define a rotation function:

function rotate2D(vecArr, byRads) {
    var mat = [ [Math.cos(byRads), -Math.sin(byRads)], 
                [Math.sin(byRads), Math.cos(byRads)] ];
    var result = [];
    for(var i=0; i < vecArr.length; ++i) {
        result[i] = [ mat[0][0]*vecArr[i][0] + mat[0][1]*vecArr[i][1],
                      mat[1][0]*vecArr[i][0] + mat[1][1]*vecArr[i][1] ];
    }
    return result;
}

Construct a star by rotating n triangles:

function generateStarTriangles(numPoints, r) {
    var triangleBase = r * Math.tan(Math.PI/numPoints);
    var triangle = [ [0,r], [triangleBase/2,0], [-triangleBase/2,0], [0,r] ];
    var result = [];
    for(var i = 0; i < numPoints; ++i) {
       result[i] = rotate2D(triangle, i*(2*Math.PI/numPoints));
    }
    return result;
}

Define a function to draw any given array of polygons:

function drawObj(ctx, obj, offset, flipVert) {
   var sign=flipVert ? -1 : 1;
   for(var objIdx=0; objIdx < obj.length; ++objIdx) {
      var elem = obj[objIdx];
      ctx.moveTo(elem[0][0] + offset[0], sign*elem[0][1] + offset[1]);
      ctx.beginPath();
      for(var vert=1; vert < elem.length; ++vert) {
        ctx.lineTo(elem[vert][0] + offset[0], sign*elem[vert][1] + offset[1]);
      }
      ctx.fill();
   }
}

Use the above to draw a 5 point star:

var canvas = document.getElementsByTagName('canvas')[0];
var ctx = canvas.getContext('2d');
var offset = [canvas.width/2, canvas.height/2];
ctx.fillStyle="#000000";
var penta = generateStarTriangles(5, 200);
drawObj(ctx, penta, offset, true);

See it here http://jsbin.com/oyonos/2/

Solution 3

This is a problem where Turtle Geometry makes things simple:

5-point star:

repeat 5 times:

fwd 100, right 144, fwd 100, left 72,

Solution 4

You need to draw the inner bits and a complete circle is 2 * PI radians. In the example below r is the radius of the encompassing circle. Code below is from an open source project (http://github.com/CIPowell/PhyloCanvas)

var alpha = (2 * Math.PI) / 10; 
// works out the angle between each vertex (5 external + 5 internal = 10)
var r_point = r * 1.75; // r_point is the radius to the external point

for(var i = 11; i != 0; i--) // or i could = 10 and you could use closePath at the end
{
var ra = i % 2 == 1 ? rb: r;

var omega = alpha * i; //omega is the angle of the current point
    //cx and cy are the center point of the star.
node.canvas.lineTo(cx + (ra * Math.sin(omega)), cy + (ra * Math.cos(omega)));

}

//Store or fill.

NB: This is one of those many ways to skin a cat things, I'm sure someone else has another way of doing it. Also, the reason for the decremental loop rather than the incremental is preformance. i != 0 is more efficient than i < 10 and i-- is more efficient than i++. But performance matters a lot for my code, it might not be so crucial for yours.

Solution 5

I was looking for such an algorithm myself and wondered if I could invent one myself. Turned out not to be too hard. So here is a small function to create stars and polygons, with options to set the number of point, outer radius, and inner radius (the latter does only apply to stars).

function makeStar(c, s, x, y , p, o, i) {
    var ct = c.getContext('2d');
    var points =  p || 5;
    var outer_radius = o || 100;
    var inner_radius = i || 40;
    var start_x = x || 100;
    var start_y = y || 100;
    var new_outer_RAD, half_new_outer_RAD;
    var RAD_distance = ( 2 * Math.PI / points);  
    var RAD_half_PI = Math.PI /2; 
    var i;
    ct.moveTo(start_x, start_y);
    ct.beginPath();

    for (i=0; i <= points; i++) {
        new_outer_RAD = (i + 1) * RAD_distance;     
        half_new_outer_RAD = new_outer_RAD - (RAD_distance / 2); 

        if (s) {
            ct.lineTo(start_x + Math.round(Math.cos(half_new_outer_RAD - RAD_half_PI) * inner_radius), start_y + Math.round(Math.sin(half_new_outer_RAD - RAD_half_PI) * inner_radius));
        }

        ct.lineTo(start_x + Math.round(Math.cos(new_outer_RAD - RAD_half_PI) * outer_radius), start_y + Math.round(Math.sin(new_outer_RAD - RAD_half_PI) * outer_radius));   

    }

    ct.stroke();
}

var canvas = document.getElementById('canvas');

makeStar(canvas);
makeStar(canvas, true, 120,200, 7, 110, 40);
Share:
24,762
Luke Haas
Author by

Luke Haas

Updated on August 07, 2022

Comments

  • Luke Haas
    Luke Haas almost 2 years

    I'm currently working on a solution for drawing a standard 5-point star on the canvas using JavaScript. I'm part way there but can't figure it out entirely. I'd appreciate any tips or pointers anyone might have.