本节书摘来自异步社区《Python极客项目编程 》一书中的第2章,第2.4节,作者 [美] Mahesh Venkitachalam,王海鹏 译,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.4 完整代码

下面是完整的万花尺程序。也可以从https://github.com/electronut/pp/blob/master/ spirograph/spiro.py 下载该项目的代码。

import sys, random, argparse

import numpy as np

import math

import turtle

import random

from PIL import Image

from datetime import datetime

from fractions import gcd

# a class that draws a Spirograph

class Spiro:

# constructor

def __init__(self, xc, yc, col, R, r, l):

# create the turtle object

self.t = turtle.Turtle()

# set the cursor shape

self.t.shape('turtle')

# set the step in degrees

self.step = 5

# set the drawing complete flag

self.drawingComplete = False

# set the parameters

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

# initialize the drawing

self.restart()

# set the parameters

def setparams(self, xc, yc, col, R, r, l):

# the 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 its smallest form by dividing with the GCD

gcdVal = gcd(self.r, self.R)

self.nRot = self.r//gcdVal

# get ratio of radii

self.k = r/float(R)

# set the color

self.t.color(*col)

# store the current angle

self.a = 0

# restart the drawing

def restart(self):

# set the flag

self.drawingComplete = False

# show the turtle

self.t.showturtle()

# go to the 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 the rest of the 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)

# drawing is now done so hide the turtle cursor

self.t.hideturtle()

# update by one step

def update(self):

# skip the rest of the steps if done

if self.drawingComplete:

return

# increment the angle

self.a += self.step

# draw a step

R, k, l = self.R, self.k, self.l

# set the 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)

# if drawing is complete, set the flag

if self.a >= 360*self.nRot:

self.drawingComplete = True

# drawing is now done so hide the turtle cursor

self.t.hideturtle()

# clear everything

def clear(self):

self.t.clear()

# a class for animating Spirographs

class SpiroAnimator:

# constructor

def __init__(self, N):

# set the timer value in milliseconds

self.deltaT = 10

# get the window dimensions

self.width = turtle.window_width()

self.height = turtle.window_height()

# create the Spiro objects

self.spiros = []

for i in range(N):

# generate random parameters

rparams = self.genRandomParams()

# set the spiro parameters

spiro = Spiro(*rparams)

self.spiros.append(spiro)

# call timer

turtle.ontimer(self.update, self.deltaT)

# restart spiro drawing

def restart(self):

for spiro in self.spiros:

# clear

spiro.clear()

# generate random parameters

rparams = self.genRandomParams()

# set the spiro parameters

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 spiros

if spiro.drawingComplete:

nComplete += 1

# restart if all spiros are complete

if nComplete == len(self.spiros):

self.restart()

# call the timer

turtle.ontimer(self.update, self.deltaT)

# toggle turtle cursor on and off

def toggleTurtles(self):

for spiro in self.spiros:

if spiro.t.isvisible():

spiro.t.hideturtle()

else:

spiro.t.showturtle()

# save drawings as PNG files

def saveDrawing():

# hide the turtle cursor

turtle.hideturtle()

# generate unique filenames

dateStr = (datetime.now()).strftime("%d%b%Y-%H%M%S")

fileName = 'spiro-' + dateStr

print('saving drawing to %s.eps/png' % fileName)

# get the tkinter canvas

canvas = turtle.getcanvas()

# save the drawing as a postscipt image

canvas.postscript(file = fileName + '.eps')

# use the Pillow module to convert the poscript image file to PNG

img = Image.open(fileName + '.eps')

img.save(fileName + '.png', 'png')

# show the turtle cursor

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 the width of the drawing window to 80 percent of the screen width

turtle.setup(width=0.8)

# set the cursor shape to turtle

turtle.shape('turtle')

# set the title to Spirographs!

turtle.title("Spirographs!")

# add the key handler to save our drawings

turtle.onkey(saveDrawing, "s")

# start listening

turtle.listen()

# hide the main turtle cursor

turtle.hideturtle()

# check for any arguments sent to --sparams and draw the Spirograph

if args.sparams:

params = [float(x) for x in args.sparams]

# draw the Spirograph with the given parameters

col = (0.0, 0.0, 0.0)

spiro = Spiro(0, 0, col, *params)

spiro.draw()

else:

# create the animator object

spiroAnim = SpiroAnimator(4)

# add a key handler to toggle the turtle cursor

turtle.onkey(spiroAnim.toggleTurtles, "t")

# add a key handler to restart the animation

turtle.onkey(spiroAnim.restart, "space")

# start the turtle main loop

turtle.mainloop()

# call main

if __name__ == '__main__':

main()

