HTML5 - canvas(3)

公開:2009-10-26 05:00
更新:2020-02-15 04:36
カテゴリ:web,html5,js

いろいろなCircleアルゴリズムで描画してみた。 元ネタ:http://openfmi.net/snippet/detail.php?type=snippet&id=8 (Google Chromeブラウザでのみ動作チェックしています)


/*--------------------------------------------------------------------
DrawingCircles.c - javascript porting version
Comparing Circles Drawed By
canvas, The Simplest Drawing Circle Algorithm,
Bresenham Circle Algorithm, Michener Algorithm
By S.F.
元ネタ:http://openfmi.net/snippet/detail.php?type=snippet&id=8
--------------------------------------------------------------------*/
var ctx;
var bmp;
var w,h;
var dt;
function pset(x,y,r,g,b,a)
{
var st = (x + w * y) * 4;
dt[st++] = r;
dt[st++] = g;
dt[st++] = b;
dt[st++] = a;
}
// the simplest way to draw a circle:
function reallySimpleCircle (radius, centerx,centery,r,g,b,a)
{
var    cx = 0, cy;
var    xLimit = Math.sqrt ((radius * radius) / 2);
while (cx++ <= xLimit)
{
cy = Math.floor (Math.sqrt (radius * radius - cx * cx));
pset ( cx + centerx, cy + centery, r,g,b,a);        // 45-90    degrees
pset ( cx + centerx, -cy + centery, r,g,b,a);        // 270-315    degrees
pset ( -cx + centerx, cy + centery, r,g,b,a);        // 90-135    degrees
pset ( -cx + centerx, -cy + centery, r,g,b,a);    // 225-270    degrees
pset ( cy + centerx, cx + centery, r,g,b,a);        // 0-45        degrees
pset ( cy + centerx, -cx + centery, r,g,b,a);        // 315-360    degrees
pset ( -cy + centerx, cx + centery, r,g,b,a);        // 135-180    degrees
pset ( -cy + centerx, -cx + centery, r,g,b,a);    // 180-225    degrees
}
}
////////////////////////////////////////////////////////
// Bresenham Circle Algorithm:
//
//               -Yi              Xi
// ---------------o---------------o---------------
//      Hi    <=  |  >  Di    <=  |  >  Vi
//                |               |
//      x++       |     x++,y--   |     y--
////////////////////////////////////////////////////////
function bresenhamCircle (radius, centerx,centery,  r,g,b,a)
{
var cx, cy, d;
cx = 0;
cy = radius;
d = 2 - 2 * radius;
// let's start drawing the circle:
pset ( cx + centerx, cy + centery, r,g,b,a);    // point (0, R);
pset ( cx + centerx, -cy + centery, r,g,b,a);    // point (0, -R);
pset ( cy + centerx, cx + centery, r,g,b,a);    // point (R, 0);
pset ( -cy + centerx, cx + centery, r,g,b,a);    // point (-R, 0);
while (1)
{
if (d > -cy)
{
--cy;
d += 1 - 2 * cy;
}
if (d <= cx)
{
++cx;
d += 1 + 2 * cx;
}
if (!cy) return;    // cy is 0, but these points are already drawn;
// the actual drawing:
pset ( cx + centerx, cy + centery, r,g,b,a);        // 0-90        degrees
pset ( -cx + centerx, cy + centery, r,g,b,a);        // 90-180    degrees
pset ( -cx + centerx, -cy + centery, r,g,b,a);    // 180-270    degrees
pset ( cx + centerx, -cy + centery, r,g,b,a);        // 270-360    degrees
}
}
// Miechener circle algorithm:
function miechenerCircle (radius, centerx,centery,  r,g,b,a)
{
var cx, cy, d;
d = 3 - 2 * radius;
cy = radius;
// let's start drawing the circle:
pset ( centerx, radius + centery, r,g,b,a);    // point (0, R);
pset ( centerx, -radius + centery, r,g,b,a);    // point (0, -R);
pset ( radius + centerx, centery, r,g,b,a);    // point (R, 0);
pset ( -radius + centerx, centery, r,g,b,a);    // point (-R, 0);
for (cx = 0; cx <= cy; cx++)
{
if (d >= 0)
// in this case we choose Hi:
d += 10 + 4 * cx - 4 * cy--;
else
// in this case we choose Di:
d += 6 + 4 * cx;
// the actual drawing:
pset ( cy + centerx, cx + centery, r,g,b,a);        // 0-45        degrees
pset ( cx + centerx, cy + centery, r,g,b,a);        // 45-90    degrees
pset ( -cx + centerx, cy + centery, r,g,b,a);        // 90-135    degrees
pset ( -cy + centerx, cx + centery, r,g,b,a);        // 135-180    degrees
pset ( -cy + centerx, -cx + centery, r,g,b,a);    // 180-225    degrees
pset ( -cx + centerx, -cy + centery, r,g,b,a);    // 225-270    degrees
pset ( cx + centerx, -cy + centery, r,g,b,a);        // 270-315    degrees
pset ( cy + centerx, -cx + centery, r,g,b,a);        // 315-360    degrees
}
}
///////////////////////////////////////////////////////////
// double substraction method for drawing a circle:
//
// d0    -> H -> d1  = d0H+d0 -> D -> d2  = d1D+d1
// d0H         -> d1H = d0H+2          -> d2H = d1H+2
// d0D         -> d1D = d0D+2          -> d2D = d1D+4
// step 0        step 1                 step 2
//
///////////////////////////////////////////////////////////
function dsCircle (radius, centerx,centery,  r,g,b,a)
{
var cx, cy, d, dH, dD;
d    = 1 - radius;
dH    = 3;
dD    = 5 - 2 * radius;
cy    = radius;
// drawing the circle:
for (cx = 0; cx <= cy; cx++)
{
if (d < 0)
{
d    += dH;
dH    += 2;
dD    += 2;
}
else
{
d    += dD;
dH    += 2;
dD    += 4;
--cy;
}
// the actual drawing:
pset ( cy + centerx, cx + centery, r,g,b,a);        // 0-45        degrees
pset ( cx + centerx, cy + centery, r,g,b,a);        // 45-90    degrees
pset ( -cx + centerx, cy + centery, r,g,b,a);        // 90-135    degrees
pset ( -cy + centerx, cx + centery, r,g,b,a);        // 135-180    degrees
pset ( -cy + centerx, -cx + centery, r,g,b,a);    // 180-225    degrees
pset ( -cx + centerx, -cy + centery, r,g,b,a);    // 225-270    degrees
pset ( cx + centerx, -cy + centery, r,g,b,a);        // 270-315    degrees
pset ( cy + centerx, -cx + centery, r,g,b,a);        // 315-360    degrees
}
}
function draw()
{
reallySimpleCircle(60,w/4,100,80,80,80,255);
bresenhamCircle(60,w/4 * 3,100,80,80,80,255);
miechenerCircle(60,w/4,240,80,80,80,255);
dsCircle(60,w/4*3,240,80,80,80,255);
ctx.putImageData(bmp,0,0);
ctx.beginPath();
ctx.arc(w/4,380, 60, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.textAlign = "center";
ctx.fillText("Simple",w/4,100);
ctx.fillText("Bresenham",w/4*3,100);
ctx.fillText("Miechener",w/4,240);
ctx.fillText("Double Substraction",w/4*3,240);
ctx.fillText("Canvas",w/4,380);
}
window.onload = function()
{
ctx = document.getElementById("ctx").getContext("2d");
w = document.getElementById("ctx").width;
h = document.getElementById("ctx").height;
bmp = ctx.createImageData(w,h);
dt = bmp.data;
draw();
}