После тестирования кода эллипса @moomoomoo309 и обнаружения проблем (печатает в неправильном месте, ширина и высота не соответствуют аргументам, игнорирует заголовок черепахи, поэтому не может печатать наклонные эллипсы, заголовок не отслеживает рисунок, не оставляет перо в исходном состоянии и т.д.) Решаю попробовать написать свой.
Я решил использовать turtle.circle()
в качестве модели относительно того, где эллипс рисуется относительно существующего положения и направления черепахи, что позволяет пользователю изменять шаги (т. е. создавать другие неправильные многоугольники), оставлять состояние пера и положение, в котором оно началось, и т. д. Вот что я придумал (я использовал self
вместо turtle
или pen
, так как предполагал установить его как метод):
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()
(Необязательно) добавьте этот метод в нашу черепаху на Добавление метода к существующему Экземпляр объекта:
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()
ПРИМЕР РЕЗУЛЬТАТА
![введите здесь описание изображения](https://i.stack.imgur.com/J9jWE.png)
Я попытался реализовать extent
а-ля 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()
Чтобы создать тонкую букву O на основе эллипса, которую хотел OP:
![введите здесь описание изображения](https://i.stack.imgur.com/EQU35.png)
person
cdlane
schedule
26.12.2016