Draw an antialiased circle?

Just starting out? Need help? Post your questions and find answers here.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Draw an antialiased circle?

Post by Dude »

I'm using Circle() on an image but it's jaggy. Is there a way (or trick) to do it anti-aliased, so it's got a smooth edge?
User avatar
heartbone
Addict
Addict
Posts: 1058
Joined: Fri Apr 12, 2013 1:55 pm
Location: just outside of Ferguson

Re: Draw an antialiased circle?

Post by heartbone »

As it exists is in this snippet, this method is pretty much unusable in actual applications, but yields the smooth circle that you seek.
After running, a file is in your temp folder for inspection.

Code: Select all

UsePNGImageEncoder()
InitSprite()
OpenWindow(0,0,0,600,600,"SOFTWARE",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,800,600,#True,0,0)
CreateImage(0,1200,1200,32)
StartDrawing(ImageOutput(0))
Circle(600,600,550,$00DDDD)
Circle(600,600,545,$000000)
StopDrawing()
ResizeImage(0,555,555,#PB_Image_Smooth)
StartDrawing(ScreenOutput())
DrawImage(ImageID(0),25,25)
StopDrawing()
FlipBuffers()
SaveImage(0,GetTemporaryDirectory()+"/smoothercircle.png")
Delay(2000)
Depending on the background imagery, if you transform the circle image into a transparent sprite, then you may have a solution.
Keep it BASIC.
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Draw an antialiased circle?

Post by IdeasVacuum »

IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
TI-994A
Addict
Addict
Posts: 2741
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Draw an antialiased circle?

Post by TI-994A »

Dude wrote:...Is there a way (or trick) to do it anti-aliased, so it's got a smooth edge?
Hello Dude. The jagged edges are caused by the low screen resolution. The trick would be to draw the circle on a high resolution context, and then transpose it onto the screen, like so:

Code: Select all

wFlags = #PB_Window_SystemMenu | #PB_Window_ScreenCentered
OpenWindow(0, 0, 0, 500, 500, "Smooth Circle", wFlags)
If CreateImage(0, 2000, 2000, 32, #Red) And StartDrawing(ImageOutput(0))
  Circle(1000, 1000, 900, #Yellow)
  StopDrawing() 
  ResizeImage(0, 500, 500)
  ImageGadget(0, 0, 0, 500, 500, ImageID(0))
EndIf
While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
Samuel
Enthusiast
Enthusiast
Posts: 755
Joined: Sun Jul 29, 2012 10:33 pm
Location: United States

Re: Draw an antialiased circle?

Post by Samuel »

You can also use gradients to create anti aliased circles.

Code: Select all

Enumeration
  #Window
  #Canvas
EndEnumeration

Declare AntialiasedCircle(StartX.d, StartY.d, Radius.d, AntiLength.d, Color.i)

Global.i WindowW = 800
Global.i WindowH = 600

If OpenWindow(#Window, 0, 0, WindowW, WindowH, "Antialiased Circle", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

  CanvasGadget(#Canvas, 0, 0, WindowW, WindowH)
  
  StartDrawing(CanvasOutput(#Canvas))
    Box(0, 0, WindowW, WindowH, RGB(30,30,30))
    AntialiasedCircle(WindowW*0.5, WindowH*0.5, 200, 2, RGB(255,0,0))
    AntialiasedCircle(        100,         100,  80, 2, RGB(0,0,255))
    AntialiasedCircle(WindowW-100,         100,  50, 2, RGB(0,255,0))
    AntialiasedCircle(        100, WindowH-100,  50, 2, RGB(0,255,0))
    AntialiasedCircle(WindowW-100, WindowH-100,  80, 2, RGB(0,0,255))
  StopDrawing()
  
  Repeat
    
    Event = WaitWindowEvent()
    
  Until Event = #PB_Event_CloseWindow
  
EndIf
End

Procedure AntialiasedCircle(StartX.d, StartY.d, Radius.d, AntiLength.d, Color.i)
  
  Define.i R,G,B
  Define.d Normal, Value
  
  If Radius <= 0
    Radius = 0.00001
  EndIf
  
  If AntiLength <= 0
    AntiLength = 0.00001
  EndIf
  
  DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Gradient)
  
  ResetGradientColors()
  
  R = Red(Color)
  G = Green(Color)
  B = Blue(Color)
  
  Normal = 1 / Radius
  Value  = 1.0 - AntiLength * Normal
  
  GradientColor(  0.0, RGBA(R,G,B,255))
  GradientColor(Value, RGBA(R,G,B,255))
  GradientColor(  1.0, RGBA(R,G,B,0))
  
  CircularGradient(StartX, StartY, Radius)
  Circle(StartX, StartY, Radius)
  
EndProcedure
User avatar
luis
Addict
Addict
Posts: 3895
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: Draw an antialiased circle?

Post by luis »

Nice idea Samuel.
"Have you tried turning it off and on again ?"
Little John
Addict
Addict
Posts: 4791
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Draw an antialiased circle?

Post by Little John »

luis wrote:Nice idea Samuel.
Yes, indeed! Thanks for sharing, Samuel.
User avatar
glomph
User
User
Posts: 48
Joined: Tue Apr 27, 2010 1:43 am
Location: St. Elsewhere / Germany
Contact:

Re: Draw an antialiased circle?

Post by glomph »

Wonderful idea Samuel.

I took your example to get also outlined circles.
It does not work for overlapping ones.

Code: Select all

Enumeration
  #Window
  #Canvas
EndEnumeration

Declare AntialiasedCircle(StartX.d, StartY.d, Radius.d,dick.d,AntiLength.d, front,back,art=0)
Global.i WindowW = 800
Global.i WindowH = 600

If OpenWindow(#Window, 0, 0, WindowW, WindowH, "Antialiased Circle", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

  CanvasGadget(#Canvas, 0, 0, WindowW, WindowH)
 
  StartDrawing(CanvasOutput(#Canvas))
    Box(0, 0, WindowW, WindowH, #White ); RGB(30,30,30))
    AntialiasedCircle(WindowW*0.5, WindowH*0.5, 200,7.1, 1, #Red,#White)
    AntialiasedCircle(WindowW*0.5, WindowH*0.5, 100,2, 2, #Blue,#Red,#PB_2DDrawing_Outlined)
    AntialiasedCircle(100,100, 80,2, 3, RGB(0,0,255),#White,#PB_2DDrawing_Outlined)
    AntialiasedCircle(WindowW-100,100, 50, 1.1, 1, RGB(0,255,0), #White, #PB_2DDrawing_Default)
    AntialiasedCircle(100, WindowH-100, 50, 1.1, 1, RGB(0,255,0), #White, #PB_2DDrawing_Outlined)
    AntialiasedCircle(WindowW-100, WindowH-100,  80,1.1,1, #Black,#White, #PB_2DDrawing_Outlined)
  StopDrawing()
 
  Repeat
   
    Event = WaitWindowEvent()
   
  Until Event = #PB_Event_CloseWindow
 
EndIf
End

Procedure AntialiasedCircle(StartX.d, StartY.d, Radius.d,dick.d, AntiLength.d, front,back,art=0)
  Define.i R,G,B
  Define.d Normal, Value
  If art=#PB_2DDrawing_Outlined
    radius+dick/2 ; to get the line in middle off the radius
  EndIf  
  If Radius <= 0
    Radius = 0.00001
  EndIf
 
  If AntiLength <= 0
    AntiLength = 0.00001
  EndIf
 
  DrawingMode(#PB_2DDrawing_AlphaBlend | #PB_2DDrawing_Gradient) ; |#PB_2DDrawing_Transparent)
 
  ResetGradientColors()
 
  R = Red(front)
  G = Green(front)
  B = Blue(front)
 
  Normal = 1 / Radius
  Value  = 1.0 - AntiLength * Normal
 
  GradientColor(  0.0, RGBA(R,G,B,255))
  GradientColor(Value, RGBA(R,G,B,255))
  GradientColor(  1.0, RGBA(R,G,B,0))
 
  CircularGradient(StartX, StartY, Radius)
  Circle(StartX, StartY, Radius)
  If art=#PB_2DDrawing_Outlined
    R = Red(back)
    G = Green(back)
    B = Blue(back)
    radius-dick
    GradientColor(  0.0, RGBA(R,G,B,255))
    GradientColor(Value, RGBA(R,G,B,255))
    GradientColor(  1.0, RGBA(R,G,B,0))
    CircularGradient(StartX, StartY, Radius)
    Circle(StartX, StartY, Radius)
  EndIf
  
EndProcedure
User avatar
heartbone
Addict
Addict
Posts: 1058
Joined: Fri Apr 12, 2013 1:55 pm
Location: just outside of Ferguson

Re: Draw an antialiased circle?

Post by heartbone »

That's a nice new trick for an old dog Samuel.
It certainly goes into the bag.
Thanks.
Keep it BASIC.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Draw an antialiased circle?

Post by Dude »

Thanks for all the awesome responses to my question! :D
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: Draw an antialiased circle?

Post by davido »

Always wanted smooth circles. Thanks for asking, Dude.

@Samuel
Brilliant. Thank you for sharing.
DE AA EB
User avatar
Michael Vogel
Addict
Addict
Posts: 2807
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Draw an antialiased circle?

Post by Michael Vogel »

Not bad :lol:

Code: Select all

Enumeration
	#Window
	#Canvas
EndEnumeration

Procedure MyCircle(x,y,radius,color,width=0,mode=0)

	Global MyCircleSmooth=2

	Protected d.d,s.d
	Protected fillcolor
	Protected xxcolor

	width-MyCircleSmooth>>1
	Debug width
	If width
		radius+width>>1
	EndIf

	If radius>0
		s=MyCircleSmooth
		If s<=0
			s=0.0001
		EndIf

		d=1/(radius+s)
		fillcolor=color|$FF000000
		xxcolor=color|$40000000

		DrawingMode(#PB_2DDrawing_AlphaBlend|#PB_2DDrawing_Gradient)
		ResetGradientColors()

		GradientColor(0,fillcolor)
		If mode=#PB_2DDrawing_Outlined
			GradientColor(0,color)
			GradientColor(d*(radius-width-s),color)
			GradientColor(d*(radius-width-s/2),xxcolor)
			GradientColor(d*(radius-width),fillcolor)
		EndIf
		GradientColor(d*radius,fillcolor)
		GradientColor(d*(radius+s/2),xxcolor)
		GradientColor(1,color)
		CircularGradient(x,y,radius)
		Circle(x,y,radius)

	EndIf

EndProcedure

Global.i WindowW = 800
Global.i WindowH = 600

If OpenWindow(#Window, 0, 0, WindowW, WindowH, "Antialiased Circle", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	CanvasGadget(#Canvas, 0, 0, WindowW, WindowH)
	StartDrawing(CanvasOutput(#Canvas))
	Box(0, 0, WindowW, WindowH, #White ); RGB(30,30,30))
	For i=1 To 15
		MyCircle(50+i*20,50+i*20,50+i*10,Random(#White),i,#PB_2DDrawing_Outlined)
		MyCircle(WindowW-50-i*20,50+i*20,50+i*10,Random(#White),16-i,#PB_2DDrawing_Outlined)
	Next i
	StopDrawing()
	Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
dige
Addict
Addict
Posts: 1407
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: Draw an antialiased circle?

Post by dige »

:shock: Wow! - well done :-)
"Daddy, I'll run faster, then it is not so far..."
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: Draw an antialiased circle?

Post by Dude »

I came with some anti-aliasing wrapping macros here: http://www.purebasic.fr/english/viewtop ... 12&t=61721
firace
Addict
Addict
Posts: 946
Joined: Wed Nov 09, 2011 8:58 am

Re: Draw an antialiased circle?

Post by firace »

Any simple cross-platform way to have the below circle antialiased AND with no visible surrounding box? Basically I want to see the default window color ($F0F0F0 by default on windows 8, but XP, for instance, has a different shade of gray) around the circle.

Code: Select all

OpenWindow(0, 0, 0, 600, 600, "Smooth Circle")
CreateImage(0, 1000, 1000, 32, $000000)            ;  would like to make this transparent
  StartDrawing(ImageOutput(0))
  Circle(500, 500, 300, $0000FF)
  StopDrawing() 
ResizeImage(0, 500, 500)
ImageGadget(0, 0, 0, 500, 500, ImageID(0))

While WaitWindowEvent() ! #PB_Event_CloseWindow : Wend
Post Reply