Canvas.drawArc () artifacts

I draw an arc on the canvas in the user view, as shown below. Paint and rectangle defined outside onDraw() and added there for simplicity.

 protected void onDraw(Canvas canvas) { super.onDraw(canvas); RectF rectangle = new RectF(60f, 60f, 480f, 480f); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(0x40000000); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(120); canvas.drawArc(rectangle, 225f, 315f, false, paint); } 

When I run this code on Galaxy Nexus with 4.3, the following artifacts appear. enter image description here

There are no such artifacts when working on Nexus 5 with 4.4.4. enter image description here

I observed artifacts at angles such as (225f, 315f) and only a few other angles. Most of the time, the arc has a regular shape.

Is there any way to avoid these artifacts?

Update: I tried to use software, hardware and not a single level using setLayerType() . Artifacts changed their form, but were still present.

+8
android android-canvas android-custom-view
source share
2 answers

I am new to StackOverflow, I wanted to add a comment, but could not (having insufficient points), so I had to put my comment in response!

It is strange that the arc overshoots the indicated end position with a straight vertical line on the outside. The internal endpoint looks fine. Of course, this and other mess of lines do not talk about the causes of the problem.

It seems to appear when the final angle is exactly a multiple of 90 degrees. This is similar to a numerical calculation error, rounding rounding error, etc. @kcoppock noticed that 314.98f is already bypassing the error. Probably any value other than exactly 315.0f can do the trick.

If code optimization is used (trying to draw an arc with as few line segments as possible), another trick that might work is to simplify the arc by cutting it into pieces β†’ use several drawArc calls, each of which has a certain maximum angle, Candidates 30 , 45, 90 and 180 degrees. It remains to be seen whether the joints will be invisible ...

A little long shot, I hope that any of these suggestions can work.

+2
source share

I found a solution! :)

Instead of this:

 RectF rectangle = new RectF(60f, 60f, 480f, 480f); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(0x40000000); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(120); canvas.drawArc(rectangle, 225f, 315f, false, paint); 

Use this:

 RectF rectangle = new RectF(60f, 60f, 480f, 480f); Paint paint = new Paint(); paint.setAntiAlias(true); paint.setColor(0x40000000); paint.setStyle(Paint.Style.FILL); float strokeWidth = 120; float startAngle = 225f; float sweepAngle = 315f; RectF pathRect = new RectF(); Path path = new Path(); float s = strokeWidth / 2; pathRect.left = rectangle.left - s; pathRect.right = rectangle.right + s; pathRect.top = rectangle.top - s; pathRect.bottom = rectangle.bottom + s; path.arcTo(pathRect, startAngle, sweepAngle); pathRect.left = rectangle.left + s; pathRect.right = rectangle.right - s; pathRect.top = rectangle.top + s; pathRect.bottom = rectangle.bottom - s; path.arcTo(pathRect, startAngle + sweepAngle, -sweepAngle); path.close(); canvas.drawPath(path, paint); 

This code leads to a slower launch, but it does not create artifacts. :)

0
source share

All Articles