ArcShape

Can anyone advise me how to draw an ArcShape so that the edges of the Arc are antialiased?

I am drawing a Pie Chart and the standard ArcShape does not have antialiased edges and visually looks very poor.

I am using a Mac with 10.9.2

Thanks

Terry

You are using a vector thingie and await for a bitmap stuff ?

The vector drawing cannot really give you anything else. Here is an idea of a workaround (please don’t spit on it)

Antialiasing works by smoothing edges with one pixel wide shades closer to the background color.

You may want to do the same by drawing several times with lighter colors for a white background. I have done that in two steps :

  • Draw the lighter color slightly bigger (to have one pixel more)
  • Draw at normal size, but with a one pixel border in a lighter color

This gives you a 3 pixels transition between plain color and white.

Here is resized what I get between the smoothed edge and the raw one :

Sub Paint(g As Graphics, areas() As REALbasic.Rect) Dim a As New ArcShape // Draw slightly larger, lightest color a.Scale = 3.04 a.Rotation = .90 a.ArcAngle = 1.57 a.StartAngle = -1.57 a.Border = 0 a.BorderColor = rgb(188,220,255) a.BorderWidth = 2.75 a.Fill = 50 a.FillColor = RGB(188,220,255) g.DrawObject(a, 100, 100) // Draw normal size, with a lighter color border 1 px a.Scale = 3 a.Rotation = .90 a.ArcAngle = 1.57 a.StartAngle = -1.57 a.Border = 10 a.BorderColor = rgb(165,182,255) a.BorderWidth = 2.75 a.Fill = 50 a.FillColor = RGB(0,26,255) g.DrawObject(a, 100, 100) // Draw without smoothing for comparison a.Scale = 3 a.Rotation = .90 a.ArcAngle = 1.57 a.StartAngle = -1.57 a.Border = 0 a.BorderColor = rgb(165,182,255) a.BorderWidth = 2.75 a.Fill = 50 a.FillColor = RGB(0,26,255) g.DrawObject(a, 300, 100) End Sub

This is quick and dirty code, drawing should be made into a method with calling parameters for size and color, but this is the idea. Once again, it may not be what you expected, but it works. With some refinements, it may do the job.

Are vector thingies in Xojo not anti-aliased?

NSBezierPath (Cocoa’s vector thingie) is anti-aliased.

I have found a solution which is to draw an OvalShape with the colour of the canvas, around the circumference of the pie chart and that masks the ragged edge of the ArcShape.

Interestingly the OvalShape (another vector thingie) is anti-aliased.

I did raise this issue 2 years ago when Xojo was RealBasic and I am surprised it has not been part of the many updates.

All the best

Terry

[quote=85351:@Terry Heaford]I have found a solution which is to draw an OvalShape with the colour of the canvas, around the circumference of the pie chart and that masks the ragged edge of the ArcShape.

Interestingly the OvalShape (another vector thingie) is anti-aliased.[/quote]

Good move. I had not noticed the oval shape was antialiased on Mac OS X. On Windows, is is jagged ; I had to devise a font to produce the help icon in my apps because of it.

Here is my drawPieSegments solution:

drawPieSegments(g As Graphics)

dim tX,tY,tDiameter,tValue,tTotalValue,n As Double
dim tSeg As New ArcShape
dim tStartAngle,tArcAngle,tNumOfSegs As Double
Dim tOval as New OvalShape

tX = pLeftMargin + pChartWidth/2
tY = pTopMargin + pChartHeight/2
tDiameter = min(pChartWidth,pChartHeight)

tNumOfSegs = UBound(pDataItem)

tStartAngle = 0
tSeg.Width = tDiameter
tSeg.Height = tDiameter
tTotalValue = 0

tOval.width = tDiameter + 1
tOval.height=tDiameter + 1
tOval.Border = 100
tOval.BorderWidth = 3
tOval.Fill = 0

for n = 1 to tNumOfSegs
tValue = pDataItem(n-1)
tTotalValue = tTotalValue + tValue
next

