Algorithm for drawing a 5-point star

I am currently working on a solution for drawing a standard 5-point star to canvas using JavaScript. I am on the sidelines, but cannot fully understand this. I would appreciate any advice or pointers everyone may have.

+3


source to share


4 answers


I made some changes to the code that Chris posted, so it will 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 ...

+3


source


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

5 point star

Define the 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 here http://jsbin.com/oyonos/2/

+2


source


You need to draw the inner bits and the full circle is 2 * PI radians. In the example below, r is the radius of the enclosing circle. Below is the code 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 ways a cat can throw things off, I'm sure someone has another way to do it. In addition, the reason for the decremental loop, rather than the incremental one, is a preliminary estimate. i! = 0 is more efficient than i <10 and i is more efficient than i ++. But performance is very important to my code, it may not be that important to you.

+1


source


I myself was looking for such an algorithm and wondered if I could come up with one myself. It turned out not too difficult. So here's a little function for creating stars and polygons with the ability to set the number of points, outer radius and inner radius (the latter only applies 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);

      

+1


source







All Articles