简体   繁体   English

QuickDraw中的python3递归动画

[英]python3 recursion animation in QuickDraw

I have a text file which has the planets and their corresponding moons/satellites along with their orbital radius and period and I would like to use this to create an animation in quickdraw similar to the one below: 我有一个有行星及其相应卫星的文本文件/他们的轨道半径和时段,以及我沿着卫星想用这个来创建一个动画quickdraw类似下面的一个:

太阳系动画

The text file is as followed: 文本文件如下:

RootObject: Sun

Object: Sun
Satellites: Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune,Ceres,Pluto,Haumea,Makemake,Eris
Radius: 20890260
Orbital Radius: 0

Object: Miranda
Orbital Radius: 5822550
Radius: 23500
Period: 1.413

Object: Ariel
Orbital Radius: 8595000
Radius: 60000
Period: 2.520379

Object: Umbriel
Orbital Radius: 11983500
Radius: 60000
Period: 4.144177

Object: Titania
Orbital Radius: 19575000
Radius: 75000
Period: 8.7058

Object: Oberon
Orbital Radius: 26235000
Radius: 75000
Period: 13.463

Object: Uranus
Orbital Radius: 453572956
Radius: 2555900
Period: 30799
Satellites: Puck,Miranda,Ariel,Umbriel,Titania,Oberon

Object: Neptune
Orbital Radius: 550000000
Radius: 2476400
Period: 60190
Satellites: Triton

Object: Triton
Orbital Radius: 40000000
Radius: 135300
Period: -5.8

Object: Mercury
Orbital Radius: 38001200
Period: 87.9691
Radius: 243900.7

Object: Venus
Orbital Radius: 57477000
Period: 224.698
Radius: 605100.8

Object: Earth
Orbital Radius: 77098290
Period: 365.256363004
Radius: 637100.0
Satellites: Moon

Object: Moon
Orbital Radius: 18128500
Radius: 173700.10
Period: 27.321582

Object: Mars
Orbital Radius: 106669000
Period: 686.971
Radius: 339600.2
Satellites: Phobos,Deimos

Object: Phobos
Orbital Radius: 3623500.6
Radius: 200000
Period: 0.31891023

Object: Deimos
Orbital Radius: 8346000
Period: 1.26244
Radius: 200000.2

Object: Jupiter
Orbital Radius: 210573600
Period: 4332.59
Radius: 7149200
Satellites: Io,Europa,Ganymede,Callisto

Object: Ceres
Orbital Radius: 130995855
Period: 1679.67
Radius: 48700

Object: Io
Orbital Radius: 22000000
Period: 1.7691377186
Radius: 182100.3

Object: Europa
Orbital Radius: 36486200
Period: 3.551181
Radius: 156000.8

Object: Ganymede
Orbital Radius: 47160000
Period: 7.15455296
Radius: 263400

Object: Callisto
Orbital Radius: 69700000
Period: 16.6890184
Radius: 241000

Object: Saturn
Orbital Radius: 353572956
Period: 10759.22
Radius: 6026800
Satellites: Mimas,Enceladus,Tethys,Dione,Rhea,Titan,Iapetus

Object: Mimas
Orbital Radius: 8433396
Radius: 20600
Period: 0.9

Object: Enceladus
Orbital Radius: 10706000
Radius: 25000
Period: 1.4

Object: Tethys
Orbital Radius: 13706000
Radius: 50000
Period: 1.9

Object: Dione
Orbital Radius: 17106000
Radius: 56000
Period: 2.7

Object: Rhea
Orbital Radius: 24000000
Radius: 75000
Period: 4.5

Object: Titan
Orbital Radius: 50706000
Radius: 257600
Period: 15.945

Object: Iapetus
Radius: 75000
Orbital Radius: 72285891
Period: 79

I've changed my original code (which was ridiculously longer) to this shorter one: (credit to sudo_O for all his awesome help ) 我把原来的代码(这个时间长得太长了)改成了这个较短的代码:(感谢sudo_O提供了所有他非常棒的帮助

file = open("data1.txt","r")

def data(file):
    d = {}
    for line in file:
        if line.strip() != '':
            key,value = line.split(":")
            if key == 'RootObject':
                continue
            if key == 'Object':                
                obj = value.strip()
                d[obj]={}
            else:
                d[obj][key] = value.strip()
    return d

planets = data(file)

print(planets)

My biggest problem is that I don't know how to write code that imports the data from the file and utilizes it through recursion to create an animation similar to the one shown. 我最大的问题是我不知道如何编写从文件导入数据的代码,并通过recursion利用它来创建类似于所示的动画。 I keep getting told that the solution is quite simple and the code is actually surprisingly short but I have no idea how to do it and it's actually very frustrating. 我不断被告知解决方案非常简单,而且代码实际上非常简短,但我不知道如何做到这一点,实际上非常令人沮丧。

Here is my code for a circle orbiting a circle but it seems too complicated... 这是我围绕圆圈运行的圆圈的代码,但它似乎太复杂了......

import math

print("circle",400,300,50)

print("flush false")

centreX=400
centreY=300
radius=100
angle=math.pi/2

while True:
    print("color 0 0 0")
    print("clear")
    print("color 255 0 255")
    print("circle",centreX,centreY,radius)
    childX=math.sin(angle)*radius*1.5+centreX
    childY=math.cos(angle)*radius*1.5+centreY
    print("circle",childX,childY,radius/2)
    print("refresh")
    angle+=0.01

code for scale: 规模代码:

