Fatih YILMAZ
Fatih YILMAZ

Reputation: 1

Graphics: How to Fill Color Between Lines?

I am trying to design a QR-Code in a circular shape. I have to code it with python but I don't have much experience about it. After a lot of effort I created the shapes. Now I need to fill color between these shapes but I couldn't make it. My output graphic curently looks like this:

screenshot of current output

I need to fill those empty shapes with color. The code that I implemented to create this graphic is given below. I am not sure if I am using the right library. I saw lots of examples about matplotlib.pyplot but I thought it is more useful for creating charts. So any contribution is appreciated. I am really stuck.

from graphics import *
import math

def rect(r, theta):
    """theta in degrees

    returns tuple; (float, float); (x,y)
    """
    x = r * math.cos(math.radians(theta))
    y = r * math.sin(math.radians(theta))
    return x, y


def polar(x, y):
    """returns r, theta(degrees)
    """
    r = (x ** 2 + y ** 2) ** .5
    if y == 0:
        theta = 180 if x < 0 else 0
    elif x == 0:
        theta = 90 if y > 0 else 270
    else:
        theta = math.degrees(math.atan(float(y) / x))
    return r, theta


def main():
    win = GraphWin('Canvas', 640, 480)  # give title and dimensions
    win.setCoords(-320, -240, 320, 240)

    seventh = Circle(Point(0, 0), 90)  # set center and radius
    # seventh.setFill("yellow")
    seventh.draw(win)

    sixth = Circle(Point(0, 0), 80)  # set center and radius
    # sixth.setFill("yellow")
    sixth.draw(win)

    fifth = Circle(Point(0, 0), 70)  # set center and radius
    # fifth.setFill("yellow")
    fifth.draw(win)

    fourth = Circle(Point(0, 0), 60)  # set center and radius
    # fourth.setFill("yellow")
    fourth.draw(win)

    third = Circle(Point(0, 0), 50)  # set center and radius
    # third.setFill("yellow")
    third.draw(win)

    second = Circle(Point(0, 0), 40)  # set center and radius
    # second.setFill("yellow")
    second.draw(win)

    first = Circle(Point(0, 0), 30)  # set center and radius
    # first.setFill("yellow")
    first.draw(win)

    line = Line(Point(0, 0), Point(rect(90, 0)[0], rect(90, 0)[1]))
    line.draw(win)

    line2 = Line(Point(0, 0), Point(rect(90, 30)[0], rect(90, 30)[1]))
    line2.draw(win)

    line3 = Line(Point(0, 0), Point(rect(90, 60)[0], rect(90, 60)[1]))
    line3.draw(win)

    line4 = Line(Point(0, 0), Point(rect(90, 90)[0], rect(90, 90)[1]))
    line4.draw(win)

    line5 = Line(Point(0, 0), Point(rect(90, 120)[0], rect(90, 120)[1]))
    line5.draw(win)

    line6 = Line(Point(0, 0), Point(rect(90, 150)[0], rect(90, 150)[1]))
    line6.draw(win)

    line7 = Line(Point(0, 0), Point(rect(90, 180)[0], rect(90, 180)[1]))
    line7.draw(win)

    line8 = Line(Point(0, 0), Point(rect(90, 210)[0], rect(90, 210)[1]))
    line8.draw(win)

    line9 = Line(Point(0, 0), Point(rect(90, 240)[0], rect(90, 240)[1]))
    line9.draw(win)

    line10 = Line(Point(0, 0), Point(rect(90, 270)[0], rect(90, 270)[1]))
    line10.draw(win)

    line11 = Line(Point(0, 0), Point(rect(90, 300)[0], rect(90, 300)[1]))
    line11.draw(win)

    line12 = Line(Point(0, 0), Point(rect(90, 330)[0], rect(90, 330)[1]))
    line12.draw(win)

    line13 = Line(Point(0, 0), Point(rect(90, 360)[0], rect(90, 360)[1]))
    line13.draw(win)

    line14 = Line(Point(0, 0), Point(rect(90, 210)[0], rect(90, 210)[1]))
    line14.draw(win)

    first.setFill('black')


    message = Text(Point(0, 200), 'Click anywhere to quit.')
    message.draw(win)
    win.getMouse()

    win.close()

