如何从等距柱状投影绘制正射投影
How to draw orthographic projection from equirectangular projection
我有这张图片:
我不知道具体是什么投影,看形状估计是等距柱状投影或者墨卡托投影。这是 an attitude indicator, b.
的纹理
我想根据由两个角度(heading 和 pitch)定义的方向向量画一个orthographic projection, b or maybe a General Perspective projection(哪个看起来更好)。这个方向在球体上定义了一个点,这个点应该是投影的中心。
我想让它从飞行员的角度看,所以只画了一半的球体。
我使用 python,我还没有选择图形库,但我可能会使用 pygame。
我找到了一些相关的东西:http://www.pygame.org/project-Off-Center+Map+Projections-2881-.html但是它使用了 OpenGL,我没有使用它的经验,但是如果需要我可以试试。
我应该怎么做?我可能可以通过计算公式中的每个像素来手动绘制它,但我认为有一些库工具可以有效地做到这一点(可能是硬件加速?)。
我看了一眼您链接的 "Off-Center Map Projections" 内容中的代码...
作为您的起点,我会说它非常好,特别是如果您想在 PyGame 中以任何形式的效率实现这一点,因为将任何形式的每像素操作卸载到 OpenGL将比 Python.
快 很多
显然,要更进一步,您需要了解 OpenGL;投影是在 main.py
的 GLSL 代码中实现的(传递给 mod_program.ShaderFragment
的字符串中的内容)- 如果您阅读过等距柱状投影,atan 和 asin 应该不会感到惊讶。
但是,要获得您想要的内容,您必须弄清楚如何渲染球体而不是视口填充四边形(在 main.py 在 glBegin(GL_QUADS);
)。或者,坚持使用屏幕填充四边形并在着色器代码中进行光线球面交集(这实际上是我其他答案中的 python 代码所做的)。
对于全 Python 解决方案(使用 numpy/scipy 数组操作,这将比任何显式每像素循环更快),此:
#!/usr/bin/env python
import math
import numpy as np
import scipy
import scipy.misc
import scipy.ndimage.interpolation
import subprocess
src=scipy.misc.imread("ji80w.png")
size=256
frames=50
for frame in xrange(0,frames):
# Image pixel co-ordinates
px=np.arange(-1.0,1.0,2.0/size)+1.0/size
py=np.arange(-1.0,1.0,2.0/size)+1.0/size
hx,hy=scipy.meshgrid(px,py)
# Compute z of sphere hit position, if pixel's ray hits
r2=hx*hx+hy*hy
hit=(r2<=1.0)
hz=np.where(
hit,
-np.sqrt(1.0-np.where(hit,r2,0.0)),
np.NaN
)
# Some spin and tilt to make things interesting
spin=2.0*np.pi*(frame+0.5)/frames
cs=math.cos(spin)
ss=math.sin(spin)
ms=np.array([[cs,0.0,ss],[0.0,1.0,0.0],[-ss,0.0,cs]])
tilt=0.125*np.pi*math.sin(2.0*spin)
ct=math.cos(tilt)
st=math.sin(tilt)
mt=np.array([[1.0,0.0,0.0],[0.0,ct,st],[0.0,-st,ct]])
# Rotate the hit points
xyz=np.dstack([hx,hy,hz])
xyz=np.tensordot(xyz,mt,axes=([2],[1]))
xyz=np.tensordot(xyz,ms,axes=([2],[1]))
x=xyz[:,:,0]
y=xyz[:,:,1]
z=xyz[:,:,2]
# Compute map position of hit
latitude =np.where(hit,(0.5+np.arcsin(y)/np.pi)*src.shape[0],0.0)
longitude=np.where(hit,(1.0+np.arctan2(z,x)/np.pi)*0.5*src.shape[1],0.0)
latlong=np.array([latitude,longitude])
# Resample, and zap non-hit pixels
dst=np.zeros((size,size,3))
for channel in [0,1,2]:
dst[:,:,channel]=np.where(
hit,
scipy.ndimage.interpolation.map_coordinates(
src[:,:,channel],
latlong,
order=1
),
0.0
)
# Save to f0000.png, f0001.png, ...
scipy.misc.imsave('f{:04}.png'.format(frame),dst)
# Use imagemagick to make an animated gif
subprocess.call('convert -delay 10 f????.png anim.gif',shell=True)
会得到你
.
OpenGL 确实是 进行这种像素处理的地方,尤其是在任何交互式的情况下。
我有这张图片:
我不知道具体是什么投影,看形状估计是等距柱状投影或者墨卡托投影。这是 an attitude indicator, b.
的纹理我想根据由两个角度(heading 和 pitch)定义的方向向量画一个orthographic projection, b or maybe a General Perspective projection(哪个看起来更好)。这个方向在球体上定义了一个点,这个点应该是投影的中心。
我想让它从飞行员的角度看,所以只画了一半的球体。
我使用 python,我还没有选择图形库,但我可能会使用 pygame。
我找到了一些相关的东西:http://www.pygame.org/project-Off-Center+Map+Projections-2881-.html但是它使用了 OpenGL,我没有使用它的经验,但是如果需要我可以试试。
我应该怎么做?我可能可以通过计算公式中的每个像素来手动绘制它,但我认为有一些库工具可以有效地做到这一点(可能是硬件加速?)。
我看了一眼您链接的 "Off-Center Map Projections" 内容中的代码...
作为您的起点,我会说它非常好,特别是如果您想在 PyGame 中以任何形式的效率实现这一点,因为将任何形式的每像素操作卸载到 OpenGL将比 Python.
快 很多显然,要更进一步,您需要了解 OpenGL;投影是在 main.py
的 GLSL 代码中实现的(传递给 mod_program.ShaderFragment
的字符串中的内容)- 如果您阅读过等距柱状投影,atan 和 asin 应该不会感到惊讶。
但是,要获得您想要的内容,您必须弄清楚如何渲染球体而不是视口填充四边形(在 main.py 在 glBegin(GL_QUADS);
)。或者,坚持使用屏幕填充四边形并在着色器代码中进行光线球面交集(这实际上是我其他答案中的 python 代码所做的)。
对于全 Python 解决方案(使用 numpy/scipy 数组操作,这将比任何显式每像素循环更快),此:
#!/usr/bin/env python
import math
import numpy as np
import scipy
import scipy.misc
import scipy.ndimage.interpolation
import subprocess
src=scipy.misc.imread("ji80w.png")
size=256
frames=50
for frame in xrange(0,frames):
# Image pixel co-ordinates
px=np.arange(-1.0,1.0,2.0/size)+1.0/size
py=np.arange(-1.0,1.0,2.0/size)+1.0/size
hx,hy=scipy.meshgrid(px,py)
# Compute z of sphere hit position, if pixel's ray hits
r2=hx*hx+hy*hy
hit=(r2<=1.0)
hz=np.where(
hit,
-np.sqrt(1.0-np.where(hit,r2,0.0)),
np.NaN
)
# Some spin and tilt to make things interesting
spin=2.0*np.pi*(frame+0.5)/frames
cs=math.cos(spin)
ss=math.sin(spin)
ms=np.array([[cs,0.0,ss],[0.0,1.0,0.0],[-ss,0.0,cs]])
tilt=0.125*np.pi*math.sin(2.0*spin)
ct=math.cos(tilt)
st=math.sin(tilt)
mt=np.array([[1.0,0.0,0.0],[0.0,ct,st],[0.0,-st,ct]])
# Rotate the hit points
xyz=np.dstack([hx,hy,hz])
xyz=np.tensordot(xyz,mt,axes=([2],[1]))
xyz=np.tensordot(xyz,ms,axes=([2],[1]))
x=xyz[:,:,0]
y=xyz[:,:,1]
z=xyz[:,:,2]
# Compute map position of hit
latitude =np.where(hit,(0.5+np.arcsin(y)/np.pi)*src.shape[0],0.0)
longitude=np.where(hit,(1.0+np.arctan2(z,x)/np.pi)*0.5*src.shape[1],0.0)
latlong=np.array([latitude,longitude])
# Resample, and zap non-hit pixels
dst=np.zeros((size,size,3))
for channel in [0,1,2]:
dst[:,:,channel]=np.where(
hit,
scipy.ndimage.interpolation.map_coordinates(
src[:,:,channel],
latlong,
order=1
),
0.0
)
# Save to f0000.png, f0001.png, ...
scipy.misc.imsave('f{:04}.png'.format(frame),dst)
# Use imagemagick to make an animated gif
subprocess.call('convert -delay 10 f????.png anim.gif',shell=True)
会得到你
OpenGL 确实是 进行这种像素处理的地方,尤其是在任何交互式的情况下。