PicoGraphics, creating shapes with Alpha

Hey folks!

I am trying to draw a hollow circle with a thickness. I am using the approach of drawing a large circle with one color and then a smaller one with the BG Color. This approach allows me to get the hollow circle. But if I were to move this shape over anything else, then the BG will overlap.

Any smart people here that can figure out a way to substract shapes, and keep whatever is in the background open?

I was thinking of uploading a PNG, but I don’t know how to nominate a color to be the alpha.

Thanks!

I’m taking along to see if anybody comes up with a solution. As this sounds really interesting and might be something I’d try to do at some point.

I draw a circle in a circle and use it as a moving marker. I’m purposely covering up the background though.

Sounds like we need a draw_ring function with a thickness option. Like the draw_line.
@gadgetoid

EDIT: There is a flurry of activity going on Pico Graphics wise, Fonts and Pico Vector.
Workflow runs · pimoroni/pimoroni-pico (github.com)

Might be a good idea to post this as an issue on Github.
It will be better seen by those that do all the hard work coding wise.
Issues · pimoroni/pimoroni-pico (github.com)

This is the method I use in my graphics system:

def clear(c):
    LCD.fill(colour(0,150,0)) # Green

def ring(x,y,r,c):
    LCD.pixel(x-r,y,c)
    LCD.pixel(x+r,y,c)
    LCD.pixel(x,y-r,c)
    LCD.pixel(x,y+r,c)
    for i in range(1,r):
        a = int(math.sqrt(r*r-i*i)) # Pythagoras - so useful!
        LCD.pixel(x-a,y-i,c)
        LCD.pixel(x+a,y-i,c)
        LCD.pixel(x-a,y+i,c)
        LCD.pixel(x+a,y+i,c)
        LCD.pixel(x-i,y-a,c)
        LCD.pixel(x+i,y-a,c)
        LCD.pixel(x-i,y+a,c)
        LCD.pixel(x+i,y+a,c)
        # Fill in the missed pixels !
        a = int(math.sqrt(r*r-i*i)+.6) # small offset outwards
        LCD.pixel(x-a,y-i,c)
        LCD.pixel(x+a,y-i,c)
        LCD.pixel(x-a,y+i,c)
        LCD.pixel(x+a,y+i,c)
        LCD.pixel(x-i,y-a,c)
        LCD.pixel(x+i,y-a,c)
        LCD.pixel(x-i,y+a,c)
        LCD.pixel(x+i,y+a,c)
        
def thick_ring(x,y,R,r,c):
    for ii in range(r,R):
        ring(x,y,ii,c)
        
clear(0)

thick_ring(120,120,100,90,colour(255,255,0))
ring(120,120,95,colour(0,0,255))
LCD.show()

You may need to change the format of the pixel instructions to your system. It works but is not terribly fast - so many calculations.

I thought about this method but the cost expense didn’t make it attractive.

This is an alternative method. It draws vertical lines between the outer and inner radii.

def thick_ring2(cx,cy,r,t,c):
    R = int(r+t/2)
    r = int(r-t/2)
    print(R,r)
    for i in range(0,R):
        t = int(math.sqrt(R*R-i*i))
        if i <= r:
            b = int(math.sqrt(r*r-i*i))
            LCD.line(cx+i,cy-t,cx+i,cy-b,c)
            LCD.line(cx-i,cy-t,cx-i,cy-b,c)
            LCD.line(cx-i,cy+t,cx-i,cy+b,c)
            LCD.line(cx+i,cy+t,cx+i,cy+b,c)
        else:
            LCD.line(cx+i,cy-t,cx+i,cy,c)
            LCD.line(cx-i,cy-t,cx-i,cy,c)
            LCD.line(cx-i,cy+t,cx-i,cy,c)
            LCD.line(cx+i,cy+t,cx+i,cy,c)            
    LCD.show()

This works pretty quickly. There will always be a great deal of calculations with rings. Using vline() might make it a bit quicker.

Quick video to show the speed here:

1 Like

You can draw a hollow circle with the new PicoVector stuff like this:

from picographics import PicoGraphics, DISPLAY_TUFTY_2040
from picovector import PicoVector, RegularPolygon, ANTIALIAS_NONE, ANTIALIAS_X4, ANTIALIAS_X16

display = PicoGraphics(DISPLAY_TUFTY_2040)

vector = PicoVector(display)
vector.set_antialiasing(ANTIALIAS_X4)

BLACK = display.create_pen(0, 0, 0)
WHITE = display.create_pen(255, 255, 255)

WIDTH, HEIGHT = display.get_bounds()

# x, y, sides, radius
inner_circle = RegularPolygon(int(WIDTH / 2), int(HEIGHT / 2), 48, HEIGHT / 2 - 8)
outer_circle = RegularPolygon(int(WIDTH / 2), int(HEIGHT / 2), 48, HEIGHT / 2)

display.set_pen(BLACK)
display.clear()
display.set_pen(WHITE)

vector.draw(outer_circle, inner_circle)
display.update()

It’s slow though!