VPython太阳系模型轨道旋转异常问题求助
解决VPython太阳系模型的行星轨道旋转问题
嘿,我来帮你搞定这个行星公转的问题!你遇到的核心问题是误用了物体的rotate()方法,同时旋转轴的设置也不对,导致行星运动异常。
问题根源分析
你之前调用的Mercury.rotate()是用来旋转行星自身的姿态(比如让行星自转),而不是改变它的位置来实现绕太阳的轨道运动。另外,你设置的旋转轴vec(Mercury.pos.y, Mercury.pos.x, 0)会随着行星位置变化而改变方向,这就导致旋转逻辑混乱,出现转四分之一圈就异常、抖动的情况。
两种可行的解决方案
方案1:用三角函数计算轨道位置(最直观)
我们可以给每个行星定义轨道半径和公转速度,在循环中通过三角函数计算每个时刻的位置,让行星绕太阳做稳定的圆周运动:
GlowScript 2.7 VPython from visual import * # 创建太阳 Sun = sphere(pos=vec(0, 0, 0), radius=10, color=color.yellow) # 定义行星参数:轨道半径、公转速度(弧度/帧)、天体对象 planets = [ {"obj": sphere(pos=vec(25, 0, 0), radius=2, color=color.green), "radius": 25, "speed": 0.05}, {"obj": sphere(pos=vec(40, 0, 0), radius=2.5, color=color.red), "radius": 40, "speed": 0.03}, {"obj": sphere(pos=vec(50, 0, 0), radius=2.65, color=color.blue), "radius": 50, "speed": 0.02}, {"obj": sphere(pos=vec(70, 0, 0), radius=2.3, color=color.orange), "radius": 70, "speed": 0.015}, {"obj": sphere(pos=vec(90, 0, 0), radius=3, color=color.orange), "radius": 90, "speed": 0.008}, {"obj": sphere(pos=vec(105, 0, 0), radius=2.9, color=color.orange), "radius": 105, "speed": 0.006}, {"obj": sphere(pos=vec(117.5, 0, 0), radius=2.9, color=color.cyan), "radius": 117.5, "speed": 0.004}, {"obj": sphere(pos=vec(135, 0, 0), radius=2.8, color=color.blue), "radius": 135, "speed": 0.003}, {"obj": sphere(pos=vec(165, 0, 0), radius=1.5, color=color.white), "radius": 165, "speed": 0.002} ] # 创建轨道环 for p in planets: p["ring"] = ring(pos=vec(0,0,0), axis=vec(0,1,0), radius=p["radius"], thickness=0.1) # 初始化每个行星的公转角度 for p in planets: p["angle"] = 0 # 主循环 while True: rate(50) # 控制帧率,避免过快 for p in planets: # 更新公转角度 p["angle"] += p["speed"] # 计算新位置:绕y轴做圆周运动,x=半径*cos(角度),z=半径*sin(角度) p["obj"].pos = vec(p["radius"] * cos(p["angle"]), 0, p["radius"] * sin(p["angle"])) # 如果需要添加自转,可以加上这行 # p["obj"].rotate(angle=0.1, axis=vec(0,1,0)) print("Error! Escaped While Loop!")
方案2:用VPython的rotate()函数更新位置向量
如果你更习惯用VPython的旋转函数,可以直接对行星的位置向量进行旋转,固定绕y轴(太阳的垂直轴)旋转:
GlowScript 2.7 VPython from visual import * # 声明天体对象 Sun = sphere(pos = vec(0, 0, 0), radius = 10, color = color.yellow) Mercury = sphere(pos = vec(25, 0, 0), radius = 2, color = color.green) Venus = sphere(pos = vec(40, 0, 0), radius = 2.5, color = color.red) Earth = sphere(pos = vec(50, 0, 0), radius = 2.65, color = color.blue) Mars = sphere(pos = vec(70, 0, 0), radius = 2.3, color = color.orange) Jupiter = sphere(pos = vec(90, 0, 0), radius = 3, color = color.orange) Saturn = sphere(pos = vec(105, 0, 0), radius = 2.9, color = color.orange) Uranus = sphere(pos = vec(117.5, 0, 0), radius = 2.9, color = color.cyan) Neptune = sphere(pos = vec(135, 0, 0), radius = 2.8, color = color.blue) Pluto = sphere(pos = vec(165, 0, 0), radius = 1.5, color = color.white) # 声明轨道环 Mercury.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=25, thickness=0.1) Venus.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=40, thickness=0.1) Earth.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=50, thickness=0.1) Mars.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=70, thickness=0.1) Jupiter.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=90, thickness=0.1) Saturn.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=105, thickness=0.1) Uranus.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=117.5, thickness=0.1) Neptune.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=135, thickness=0.1) Pluto.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=165, thickness=0.1) # 主循环 while True: rate(50) # 绕y轴(vec(0,1,0))旋转位置向量,原点是太阳 Mercury.pos = rotate(Mercury.pos, angle=0.05, axis=vec(0,1,0), origin=vec(0,0,0)) Venus.pos = rotate(Venus.pos, angle=0.03, axis=vec(0,1,0), origin=vec(0,0,0)) Earth.pos = rotate(Earth.pos, angle=0.02, axis=vec(0,1,0), origin=vec(0,0,0)) Mars.pos = rotate(Mars.pos, angle=0.015, axis=vec(0,1,0), origin=vec(0,0,0)) Jupiter.pos = rotate(Jupiter.pos, angle=0.008, axis=vec(0,1,0), origin=vec(0,0,0)) Saturn.pos = rotate(Saturn.pos, angle=0.006, axis=vec(0,1,0), origin=vec(0,0,0)) Uranus.pos = rotate(Uranus.pos, angle=0.004, axis=vec(0,1,0), origin=vec(0,0,0)) Neptune.pos = rotate(Neptune.pos, angle=0.003, axis=vec(0,1,0), origin=vec(0,0,0)) Pluto.pos = rotate(Pluto.pos, angle=0.002, axis=vec(0,1,0), origin=vec(0,0,0)) print("Error! Escaped While Loop!")
关键注意点
- 公转是位置的变化,不是物体自身的旋转,所以要更新的是行星的
pos属性,而不是调用物体的rotate()方法(那是用来做自转的)。 - 旋转轴要固定为
vec(0,1,0)(y轴),这样所有行星都会绕着太阳的垂直轴做稳定的圆周运动,不会出现方向混乱。 - 调整
angle参数(公转速度)可以让行星的公转周期符合真实比例,数值越小,公转越慢。
内容的提问来源于stack exchange,提问作者Connor
相关产品推荐
相关产品推荐

