Skip to content

adafruit_display_shapes.arc outline vs. display rotation #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dmca-glasgow opened this issue Nov 27, 2024 · 6 comments
Closed

adafruit_display_shapes.arc outline vs. display rotation #77

dmca-glasgow opened this issue Nov 27, 2024 · 6 comments

Comments

@dmca-glasgow
Copy link

Hi there,

I've had a great couple of days experimenting with python (JavaScript dev here), CircuitPython and an M5Dial. Thanks for a great open source ecosystem.

Using the following code:

import displayio
from adafruit_display_shapes.arc import Arc

volumeGauge = displayio.Group()
foreColour = 0xff5400
bgColour = 0x2a2a2a
resolution = 25

for n in range(resolution):
  angle = 270 / resolution
  direction = 180 + 45 - (angle * n)
  segment = Arc(
    x = 120,
    y = 120,
    radius = 116,
    arc_width = 8,
    segments = 25,
    angle = angle,
    direction = direction - (angle / 2),
    fill = bgColour,
    outline = 0x000000,
  )
  volumeGauge.append(segment)

I've noticed a difference in the rendering of outline depending on the display rotation.

It looks as expected when rotation is set to 0 (outline is creating the thin black tick marks on the gauge):

PXL_20241127_110404491

but when used along with board.DISPLAY.rotation = 180, the outline doesn't seem to line up with the filled arc:

PXL_20241127_110333222

Thanks.

@FoamyGuy FoamyGuy transferred this issue from adafruit/Adafruit_CircuitPython_Bundle Nov 27, 2024
@FoamyGuy
Copy link

I moved this to https://github.com/adafruit/Adafruit_CircuitPython_Display_Shapes because the bundle is just the grouping of all of the libraries. Display_Shapes is the one that contains Arc which you are experiencing this issue with.

However ultimately this may be down to a difference in the way that rotation is treated by core vectorio module which draws the inside filled portion of the Arc, and the python code in Display_Shapes which uses a bitmap and line drawing function to draw the outline of the Arc. I am not sure how quick or easy a fix will come if that is he case. I'll try to work out a way to validate that and if it's the case this issue can probably be moved to the core repo.

@dmca-glasgow as a work around in the shorter term: Since you're using the outline mostly to draw "emptiness" between the segments of Arc maybe instead of relying on outline to draw those tick marks you could make the angle of your Arc segments 1 degree smaller and then offset the direction on each one by 1 extra pixel. That way you're left with segments that don't contain outlines but should have a small gap in between them. You can play with angle and direction to try to get it looking similar to the tick marks from the outlines in your photo I believe.

@dmca-glasgow
Copy link
Author

Thanks @FoamyGuy, I learned how to get up and running from your YouTube video :)

@FoamyGuy
Copy link

@dmca-glasgow Nice! I'm glad to hear it!

I confirmed this behavior on a PyPortal.

0 degrees:
image

180 degrees:
image

It feels like a potential core bug since I would expect the rotations to not really effect the actual pixels that end up being drawn. My best guess is maybe there is some math involved with the rotation that is suffering from rounding causing it to drift by an amount that becomes noticeable as individual pixels. But that is just an uncertain hunch.

@FoamyGuy
Copy link

I think that I have narrowed this down further to technically an issue with vectorio.Polygon which is what is used to draw the fill color of the Arc. With this code it's possible to see that there is 1px difference in the placement of the vectorio.Polygon

resolution = 25
angle = 270 / resolution
direction = 180 + 45 - (angle * 4)
segment = Arc(
    x=120,
    y=120,
    radius=116,
    arc_width=8,
    segments=25,
    angle=angle,
    direction=direction - (angle / 2),
    fill=bgColour,
    outline=None,
)
volumeGauge.append(segment)

display.root_group = volumeGauge

bmp = displayio.Bitmap(4, 4, 1)
palette = displayio.Palette(1)
palette[0] = 0xbbbb00

tg = displayio.TileGrid(bmp, pixel_shader=palette)
tg.y = 114
volumeGauge.append(tg)

When rotation is 0 there is a 1px gap between the yellow square and the red Arc segment. When rotation is 180 there are no pixels between the yellow square and the red Arc segment.

So the vectorio.Polygon is off by 1px from where it is positioned in the different orientations.

This might actually be the same root cause as: adafruit/circuitpython#8742

@FoamyGuy
Copy link

FoamyGuy commented Dec 2, 2024

@dmca-glasgow this was indeed the same root cause as the core issue #8742. I went down the vectorio rabbit hole a little bit and managed to find a solution which is now merged in adafruit/circuitpython#9851 (review)

If you get the "absolute newest" firmware build from S3 for your device it should have the fix in it. Or if you wait a bit eventually there will be more official pre-release build that contains it.

Since that fix is merged I'm going to close this. Let me know if you have any trouble if you get a chance to try it out.

@FoamyGuy FoamyGuy closed this as completed Dec 2, 2024
@daviestar
Copy link

Thanks @FoamyGuy 👍

I'm currently stuck on a different problem if you have any advice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants