Python - 球面坐标有 Z 轴偏差
Python - spherical coordinates have Z axis bias
长话短说,我需要让一堆球在 space 中随机移动。我正在使用带有 VRED(3D 渲染软件)的 python 脚本在屏幕上显示球。
我正在尝试使用球坐标,但不知何故 space 中球的分布偏向 Z 轴。实在想不通哪里错了
我是这样处理的:
我生成随机偏航起始方向(-180, 180)和随机起始俯仰(0, 180)
在每一帧,我都会稍微改变偏航和俯仰,然后将球朝新的方向移动。
这是我的 Python 代码(我希望它不会太难读;vrAEBase
是与 VRED 相关的 class,它允许更新 loop()
每帧):
import random
import math
populationsize = 1000
balllist = []
#________________________________________BALL CLASS______________________________________________
class Ball(vrAEBase):
def __init__(self):
vrAEBase.__init__(self)
self.addLoop()
self.body = createSphere(2,100,1,1,1) # create sphere
self.isplaying = false
self.steplength = 20 #step length between each frame
self.yaw = random.uniform(-180, 180) #set starting yaw
self.pitch = random.uniform(0, 180) #set starting pitch
self.maxsteering = 1 # max angular change for yaw/pitch for each frame
self.x = 0 #startting X location
self.y = 0 #startting Y location
self.z = 0 #startting Z location
def loop(self): #loop is executed every frame
if self.isplaying:
self.yaw = self.yaw + random.uniform(-1*self.maxsteering, self.maxsteering) #set new yaw
self.pitch = self.pitch + random.uniform(-1*self.maxsteering, self.maxsteering) #set new pitch
localX = self.steplength * (math.sin(self.pitch)) * (math.cos(self.yaw)) #calculate X step length
localY = self.steplength * (math.sin(self.pitch)) * (math.sin(self.yaw)) #calculate Y step length
localZ = self.steplength * (math.cos(self.pitch)) #calculate Z step length
self.x += localX
self.y += localY
self.z += localZ
setTransformNodeTranslation(self.body, self.x,self.y,self.z,true)
def rewind(self):
self.isplaying = false
self.x = 0
self.y = 0
self.z = 0
setTransformNodeTranslation(self.body, self.x,self.y,self.z,true)
#__________________________________PLAY__________________________________
def play():
global balllist
for ball in balllist:
if ball.isplaying == false:
ball.isplaying = true
else:
ball.isplaying = false
#__________________________________REWIND_________________________________
def rewind():
global balllist
for ball in balllist:
ball.rewind()
#_______________________________SPAWN BALLS________________________________
for x in range(0, populationsize):
newball = Ball() #create ball
balllist.append(newball) #add ball to list
play()
print("end")
这是最终分布图:
问题是,为了在球体周围生成均匀分布的点,您不能执行 phi = [0,pi] 和 theta=[-pi,pi],因为这会导致表面元素 dA= dphi*dtheta 而不是正确的 dA= sin(phi)*dphi*dtheta.
为了实现正确的体积元素变化
def __init__( self):
...
self.yaw = random.uniform(-180, 180) #set starting yaw
self.pitch = random.uniform(0, 180) #set starting pitch
...
到
def __init__( self):
...
u = random.uniform(0,1)
v = random.uniform(0,1)
self.yaw = 2 * math.pi * u #set starting yaw
self.pitch = math.acos( 2*v -1) #set starting pitch
...
有关更多文档,请参阅 http://mathworld.wolfram.com/SpherePointPicking.html。
还要注意您的时间步例程的行为,截至目前,这些点似乎更倾向于向该分布折叠。我不知道这是不是你想要的行为
长话短说,我需要让一堆球在 space 中随机移动。我正在使用带有 VRED(3D 渲染软件)的 python 脚本在屏幕上显示球。
我正在尝试使用球坐标,但不知何故 space 中球的分布偏向 Z 轴。实在想不通哪里错了
我是这样处理的:
我生成随机偏航起始方向(-180, 180)和随机起始俯仰(0, 180)
在每一帧,我都会稍微改变偏航和俯仰,然后将球朝新的方向移动。
这是我的 Python 代码(我希望它不会太难读;vrAEBase
是与 VRED 相关的 class,它允许更新 loop()
每帧):
import random
import math
populationsize = 1000
balllist = []
#________________________________________BALL CLASS______________________________________________
class Ball(vrAEBase):
def __init__(self):
vrAEBase.__init__(self)
self.addLoop()
self.body = createSphere(2,100,1,1,1) # create sphere
self.isplaying = false
self.steplength = 20 #step length between each frame
self.yaw = random.uniform(-180, 180) #set starting yaw
self.pitch = random.uniform(0, 180) #set starting pitch
self.maxsteering = 1 # max angular change for yaw/pitch for each frame
self.x = 0 #startting X location
self.y = 0 #startting Y location
self.z = 0 #startting Z location
def loop(self): #loop is executed every frame
if self.isplaying:
self.yaw = self.yaw + random.uniform(-1*self.maxsteering, self.maxsteering) #set new yaw
self.pitch = self.pitch + random.uniform(-1*self.maxsteering, self.maxsteering) #set new pitch
localX = self.steplength * (math.sin(self.pitch)) * (math.cos(self.yaw)) #calculate X step length
localY = self.steplength * (math.sin(self.pitch)) * (math.sin(self.yaw)) #calculate Y step length
localZ = self.steplength * (math.cos(self.pitch)) #calculate Z step length
self.x += localX
self.y += localY
self.z += localZ
setTransformNodeTranslation(self.body, self.x,self.y,self.z,true)
def rewind(self):
self.isplaying = false
self.x = 0
self.y = 0
self.z = 0
setTransformNodeTranslation(self.body, self.x,self.y,self.z,true)
#__________________________________PLAY__________________________________
def play():
global balllist
for ball in balllist:
if ball.isplaying == false:
ball.isplaying = true
else:
ball.isplaying = false
#__________________________________REWIND_________________________________
def rewind():
global balllist
for ball in balllist:
ball.rewind()
#_______________________________SPAWN BALLS________________________________
for x in range(0, populationsize):
newball = Ball() #create ball
balllist.append(newball) #add ball to list
play()
print("end")
这是最终分布图:
问题是,为了在球体周围生成均匀分布的点,您不能执行 phi = [0,pi] 和 theta=[-pi,pi],因为这会导致表面元素 dA= dphi*dtheta 而不是正确的 dA= sin(phi)*dphi*dtheta.
为了实现正确的体积元素变化
def __init__( self):
...
self.yaw = random.uniform(-180, 180) #set starting yaw
self.pitch = random.uniform(0, 180) #set starting pitch
...
到
def __init__( self):
...
u = random.uniform(0,1)
v = random.uniform(0,1)
self.yaw = 2 * math.pi * u #set starting yaw
self.pitch = math.acos( 2*v -1) #set starting pitch
...
有关更多文档,请参阅 http://mathworld.wolfram.com/SpherePointPicking.html。
还要注意您的时间步例程的行为,截至目前,这些点似乎更倾向于向该分布折叠。我不知道这是不是你想要的行为