python极客项目编程pdf微盘下载_《Python极客项目编程 》——2.4 完整代码相关推荐

  1. 神经网络书籍pdf微盘下载,神经网络书籍推荐知乎

    想要学习人工神经网络,需要什么样的基础知识? 人工神经网络理论百度网盘下载:链接:   提取码:rxlc简介:本书是人工神经网络理论的入门书籍.全书共分十章. 第一章主要阐述人工神经网络理论的产生及发 ...

  2. python练手经典100例微盘_20个Python练手经典案例,能全做对的人确实很少!

    100个Python练手小程序,学习python的很好的资料,覆盖了python中的每一部分,可以边学习边练习,更容易掌握python. 如果你感觉学不会?莫慌,小编推荐大家加入群, 前面548中间3 ...

  3. mysql pdf微盘下载失败怎么办_mysql线上常见故障剖析.pdf

    mysql线上常见故障剖析.pdf 还剩 30页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,很抱歉,此页已超出免费预览范围啦! 如果喜欢就下载吧,价低环保! 内容要点: 谢谢大家Summ ...

  4. Head First 系列图书资源-PDF网盘下载(更新中)

    Head First 系列图书资源-PDF网盘下载(更新中) <Head First Python 中文版>.pdf: https://u21476951.ctfile.com/fs/21 ...

  5. 基于Python实现的网络爬虫项目——多线程下载小说并保存为txt文件(包含完整代码及注释)

    基于Python实现的网络爬虫项目--多线程下载小说并保存为txt文件(包含完整代码及注释) 一.确立预期目标 二.完成项目所需工具 三.项目需要解决的问题 问题一 问题二 问题三 问题四 问题五 问 ...

  6. 解决新浪微盘下载没反应下载中断

    解决新浪微盘下载没反应下载中断      最近发现,用浏览器下载新浪微盘的资料,要么点击没反应,要么下载到一般就中断,下载失败.用了好多办法都不能解决.起初以为是服务器的问题,后来发现是浏览器的问题. ...

  7. 从python开始学编程pdf 解压密码_从Python开始学编程PDF高清完整版网盘免费分享...

    提取码:szq0 image 内容简介 · · · · · · 改编自Vamei博客的<Python快速教程>.本书以Python为样本,不仅介绍了编程的基本概念,还着重讲解编程语言的主流 ...

  8. python3破冰人工智能pdf 微盘_Python 3破冰人工智能 从入门到实战

    <Python 3破冰人工智能 从入门到实战>简介: 内容简介: 本书创新性地从数学建模竞赛入手,深入浅出地讲解了人工智能领域的相关知识.本书内容基于Python 3.6,从人工智能领域的 ...

  9. Python爬虫——百度+新浪微盘下载歌曲

    本篇分享将讲解如何利用Python爬虫在百度上下载新浪微盘里自己想要的歌手的歌曲,随便你喜欢的歌手! 首先我们先探索一下我们操作的步骤(以下载Westlife的歌曲为例):打开百度,输入"W ...

最新文章

  1. asp php 语法区别,asp与php语法对比
  2. Redis 很屌,不懂使用规范就糟蹋了
  3. 实名羡慕!蚂蚁员工激励达 1376.9 亿,人均能在杭州买套 283 平的房子?
  4. WebAssembly 的由来
  5. Socket实现java服务端与AndroidApp端数据交互
  6. C语言N台服务器通信,使用socket的Linux上的C语言文件传输顺序服务器和客户端示例程序 ....
  7. 心灵战争服务器维护,心灵战争服务器异常产生哪些问题如何解决_心灵战争服务器异常产生问题及解决方法_玩游戏网...
  8. JavaScript基础08-day10【函数的返回值、实参、立即执行函数、方法、全局作用域、函数作用域、提前声明、this、工厂方法创建对象、构造函数】
  9. jQuery添加/改变/移除CSS类
  10. SQL2005利用ROW_NUMER实现分页的两种常用方式
  11. 电子商务实战课程-张晨光-专题视频课程
  12. 网络编程+Python
  13. Nginx + Apache 公用 80 端口的配置方案。
  14. 发行版迁移及二进制兼容性注意事项
  15. -e mysql_root_password 无效_43万的价格,53万的面子!宝马5系对比奔驰E级
  16. windows桌面的“我的电脑”“IE”等消失的解决方法
  17. 主干网络系列(2) -ResNet V2:深度残差网络中的恒等映射
  18. MatConvNet中关于vl_simplenn_display的一些分析
  19. 横向对比EXT4,带你感受真实的Linux文件系统F2FS
  20. 告诉你一个真实的Google

热门文章

  1. 【cf】Codeforces Round #784(Div 4)
  2. 杰理AC696N串口通信实验
  3. iOS 轻松使用 App 数据统计
  4. SpringBoot入门建站全系列(二十七)WebSocket做简单的聊天室
  5. 让我摘下星星送给你_摘下星星给你摘下月亮给你是什么歌
  6. 不管过去如何,未来我们都要奋力前行!
  7. 11-stream流-流水线编码、filter等中间方法、forEach等终止方法、collect获取返回结果方法、lambda练习
  8. 基于单片机温湿度光照自动窗帘系统设计(毕业设计资料)
  9. 【Android取证篇】华为设备无法识别解决方案
  10. 论文阅读:Personalizing Dialogue Agents via Meta-Learning