main()

If I can achieve it, I want to draw a picture that looks like this (drawn in Photoshop):

screenshot of desired image created with Photoshop

After some helpful comments I decided to find another appropriate python module. But I couldn't find the right one. If are there anyone who understand my problem can suggest the appropriate python module?

Upvotes: 0

Views: 1769

Answers (1)

cdlane
cdlane

Reputation: 41872

I believe Python turtle, also built on tkinter, has enough capability to simulate your circular QR-Code with more intuitive logic:

from math import pi, sin, cos
from turtle import Turtle, Screen

TWO_PI = pi * 2

SEGMENTS = 10  # pie slices
SECTORS = 8  # concentric circles
MAXIMUM_RADIUS = 100
MINIMUM_RADIUS = 10
DELTA_RADIUS = (MAXIMUM_RADIUS - MINIMUM_RADIUS) // SECTORS
SEGMENT_EXTENT = TWO_PI / SEGMENTS
DEFAULT_LINE_WIDTH = 1

DATA = [  # data to match OP's example chart
    (2, 0), (2, 3), (2, 5), (2, 6), (2, 9),
    (3, 0), (3, 1), (3, 3), (3, 4), (3, 6),
    (4, 1), (4, 2), (4, 7), (4, 8),
    (5, 0), (5, 1), (5, 4), (5, 5), (5, 6), (5, 7),
    (6, 3), (6, 5), (6, 8), (6, 9),
    (7, 0), (7, 2), (7, 3), (7, 4), (7, 5), (7, 6), (7, 8),
    ]

def centered_circle(turtle, radius, extent=TWO_PI):
    """ draw a circle centered about the current turtle location """

    position = turtle.position()
    heading = turtle.heading()

    turtle.penup()
    turtle.setx(turtle.xcor() + cos(heading) * radius)
    turtle.sety(turtle.ycor() - sin(heading) * radius)
    turtle.pendown()

    turtle.circle(radius, extent, steps=60)

    turtle.penup()
    turtle.setposition(position)  # return turtle to starting position
    turtle.pendown()

def draw_blank_chart(turtle):
    """ draw the empty chart """

    turtle.dot(MINIMUM_RADIUS * 2)  # center of chart

    for radius in range(MINIMUM_RADIUS + DELTA_RADIUS, MAXIMUM_RADIUS + 1, DELTA_RADIUS):
        centered_circle(turtle, radius)  # divide chart into sectors

    turtle.width(2 * DELTA_RADIUS / 3)  # outer edge of chart
    centered_circle(turtle, MAXIMUM_RADIUS + DELTA_RADIUS)
    turtle.width(DEFAULT_LINE_WIDTH)

    for _ in range(SEGMENTS):  # divide chart into segments
        turtle.forward(MAXIMUM_RADIUS + DELTA_RADIUS)
        turtle.backward(MAXIMUM_RADIUS + DELTA_RADIUS)
        turtle.left(SEGMENT_EXTENT)

def set_bit(turtle, sector, segment):
    """ turn on (blacken) one sector:segment of chart """

    turtle.setheading(SEGMENT_EXTENT * segment - pi/2)
    turtle.width(DELTA_RADIUS)
    centered_circle(turtle, (MINIMUM_RADIUS + DELTA_RADIUS * sector + DELTA_RADIUS/2), -SEGMENT_EXTENT)

screen = Screen()
screen.mode('logo')  # force zero degrees to be straight up

yertle = Turtle(visible=False)
yertle.width(DEFAULT_LINE_WIDTH)
yertle.speed('fastest')
yertle.radians()  # to make working with sin and cos easier

draw_blank_chart(yertle)

for sector, segment in DATA:
    set_bit(yertle, sector, segment)

screen.exitonclick()

enter image description here

Upvotes: 1

Related Questions