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:# constructordef __init__(self, xc, yc, col, R, r, l):# create own turtleself.t = turtle.Turtle()# set cursor shapeself.t.shape('turtle')# set step in degreesself.step = 5# set drawing complete flagself.drawingComplete = False# set parametersself.setparams(xc, yc, col, R, r, l)# initiatize drawingself.restart()# set parametersdef setparams(self, xc, yc, col, R, r, l):# spirograph parametersself.xc = xcself.yc = ycself.R = int(R)self.r = int(r)self.l = lself.col = col# reduce r/R to smallest form by dividing with GCDgcdVal = gcd(self.r, self.R)self.nRot = self.r // gcdVal# get ratio of radiiself.k = r / float(R)# set colorself.t.color(*col)# current angleself.a = 0# restart drawingdef restart(self):# set flagself.drawingComplete = False# show turtleself.t.showturtle()# go to first pointself.t.up()R, k, l = self.R, self.k, self.la = 0.0x = 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 thingdef draw(self):# draw rest of pointsR, k, l = self.R, self.k, self.lfor 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 turtleself.t.hideturtle()# update by one stepdef update(self):# skip if doneif self.drawingComplete:return# increment angleself.a += self.step# draw stepR, k, l = self.R, self.k, self.l# set anglea = 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 flagif self.a >= 360 * self.nRot:self.drawingComplete = True# done - hide turtleself.t.hideturtle()# clear everythingdef clear(self):self.t.clear()# A class for animating spirographs class SpiroAnimator:# constructordef __init__(self, N):# timer value in millisecondsself.deltaT = 10# get window dimensionsself.width = turtle.window_width()self.height = turtle.window_height()# create spiro objectsself.spiros = []for i in range(N):# generate random parametersrparams = self.genRandomParams()# set spiro paramsspiro = Spiro(*rparams)self.spiros.append(spiro)# call timerturtle.ontimer(self.update, self.deltaT)# restart sprio drawingdef restart(self):for spiro in self.spiros:# clearspiro.clear()# generate random parametersrparams = self.genRandomParams()# set spiro paramsspiro.setparams(*rparams)# restart drawingspiro.restart()# generate random parametersdef genRandomParams(self):width, height = self.width, self.heightR = 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 spirosnComplete = 0for spiro in self.spiros:# updatespiro.update()# count completed onesif spiro.drawingComplete:nComplete += 1# if all spiros are complete, restartif nComplete == len(self.spiros):self.restart()# call timerturtle.ontimer(self.update, self.deltaT)# toggle turtle on/offdef 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 turtleturtle.hideturtle()# generate unique file namedateStr = (datetime.now()).strftime("%d%b%Y-%H%M%S")fileName = 'spiro-' + dateStrprint('saving drawing to %s.eps/png' % fileName)# get tkinter canvascanvas = turtle.getcanvas()# save postscipt imagecanvas.postscript(file=fileName + '.eps')# use PIL to convert to PNGimg = Image.open(fileName + '.eps')img.save(fileName + '.png', 'png')# show turtleturtle.showturtle()# main() function def main():# use sys.argv if neededprint('generating spirograph...')# create parserdescStr = """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 argumentsparser.add_argument('--sparams', nargs=3, dest='sparams', required=False,help="The three arguments in sparams: R, r, l.")# parse argsargs = parser.parse_args()# set to 80% screen widthturtle.setup(width=0.8)# set cursor shapeturtle.shape('turtle')# set titleturtle.title("Spirographs!")# add key handler for saving imagesturtle.onkey(saveDrawing, "s")# start listeningturtle.listen()# hide main turtle cursorturtle.hideturtle()# checks args and drawif args.sparams:params = [float(x) for x in args.sparams]# draw spirograph with given parameters# black by defaultcol = (0.0, 0.0, 0.0)spiro = Spiro(0, 0, col, *params)spiro.draw()else:# create animator objectspiroAnim = SpiroAnimator(4)# add key handler to toggle turtle cursorturtle.onkey(spiroAnim.toggleTurtles, "t")# add key handler to restart animationturtle.onkey(spiroAnim.restart, "space")# start turtle main loopturtle.mainloop()# call main if __name__ == '__main__':main()注意缩进,注意运行需要在命令行进行运行虽然在pycharm上可以运行但是没办法自己挑选参数