Bitmap/Midpoint circle algorithm

You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Using the data storage type defined on this page for raster images, write an implementation of the midpoint circle algorithm (also known as Bresenham's circle algorithm).
11l
T Colour = BVec3 V black = Colour(0, 0, 0) V white = Colour(255, 255, 255) T Bitmap Int width, height Colour background [[Colour]] map F (width = 40, height = 40, background = white) assert(width > 0 & height > 0) .width = width .height = height .background = background .map = (0 .< height).map(h -> (0 .< @width).map(w -> @@background)) F fillrect(x, y, width, height, colour = black) assert(x >= 0 & y >= 0 & width > 0 & height > 0) L(h) 0 .< height L(w) 0 .< width .map[y + h][x + w] = colour F chardisplay() V txt = .map.map(row -> row.map(bit -> (I bit == @@.background {‘ ’} E ‘@’)).join(‘’)) txt = txt.map(row -> ‘|’row‘|’) txt.insert(0, ‘+’(‘-’ * .width)‘+’) txt.append(‘+’(‘-’ * .width)‘+’) print(reversed(txt).join("\n")) F set(x, y, colour = black) .map[y][x] = colour F get(x, y) R .map[y][x] F circle(x0, y0, radius, colour = black) V f = 1 - radius V ddf_x = 1 V ddf_y = -2 * radius V x = 0 V y = radius .set(x0, y0 + radius, colour) .set(x0, y0 - radius, colour) .set(x0 + radius, y0, colour) .set(x0 - radius, y0, colour) L x < y I f >= 0 y-- ddf_y += 2 f += ddf_y x++ ddf_x += 2 f += ddf_x .set(x0 + x, y0 + y, colour) .set(x0 - x, y0 + y, colour) .set(x0 + x, y0 - y, colour) .set(x0 - x, y0 - y, colour) .set(x0 + y, y0 + x, colour) .set(x0 - y, y0 + x, colour) .set(x0 + y, y0 - x, colour) .set(x0 - y, y0 - x, colour) V bitmap = Bitmap(25, 25) bitmap.circle(x0' 12, y0' 12, radius' 12) bitmap.chardisplay()
- Output:
+-------------------------+ | @@@@@@@ | | @@ @@ | | @@ @@ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @ | |@ @| |@ @| |@ @| |@ @| |@ @| |@ @| |@ @| | @ @ | | @ @ | | @ @ | | @ @ | | @ @ | | @ @ | | @@ @@ | | @@ @@ | | @@@@@@@ | +-------------------------+
Action!
Part of the task is available in RGBCIRCL.ACT.
INCLUDE "H6:RGBCIRCL.ACT" ;from task Midpoint circle algorithm RGB black,yellow,violet,blue PROC DrawImage(RgbImage POINTER img BYTE x,y) RGB POINTER ptr BYTE i,j ptr=img.data FOR j=0 TO img.h-1 DO FOR i=0 TO img.w-1 DO IF RgbEqual(ptr,yellow) THEN Color=1 ELSEIF RgbEqual(ptr,violet) THEN Color=2 ELSEIF RgbEqual(ptr,blue) THEN Color=3 ELSE Color=0 FI Plot(x+i,y+j) ptr==+RGBSIZE OD OD RETURN PROC Main() RgbImage img BYTE CH=$02FC,width=[81],height=[51],st=[3] BYTE ARRAY ptr(12393) BYTE n INT x,y RGB POINTER col Graphics(7+16) SetColor(0,13,12) ;yellow SetColor(1,4,8) ;violet SetColor(2,8,6) ;blue SetColor(4,0,0) ;black RgbBlack(black) RgbYellow(yellow) RgbViolet(violet) RgbBlue(blue) InitRgbImage(img,width,height,ptr) FillRgbImage(img,black) FOR n=0 TO height/st DO IF n MOD 3=0 THEN col=yellow ELSEIF n MOD 3=1 THEN col=violet ELSE col=blue FI RgbCircle(img,width/2,height/2,st*n,col) OD DrawImage(img,(160-width)/2,(96-height)/2) DO UNTIL CH#$FF OD CH=$FF RETURN
- Output:
Screenshot from Atari 8-bit computer
Ada
procedureCircle(Picture: inoutImage;Center: Point;Radius: Natural;Color: Pixel)isF:Integer:=1-Radius;ddF_X:Integer:=0;ddF_Y:Integer:=-2*Radius;X:Integer:=0;Y:Integer:=Radius;beginPicture(Center.X,Center.Y+Radius):=Color;Picture(Center.X,Center.Y-Radius):=Color;Picture(Center.X+Radius,Center.Y):=Color;Picture(Center.X-Radius,Center.Y):=Color;whileX<YloopifF>=0thenY:=Y-1;ddF_Y:=ddF_Y+2;F:=F+ddF_Y;endif;X:=X+1;ddF_X:=ddF_X+2;F:=F+ddF_X+1;Picture(Center.X+X,Center.Y+Y):=Color;Picture(Center.X-X,Center.Y+Y):=Color;Picture(Center.X+X,Center.Y-Y):=Color;Picture(Center.X-X,Center.Y-Y):=Color;Picture(Center.X+Y,Center.Y+X):=Color;Picture(Center.X-Y,Center.Y+X):=Color;Picture(Center.X+Y,Center.Y-X):=Color;Picture(Center.X-Y,Center.Y-X):=Color;endloop;endCircle;
The following illustrates use:
X:Image(1..16,1..16);beginFill(X,White);Circle(X,(8,8),5,Black);Print(X);
- Output:
HHHHH H H H H H H H H H H H H H H H H H H HHHHH
ALGOL 68
File: prelude/Bitmap.a68 is on Rosetta Code at ALGOL 68/prelude#prelude/Bitmap.a68
File: prelude/Bitmap/Bresenhams_line_algorithm.a68 is on Rosetta Code at ALGOL 68/prelude#prelude/Bitmap/Bresenhams_line_algorithm.a68
File: prelude/Bitmap/Midpoint_circle_algorithm.a68
# -*- coding: utf-8 -*- # circle OF class image := ( REF IMAGE picture, POINT center, INT radius, PIXEL color )VOID: BEGIN INT f := 1 - radius, POINT ddf := (0, -2 * radius), df := (0, radius); picture [x OF center, y OF center + radius] := picture [x OF center, y OF center - radius] := picture [x OF center + radius, y OF center] := picture [x OF center - radius, y OF center] := color; WHILE x OF df < y OF df DO IF f >= 0 THEN y OF df -:= 1; y OF ddf +:= 2; f +:= y OF ddf FI; x OF df +:= 1; x OF ddf +:= 2; f +:= x OF ddf + 1; picture [x OF center + x OF df, y OF center + y OF df] := picture [x OF center - x OF df, y OF center + y OF df] := picture [x OF center + x OF df, y OF center - y OF df] := picture [x OF center - x OF df, y OF center - y OF df] := picture [x OF center + y OF df, y OF center + x OF df] := picture [x OF center - y OF df, y OF center + x OF df] := picture [x OF center + y OF df, y OF center - x OF df] := picture [x OF center - y OF df, y OF center - x OF df] := color OD END # circle #; SKIP
File: test/Bitmap/Midpoint_circle_algorithm.a68
#!/usr/bin/a68g --script # # -*- coding: utf-8 -*- # PR READ "prelude/Bitmap.a68" PR; PR READ "prelude/Bitmap/Bresenhams_line_algorithm.a68" PR; PR READ "prelude/Bitmap/Midpoint_circle_algorithm.a68" PR; # The following illustrates use: # ( REF IMAGE x = INIT LOC [1:16, 1:16] PIXEL; (fill OF class image)(x, (white OF class image)); (circle OF class image)(x, (8, 8), 5, (black OF class image)); (print OF class image)(x) )
- Output:
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffff000000000000000000000000000000ffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffff000000ffffffffffffffffffffffffffffff000000ffffffffffffffffffffffffffffff ffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffffffffff ffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffff ffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffff ffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffff ffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffff ffffffffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffff ffffffffffffffffff000000ffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffffffffffffff ffffffffffffffffffffffff000000ffffffffffffffffffffffffffffff000000ffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffff000000000000000000000000000000ffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
Applesoft BASIC
10GR:GOSUB330:END330COLOR=15:CX=20:CY=20:R=18:GOSUB350"CIRCLE"340COLOR=0:CX=15:CY=15:R=6350F=1-R:X=0:Y=R:DX=0:DY=-2*R:PLOTCX,CY+R:PLOTCX,CY-R:HLINCX-R,CX+RATCY:IFX>=YTHENRETURN360FORI=0TO1:IFF>=0THENY=Y-1:DY=DY+2:F=F+DY370X=X+1:DX=DX+2:F=F+DX+1:HLINCX-X,CX+XATCY+Y:HLINCX-X,CX+XATCY-Y:HLINCX-Y,CX+YATCY+X:HLINCX-Y,CX+YATCY-X:I=X>=Y:NEXTI:RETURN
ATS
bash
#! /bin/bash# Based on https://en.wikipedia.org/wiki/Midpoint_circle_algorithmfunctionputpixel{echo-en"\e[$2;$1H#"}functiondrawcircle{x0=$1y0=$2radius=$3foryin$(seq$((y0-radius))$((y0+radius)))doecho-en"\e[${y}H"forxin$(seq$((x0+radius)))doecho-n"-"donedonex=$((radius-1))y=0dx=1dy=1err=$((dx-(radius<<1)))while[$x-ge$y]doputpixel$((x0+x))$((y0+y))putpixel$((x0+y))$((y0+x))putpixel$((x0-y))$((y0+x))putpixel$((x0-x))$((y0+y))putpixel$((x0-x))$((y0-y))putpixel$((x0-y))$((y0-x))putpixel$((x0+y))$((y0-x))putpixel$((x0+x))$((y0-y))if[$err-le0]then((++y))((err+=dy))((dy+=2))fiif[$err-gt0]then((--x))((dx+=2))((err+=dx-(radius<<1))) fi done}cleardrawcircle 131311echo-en"\e[H"
- Output:
------#########------ ----##---------##---- ---#-------------#--- --#---------------#-- -#-----------------#- -#-----------------#- #-------------------# #-------------------# #-------------------# #-------------------# #-------------------# #-------------------# #-------------------# #-------------------# #-------------------# -#-----------------#- -#-----------------#- --#---------------#-- ---#-------------#--- ----##---------##---- ------#########------
BASIC
BASIC256
fastgraphics clg color red call DrawCircle(150,100,100) refresh color blue call DrawCircle(200,200,50) refresh #Function DrawCircle #1st param = X-coord of center #2nd param = Y-coord of center #3rd param = radius Function DrawCircle(x0,y0,radius) x=radius y=0 decisionOver2=1-x while x>=y plot( x + x0, y + y0) plot( y + x0, x + y0) plot(-x + x0, y + y0) plot(-y + x0, x + y0) plot(-x + x0, -y + y0) plot(-y + x0, -x + y0) plot( x + x0, -y + y0) plot( y + x0, -x + y0) y++ if decisionOver2<=0 then decisionOver2+=2*y+1 else x-- decisionOver2+=2*(y-x)+1 end if end while return 0 End Function
- Output:
http://s16.postimg.org/ge0ndfs9h/Output.jpg
Batch File
@echo off setlocal enabledelayedexpansion %== Initializations ==%setwidth=50 setheight=30 set/aallowance=height+2 mode %width%,%allowance%echo Rendering... set"outp="for/l%%i in(1,1,%height%)do(for/l%%j in(1,1,%width%)do(set"c[%%i][%%j]= "))%== Set the parameters for making circle ==%call:DrawCircle 20 20 10 call:DrawCircle 10 30 15 %== Output result ==%for/l%%i in(1,1,%height%)do(for/l%%j in(1,1,%width%)do(set"outp=!outp!!c[%%i][%%j]!"))clsecho!outp!pause>nul exit /b %== The main function ==%:DrawCirclesetx0=%1sety0=%2setradius=%3setx=!radius!sety=0 set/adecisionOver2=1-!x!:circle_loopif!x!geq!y!(set/a"hor=x + x0","ver=y + y0"set"c[!hor!][!ver!]=Û"set/a"hor=y + x0","ver=x + y0"set"c[!hor!][!ver!]=Û"set/a"hor=-x + x0","ver=y + y0"set"c[!hor!][!ver!]=Û"set/a"hor=-y + x0","ver=x + y0"set"c[!hor!][!ver!]=Û"set/a"hor=-x + x0","ver=-y + y0"set"c[!hor!][!ver!]=Û"set/a"hor=-y + x0","ver=-x + y0"set"c[!hor!][!ver!]=Û"set/a"hor=x + x0","ver=-y + y0"set"c[!hor!][!ver!]=Û"set/a"hor=y + x0","ver=-x + y0"set"c[!hor!][!ver!]=Û"set/ay+=1if!decisionOver2!leq 0 (set/a"decisionOver2 = !decisionOver2! + (2 * y^) + 1")else(set/ax-=1set/a"decisionOver2 = !decisionOver2! + 2 * (y - x^) + 1")gotocircle_loop)goto:EOF
- Output:
█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ███████ █ ██ ██ █ ██ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ██ █ ██ █ ███ █ ███ █ ███████ █ █ █ █ █ █ ██ ██ ███████
BBC BASIC

Width%=200Height%=200REM Set window size:VDU23,22,Width%;Height%;8,16,16,128REM Draw circles:PROCcircle(100,100,40,0,0,0)PROCcircle(100,100,80,255,0,0)ENDDEFPROCcircle(cx%,cy%,r%,R%,G%,B%)LOCALf%,x%,y%,ddx%,ddy%f%=1-r%:y%=r%:ddy%=-2*r%PROCsetpixel(cx%,cy%+r%,R%,G%,B%)PROCsetpixel(cx%,cy%-r%,R%,G%,B%)PROCsetpixel(cx%+r%,cy%,R%,G%,B%)PROCsetpixel(cx%-r%,cy%,R%,G%,B%)WHILEx%<y%IFf%>=0THENy%-=1ddy%+=2f%+=ddy%ENDIFx%+=1ddx%+=2f%+=ddx%+1PROCsetpixel(cx%+x%,cy%+y%,R%,G%,B%)PROCsetpixel(cx%-x%,cy%+y%,R%,G%,B%)PROCsetpixel(cx%+x%,cy%-y%,R%,G%,B%)PROCsetpixel(cx%-x%,cy%-y%,R%,G%,B%)PROCsetpixel(cx%+y%,cy%+x%,R%,G%,B%)PROCsetpixel(cx%-y%,cy%+x%,R%,G%,B%)PROCsetpixel(cx%+y%,cy%-x%,R%,G%,B%)PROCsetpixel(cx%-y%,cy%-x%,R%,G%,B%)ENDWHILEENDPROCDEFPROCsetpixel(x%,y%,r%,g%,b%)COLOUR1,r%,g%,b%GCOL1LINEx%*2,y%*2,x%*2,y%*2ENDPROC
C
Interface:
voidraster_circle(imageimg,unsignedintx0,unsignedinty0,unsignedintradius,color_componentr,color_componentg,color_componentb);
Implementation:
#define plot(x, y) put_pixel_clip(img, x, y, r, g, b)voidraster_circle(imageimg,unsignedintx0,unsignedinty0,unsignedintradius,color_componentr,color_componentg,color_componentb){intf=1-radius;intddF_x=0;intddF_y=-2*radius;intx=0;inty=radius;plot(x0,y0+radius);plot(x0,y0-radius);plot(x0+radius,y0);plot(x0-radius,y0);while(x<y){if(f>=0){y--;ddF_y+=2;f+=ddF_y;}x++;ddF_x+=2;f+=ddF_x+1;plot(x0+x,y0+y);plot(x0-x,y0+y);plot(x0+x,y0-y);plot(x0-x,y0-y);plot(x0+y,y0+x);plot(x0-y,y0+x);plot(x0+y,y0-x);plot(x0-y,y0-x);}}#undef plot
C#
This extension method extends GenericImage which is very similar to Bitmap but instead of using a SetPixel method it uses a "Color this[int x, int y] { get; set; }" property to get and set pixels.
/// <summary>/// Draws a circle./// </summary>/// <param name="image">/// The destination image./// </param>/// <param name="centerX">/// The x center position of the circle./// </param>/// <param name="centerY">/// The y center position of the circle./// </param>/// <param name="radius">/// The radius of the circle./// </param> /// <param name="color">/// The color to use./// </param> publicstaticvoidDrawCircle(thisGenericImageimage,intcenterX,intcenterY,intradius,Colorcolor){intd=(5-radius*4)/4;intx=0;inty=radius;do{// ensure index is in range before setting (depends on your image implementation)// in this case we check if the pixel location is within the bounds of the image before setting the pixelif(centerX+x>=0&¢erX+x<=image.Width-1&¢erY+y>=0&¢erY+y<=image.Height-1)image[centerX+x,centerY+y]=color;if(centerX+x>=0&¢erX+x<=image.Width-1&¢erY-y>=0&¢erY-y<=image.Height-1)image[centerX+x,centerY-y]=color;if(centerX-x>=0&¢erX-x<=image.Width-1&¢erY+y>=0&¢erY+y<=image.Height-1)image[centerX-x,centerY+y]=color;if(centerX-x>=0&¢erX-x<=image.Width-1&¢erY-y>=0&¢erY-y<=image.Height-1)image[centerX-x,centerY-y]=color;if(centerX+y>=0&¢erX+y<=image.Width-1&¢erY+x>=0&¢erY+x<=image.Height-1)image[centerX+y,centerY+x]=color;if(centerX+y>=0&¢erX+y<=image.Width-1&¢erY-x>=0&¢erY-x<=image.Height-1)image[centerX+y,centerY-x]=color;if(centerX-y>=0&¢erX-y<=image.Width-1&¢erY+x>=0&¢erY+x<=image.Height-1)image[centerX-y,centerY+x]=color;if(centerX-y>=0&¢erX-y<=image.Width-1&¢erY-x>=0&¢erY-x<=image.Height-1)image[centerX-y,centerY-x]=color;if(d<0){d+=2*x+1;}else{d+=2*(x-y)+1;y--;}x++;}while(x<=y);}
Clojure
Based upon the Common Lisp version.
(defn draw-circle[draw-functionx0y0radius](letfn[(put[xym](let [x+(+ x0x)x-(- x0x)y+(+ y0y)y-(- y0y)x0y+(+ x0y)x0y-(- x0y)xy0+(+ y0x)xy0-(- y0x)](draw-functionx+y+)(draw-functionx+y-)(draw-functionx-y+)(draw-functionx-y-)(draw-functionx0y+xy0+)(draw-functionx0y+xy0-)(draw-functionx0y-xy0+)(draw-functionx0y-xy0-)(let [[ym](if (pos? m)[(dec y)(- m(* 8y))][ym])](when (<= xy)(put(inc x)y(+ m4(* 8x)))))))](put0radius(- 5(* 4radius)))))
(let [circle-points(atom[])](letfn[(draw-fn[xy](swap!circle-points#(conj %[xy])))](draw-circledraw-fn10107))(let [empty-grid(vec(repeat 20(vec(repeat 20" "))))grid(reduce (fn [gridxy](assoc-ingridxy"x"))empty-grid@circle-points)](doseq [linegrid](println (clojure.string/joinline)))))
xxxxxxx xx xx x x x x x x x x x x x x x x x x x x x x x x xx xx xxxxxxx nil
Common Lisp
Based upon the OCaml version.
(defundraw-circle(draw-functionx0y0radius)(labels((foo(xy)(funcalldraw-functionxy))(put(xym)(let((x+(+x0x))(x-(-x0x))(y+(+y0y))(y-(-y0y))(x0y+(+x0y))(x0y-(-x0y))(xy0+(+y0x))(xy0-(-y0x)))(foox+y+)(foox+y-)(foox-y+)(foox-y-)(foox0y+xy0+)(foox0y+xy0-)(foox0y-xy0+)(foox0y-xy0-)(multiple-value-bind(ym)(if(pluspm)(values(1-y)(-m(*8y)))(valuesym))(when(<=xy)(put(1+x)y(+m4(*8x))))))))(put0radius(-5(*4radius)))(values)))
CL-USER>(let((buffer(make-array'(3030):element-type'bit)))(draw-circle(lambda(xy)(setf(bitbufferxy)1))151510)buffer)
;; edited for your convenience (( ) ( 1 1 1 1 1 1 1 ) ( 1 1 1 1 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 ) ( 1 1 1 1 1 1 ) ( 1 1 1 1 1 1 1 ) ( ))
D
Uses the bitmap module from the Bitmap Task.
importbitmap:Image,RGB;voidcircle(Color)(Image!Colorimg,inintx0,ininty0,inintradius,inColorcolor)purenothrow@nogc@safe{intf=1-radius;intddfX=1;intddfY=-2*radius;intx=0;inty=radius;img[x0,y0+radius]=color;img[x0,y0-radius]=color;img[x0+radius,y0]=color;img[x0-radius,y0]=color;while(x<y){if(f>=0){y--;ddfY+=2;f+=ddfY;}x++;ddfX+=2;f+=ddfX;img[x0+x,y0+y]=color;img[x0-x,y0+y]=color;img[x0+x,y0-y]=color;img[x0-x,y0-y]=color;img[x0+y,y0+x]=color;img[x0-y,y0+x]=color;img[x0+y,y0-x]=color;img[x0-y,y0-x]=color;}}voidmain()@safe{autoimg=newImage!RGB(25,25);img.clear(RGB.white);circle(img,12,12,12,RGB.black);img.textualShow;}
- Output:
.........#######......... .......##.......##....... .....##...........##..... ....#...............#.... ...#.................#... ..#...................#.. ..#...................#.. .#.....................#. .#.....................#. #.......................# #.......................# #.......................# #.......................# #.......................# #.......................# #.......................# .#.....................#. .#.....................#. ..#...................#.. ..#...................#.. ...#.................#... ....#...............#.... .....##...........##..... .......##.......##....... .........#######.........
Delphi

procedureDrawCircle(Image:TImage;Radius:integer;Center:TPoint);varT1,T2:integer;varX,Y:integer;varCnt:integer;procedureDrawPixels(X,Y:integer);{Draw pixel into all 8 octents}beginImage.Canvas.Pixels[Center.X+x,Center.Y+y]:=clRed;Image.Canvas.Pixels[Center.X-X,Center.Y+Y]:=clRed;Image.Canvas.Pixels[Center.X+X,Center.Y-Y]:=clRed;Image.Canvas.Pixels[Center.X-X,Center.Y-Y]:=clRed;Image.Canvas.Pixels[Center.X+Y,Center.Y+X]:=clRed;Image.Canvas.Pixels[Center.X-Y,Center.Y+X]:=clRed;Image.Canvas.Pixels[Center.X+y,Center.Y-X]:=clRed;Image.Canvas.Pixels[Center.X-Y,Center.Y-X]:=clRed;end;beginCnt:=0;T1:=Radiusdiv32;{Start on X-axis}X:=Radius;Y:=0;repeatbeginDrawPixels(X,Y);Y:=Y+1;T1:=T1+Y;T2:=T1-X;ifT2>=0thenbeginT1:=T2;X:=X-1;end;Inc(Cnt);enduntilx<y;Form1.Caption:=IntToStr(Cnt);end;procedureShowBrezCircle(Image:TImage);begin{Draw three times to make line thicker}DrawCircle(Image,100,Point(200,200));DrawCircle(Image,99,Point(200,200));DrawCircle(Image,98,Point(200,200));Image.Invalidate;end;
- Output:
Elapsed Time: 7.341 ms.
ERRE
PROGRAM BCircle !$INCLUDE="PC.LIB" PROCEDURE BCircle(cx%,cy%,r%) local f%,x%,y%,ddx%,ddy% f%=1-r% y%=r% ddy%=-2*r% PSET(cx%,cy%+r%,1) PSET(cx%,cy%-r%,1) PSET(cx%+r%,cy%,1) PSET(cx%-r%,cy%,1) WHILE x%<y% DO IF f%>=0 THEN y%=y%-1 ddy%=ddy%+2 f%=f%+ddy% END IF x%=x%+1 ddx%=ddx%+2 f%=f%+ddx%+1 PSET(cx%+x%,cy%+y%,1) PSET(cx%-x%,cy%+y%,1) PSET(cx%+x%,cy%-y%,1) PSET(cx%-x%,cy%-y%,1) PSET(cx%+y%,cy%+x%,1) PSET(cx%-y%,cy%+x%,1) PSET(cx%+y%,cy%-x%,1) PSET(cx%-y%,cy%-x%,1) END WHILE END PROCEDURE BEGIN SCREEN(1) ! Draw circles BCircle(100,100,40) BCircle(100,100,80) END PROGRAM
Evaldraw
Gives slightly faster (in some cases), but more importantly prettier circles than the builtin drawsph(x,y,-rad) function.
(){cls(0);setcol(0xffffff);srand(1234);for(i=0;i<1000;i++){rad=int(abs(nrnd*10));x=rnd*xres;y=rnd*yres;drawcircle(x,y,rad);//drawsph(x,y,-rad);}}drawcircle(cx,cy,r){if(cx+r<0||cy+r<0)return;if(cx-r>xres||cy-r>yres)return;r=int(r);if(r<=0)return;r2=r+r;x=r;y=0;dy=-2;dx=r2+r2-4;d=r2-1;while(y<=x){setpix(cx-x,cy-y);setpix(cx+x,cy-y);setpix(cx-x,cy+y);setpix(cx+x,cy+y);setpix(cx-y,cy-x);setpix(cx+y,cy-x);setpix(cx-y,cy+x);setpix(cx+y,cy+x);d+=dy;dy-=4;++y;if(d<0){d+=dx;dx-=4;--x;}}}
FBSL
Using pure FBSL's built-in graphics functions:
#DEFINEWM_LBUTTONDOWN513#DEFINEWM_CLOSE16FBSLSETTEXT(ME,"Bresenham Circle")' Set form captionFBSLSETFORMCOLOR(ME,RGB(0,255,255))' Cyan: persistent background colorFBSL.GETDC(ME)' Use volatile FBSL.GETDC below to avoid extra assignmentsRESIZE(ME,0,0,220,220)CENTER(ME)SHOW(ME)DIMBreadthASINTEGER,HeightASINTEGERFBSL.GETCLIENTRECT(ME,0,0,Breadth,Height)BEGINEVENTS' Main message loopSELECT CASECBMSGCASEWM_LBUTTONDOWN:MidpointCircle()' DrawCASEWM_CLOSE:FBSL.RELEASEDC(ME,FBSL.GETDC)' Clean upENDSELECTENDEVENTSSUBMidpointCircle()BresenhamCircle(Breadth\2,Height\2,80,&HFF)' Red: Windows stores colors in BGR orderBresenhamCircle(Breadth\2,Height\2,40,0)' BlackSUBBresenhamCircle(cx,cy,radius,colour)DIMx=0,y=radius,f=1-radius,dx=0,dy=-2*radiusPSET(FBSL.GETDC,cx,cy+radius,colour)(FBSL.GETDC,cx,cy-radius,colour)PSET(FBSL.GETDC,cx+radius,cy,colour)(FBSL.GETDC,cx-radius,cy,colour)WHILEx<yIFf>=0THEN:DECR(y):INCR(dy,2)(f,dy):ENDIF' Try also "IF f THEN" :)INCR(x)(dx,2)(f,dx+1)PSET(FBSL.GETDC,cx+x,cy+y,colour)(FBSL.GETDC,cx-x,cy+y,colour)PSET(FBSL.GETDC,cx+x,cy-y,colour)(FBSL.GETDC,cx-x,cy-y,colour)PSET(FBSL.GETDC,cx+y,cy+x,colour)(FBSL.GETDC,cx-y,cy+x,colour)PSET(FBSL.GETDC,cx+y,cy-x,colour)(FBSL.GETDC,cx-y,cy-x,colour)WENDENDSUBENDSUB
Forth
:circle{xyrcolorbmp--}1r-0r2*negate0r{fddxddydxdy}colorxyr+bmpb!colorxyr-bmpb!colorxr+ybmpb!colorxr-ybmpb!begindxdy<whilef0<0=ifdy1-todyddy2+duptoddyf+tofthendx1+todxddx2+duptoddxf1++tofcolorxdx+ydy+bmpb!colorxdx-ydy+bmpb!colorxdx+ydy-bmpb!colorxdx-ydy-bmpb!colorxdy+ydx+bmpb!colorxdy-ydx+bmpb!colorxdy+ydx-bmpb!colorxdy-ydx-bmpb!repeat;1212bitmapvaluetest0testbfill665bluetestcircletestbshowcr
Fortran
This code should be inside RCImagePrimitive (see here). The private subroutine draw_circle_toch
, which writes to a channel, is used by both draw_circle_rgb
and draw_circle_sc
and the interface allows to use draw_circle
with rgb images and grayscale images.
interface draw_circlemodule procedure draw_circle_sc,draw_circle_rgbend interfaceprivate::plot,draw_circle_toch
subroutine plot(ch,p,v)integer,dimension(:,:),intent(out)::chtype(point),intent(in)::pinteger,intent(in)::vinteger::cx,cy! I've kept the default 1-based array, but top-left corner pixel! is labelled as (0,0).cx=p%x+1cy=p%y+1if((cx>0).and.(cx<=ubound(ch,1)).and.&(cy>0).and.(cy<=ubound(ch,2)))thench(cx,cy)=vend ifend subroutine plotsubroutine draw_circle_toch(ch,c,radius,v)integer,dimension(:,:),intent(out)::chtype(point),intent(in)::cinteger,intent(in)::radius,vinteger::f,ddf_x,ddf_y,x,yf=1-radiusddf_x=0ddf_y=-2*radiusx=0y=radiuscall plot(ch,point(c%x,c%y+radius),v)call plot(ch,point(c%x,c%y-radius),v)call plot(ch,point(c%x+radius,c%y),v)call plot(ch,point(c%x-radius,c%y),v)do while(x<y)if(f>=0)theny=y-1ddf_y=ddf_y+2f=f+ddf_yend ifx=x+1ddf_x=ddf_x+2f=f+ddf_x+1call plot(ch,point(c%x+x,c%y+y),v)call plot(ch,point(c%x-x,c%y+y),v)call plot(ch,point(c%x+x,c%y-y),v)call plot(ch,point(c%x-x,c%y-y),v)call plot(ch,point(c%x+y,c%y+x),v)call plot(ch,point(c%x-y,c%y+x),v)call plot(ch,point(c%x+y,c%y-x),v)call plot(ch,point(c%x-y,c%y-x),v)end doend subroutine draw_circle_tochsubroutine draw_circle_rgb(img,c,radius,color)type(rgbimage),intent(out)::imgtype(point),intent(in)::cinteger,intent(in)::radiustype(rgb),intent(in)::colorcall draw_circle_toch(img%red,c,radius,color%red)call draw_circle_toch(img%green,c,radius,color%green)call draw_circle_toch(img%blue,c,radius,color%blue)end subroutine draw_circle_rgbsubroutine draw_circle_sc(img,c,radius,lum)type(scimage),intent(out)::imgtype(point),intent(in)::cinteger,intent(in)::radius,lumcall draw_circle_toch(img%channel,c,radius,lum)end subroutine draw_circle_sc
FreeBASIC
' version 15-10-2016' compile with: fbc -s gui' Variant with Integer-Based Arithmetic from Wikipedia page:' Midpoint circle algorithmSubcircle_(x0AsInteger,y0AsInteger,radiusAsInteger,ColAsInteger)DimAsIntegerx=radiusDimAsIntegery' Decision criterion divided by 2 evaluated at x=r, y=0DimAsIntegerdecisionOver2=1-xWhile(x>=y)PSet(x0+x,y0+y),colPSet(x0-x,y0+y),colPSet(x0+x,y0-y),colPSet(x0-x,y0-y),colPSet(x0+y,y0+x),colPSet(x0-y,y0+x),colPSet(x0+y,y0-x),colPSet(x0-y,y0-x),coly=y+1IfdecisionOver2<=0ThendecisionOver2+=y*2+1' Change in decision criterion for y -> y +1Elsex=x-1decisionOver2+=(y-x)*2+1' Change for y -> y +1, x -> x -1EndIfWendEndSub' ------=< MAIN >=------ScreenRes600,600,32DimAsIntegerw,h,depthRandomizeTimerScreenInfow,hForiAsInteger=1To10circle_(Rnd*w,Rnd*h,Rnd*200,Int(Rnd*&hFFFFFF))Next'save screen to BMP fileBSave"Name.BMP",0' empty keyboard bufferWhileInkey<>"":WendWindowTitle"hit any key to end program"SleepEnd
FutureBasic
FB has native functions that handle bitmap calculations. This compiles as a stand-alone Macintosh app that allows the user to adjust the screen-centered bitmap width from a single pixel to a large circle.
_wndW = 600 _wndH = 600 _window = 1 begin enum 1 _sliderBtn _sliderValue _cWell _pixelView _quitBtn end enum void local fn ViewDrawRect CGRect viewRect, dotRect CGContextRef ctx = fn GraphicsContextCurrentCGContext viewRect = fn ViewBounds( _pixelView ) long sliderValue = fn ControlIntegerValue( _sliderBtn ) CGContextSaveGState( ctx ) CGContextSetLineWidth(ctx, 1.0) CGContextSetRGBStrokeColor( ctx, 0.0, 0.0, 0.0, 1.0 ) CGContextStrokeRect( ctx, viewRect ) dotRect.origin.x = viewRect.size.width/2 - sliderValue dotRect.origin.y = viewRect.size.height/2 - sliderValue dotRect.size.width = 2 * sliderValue dotRect.size.height = 2 * sliderValue ColorRef col = fn ColorWellColor(_cWell) CGColorRef myColor = fn ColorCGColor( col ) CGContextSetStrokeColorWithColor( ctx, myColor ) CGContextStrokeEllipseInRect( ctx, dotRect ) CGContextRestoreGState( ctx ) end fn void local fn BuildWindow window 1, @"DotView", ( 0, 0, _wndW, _wndH ) view subclass _pixelView, ( 0, 0, _wndH, _wndW) ColorRef myColor = fn ColorWithRGB( 1.0, 0.0, 0.0, 1.0 ) colorwell _cWell,, myColor, ( 30, 30, 50, 30 ) ViewAddSubview( _pixelView, _cWell ) slider _sliderBtn,, 75, ( 170, 30, 250, 20 ), 1, 240 ControlSetContinuous( _sliderBtn, YES ) ViewAddSubview( _pixelView, _sliderBtn ) textlabel _sliderValue, @"75", ( 430, 35, 36, 17 ) ControlSetAlignment( _sliderValue, NSTextAlignmentCenter ) ViewAddSubview( _pixelView, _sliderValue ) button _quitBtn, , , @"Q", (_wndW - 50, 10, 40, 40),, NSBezelStyleCircular ControlSetAction( _quitBtn, @"terminate:" ) end fn void local fn DoDialog( ev as long, tag as long ) select ( ev ) case _btnClick select (tag) case _cWell : ViewSetNeedsDisplay( _pixelView ) case _sliderBtn ControlTakeIntegerValueFrom( _sliderValue, _sliderBtn ) ViewSetNeedsDisplay( _pixelView ) end select case _viewDrawRect select ( tag ) case _pixelView : fn ViewDrawRect end select end select end fn on dialog fn DoDialog fn BuildWindow HandleEvents
Go
This produces identical results to the C code in the WP article, but with more compact code.
packageraster// Circle plots a circle with center x, y and radius r.// Limiting behavior:// r < 0 plots no pixels.// r = 0 plots a single pixel at x, y.// r = 1 plots four pixels in a diamond shape around the center pixel at x, y.func(b*Bitmap)Circle(x,y,rint,pPixel){ifr<0{return}// Bresenham algorithmx1,y1,err:=-r,0,2-2*rfor{b.SetPx(x-x1,y+y1,p)b.SetPx(x-y1,y-x1,p)b.SetPx(x+x1,y-y1,p)b.SetPx(x+y1,y+x1,p)r=errifr>x1{x1++err+=x1*2+1}ifr<=y1{y1++err+=y1*2+1}ifx1>=0{break}}}func(b*Bitmap)CircleRgb(x,y,rint,cRgb){b.Circle(x,y,r,c.Pixel())}
Demonstration program:
package main // Files required to build supporting package raster are found in: // * This task (immediately above) // * Bitmap // * Write a PPM file import ( "raster" "fmt" ) func main() { b := raster.NewBitmap(400, 300) b.FillRgb(0xffdf20) // yellow // large circle, demonstrating clipping to image boundaries b.CircleRgb(300, 249, 200, 0xff2020) // red if err := b.WritePpmFile("circle.ppm"); err != nil { fmt.Println(err) } }
Haskell
The basic algorithm can be implemented generically.
moduleCirclewhereimportData.ListtypePoint=(Int,Int)-- Takes the center of the circle and radius, and returns the circle pointsgenerateCirclePoints::Point->Int->[Point]generateCirclePoints(x0,y0)radius-- Four initial points, plus the generated points=(x0,y0+radius):(x0,y0-radius):(x0+radius,y0):(x0-radius,y0):pointswhere-- Creates the (x, y) octet offsets, then maps them to absolute points in all octets.points=concatMapgeneratePoints$unfoldrstepinitialValuesgeneratePoints(x,y)=[(xopx0x',yopy0y')|(x',y')<-[(x,y),(y,x)],xop<-[(+),(-)],yop<-[(+),(-)]]-- The initial values for the loopinitialValues=(1-radius,1,(-2)*radius,0,radius)-- One step of the loop. The loop itself stops at Nothing.step(f,ddf_x,ddf_y,x,y)|x>=y=Nothing|otherwise=Just((x',y'),(f',ddf_x',ddf_y',x',y'))where(f',ddf_y',y')|f>=0=(f+ddf_y'+ddf_x',ddf_y+2,y-1)|otherwise=(f+ddf_x,ddf_y,y)ddf_x'=ddf_x+2x'=x+1
An example using regular 2d arrays of characters to represent a bitmap:
moduleCircleArrayExamplewhereimportCircle-- A surface is just a 2d array of characters for the purposes of this exampletypeColour=ChartypeSurface=Array(Int,Int)Colour-- Returns a surface of the given width and height filled with the colourblankSurface::Int->Int->Colour->SurfaceblankSurfacewidthheightfiller=listArraybounds(repeatfiller)wherebounds=((0,0),(width-1,height-1))-- Generic plotting function. Plots points onto a surface with the given colour.plotPoints::Surface->Colour->[Point]->SurfaceplotPointssurfacecolourpoints=surface//zippoints(repeatcolour)-- Draws a circle of the given colour on the surface given a center and radiusdrawCircle::Surface->Colour->Point->Int->SurfacedrawCirclesurfacecolourcenterradius=plotPointssurfacecolour(generateCirclePointscenterradius)-- Converts a surface to a stringshowSurfaceimage=unlines[[image!(x,y)|x<-xRange]|y<-yRange]where((xLow,yLow),(xHigh,yHigh))=boundsimage(xRange,yRange)=([xLow..xHigh],[yLow..yHigh])-- Converts a surface to a string and prints itprintSurface=putStrLn.showSurface
Using the Image type from the Bitmap module defined here:
moduleCircleBitmapExamplewhereimportCircleimportBitmapimportControl.Monad.STdrawCircle::(Colorc)=>Imagesc->c->Point->Int->STs(Imagesc)drawCircleimagecolourcenterradius=doletpixels=mapPixel(generateCirclePointscenterradius)forM_pixels$\pixel->setPiximagepixelcolourreturnimage
J
Solution:
Using definitions from Basic bitmap storage. (Note that viewRGB is at the bottom of the entry - separate from the rest of the definitions.)
NB.*getBresenhamCircle v Returns points for a circle given center and radiusNB. y is: y0 x0 radiusgetBresenhamCircle=:monaddefine'y0 x0 radius'=.yx=.0y=.radiusf=.-.radiuspts=.02$0while.x<:ydo.pts=.pts,y,xif.f>:0do.y=.<:yf=.f+_2*yend.x=.>:xf=.f+>:2*xend.offsets=.(,|."1)(1_1{~#:i.4)*"1"1_pts~.,/(y0,x0)+"1offsets)NB.*drawCircles v Draws circle(s) (x) on image (y)NB. x is: 2-item list of boxed (y0 x0 radius) ; (color)drawCircles=:(1&{::;~[:;[:<@getBresenhamCircle"1(0&{::))@[setPixels]
Example usage:
myimg=:02550makeRGB2525NB. 25 by 25 green imagemyimg=:(121212;25500)drawCirclesmyimgNB. draw red circle with radius 12viewRGB((12129,:12126);00255)drawCirclesmyimgNB. draw two more concentric circles
Java
importjava.awt.Color;publicclassMidPointCircle{privateBasicBitmapStorageimage;publicMidPointCircle(finalintimageWidth,finalintimageHeight){this.image=newBasicBitmapStorage(imageWidth,imageHeight);}privatevoiddrawCircle(finalintcenterX,finalintcenterY,finalintradius){intd=(5-radius*4)/4;intx=0;inty=radius;ColorcircleColor=Color.white;do{image.setPixel(centerX+x,centerY+y,circleColor);image.setPixel(centerX+x,centerY-y,circleColor);image.setPixel(centerX-x,centerY+y,circleColor);image.setPixel(centerX-x,centerY-y,circleColor);image.setPixel(centerX+y,centerY+x,circleColor);image.setPixel(centerX+y,centerY-x,circleColor);image.setPixel(centerX-y,centerY+x,circleColor);image.setPixel(centerX-y,centerY-x,circleColor);if(d<0){d+=2*x+1;}else{d+=2*(x-y)+1;y--;}x++;}while(x<=y);}}
Julia
functiondrawcircle!(img::Matrix{T},col::T,x0::Int,y0::Int,radius::Int)whereTx=radius-1y=0δx=δy=1er=δx-(radius<<1)s=x+ywhilex≥yforopxin(+,-),opyin(+,-),elin(x,y)@inboundsimg[opx(x0,el)+1,opy(y0,s-el)+1]=colendifer≤0y+=1er+=δyδy+=2endifer>0x-=1δx+=2er+=(-radius<<1)+δxends=x+yendreturnimgend# TestusingImagesimg=fill(Gray(255.0),25,25);drawcircle!(img,Gray(0.0),12,12,12)
Kotlin
// version 1.1.4-3importjava.awt.Colorimportjava.awt.Graphicsimportjava.awt.image.BufferedImageimportjavax.swing.JOptionPaneimportjavax.swing.JLabelimportjavax.swing.ImageIconclassBasicBitmapStorage(width:Int,height:Int){valimage=BufferedImage(width,height,BufferedImage.TYPE_3BYTE_BGR)funfill(c:Color){valg=image.graphicsg.color=cg.fillRect(0,0,image.width,image.height)}funsetPixel(x:Int,y:Int,c:Color)=image.setRGB(x,y,c.getRGB())fungetPixel(x:Int,y:Int)=Color(image.getRGB(x,y))}fundrawCircle(bbs:BasicBitmapStorage,centerX:Int,centerY:Int,radius:Int,circleColor:Color){vard=(5-radius*4)/4varx=0vary=radiusdo{with(bbs){setPixel(centerX+x,centerY+y,circleColor)setPixel(centerX+x,centerY-y,circleColor)setPixel(centerX-x,centerY+y,circleColor)setPixel(centerX-x,centerY-y,circleColor)setPixel(centerX+y,centerY+x,circleColor)setPixel(centerX+y,centerY-x,circleColor)setPixel(centerX-y,centerY+x,circleColor)setPixel(centerX-y,centerY-x,circleColor)}if(d<0){d+=2*x+1}else{d+=2*(x-y)+1y--}x++}while(x<=y)}funmain(args:Array<String>){valbbs=BasicBitmapStorage(400,400)bbs.fill(Color.pink)drawCircle(bbs,200,200,100,Color.black)drawCircle(bbs,200,200,50,Color.white)vallabel=JLabel(ImageIcon(bbs.image))valtitle="Bresenham's circle algorithm"JOptionPane.showMessageDialog(null,label,title,JOptionPane.PLAIN_MESSAGE)}
Lua
Uses Bitmap class here, with an ASCII pixel representation, then extending..
functionBitmap:circle(x,y,r,c)localdx,dy,err=r,0,1-rwhiledx>=dydoself:set(x+dx,y+dy,c)self:set(x-dx,y+dy,c)self:set(x+dx,y-dy,c)self:set(x-dx,y-dy,c)self:set(x+dy,y+dx,c)self:set(x-dy,y+dx,c)self:set(x+dy,y-dx,c)self:set(x-dy,y-dx,c)dy=dy+1iferr<0thenerr=err+2*dy+1elsedx,err=dx-1,err+2*(dy-dx)+1endendend
Demo:
functionBitmap:axes()localhw,hh=math.floor(self.width/2),math.floor(self.height/2)fori=0,self.width-1doself:set(i,hh,"-")endfori=0,self.height-1doself:set(hw,i,"|")endself:set(hw,hh,"+")endfunctionBitmap:render()fory=1,self.heightdoprint(table.concat(self.pixels[y]," "))endendbitmap=Bitmap(25,25)bitmap:clear("·")bitmap:axes()bitmap:circle(12,12,11,"■")bitmap:circle(12,12,8,"■")bitmap:circle(12,12,5,"■")bitmap:circle(12,12,2,"■")bitmap:render()
- Output:
· · · · · · · · · · · · | · · · · · · · · · · · · · · · · · · · · · ■ ■ ■ ■ ■ ■ ■ · · · · · · · · · · · · · · · · ■ ■ · · · | · · · ■ ■ · · · · · · · · · · · · ■ ■ · · · · · | · · · · · ■ ■ · · · · · · · · · ■ · · · · · ■ ■ ■ ■ ■ · · · · · ■ · · · · · · · ■ · · · · ■ ■ · · | · · ■ ■ · · · · ■ · · · · · · ■ · · ■ ■ · · · · | · · · · ■ ■ · · ■ · · · · · ■ · · · ■ · · · ■ ■ ■ ■ ■ · · · ■ · · · ■ · · · · ■ · · ■ · · · ■ · · | · · ■ · · · ■ · · ■ · · · ■ · · · ■ · · ■ · · · | · · · ■ · · ■ · · · ■ · · ■ · · ■ · · ■ · · · ■ ■ ■ · · · ■ · · ■ · · ■ · · ■ · · ■ · · ■ · · ■ · | · ■ · · ■ · · ■ · · ■ · - ■ - - ■ - - ■ - - ■ - + - ■ - - ■ - - ■ - - ■ - · ■ · · ■ · · ■ · · ■ · | · ■ · · ■ · · ■ · · ■ · · ■ · · ■ · · ■ · · · ■ ■ ■ · · · ■ · · ■ · · ■ · · ■ · · · ■ · · ■ · · · | · · · ■ · · ■ · · · ■ · · · ■ · · ■ · · · ■ · · | · · ■ · · · ■ · · ■ · · · · ■ · · · ■ · · · ■ ■ ■ ■ ■ · · · ■ · · · ■ · · · · · ■ · · ■ ■ · · · · | · · · · ■ ■ · · ■ · · · · · · ■ · · · · ■ ■ · · | · · ■ ■ · · · · ■ · · · · · · · ■ · · · · · ■ ■ ■ ■ ■ · · · · · ■ · · · · · · · · · ■ ■ · · · · · | · · · · · ■ ■ · · · · · · · · · · · · ■ ■ · · · | · · · ■ ■ · · · · · · · · · · · · · · · · ■ ■ ■ ■ ■ ■ ■ · · · · · · · · · · · · · · · · · · · · · | · · · · · · · · · · · ·
Mathematica / Wolfram Language
SetAttributes[drawcircle,HoldFirst];drawcircle[img_,{x0_,y0_},r_,color_:White]:=Module[{f=1-r,ddfx=1,ddfy=-2r,x=0,y=r,pixels={{0,r},{0,-r},{r,0},{-r,0}}},While[x<y,If[f>=0,y--;ddfy+=2;f+=ddfy];x++;ddfx+=2;f+=ddfx;pixels=Join[pixels,{{x,y},{x,-y},{-x,y},{-x,-y},{y,x},{y,-x},{-y,x},{-y,-x}}]];img=ReplacePixelValue[img,{x0,y0}+#->color&/@pixels]]
Example usage(it will draw a circle on Lena's face.):
img=ExampleData[{"TestImage","Lena"}];drawcircle[img,{250,250},100]
Modula-3
INTERFACECircle;IMPORTBitmap;PROCEDUREDraw(img:Bitmap.T;center:Bitmap.Point;radius:CARDINAL;color:Bitmap.Pixel);ENDCircle.
MODULECircle;IMPORTBitmap;PROCEDUREDraw(img:Bitmap.T;center:Bitmap.Point;radius:CARDINAL;color:Bitmap.Pixel)=VARf:=1-radius;ddfx:=0;ddfy:=-2*radius;x:=0;y:=radius;BEGINBitmap.SetPixel(img,Bitmap.Point{center.x,center.y+radius},color);Bitmap.SetPixel(img,Bitmap.Point{center.x,center.y-radius},color);Bitmap.SetPixel(img,Bitmap.Point{center.x+radius,center.y},color);Bitmap.SetPixel(img,Bitmap.Point{center.x-radius,center.y},color);WHILEx<yDOIFf>=0THENy:=y-1;ddfy:=ddfy+2;f:=f+ddfy;END;x:=x+1;ddfx:=ddfx+2;f:=f+ddfx+1;Bitmap.SetPixel(img,Bitmap.Point{center.x+x,center.y+y},color);Bitmap.SetPixel(img,Bitmap.Point{center.x-x,center.y+y},color);Bitmap.SetPixel(img,Bitmap.Point{center.x+x,center.y-y},color);Bitmap.SetPixel(img,Bitmap.Point{center.x-x,center.y-y},color);Bitmap.SetPixel(img,Bitmap.Point{center.x+y,center.y+x},color);Bitmap.SetPixel(img,Bitmap.Point{center.x-y,center.y+x},color);Bitmap.SetPixel(img,Bitmap.Point{center.x+y,center.y-x},color);Bitmap.SetPixel(img,Bitmap.Point{center.x-y,center.y-x},color);END;ENDDraw;BEGINENDCircle.
Example (outputs a PPM image):
MODULEMain;IMPORTCircle,Bitmap,PPM;VARtestpic:Bitmap.T;BEGINtestpic:=Bitmap.NewImage(32,32);Bitmap.Fill(testpic,Bitmap.White);Circle.Draw(testpic,Bitmap.Point{16,16},10,Bitmap.Black);PPM.Create("testpic.ppm",testpic);ENDMain.
Nim
importbitmapprocsetPixel(img:Image;x,y:int;color:Color){.inline.}=# Set a pixel at a given color.# Ignore if the point is outside of the image.ifxin0..<img.wandyin0..<img.h:img[x,y]=colorprocdrawCircle(img:Image;center:Point;radius:Natural;color:Color)=## Draw a circle using midpoint circle algorithm.varf=1-radiusddFX=0ddFY=-2*radiusx=0y=radiusimg.setPixel(center.x,center.y+radius,color)img.setPixel(center.x,center.y-radius,color)img.setPixel(center.x+radius,center.y,color)img.setPixel(center.x-radius,center.y,color)whilex<y:iff>=0:decyincddFY,2incf,ddFYincxincddFX,2incf,ddFX+1img.setPixel(center.x+x,center.y+y,color)img.setPixel(center.x-x,center.y+y,color)img.setPixel(center.x+x,center.y-y,color)img.setPixel(center.x-x,center.y-y,color)img.setPixel(center.x+y,center.y+x,color)img.setPixel(center.x-y,center.y+x,color)img.setPixel(center.x+y,center.y-x,color)img.setPixel(center.x-y,center.y-x,color)#———————————————————————————————————————————————————————————————————————————————————————————————————whenisMainModule:varimg=newImage(16,16)img.fill(White)img.drawCircle((7,7),5,Black)img.print()
- Output:
................ ................ .....HHHHH...... ....H.....H..... ...H.......H.... ..H.........H... ..H.........H... ..H.........H... ..H.........H... ..H.........H... ...H.......H.... ....H.....H..... .....HHHHH...... ................ ................ ................
OCaml
letraster_circle~img~color~c:(x0,y0)~r=letplot=put_pixelimgcolorinletx=0andy=randm=5-4*rinletrecloopxym=plot(x0+x)(y0+y);plot(x0+y)(y0+x);plot(x0-x)(y0+y);plot(x0-y)(y0+x);plot(x0+x)(y0-y);plot(x0+y)(y0-x);plot(x0-x)(y0-y);plot(x0-y)(y0-x);lety,m=ifm>0then(y-1),(m-8*y)elsey,minifx<=ythenletx=x+1inletm=m+8*x+4inloopxyminloopxym;;
Perl
# 20220301 Perl programming solutionusestrict;usewarnings;useAlgorithm::Line::Bresenham'circle';my@points;my@circle=circle((10)x3);for(@circle){$points[$_->[0]][$_->[1]]='#'}printjoin"\n",map{join'',map{$_||' '}@$_}@points
- Output:
####### ## ## # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## ## #######
Phix
Requires new_image() from Bitmap, write_ppm() from Write_a_PPM_file.
Results may be verified with demo\rosetta\viewppm.exw
-- demo\rosetta\Bitmap_Circle.exw (runnable version)includeppm.e-- red, yellow, new_image(), write_ppm() -- (covers above requirements)functionSetPx(sequenceimg,atomx,y,integercolour)ifx>=1andx<=length(img)andy>=1andy<=length(img[x])thenimg[x][y]=colour endifreturnimg endfunctionfunctionCircle(sequenceimg,atomx,y,r,integercolour)atomx1=-r,y1=0,err=2-2*r ifr>=0then-- Bresenham algorithmwhile1doimg=SetPx(img,x-x1,y+y1,colour)img=SetPx(img,x-y1,y-x1,colour)img=SetPx(img,x+x1,y-y1,colour)img=SetPx(img,x+y1,y+x1,colour)r=err ifr>x1thenx1+=1 err+=x1*2+1 endififr<=y1theny1+=1 err+=y1*2+1 endififx1>=0thenexitendifendwhileendifreturnimg endfunctionsequenceimg=new_image(400,300,yellow) img=Circle(img,200,150,100,red) write_ppm("Circle.ppm",img)
PicoLisp
(de midPtCircle (Img CX CY Rad) (let (F (- 1 Rad) DdFx 0 DdFy (* -2 Rad) X 0 Y Rad) (set (nth Img (+ CY Rad) CX) 1) (set (nth Img (- CY Rad) CX) 1) (set (nth Img CY (+ CX Rad)) 1) (set (nth Img CY (- CX Rad)) 1) (while (> Y X) (when (ge0 F) (dec 'Y) (inc 'F (inc 'DdFy 2)) ) (inc 'X) (inc 'F (inc (inc 'DdFx 2))) (set (nth Img (+ CY Y) (+ CX X)) 1) (set (nth Img (+ CY Y) (- CX X)) 1) (set (nth Img (- CY Y) (+ CX X)) 1) (set (nth Img (- CY Y) (- CX X)) 1) (set (nth Img (+ CY X) (+ CX Y)) 1) (set (nth Img (+ CY X) (- CX Y)) 1) (set (nth Img (- CY X) (+ CX Y)) 1) (set (nth Img (- CY X) (- CX Y)) 1) ) ) ) (let Img (make (do 120 (link (need 120 0)))) # Create image 120 x 120 (midPtCircle Img 60 60 50) # Draw circle (out "img.pbm" # Write to bitmap file (prinl "P1") (prinl 120 " " 120) (mapc prinl Img) ) )
PL/I
/* Plot three circles. */ CIRCLE: PROCEDURE OPTIONS (MAIN); declare image (-20:20, -20:20) character (1); declare j fixed binary; image = '.'; image(0,*) = '-'; image(*,0) = '|'; image(0,0) = '+'; CALL DRAW_CIRCLE (0, 0, 11); CALL DRAW_CIRCLE (0, 0, 8); CALL DRAW_CIRCLE (0, 0, 19); do j = hbound(image,1) to lbound(image,1) by -1; put skip edit (image(j,*)) (a(1)); end; draw_circle: procedure (x0, y0, radius); /* 14 May 2010. */ declare ( x0, y0, radius ) fixed binary; declare ( ddfx, ddfy, x, y, f ) fixed binary; declare debug bit (1) aligned static initial ('0'b); f = 1-radius; ddfx = 1; ddfy = -2*radius; x = 0; y = radius; image(x0, y0+radius) = '*'; /* Octet 0. */ image(x0+radius, y0) = '*'; /* Octet 1. */ image(x0, y0-radius) = '*'; /* Octet 2. */ image(x0-radius, y0) = '*'; /* Octet 3. */ do while (x < y); if f >= 0 then do; y = y - 1; ddfy = ddfy +2; f = f + ddfy; end; x = x + 1; ddfx = ddfx + 2; f = f + ddfx; image(x0+x, y0+y) = '0'; /* Draws octant 0. */ image(x0+y, y0+x) = '1'; /* Draws octant 1. */ image(x0+y, y0-x) = '2'; /* Draws octant 2. */ image(x0+x, y0-y) = '3'; /* Draws octant 3. */ image(x0-x, y0-y) = '4'; /* Draws octant 4. */ image(x0-y, y0-x) = '5'; /* Draws octant 5. */ image(x0-y, y0+x) = '6'; /* Draws octant 6. */ image(x0-x, y0+y) = '7'; /* Draws octant 7. */ end; end draw_circle; END CIRCLE;
- Output:
for three circles centered at the origin.
....................|.................... ................2222*1111................ .............222....|....111............. ...........22.......|.......11........... ..........2.........|.........1.......... ........22..........|..........11........ .......3............|............0....... ......2.............|.............1...... .....3..............|..............0..... .....3...........222*111...........0..... ....3..........22...|...11..........0.... ...3..........2.....|.....1..........0... ...3........32....22*11....11........0... ..3.........3...22..|..11...0.........0.. ..3........3...3....|....0...0........0.. ..3.......3...2.....|.....1...0.......0.. .3........3..3......|......0..0........0. .3.......3...3......|......0...0.......0. .3.......3..3.......|.......0..0.......0. .3.......3..3.......|.......0..0.......0. -*-------*--*-------+-------*--*-------*- .4.......4..4.......|.......7..7.......7. .4.......4..4.......|.......7..7.......7. .4.......4...4......|......7...7.......7. .4........4..4......|......7..7........7. ..4.......4...5.....|.....6...7.......7.. ..4........4...4....|....7...7........7.. ..4.........4...55..|..66...7.........7.. ...4........55....55*66....67........7... ...4..........5.....|.....6..........7... ....4..........55...|...66..........7.... .....4...........555*666...........7..... .....4..............|..............7..... ......5.............|.............6...... .......4............|............7....... ........55..........|..........66........ ..........5.........|.........6.......... ...........55.......|.......66........... .............555....|....666............. ................5555*6666................ ....................|....................
PureBasic
ProcedurerasterCircle(cx,cy,r,Color);circlemustliecompletelywithintheimageboundariesProtectedf=1-rProtectedddF_X,ddF_Y=-2*rProtectedx,y=rPlot(cx,cy+r,Color)Plot(cx,cy-r,Color)Plot(cx+r,cy,Color)Plot(cx-r,cy,Color)Whilex<yIff>=0y-1ddF_Y+2f+ddF_YEndIfx+1ddF_X+2f+ddF_X+1Plot(cx+x,cy+y,Color)Plot(cx-x,cy+y,Color)Plot(cx+x,cy-y,Color)Plot(cx-x,cy-y,Color)Plot(cx+y,cy+x,Color)Plot(cx-y,cy+x,Color)Plot(cx+y,cy-x,Color)Plot(cx-y,cy-x,Color)WendEndProcedureOpenWindow(0,0,0,100,100,"MidPoint Circle Algorithm",#PB_Window_SystemMenu)CreateImage(0,100,100,32)StartDrawing(ImageOutput(0))Box(0,0,100,100,RGB(0,0,0))rasterCircle(25,25,20,RGB(255,255,255))rasterCircle(50,50,40,RGB(255,0,0))StopDrawing()ImageGadget(0,0,0,0,0,ImageID(0))Repeat:UntilWaitWindowEvent()=#PB_Event_CloseWindow
Python
Extending the example given here
defcircle(self,x0,y0,radius,colour=black):f=1-radiusddf_x=1ddf_y=-2*radiusx=0y=radiusself.set(x0,y0+radius,colour)self.set(x0,y0-radius,colour)self.set(x0+radius,y0,colour)self.set(x0-radius,y0,colour)whilex<y:iff>=0:y-=1ddf_y+=2f+=ddf_yx+=1ddf_x+=2f+=ddf_xself.set(x0+x,y0+y,colour)self.set(x0-x,y0+y,colour)self.set(x0+x,y0-y,colour)self.set(x0-x,y0-y,colour)self.set(x0+y,y0+x,colour)self.set(x0-y,y0+x,colour)self.set(x0+y,y0-x,colour)self.set(x0-y,y0-x,colour)Bitmap.circle=circlebitmap=Bitmap(25,25)bitmap.circle(x0=12,y0=12,radius=12)bitmap.chardisplay()'''The origin, 0,0; is the lower left, with x increasing to the right,and Y increasing upwards.The program above produces the following display :+-------------------------+| @@@@@@@ || @@ @@ || @@ @@ || @ @ || @ @ || @ @ || @ @ || @ @ || @ @ ||@ @||@ @||@ @||@ @||@ @||@ @||@ @|| @ @ || @ @ || @ @ || @ @ || @ @ || @ @ || @@ @@ || @@ @@ || @@@@@@@ |+-------------------------+'''
Racket
Port of the Pyhton solution.
#lang racket(requireracket/draw)(define-syntax⊕(syntax-rules()[(_ide)(set!id(+ide))]))(define(draw-pointdcxy)(senddcdraw-pointxy))(define(draw-circledcx0y0r)(definef(-1r))(defineddf_x1)(defineddf_y(*-2r))(definex0)(defineyr)(draw-pointdcx0(+y0r))(draw-pointdcx0(-y0r))(draw-pointdc(+x0r)y0)(draw-pointdc(-x0r)y0)(letloop()(when(<xy)(when(>=f0)(⊕y-1)(⊕ddf_y2)(⊕fddf_y))(⊕x1)(⊕ddf_x2)(⊕fddf_x)(draw-pointdc(+x0x)(+y0y))(draw-pointdc(-x0x)(+y0y))(draw-pointdc(+x0x)(-y0y))(draw-pointdc(-x0x)(-y0y))(draw-pointdc(+x0y)(+y0x))(draw-pointdc(-x0y)(+y0x))(draw-pointdc(+x0y)(-y0x))(draw-pointdc(-x0y)(-y0x))(loop))))(definebm(make-objectbitmap%2525))(definedc(newbitmap-dc%[bitmapbm]))(senddcset-smoothing'unsmoothed)(senddcset-pen"red"1'solid)(draw-circledc121212)bm
Raku
(formerly Perl 6)
We'll augment the Pixel and Bitmap classes from the Bitmap task.
useMONKEY-TYPING; classPixel { hasUInt ($.R, $.G, $.B) } classBitmap { hasUInt ($.width, $.height); hasPixel@!data; methodfill(Pixel \p) { @!data = pxx ($!width × $!height) } methodpixel( \iwhere ^$!width, \jwhere ^$!height --> Pixel) isrw { @!data[i × $!width + j] } methodset-pixel (\i, \j, Pixel \p) { self.pixel(i, j) = p; } methodget-pixel (\i, \j) returnsPixel { self.pixel(i, j); } } augmentclassPixel { methodStr { "$.R $.G $.B" } } augmentclassBitmap { methodP3 { join"\n", «P3"$.width $.height"255», dofor ^($.width × $.height) { join' ', @!data[$_] } } methodraster-circle ( \x0, \y0, \r, Pixel \value ) { my$ddF_x = 0; my$ddF_y = -2 × r; my$f = 1 - r; my ($x, $y) = 0, r; forflat (0X1,-1),(1,-1X0) -> \i, \j { self.set-pixel(x0 + i×r, y0 + j×r, value) } while$x < $y { ($y--; $f += ($ddF_y += 2)) if$f ≥ 0; $x++; $f += 1 + ($ddF_x += 2); forflat (1,-1) X (1,-1) -> \i, \j { self.set-pixel(x0 + i×$x, y0 + j×$y, value); self.set-pixel(x0 + i×$y, y0 + j×$x, value); } } } } myBitmap$b = Bitmap.new( width => 32, height => 32); $b.fill( Pixel.new( R => 0, G => 0, B => 0) ); $b.raster-circle(16, 16, 15, Pixel.new(R=>0, G=>0, B=>100)); say$b.P3;
REXX
Programming note: because of character output to a terminal screen, a circle appears to be elongated in the
vertical direction because characters are "taller" than they're "wide", so this REXX version attempts to maintain
a good aspect ratio.
The program automatically shows all of the plot's points by finding the minimum and maximum X,Y coördinates.
/*REXX program plots three circles using midpoint/Bresenham's circle algorithm. */@.='·'/*fill the array with middle─dots char.*/ minX=0;maxX=0;minY=0;maxY=0/*initialize the minimums and maximums.*/calldrawCircle0,0,8,'#'/*plot 1st circle with pound character.*/calldrawCircle0,0,11,'$'/* " 2nd " " dollar " */calldrawCircle0,0,19,'@'/* " 3rd " " commercial at. */ border=2/*BORDER: shows N extra grid points.*/ minX=minX-border*2;maxX=maxX+border*2/*adjust min and max X to show border*/ minY=minY-border;maxY=maxY+border/* " " " " Y " " " */if@.0.0==@.then@.0.0='┼'/*maybe define the plot's axis origin. *//*define the plot's horizontal grid──┐ */doh=minXtomaxX;if@.h.0==@.then@.h.0='─';end/* ◄───────────┘ */dov=minYtomaxY;if@.0.v==@.then@.0.v='│';end/* ◄──────────┐ *//*define the plot's vertical grid───┘ */doy=maxYby-1tominY;_=/* [↓] draw grid from top ──► bottom.*/dox=minXtomaxX;_=_||@.x.y/* ◄─── " " " left ──► right. */end/*x*//* [↑] a grid row should be finished. */say_/*display a single row of the grid. */end/*y*/exit/*stick a fork in it, we're all done. *//*──────────────────────────────────────────────────────────────────────────────────────*/drawCircle:procedureexpose@.minXmaxXminYmaxY parseargxx,yy,r1y,plotChar;fx=1;fy=-2*r/*get X,Y coördinates*/f=1-r dox=0whilex<y/*▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒*/iff>=0thendo;y=y-1;fy=fy+2;f=f+fy;end/*▒*/fx=fx+2;f=f+fx/*▒*/callplotPointxx+x,yy+y/*▒*/callplotPointxx+y,yy+x/*▒*/callplotPointxx+y,yy-x/*▒*/callplotPointxx+x,yy-y/*▒*/callplotPointxx-y,yy+x/*▒*/callplotPointxx-x,yy+y/*▒*/callplotPointxx-x,yy-y/*▒*/callplotPointxx-y,yy-x/*▒*/end/*x*//* [↑] place plot points ══► plot.▒▒▒▒▒▒▒▒▒▒▒▒*/return/*──────────────────────────────────────────────────────────────────────────────────────*/plotPoint:parseargc,r;@.c.r=plotChar/*assign a character to be plotted. */minX=min(minX,c);maxX=max(maxX,c)/*determine the minimum and maximum X.*/minY=min(minY,r);maxY=max(maxY,r)/* " " " " " Y.*/return
- output when using the default inputs:
·······················│······················· ·······················│······················· ····················@@@@@@@···················· ·················@@@···│···@@@················· ···············@@······│······@@··············· ··············@········│········@·············· ············@@·········│·········@@············ ···········@···········│···········@··········· ··········@············│············@·········· ·········@·············│·············@········· ········@············$$$$$············@········ ········@··········$$··│··$$··········@········ ·······@··········$····│····$··········@······· ······@·········$$····###····$$·········@······ ······@········$····##·│·##····$········@······ ·····@·········$···#···│···#···$·········@····· ·····@········$···#····│····#···$········@····· ·····@·······$···#·····│·····#···$·······@····· ····@········$··#······│······#··$········@···· ····@·······$···#······│······#···$·······@···· ····@·······$··#·······│·······#··$·······@···· ────@───────$──#───────┼───────#──$───────@──── ····@·······$··#·······│·······#··$·······@···· ····@·······$···#······│······#···$·······@···· ····@········$··#······│······#··$········@···· ·····@·······$···#·····│·····#···$·······@····· ·····@········$···#····│····#···$········@····· ·····@·········$···#···│···#···$·········@····· ······@········$····##·│·##····$········@······ ······@·········$$····###····$$·········@······ ·······@··········$····│····$··········@······· ········@··········$$··│··$$··········@········ ········@············$$$$$············@········ ·········@·············│·············@········· ··········@············│············@·········· ···········@···········│···········@··········· ············@@·········│·········@@············ ··············@········│········@·············· ···············@@······│······@@··············· ·················@@@···│···@@@················· ····················@@@@@@@···················· ·······················│······················· ·······················│·······················
Ruby
Pixel=Struct.new(:x,:y)classPixmapdefdraw_circle(pixel,radius,colour)validate_pixel(pixel.x,pixel.y)self[pixel.x,pixel.y+radius]=colourself[pixel.x,pixel.y-radius]=colourself[pixel.x+radius,pixel.y]=colourself[pixel.x-radius,pixel.y]=colourf=1-radiusddF_x=1ddF_y=-2*radiusx=0y=radiuswhilex<yiff>=0y-=1ddF_y+=2f+=ddF_yendx+=1ddF_x+=2f+=ddF_xself[pixel.x+x,pixel.y+y]=colourself[pixel.x+x,pixel.y-y]=colourself[pixel.x-x,pixel.y+y]=colourself[pixel.x-x,pixel.y-y]=colourself[pixel.x+y,pixel.y+x]=colourself[pixel.x+y,pixel.y-x]=colourself[pixel.x-y,pixel.y+x]=colourself[pixel.x-y,pixel.y-x]=colourendendendbitmap=Pixmap.new(30,30)bitmap.draw_circle(Pixel[14,14],12,RGBColour::BLACK)
Scala
Uses the Scala Basic Bitmap Storage class.
objectBitmapOps{defmidpoint(bm:RgbBitmap,x0:Int,y0:Int,radius:Int,c:Color)={varf=1-radiusvarddF_x=1varddF_y=-2*radiusvarx=0vary=radiusbm.setPixel(x0,y0+radius,c)bm.setPixel(x0,y0-radius,c)bm.setPixel(x0+radius,y0,c)bm.setPixel(x0-radius,y0,c)while(x<y){if(f>=0){y-=1ddF_y+=2f+=ddF_y}x+=1ddF_x+=2f+=ddF_xbm.setPixel(x0+x,y0+y,c)bm.setPixel(x0-x,y0+y,c)bm.setPixel(x0+x,y0-y,c)bm.setPixel(x0-x,y0-y,c)bm.setPixel(x0+y,y0+x,c)bm.setPixel(x0-y,y0+x,c)bm.setPixel(x0+y,y0-x,c)bm.setPixel(x0-y,y0-x,c)}}}
Tcl
ref Basic bitmap storage#Tcl and Assertions#Tcl
packagerequireTcl8.5packagerequireTk procdrawCircle{imagecolourpointradius}{lassign$pointx0y0 setPixel$image$colour[list$x0[expr{$y0+$radius}]]setPixel$image$colour[list$x0[expr{$y0-$radius}]]setPixel$image$colour[list[expr{$x0+$radius}]$y0]setPixel$image$colour[list[expr{$x0-$radius}]$y0]setf[expr{1-$radius}]setddF_x1setddF_y[expr{-2*$radius}]setx0sety$radiuswhile{$x<$y}{assert{$ddF_x==2*$x+1}assert{$ddF_y==-2*$y}assert{$f==$x*$x+$y*$y-$radius*$radius+2*$x-$y+1}if{$f>=0}{incry-1incrddF_y2incrf$ddF_y}incrx incrddF_x2incrf$ddF_xsetPixel$image$colour[list[expr{$x0+$x}][expr{$y0+$y}]]setPixel$image$colour[list[expr{$x0-$x}][expr{$y0+$y}]]setPixel$image$colour[list[expr{$x0+$x}][expr{$y0-$y}]]setPixel$image$colour[list[expr{$x0-$x}][expr{$y0-$y}]]setPixel$image$colour[list[expr{$x0+$y}][expr{$y0+$x}]]setPixel$image$colour[list[expr{$x0-$y}][expr{$y0+$x}]]setPixel$image$colour[list[expr{$x0+$y}][expr{$y0-$x}]]setPixel$image$colour[list[expr{$x0-$y}][expr{$y0-$x}]]}}# create the image and display itsetimg[newImage200100]label.l-image$imgpack.l fill$imgblack drawCircle$imgblue{10050}49
Vedit macro language
// Draw a circle using Bresenham's circle algorithm. // #21 = center x, #22 = center y; #23 = radius :DRAW_CIRCLE: #30 = 1 - #23 // f #31 = 0 // ddF_x #32 = -2 * #23 // ddF_y #41 = 0 // x #42 = #23 // y while (#41 <= #42) { #1 = #21+#41; #2 = #22+#42; Call("DRAW_PIXEL") #1 = #21-#41; #2 = #22+#42; Call("DRAW_PIXEL") #1 = #21+#41; #2 = #22-#42; Call("DRAW_PIXEL") #1 = #21-#41; #2 = #22-#42; Call("DRAW_PIXEL") #1 = #21+#42; #2 = #22+#41; Call("DRAW_PIXEL") #1 = #21-#42; #2 = #22+#41; Call("DRAW_PIXEL") #1 = #21+#42; #2 = #22-#41; Call("DRAW_PIXEL") #1 = #21-#42; #2 = #22-#41; Call("DRAW_PIXEL") if (#30 >= 0) { #42-- #32 += 2 #30 += #32 } #41++ #31 += 2 #30 += #31 + 1 } return
Wren
import"graphics"forCanvas,Color,ImageDataimport"dome"forWindowclassMidpointCircle{constructnew(width,height){Window.title="Midpoint Circle"Window.resize(width,height)Canvas.resize(width,height)_w=width_h=height_bmp=ImageData.create("midpoint circle",width,height)}init(){fill(Color.pink)drawCircle(200,200,100,Color.black)drawCircle(200,200,50,Color.white)_bmp.draw(0,0)}fill(col){for(xin0..._w){for(yin0..._h)pset(x,y,col)}}drawCircle(centerX,centerY,radius,circleColor){vard=((5-radius*4)/4).truncatevarx=0vary=radiuswhile(true){pset(centerX+x,centerY+y,circleColor)pset(centerX+x,centerY-y,circleColor)pset(centerX-x,centerY+y,circleColor)pset(centerX-x,centerY-y,circleColor)pset(centerX+y,centerY+x,circleColor)pset(centerX+y,centerY-x,circleColor)pset(centerX-y,centerY+x,circleColor)pset(centerX-y,centerY-x,circleColor)if(d<0){d=d+2*x+1}else{d=d+2*(x-y)+1y=y-1}x=x+1if(x>y)break}}pset(x,y,col){_bmp.pset(x,y,col)}pget(x,y){_bmp.pget(x,y)}update(){}draw(alpha){}}varGame=MidpointCircle.new(400,400)
XPL0
include c:\cxpl\codes; \include 'code' declarations proc Circle(X0, Y0, Radius, Color); \Display a circle int X0, Y0, \coordinates of center Radius, \radius in (pixels) Color; \line color int X, Y, E, U, V; proc PlotOctants; \Segment [Point(X0+Y, Y0+X, Color); \ 0 Point(X0+X, Y0+Y, Color); \ 1 Point(X0-X, Y0+Y, Color); \ 2 Point(X0-Y, Y0+X, Color); \ 3 Point(X0-Y, Y0-X, Color); \ 4 Point(X0-X, Y0-Y, Color); \ 5 Point(X0+X, Y0-Y, Color); \ 6 Point(X0+Y, Y0-X, Color); \ 7 ]; \PlotOctants [X:= 0; Y:= Radius; U:= 1; V:= 1 -Radius -Radius; E:= 1 -Radius; while X < Y do [PlotOctants; if E < 0 then [U:= U+2; V:= V+2; E:= E+U] else [U:= U+2; V:= V+4; E:= E+V; Y:= Y-1]; X:= X+1; ]; if X = Y then PlotOctants; ]; \Circle [SetVid($112); \640x480 in 24-bit RGB color Circle(110, 110, 50, $FFFF00); if ChIn(1) then []; \wait for keystroke SetVid(3); \restore normal text mode ]
zkl
Image cribbed from the BBC BASIC entry. Algorithm from Wikipedia article.
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

This is the code from the PPM class:
fcn circle(x0,y0,r,rgb){ x:=r; y:=0; radiusError:=1-x; while(x >= y){ __sSet(rgb, x + x0, y + y0); __sSet(rgb, y + x0, x + y0); __sSet(rgb,-x + x0, y + y0); __sSet(rgb,-y + x0, x + y0); self[-x + x0, -y + y0]=rgb; // or do it this way, __sSet gets called as above self[-y + x0, -x + y0]=rgb; self[ x + x0, -y + y0]=rgb; self[ y + x0, -x + y0]=rgb; y+=1; if (radiusError<0) radiusError+=2*y + 1; else{ x-=1; radiusError+=2*(y - x + 1); } } }
ppm:=PPM(200,200,0xFF|FF|FF); ppm.circle(100,100,40,00); // black circle ppm.circle(100,100,80,0xFF|00|00); // red circle ppm.write(File("foo.ppm","wb"));
- Geometry
- Programming Tasks
- Raster graphics operations
- 11l
- Action!
- Action! Bitmap tools
- Ada
- ALGOL 68
- Applesoft BASIC
- ATS
- Bash
- BASIC
- BASIC256
- Batch File
- BBC BASIC
- C
- C sharp
- Clojure
- Common Lisp
- D
- Delphi
- SysUtils,StdCtrls
- ERRE
- Evaldraw
- FBSL
- Forth
- Fortran
- FreeBASIC
- FutureBasic
- Go
- Haskell
- J
- Java
- Julia
- Kotlin
- Lua
- Mathematica
- Wolfram Language
- Modula-3
- Nim
- OCaml
- Perl
- Phix
- PicoLisp
- PL/I
- PureBasic
- Python
- Racket
- Raku
- REXX
- Ruby
- Scala
- Tcl
- Tk
- Vedit macro language
- Wren
- DOME
- XPL0
- Zkl
- AWK/Omit
- PARI/GP/Omit