Unfortunately, Bresenham's doesn't give a symmetrical circle.
I had to port the Delphi code linked to on Wikipedia for ellipses. It's a bit broken on skinny ellipses though, and I'm certain I did a faithful port.
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
/**
* ...
* @author Aaron Steed, nitrome.com
*/
[SWF(width = "400", height = "400", frameRate="30", backgroundColor = "#CCCCCC")]
public class Main extends Sprite {
public var bitmap:Bitmap;
public var bitmapData:BitmapData;
public function Main():void {
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void {
removeEventListener(Event.ADDED_TO_STAGE, init);
bitmapData = new BitmapData(40, 40, true, 0xFFDDDDDD);
bitmap = new Bitmap(bitmapData);
addChild(bitmap);
bitmap.scaleX = bitmap.scaleY = 10;
addEventListener(Event.ENTER_FRAME, loop);
}
private function loop(e:Event):void{
var cx:int = 20;
var cy:int = 20;
var width:int = Math.max(1, Math.abs((cx - (mouseX / 10)) * 2));
var height:int = Math.max(1, Math.abs((cy - (mouseY / 10)) * 2));
bitmapData.fillRect(bitmapData.rect, 0xFFDDDDDD);
bresenhamEllipse(cx, cy, width, height, bitmapData, 0xFF333333);
}
/* Draws a Bresenham Ellipse.
*
* ported from:
* http://homepage.smc.edu/kennedy_john/belipse.pdf
*
* (if he mentioned it was written in Delphi in the paper it would have saved me some time)
*/
public function bresenhamEllipse(cx:int, cy:int, radiusX:int, radiusY:int, bitmapData:BitmapData, col:uint = 0x00000000):void{
var x:int, y:int;
var changeX:int, changeY:int;
var error:int;
var twoASquare:int, twoBSquare:int;
var stoppingX:int, stoppingY:int;
twoASquare = 2 * radiusX * radiusX;
twoBSquare = 2 * radiusY * radiusY;
x = radiusX;
y = 0;
changeX = radiusY * radiusY * (1 - 2 * radiusX);
changeY = radiusX * radiusX;
error = 0;
stoppingX = twoBSquare * radiusX;
stoppingY = 0;
while(stoppingX >= stoppingY){
bitmapData.setPixel32(cx + x, cy + y, col);
bitmapData.setPixel32(cx - x, cy + y, col);
bitmapData.setPixel32(cx - x, cy - y, col);
bitmapData.setPixel32(cx + x, cy - y, col);
y++;
stoppingY += twoASquare;
error += changeY;
changeY += twoASquare;
if(2 * error + changeX > 0){
x--;
stoppingX -= twoBSquare;
error += changeX;
changeX += twoBSquare;
}
}
x = 0;
y = radiusY;
changeX = radiusY * radiusY;
changeY = radiusX * radiusX * (1 - 2 * radiusY);
error = 0;
stoppingX = 0;
stoppingY = twoASquare * radiusY;
while(stoppingX <= stoppingY){
bitmapData.setPixel32(cx + x, cy + y, col);
bitmapData.setPixel32(cx - x, cy + y, col);
bitmapData.setPixel32(cx - x, cy - y, col);
bitmapData.setPixel32(cx + x, cy - y, col);
x++;
stoppingX += twoBSquare;
error += changeX;
changeX += twoBSquare;
if(2 * error + changeY > 0){
y--;
stoppingY -= twoASquare;
error += changeY;
changeY += twoASquare;
}
}
}
}
}