我编写了一个程序来计算和激活冥王星的轨道,并开始使用类重写它,因为这似乎是一种将更多行星引入模拟的合理方法。即有一个定义物理学的类,然后输入特定的行星数据以获得轨道数据。
class Planet(object):
m_sun = 1.989*(10**30)
G = 6.67*(10**-11)
dt = 1
coords = []
def __init__(self, x, y, vx, vy, m):
self.x = x
self.y = y
self.vx = vx
self.vy = vy
self.m = m
def genData(self):
while self.dt < 100000000:
r = ((self.x)**2 + (self.y)**2)**0.5
a = ((self.G*self.m_sun)/r**2)
ax = -a*((self.x)/r)
ay = -a*((self.y)/r)
self.vx = self.vx + ax*self.dt
self.vy = self.vy + ay*self.dt
self.x = self.x + self.vx*self.dt
self.y = self.y + self.vy*self.dt
coord = (self.x, self.y)
print coord
self.coords.append(coord)
self.dt = self.dt + 1000
pluto = Planet(4495978707000, 0, 0, 4670, 1.305*(10**22))
pluto.genData()
我确定它并不完美,但似乎有效(这是我自己建立的第一堂课)。我的问题是如何将“coords”中的数据提取到我可以在课堂外工作的列表中。
我想为每个星球生成数据,然后使用这些数据在Pygame中创建动画。例如,冥王星,地球,土星等的(x,y)坐标列表。就目前而言,它会生成数据,但似乎无法从课外访问。
我希望我的问题有道理。
谢谢!
答案 0 :(得分:4)
您的问题已得到解答,但我发现您应该找到一些有助于改进您的计划的信息。从技术上讲,这个信息属于评论(因为你在你的问题中没有真正询问过这个问题),但它不适合。 :)
冥王星的轨道相对于黄道很倾向,所以如果你想在太阳系中将它与其他几颗行星一起绘制,你需要在3D中工作才能准确。但我想这对你的申请来说并不是什么大问题。
与冥王星相比,地球的轨道很小,因此您可能需要实施缩放以在一个动画上看到它们。
使用Standard gravitational parameter而不是使用单独的G和质量值,您可以在计算中获得更高的准确性。
您计算速度和位置的算法称为Euler integration。它相当于用多边形近似轨道曲线。它有效,但不是很准确。因此,您需要使时间差非常小,否则轨道不会非常逼真,甚至可能不是闭合曲线。即使这并没有多大帮助,因为错误是累积的,所以最终计算出的轨道与现实几乎没有相似之处。
没有任何数值积分技术是完美的(除了非常简单的函数),但是一个更流行的集成技术系列更准确(因此工作正常,时间步长更大)是Runge-Kutta methods。您可以使用Runge-Kutta方法找到许多示例轨道计算代码;大多数代码示例使用称为RK4的变体。
但是,强烈敦促您尝试Leapfrog集成。编写Leapfrog的同步形式非常容易,并且它比Runge-Kutta有一个主要的好处,因为它是辛的,它(大致)意味着它节省了能量,所以错误赢得了&#39;从轨道到轨道累积。
答案 1 :(得分:3)
你试过pluto.coords
吗?
您可以使用后跟dot后跟成员名称的实例(即属性访问权限)从外部访问类的成员。这与调用genData()
方法时一样。
顺便说一句,您可以使用指数表示法定义常量:
m_sun = 1.989e+30
G = 6.67e-11
和
pluto = Planet(4495978707000, 0, 0, 4670, 1.305e+22)
更具可读性(重要性)并为您的班级定义保存一些计算(更少/不重要)。
答案 2 :(得分:3)
而不是将值存储在self.coords
,yield the values:
def genData(self):
while self.dt < 100000000:
...
self.x = self.x + self.vx*self.dt
self.y = self.y + self.vy*self.dt
coord = (self.x, self.y)
yield coord
self.dt = self.dt + 1000
pluto = Planet(4495978707000, 0, 0, 4670, 1.305*(10**22))
for coord in pluto.genData():
print(coord)
请注意,这会使genData
成为generator function。
要获取坐标列表,您可以在循环中累积值:
coords = []
for coord in pluto.genData():
coords.append(coord)
或使用coords = list(pluto.genData())
。
顺便说一下,将代码计算与代码打印分开通常是一个很好的策略。这样你可以多次调用代码计算,或者将它包含在一系列计算中,而不必总是发出打印语句。
我想为每个星球生成数据,然后使用这些数据在Pygame中创建动画。
听起来您不需要累积数据。您可以绘制每个行星的当前点,而无需了解行星的坐标历史。在这种情况下,使用生成器函数将更具内存效率,因为它们允许您为每个行星生成下一个坐标,而不必首先将所有坐标存储在列表中:
# In Python2
import itertools as IT
for coords in IT.izip(*[planet.genData() for planet in [pluto, neptune, uranus, ...]]):
# plot coords
或
# In Python3
for coords in zip(*[planet.genData() for planet in [pluto, neptune, uranus, ...]]):
# plot coords
答案 3 :(得分:2)
实际上这很容易,只有pluto.coords
:
pluto = Planet(4495978707000, 0, 0, 4670, 1.305*(10**22))
pluto.genData()
print pluto.coords