Updated for MWE:
SCREEN_SIZE = 400
screen = pygame.display.set_mode((SCREEN_SIZE, SCREEN_SIZE))
color = (119, 221, 119) # could be any color, makes no difference
width = 6
radius = (90 width) * 0.8250
dial_x, dial_y = 10, 10
rect = (dial_x - radius, dial_y - radius, 2*radius, 2*radius)
start_angle_in_deg = 10
stop_angle_in_deg = 60
pygame.draw.arc(screen, color, rect, math.radians(start_angle_in_deg), math.radians(stop_angle_in_deg), width)
The current output I'm getting is:
It appears the arcs are not 'holding' the full color, and appear to be fading in some sections.
Question:
What could be the cause? How do I fix this?
Research and due diligence:
CodePudding user response:
I can confirm this - Using concrete numbers so that others can reproduce:
import pygame, math
disp = pygame.display.set_mode((800,600))
disp.fill((255,255,255))
f = lambda:pygame.display.flip()
pygame.draw.arc(disp, (0,255,0), (0,0,400,300), math.radians(0),math.radians(120), 30)
f()
input() # will pause the program before terminating
So, analasing the pixels, there is one veredict: the algorithm Pygame currently uses for drawing arcs with a certain width does not care about pixels that are not covered due to rounding errors. Internally, it will draw a series of lines of width
(the past parameter to arc
) pixels, perpendicular to the abstract path marking the center of the arc. Anyone who had done this by hand will know that without some extra care, like iterating the integer destination coordinates and searchign backwards whether each pixesl should be colored, or some adaptative sampling to space the strokes so that are no gaps, the result will be faulty.
In short, this means there will be no workaround for that using pygame by itself - you will have to resort to another drawing library, such as PIL (the Pillow package) or Cairo to do your drawing, and paste the results back to pygame surfaces.
Alternatively to using other libraries, you can try making your drawing into a smaller surface (exactly half width and half height, for example), then using pygame.transform.rotozoom
to scale it to the desired size, and blitting it to your target surface (i.e. the display, in this case). This should give you an arc with blurry edges, but its interior should be 100% filled, as .rotozoom
does the backward-looking thing in order not to skip pixels.
update sorry - I was trying the technique in the last paragraph in order to have a working example, but it won't fix the results - instead, there are still faults, and they get twice as big. The only way out is using another drawing library.
CodePudding user response:
It appears that this post found that it is a problem with anti-aliasing, and their suggestions were to either draw multiple copies of the same arc, or disregard pygame's built-in arc function and create your own.