Search code examples
python-3.xgeometrypixel

Drawing circles in python pixel by pixel


Hey guys so I have a question. I would like to draw a circle in python pixel by pixel but I can't seem to get it.

It was a question we talked about in my programming class today and my teacher said it was possible by using the distance formula to find the distance between the center of the window and the points on the outside of the circle and then just telling the program to fill it in if it fits that case.

So this is not homework, purely for my own curiosity. I have been working on it for hours and I feel like I am close but definitely missing a key element.

My goal is to put a red circle in the middle of the window, which has a width and height between 300 and 400.

I said that the center point is = to (w/2, h/2) and I want to fill in every point that is a fixed distance away from that.

I chose (100, 50) as a random point that would be on the circle and then set the variable distance = to the distance formula using those previous two points.

The two for-loops are there to iterate over every pixel in the window. I was able to create a box right where I want my circle... But I can't seem to get anything close to a circle to appear

here is my code, I named my function Japanese flag as it seemed appropriate:

import cImage
import math


def japanese_flag(w, h):
    newimg = EmptyImage(w, h)
    distance = int(math.sqrt((50 - h / 2) ** 2 + (100 - w / 2) ** 2))

    for col in range(w):
        for row in range(h):
            if h/2 - distance < row < (h/2 + distance) and w / 2 - distance < col < (w / 2 + distance):
                    newpixel = Pixel(255, 0, 0) # this denotes the color red
                    newimg.setPixel(col, row, newpixel)
    return newimg

def show_one_flag(func_name):
    import random
    width = random.randint(300, 400)
    height = random.randint(200, 300)
    win = ImageWin(str(func_name),width,height)
    newimg = func_name(width, height)
    newimg.draw(win)

show_one_flag(japanese_flag)

Solution

  • Use squared radius for simpler comparison

    SqDist = (50 - h / 2) ** 2 + (100 - w / 2) ** 2
    

    To draw only circumference, compare with some tolerance level

    Eps = 1
    ...
    if (Math.Abs((h/2 - row) ** 2 + (w/2 - col) ** 2 - SqDist) < Eps)
         draw pixel
    

    To draw filled circle:

    if ((h/2 - row) ** 2 + (w/2 - col) ** 2 < SqDist)
         draw pixel