除了标记之外,如何在Python龟图形中绘制椭圆?

时间:2015-12-15 09:06:17

标签: python python-3.x turtle-graphics ellipse

我正在尝试使用Python龟图形绘制一个字母“O”。为了提示“O”的绘图,用按键调用它的功能。以下是我到目前为止的情况:

def draw_O():
# Draw an O

penup()
forward(letter_height/4)
pendown()
forward(letter_width/2)
circle(letter_height/4, 90)
forward(letter_height/2)
circle(letter_height/4, 90)
forward(letter_width/2)
circle(letter_height/4, 90)
forward(letter_height/2)
circle(letter_height/4, 90)
forward(letter_width/2)
penup()
forward(space_width + letter_height/4)
pendown()

onkey(draw_O, "o")

letter_height&用户可以使用另一个按键提示的对话框,在10-170之间的任何值更改letter_width个变量。现在,如果letter_height = 170& letter_width = 10

O when letter_height = 170 & letter_width = 10

但是,如果将其与“H”(我的程序可以绘制的另一个字母)进行比较,您可以很容易地看出它们不是按比例分配的:

O next to H

我想要做的是为“O”绘制一个椭圆,其垂直半径等于letter_height&它的水平半径等于letter_width,这样随着letter_width的增加,“O”会变短,而letter_height的增加会变得更高。问题是,我真的不知道该怎么做!我听说你可以盖章,但我真的 想要使用stamp方法,因为它的动画看起来并不吸引人。此外,当我尝试将letter_heightletter_width值映射到它时,它会出于某种原因覆盖整个屏幕!

总之,我想知道如何在乌龟图形中绘制椭圆,可以像圆圈一样进行操作(更改椭圆的半径长度,更改椭圆的范围等)。我 不希望想要使用turtle.stamp()方法,那么除了在画布上标记椭圆之外,有没有办法绘制椭圆?非常感谢任何帮助!

2 个答案:

答案 0 :(得分:2)

在测试了@ moomoomoo309的椭圆代码并发现问题(在错误的位置打印,宽度和高度不匹配参数,忽略了龟标题,因此无法打印倾斜的椭圆,标题没有&#39 ; t跟踪绘图,不将笔留在原始状态等。)我决定尝试自己编写。

我选择使用turtle.circle()作为相对于现有乌龟位置和标题绘制椭圆的位置的模型,允许用户更改步骤(即制作其他不规则多边形),留下笔它开始的状态和位置等等。这就是我提出的(我使用self代替turtlepen,因为我打算将其作为方法安装):< / p>

import turtle
import math

def ellipse(self, x_radius, y_radius, steps=60):

    down = self.isdown()  # record pen state for restoration later

    if not down:
        self.pendown()

    heading_radians = math.radians(self.heading())
    theta_radians = -math.pi / 2
    extent_radians = 2 * math.pi
    step_radians = extent_radians / steps
    extent_radians += theta_radians
    x_center, y_start = self.position()
    y_center = y_start + y_radius

    cos_heading, sin_heading = math.cos(heading_radians), math.sin(heading_radians)

    while True:
        x, y = x_center + math.cos(theta_radians) * x_radius, y_center + math.sin(theta_radians) * y_radius
        # readjust x & y to set the angle of the ellipse based on the original heading of the turtle
        x, y = x - x_center, y - y_start
        x, y = x * cos_heading - y * sin_heading, x * sin_heading + y * cos_heading
        x, y = x + x_center, y + y_start

        self.setheading(self.towards(x, y))  # turtle faces direction in which ellipse is drawn
        self.goto(x, y)

        if theta_radians == extent_radians:
            break

        theta_radians = min(theta_radians + step_radians, extent_radians)  # don't overshoot our starting point

    self.setheading(self.towards(x_center, y_start))  # set correct heading for the next thing we draw

    if not down:  # restore pen state on return
        self.penup()

(可选)将此方法添加到我们的龟Adding a Method to an Existing Object Instance

from functools import partial

yertle = turtle.Turtle()
yertle.ellipse = partial(ellipse, yertle)

显示我们可以使用turtle.ellipse()绘制的所有新形状的演示代码:

if __name__ == "__main__":

    from functools import partial

    yertle = turtle.Turtle()
    yertle.ellipse = partial(ellipse, yertle)

    import random

    yertle.speed("fastest")
    yertle.hideturtle()
    yertle.penup()

    screen = turtle.Screen()

    for _ in range(75):

        radius = random.randint(10, 50)

        yertle.setheading(random.randint(0, 360))
        yertle.setx(random.randint(-screen.window_width()/2 + radius * 2, screen.window_width()/2 - radius * 2))
        yertle.sety(random.randint(-screen.window_height()/2 + radius + 2, screen.window_height()/2 - radius * 2))
        yertle.color((random.random(), random.random(), random.random()), (random.random(), random.random(), random.random()))

        flag = random.choice([True, False, False])

        if flag:
            yertle.begin_fill()

        yertle.ellipse(radius, radius / 0.5 + random.random() * 3, steps=random.choice([3, 4, 5, 6, 7, 8, 60, 60, 60]))

        if flag:
            yertle.end_fill()

    screen.exitonclick()

示例输出

enter image description here

我尝试实施extent a la turtle.circle(),但无法正常使用它(即以这样一种方式调用turtle.ellipse() }两次具有相同的范围,并继续它离开的曲线)所以我已经离开了那一天。

回答OP的原始问题,我们现在可以做到:

import turtle
import math

def ellipse(self, x_radius, y_radius, steps=60):

    # ...

def draw_O():
    # Draw an O

    turtle.penup()
    turtle.forward(letter_height/4)
    turtle.pendown()

    ellipse(turtle, letter_width, letter_height)

    turtle.penup()
    turtle.forward(space_width + letter_height/4)
    turtle.pendown()

letter_width = 10
letter_height = 170

space_width = 5

turtle.onkey(draw_O, "o")

turtle.listen()
turtle.done()

生成OP所需的基于椭圆的骨骼字母O:

enter image description here

答案 1 :(得分:0)

我很确定这会起作用,但宽度为180/180和高度/ 180可能会关闭。

structure(list(productId = c(870826L, 870826L, 870826L, 870826L, 
870826L, 870826L), customerID = c(1186951L, 1244216L, 1244216L, 
1308671L, 1308671L, 1308671L), transactionDate = structure(c(16888, 
16891, 16899, 16888, 16889, 17134), class = "Date"), purchaseQty = c(162000L, 
5000L, 6500L, 221367L, 83633L, 60500L)), .Names = c("productId", 
"customerID", "transactionDate", "purchaseQty"), row.names = c("1:", 
"2:", "3:", "4:", "5:", "6:"), class = "data.frame")