python之万花尺

本文介绍了如何使用Python的Turtle模块和相关库创建Spirograph动画,包括Spiro类的定义、参数设置、动画绘制以及用户交互功能,如图像保存和动画控制。
摘要由CSDN通过智能技术生成

1、使用模块

import sys, random, argparse
import numpy as np
import math
import turtle
import random
from PIL import Image
from datetime import datetime
from math import gcd

依次使用pip下载即可

2、代码

import sys, random, argparse
import numpy as np
import math
import turtle
import random
from PIL import Image
from datetime import datetime
from math import gcd


# A class that draws a spirograph
class Spiro:
    # constructor
    def __init__(self, xc, yc, col, R, r, l):

        # create own turtle
        self.t = turtle.Turtle()
        # set cursor shape
        self.t.shape('turtle')
        # set step in degrees
        self.step = 5
        # set drawing complete flag
        self.drawingComplete = False

        # set parameters
        self.setparams(xc, yc, col, R, r, l)

        # initiatize drawing
        self.restart()

    # set parameters
    def setparams(self, xc, yc, col, R, r, l):
        # spirograph parameters
        self.xc = xc
        self.yc = yc
        self.R = int(R)
        self.r = int(r)
        self.l = l
        self.col = col
        # reduce r/R to smallest form by dividing with GCD
        gcdVal = gcd(self.r, self.R)
        self.nRot = self.r // gcdVal
        # get ratio of radii
        self.k = r / float(R)
        # set color
        self.t.color(*col)
        # current angle
        self.a = 0

    # restart drawing
    def restart(self):
        # set flag
        self.drawingComplete = False
        # show turtle
        self.t.showturtle()
        # go to first point
        self.t.up()
        R, k, l = self.R, self.k, self.l
        a = 0.0
        x = R * ((1 - k) * math.cos(a) + l * k * math.cos((1 - k) * a / k))
        y = R * ((1 - k) * math.sin(a) - l * k * math.sin((1 - k) * a / k))
        self.t.setpos(self.xc + x, self.yc + y)
        self.t.down()

    # draw the whole thing
    def draw(self):
        # draw rest of points
        R, k, l = self.R, self.k, self.l
        for i in range(0, 360 * self.nRot + 1, self.step):
            a = math.radians(i)
            x = R * ((1 - k) * math.cos(a) + l * k * math.cos((1 - k) * a / k))
            y = R * ((1 - k) * math.sin(a) - l * k * math.sin((1 - k) * a / k))
            self.t.setpos(self.xc + x, self.yc + y)
        # done - hide turtle
        self.t.hideturtle()

    # update by one step
    def update(self):
        # skip if done
        if self.drawingComplete:
            return
        # increment angle
        self.a += self.step
        # draw step
        R, k, l = self.R, self.k, self.l
        # set angle
        a = math.radians(self.a)
        x = self.R * ((1 - k) * math.cos(a) + l * k * math.cos((1 - k) * a / k))
        y = self.R * ((1 - k) * math.sin(a) - l * k * math.sin((1 - k) * a / k))
        self.t.setpos(self.xc + x, self.yc + y)
        # check if drawing is complete and set flag
        if self.a >= 360 * self.nRot:
            self.drawingComplete = True
            # done - hide turtle
            self.t.hideturtle()

    # clear everything
    def clear(self):
        self.t.clear()