for n = 1 to tNumOfSegs
tValue = pDataItem(n-1)
tArcAngle = tValue/tTotalValue * 360
tArcAngle = degreesToRadians(tArcAngle)
tSeg.ArcAngle = tArcAngle
tSeg.StartAngle = tStartAngle
tSeg.FillColor = pDataColor(n-1)
g.DrawObject(tSeg, tX, tY)
tStartAngle = tStartAngle + tArcAngle
next

tOval.BorderColor = &cFFFFFF00
g.DrawObject(tOval, tX, tY)

I have just had a quick look at the Object2D class and most of the objects seem to have some sort of anti-aliasing.

The ones that clearly don’t are the ArcShape (the subject of this thread) and the RoundRectShape which probably uses a derivative of the ArcShape code.

I wonder why Xojo does not implement anti-aliasing for this class? with an option to turn it on/off.

If the underlying code in the Cocoa implementation is based on NSBezierPath then it is easy.

All the best

Terry

Terry:

Did you try to save the vector image ?

Emile,

No I haven’t because I am only concerned with the screen and printing.

If I save to PDF in the OSX print dialogue box, all seems OK.

Is there an issue with saving vector images?

All the best

Terry

I believe the ANTIALIAS property of the GRAPHICS object controls this…

The anti-alias property of a Graphics object is true by default according to the docs.

It certainly doesn’t affect the display of an ArcShape in OSX.

All the best

Terry

FWIW there maybe another workaround : Drawline is antialiased (even the tip).
Drawing an arcshape is possible with a succession of lines.

You can also draw into a larger (2x works well) buffer image and scale it down with drawpicture. win32 would require setting interpolationmode (a simple declare) on the graphics, but it works well for Cocoa…

I think my idea of drawing an oval around the border of the ArcShape (PieChart) is the solution I will adopt. Thanks to all who have replied.

Is a request to Xojo worthwhile to ask for the vector graphics classes to be anti-aliased?

Here are two screen shots (ignore the colours, they are the same part of the same pie chart) that show with and without an oval drawn over the border of the pie chart. They have both been zoomed in OSX preview by the same amount.

With:

Without:

[quote=85564:@Terry Heaford]Here are two screen shots (ignore the colours, they are the same part of the same pie chart) that show with and without an oval drawn over the border of the pie chart. They have both been zoomed in OSX preview by the same amount.

[/quote]

Just curious :

  • How come the pixels are not square ?
  • How do you draw only portions of the oval to keep colors separate on the edge of the circle ?

[quote=85595:@Michel Bujardet]Just curious :

How come the pixels are not square ?
How do you draw only portions of the oval to keep colors separate on the edge of the circle ?[/quote]

I am actually cropping off the jaggies by overlaying the Oval using the colour of the canvas, in this case white and using a border width of 3 without a fill colour.

[code]tOval.width = tDiameter + 1
tOval.height=tDiameter + 1
tOval.Border = 100
tOval.BorderWidth = 3
tOval.Fill = 0

tOval.BorderColor = &cFFFFFF00
g.DrawObject(tOval, tX, tY)[/code]

All the best

Terry

[quote=85604:@Terry Heaford]I am actually cropping off the jaggies by overlaying the Oval using the colour of the canvas, in this case white and using a border width of 3 without a fill colour.

[code]tOval.width = tDiameter + 1
tOval.height=tDiameter + 1
tOval.Border = 100
tOval.BorderWidth = 3
tOval.Fill = 0

tOval.BorderColor = &cFFFFFF00
g.DrawObject(tOval, tX, tY)[/code]

[/quote]

So this draws an oval. Good. It does not explain in any way how it could eliminate the jaggies in arcshape …

Good luck anyway.

Hopefully you can grasp the idea from the image below where I have the oval drawn in red with no fill. Ovals do not have jaggies.
Change the border colour of the oval to white or the colour of your canvas if not white and where it overlays the edge of the pie chart no jaggies.

All right. Now it makes sense. Thank you.

You might want to take a look at the arcShape.segments property. It determines how many lines are used to render the shape. I think there is a bug in the way the renderer determines the number of segments, but I couldn’t say for sure. Seems to guess pretty badly. That’s what the example above looks like…