scale=250/max([dict[planets]["Orbital Radius"] for x in dict if "Orbital Radius" in dict[planets]])

Code for orbiting planets: 轨道行星代码:

print("flush false")
scale=250/max([dict[planets]["Orbital Radius"] for x in dict if "Orbital Radius" in dict[planets]])
t=0
x=400
y=300
while True:
    print("refresh")
    print("colour 0 0 0")
    print("clear")
    print("colour 255 255 255")
    print("fillcircle",x,y,dict['Sun']['Radius']*scale)
    print("text ", "\"Sun\"",x+dict['Sun']['Radius']*scale,y)
    r_earth=dict['Earth']['Orbital Radius']*scale;
    print("circle",x,y,r_earth)
    r_X=x+math.sin(t*2*math.pi/dict['Earth']['Period'])*r_earth
    r_Y=y+math.cos(t*2*math.pi/dict['Earth']['Period'])*r_earth
    print("fillcircle",r_X,r_Y,dict['Earth']['Radius']*scale)
    print("text ", "\"Earth\"",r_X+dict['Earth']['Radius']*scale,r_Y)
    t+=0.02

this code does not work very well however and as a beginner, I am at my limits for this problem... 这段代码不能很好地工作,但作为一个初学者,我对这个问题的极限......

last ditch effort !! 最后的努力!! would this could work? 这会起作用吗?

print("flush false")
scale = 250/max([dict[planets]["Orbital Radius"] for x in dict if "Orbital Radius" in dict[planets]])
t = 0
x = 400
y = 300
print("fillcircle",400,300,dict['Sun']['Radius']*scale)
print("text ", "\"Sun\"",x+dict['Sun']['Radius']*scale,y)


while True:
    r_new = dict['Object']['Orbital Radius']*scale
    print("circle",x,y,r_new)
    r_X = x + math.sin(t*2*math.pi/dict['Object']['Period'])*r_new
    r_Y = y + math.cos(t*2*math.pi/dict['Object']['Period'])*r_new
    print("fillcircle",r_X,r_Y,dict['Object']['Radius']*scale)
    print("text ",Object,r_X+dict['Object']['Radius']*scale,r_Y)
    t += 0.02
    if planets['Object']['Satellites'] = 0
        return
    else:
        r_sat = dict['Object']['Satellites']['Orbital Radius']*scale
        print("circle",x,y,r_sat)
        r_satX = x + math.sin(t*2*math.pi/dict['Object']['Satellites']['Period'])*r_sat
        r_satY = y + math.cos(t*2*math.pi/dict['Object']['Satellites']['Period'])*r_sat
        print("fillcircle",r_satX,r_satY,dict['Object']['Satellites']['Radius']*scale)
        print("text ",['Object']['Satellites'],r_satX+dict['Object']['Satellites']['Radius']*scale,r_satY)
        t += 0.02

First problem recursion - a recursive function is one that calls itself! 第一个问题递归 - 递归函数是一个自我调用的函数! A simple example of this is a countdown function such as: 一个简单的例子是倒计时功能,例如:

def countdown(n):
    # counting down the recursive way! 
    if n > 0:
        print n
        countdown(n-1)
    else:
        return

Calling countdown(10) will print 10, 9, 8,.., 2, 1 . 调用countdown(10)将打印10, 9, 8,.., 2, 1

You can see that countdown is passed a number n and all it does is prints that number and then calls itself but passing n-1 this time. 您可以看到countdown传递了一个数字n ,它所做的就是打印该数字,然后自己调用,但这次传递n-1 Only once n=0 is passed will it not have anything left to do so each recursive call is returned. 只有在n=0才会传递它没有任何事情要做,所以返回每个递归调用。 For your dictionary of dictionaries case (lets call it a library of dictionaries to avoid confusion) a recursive printing approach would be: 对于你的字典词典案例(让我们称之为词典库以避免混淆)recursive打印方法将是:

  1. Pass the whole library to the printing routine. 将整个库传递给打印例程。
  2. Print the first dictionary. 打印第一本字典。
  3. Recursively call itself and pass the library minus the first dictionary. 递归调用自身并传递库减去第一个字典。
  4. Return when the library has no more dictionaries to print. 当库没有更多字典要打印时返回。

Something like this: 像这样的东西:

def recursive_print(dic):

    if len(dic) > 0:                  # If dictionaries in library > 0 
        print dic.keys()[0]           # Print the key i.e Earth
        print dic[dic.keys()[0]]      # Print the dictionary value for i.e Earth
        dic.popitem()                 # Remove the Earth dictionary from library
        recursive_print(dic)          # Recursive call 
    else:
        return                        # Printed all, return up the stack.


planets = data(file)
recursive_print(planets)

The next step would be instead of printing the dictionaries in there current format you would do some calculations/conversion so the output is valid quickdraw input, like the code you have already for printing circles using quickdraw . 下一步是不是以当前格式打印字典,而是进行一些计算/转换,因此输出是有效的quickdraw输入,就像你已经使用quickdraw打印圆圈的代码quickdraw

You will need to worry about the scale, to ensure all objects fit on the drawing surface find the celestial body with the largest Orbital Radius and use that to calculate the scale. 您将需要担心比例,以确保所有对象适合绘图表面找到具有最大Orbital Radius的天体并使用它来计算比例。

Using list comprehension similar to your code we can find the largest value: 使用类似于您的代码的列表理解,我们可以找到最大的值:

max([planet[key]['Orbital Radius'] for key in planet])

>>> 8595000

scale = gridsize/max([planet[key]['Orbital Radius'] for key in planet])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM