如何从等角投影中绘制正交投影

时间:2015-05-15 17:24:41

标签: python opengl pygame map-projections

我有这张图片:https://raw.githubusercontent.com/Mihara/RasterPropMonitor/master/GameData/JSI/RasterPropMonitor/Library/Components/NavBall/NavBall000.png

我不知道究竟是什么样的投影,我猜是形状的equirectangular或mercator。它是an attitude indicatorb的纹理。

我想根据由两个角度(航向和俯仰)定义的方向向量绘制orthographic projectionb或者General Perspective projection(其中一个看起来更好)。此方向定义球体上的一个点,该点应该是投影的中心。

我希望它从飞行员的角度来看,因此只应绘制一半球体。

我使用python,我还没有选择图形库,但我可能会使用pygame。

我发现了一些相关内容:http://www.pygame.org/project-Off-Center+Map+Projections-2881-.html但是它使用的是OpenGL而我没有使用它的经验,但我可以尝试。

我该怎么做?我可能可以通过计算计算公式中的每个像素来手动绘制它,但我认为有一些库工具可以有效地做到这一点(硬件加速可能?)。

2 个答案:

答案 0 :(得分:8)

对于全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)

会帮你的

animated thing

OpenGL实际上是 做这种像素争论的地方,特别是如果它适用于任何交互式的。

答案 1 :(得分:2)

我瞥了一眼&#34;偏离中心地图预测中的代码&#34;你联系的东西......

作为一个起点,我说它非常好,特别是如果你想在PyGame中以任何效率实现这一点,因为将任何类型的每像素操作卸载到OpenGL将是很多比他们用Python更快。

显然,为了进一步了解你需要了解OpenGL;投影是用main.py的GLSL代码(传递给mod_program.ShaderFragment的字符串中的内容)实现的 - 如果你是&#39;那么atan和asin不应该是一个惊喜。阅读了equirectangular预测。

但是,为了达到想要的东西,你必须弄清楚如何渲染一个球体而不是视口填充四边形(在{{1的main.py中渲染) }})。或者,坚持使用屏幕填充四边形,并在着色器代码中执行光线球体交叉(这实际上是我的另一个答案中的python代码)。