【问题标题】:Graphics: How to Fill Color Between Lines?图形:如何在线条之间填充颜色?
【发布时间】:2018-03-19 19:53:57
【问题描述】:

我正在尝试设计一个圆形的二维码。我必须用python对其进行编码,但我对此没有太多经验。经过大量的努力,我创建了形状。现在我需要在这些形状之间填充颜色,但我做不到。我的输出图形目前看起来像这样:

我需要用颜色填充那些空的形状。下面给出了我为创建此图形而实现的代码。我不确定我是否使用了正确的库。我看到了很多关于 matplotlib.pyplot 的例子,但我认为它对于创建图表更有用。因此,任何贡献都会受到赞赏。我真的被困住了。

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()

如果我能做到的话,我想画一张看起来像这样的图片(在 Photoshop 中绘制):

在一些有用的 cmets 之后,我决定寻找另一个合适的 python 模块。但我找不到合适的。如果有谁了解我的问题可以推荐合适的python模块?

【问题讨论】:

  • 您知道二维码以“形状”对数据进行编码,因此通过设计圆形二维码可以创建随机数据?那有什么用?
  • @PatrickArtner 我知道二维码以自己的形式编码数据。我正在尝试设计一个与原始二维码有很多共同点的圆形二维条码。但我的问题是,我无法用这个库填充这些行。
  • 您已将所有 setFill() 调用注释掉。你想要什么颜色在什么线条之间?
  • John Zelle 的graphics.py 模块建立在tkinter 之上,因此直接使用它可能会给您更多的控制权。如果没有,您可能需要 Zelle 模块的 Polygon 形状,如果您可以提供包含要填充区域轮廓的顶点列表,该形状应该允许为任意形状的内部着色。
  • @martineau setFill() 正在填充整个圆圈,但我需要填充由两个圆圈和两条线包围的区域。图中有 72 个。现在,我可以用 seventhsixthline2line3 对象来描述其中之一。如果我可以填充这些对象所描述的区域,我可以填充我想要的区域。我在最后绘制了我想要的 Photoshop 我将通过添加该图片来编辑我的问题。谢谢。

标签: python graphics fill area zelle-graphics


【解决方案1】:

我相信同样基于 tkinter 构建的 Python turtle 有足够的能力以更直观的逻辑模拟你的循环二维码:

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()

【讨论】:

    猜你喜欢
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    相关资源
    最近更新 更多