# A class for animating spirographs
class SpiroAnimator:
    # constructor
    def __init__(self, N):
        # timer value in milliseconds
        self.deltaT = 10
        # get window dimensions
        self.width = turtle.window_width()
        self.height = turtle.window_height()
        # create spiro objects
        self.spiros = []
        for i in range(N):
            # generate random parameters
            rparams = self.genRandomParams()
            # set spiro params
            spiro = Spiro(*rparams)
            self.spiros.append(spiro)
        # call timer
        turtle.ontimer(self.update, self.deltaT)

    # restart sprio drawing
    def restart(self):
        for spiro in self.spiros:
            # clear
            spiro.clear()
            # generate random parameters
            rparams = self.genRandomParams()
            # set spiro params
            spiro.setparams(*rparams)
            # restart drawing
            spiro.restart()

    # generate random parameters
    def genRandomParams(self):
        width, height = self.width, self.height
        R = random.randint(50, min(width, height) // 2)
        r = random.randint(10, 9 * R // 10)
        l = random.uniform(0.1, 0.9)
        xc = random.randint(-width // 2, width // 2)
        yc = random.randint(-height // 2, height // 2)
        col = (random.random(),
               random.random(),
               random.random())
        return (xc, yc, col, R, r, l)

    def update(self):
        # update all spiros
        nComplete = 0
        for spiro in self.spiros:
            # update
            spiro.update()
            # count completed ones
            if spiro.drawingComplete:
                nComplete += 1
        # if all spiros are complete, restart
        if nComplete == len(self.spiros):
            self.restart()
        # call timer
        turtle.ontimer(self.update, self.deltaT)

    # toggle turtle on/off
    def toggleTurtles(self):
        for spiro in self.spiros:
            if spiro.t.isvisible():
                spiro.t.hideturtle()
            else:
                spiro.t.showturtle()


# save spiros to image
def saveDrawing():
    # hide turtle
    turtle.hideturtle()
    # generate unique file name
    dateStr = (datetime.now()).strftime("%d%b%Y-%H%M%S")
    fileName = 'spiro-' + dateStr
    print('saving drawing to %s.eps/png' % fileName)
    # get tkinter canvas
    canvas = turtle.getcanvas()
    # save postscipt image
    canvas.postscript(file=fileName + '.eps')
    # use PIL to convert to PNG
    img = Image.open(fileName + '.eps')
    img.save(fileName + '.png', 'png')
    # show turtle
    turtle.showturtle()


# main() function
def main():
    # use sys.argv if needed
    print('generating spirograph...')
    # create parser
    descStr = """This program draws spirographs using the Turtle module. 
    When run with no arguments, this program draws random spirographs.

    Terminology:

    R: radius of outer circle.
    r: radius of inner circle.
    l: ratio of hole distance to r.
    """
    parser = argparse.ArgumentParser(description=descStr)

    # add expected arguments
    parser.add_argument('--sparams', nargs=3, dest='sparams', required=False,
                        help="The three arguments in sparams: R, r, l.")

    # parse args
    args = parser.parse_args()

    # set to 80% screen width
    turtle.setup(width=0.8)

    # set cursor shape
    turtle.shape('turtle')

    # set title
    turtle.title("Spirographs!")
    # add key handler for saving images
    turtle.onkey(saveDrawing, "s")
    # start listening
    turtle.listen()

    # hide main turtle cursor
    turtle.hideturtle()

    # checks args and draw
    if args.sparams:
        params = [float(x) for x in args.sparams]
        # draw spirograph with given parameters
        # black by default
        col = (0.0, 0.0, 0.0)
        spiro = Spiro(0, 0, col, *params)
        spiro.draw()
    else:
        # create animator object
        spiroAnim = SpiroAnimator(4)
        # add key handler to toggle turtle cursor
        turtle.onkey(spiroAnim.toggleTurtles, "t")
        # add key handler to restart animation
        turtle.onkey(spiroAnim.restart, "space")

    # start turtle main loop
    turtle.mainloop()


# call main
if __name__ == '__main__':
    main()




注意缩进,注意运行需要在命令行进行运行虽然在pycharm上可以运行但是没办法自己挑选参数

3、结果

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 抱歉,作为AI语言模型,我无法提供图形化的代码。但我可以提供一些思路供您参考。 万花尺是一种绘制曲线的工具,可以在平面上绘制出各种复杂的图形。实现万花尺需要用到一些数学知识和图形库。 以下是一个简单的万花尺实现思路: 1. 导入必要的模块 ```python import turtle import math ``` 2. 定义绘制曲线的函数 ```python def draw_curve(t, length, n): if n == 0: t.forward(length) else: angle = 60 t.left(angle) draw_curve(t, length / 2, n - 1) t.right(angle * 2) draw_curve(t, length / 2, n - 1) t.left(angle) ``` 3. 初始化画布和画笔 ```python t = turtle.Turtle() t.speed(0) t.hideturtle() t.penup() t.setposition(-200, 0) t.pendown() ``` 4. 调用绘制函数,绘制曲线 ```python draw_curve(t, 400, 3) ``` 5. 关闭画布 ```python turtle.done() ``` 这是一个简单的万花尺实现,您可以根据需求进行修改和扩展。 ### 回答2: 万花尺是一种几何绘图工具,它能够通过调整角度和长度来绘制出各种不同的图形,如五角星、六边形等等。下面是一个用Python实现的万花尺的简单代码: ```python import turtle def draw_flower(length, angle): turtle.speed(10) # 设置绘制速度 for _ in range(int(360 / angle)): turtle.forward(length) # 绘制线段 turtle.right(angle) # 调整角度 if __name__ == "__main__": length = 100 # 线段长度 angle = 60 # 调整角度 draw_flower(length, angle) turtle.done() ``` 以上代码使用`turtle`库来进行绘图。首先我们设置绘制的速度为10,然后通过循环来绘制多条线段,绘制的线段长度为`length`,每绘制一条线段之后,我们通过`right()`函数将角度调整为`angle`,以此来绘制出各种不同的图形。 在该代码中,我们通过调整`length`和`angle`的值,可以绘制出不同的万花尺图形。例如,将`length`设置为50,`angle`设置为90,就可以画出正方形。将`length`设置为100,`angle`设置为60,可以画出六边形。 当程序运行时,会弹出一个窗口,并在窗口上绘制出我们所期望的图形。 ### 回答3: 万花尺是一种用于绘制圆形、椭圆形和曲线轨迹的绘图工具。下面是使用Python编写一个简单的万花尺的代码: ```python import turtle import math # 定义万花尺的绘制函数 def draw_spiral(): turtle.speed(10) # 设置绘制速度 length = 1 # 初始线段长度 angle = 0 # 初始角度 # 通过循环绘制螺旋线 while length < 600: turtle.forward(length) turtle.right(angle) length += 0.5 angle += math.sin(math.radians(angle)) * 5 turtle.done() # 绘制完成后保持窗口不关闭 # 调用绘制函数 draw_spiral() ``` 运行以上代码,会弹出一个绘图窗口,然后通过循环不断绘制线段,线段的长度逐渐增加,同时绘制的角度也逐渐增加,从而形成一个螺旋线。最终绘制出来的螺旋线就是我们所谓的万花尺效果。 这只是一个简单的示例,只实现了万花尺的基本效果。如果需要实现更复杂的效果,可以根据需求进行调整和改进。希望能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

过度引用

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值