【问题标题】:How to draw orthographic projection from equirectangular projection如何从等角投影绘制正交投影
【发布时间】:2015-07-27 17:23:40
【问题描述】:

我有这张图片:

我不知道它到底是什么投影,我猜是等距矩形或墨卡托的形状。这是an attitude indicatorb 的纹理。

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

我希望它从飞行员的角度来看,所以应该只画出一半的球体。

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

我找到了一些相关的东西:http://www.pygame.org/project-Off-Center+Map+Projections-2881-.html,但它使用 OpenGL,我没有使用它的经验,但如果需要我可以尝试。

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

【问题讨论】:

    标签: python opengl pygame map-projections


    【解决方案1】:

    对于全 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 确实是 进行这种像素争吵的地方,尤其是当它用于任何交互时。

    【讨论】:

      【解决方案2】:

      我看了你链接的“Off-Center Map Projections”中的代码...

      作为您的起点,我想说这非常好,尤其是如果您想在 PyGame 中以任何形式的效率来实现这一点,因为将任何类型的每像素操作卸载到 OpenGL 将很多 比在 Python 中更快。

      显然,您需要进一步了解 OpenGL;投影是在 main.py 的 GLSL 代码中实现的(传递给 mod_program.ShaderFragment 的字符串中的内容) - 如果您阅读过 equirectangular 投影,那么 atan 和 asin 应该不会感到惊讶。

      但是,要获得想要的效果,您必须弄清楚如何渲染球体而不是填充视口的四边形(在 glBegin(GL_QUADS); 的 main.py 中渲染)。或者,坚持使用屏幕填充四边形并在着色器代码中进行射线球相交(这实际上是我其他答案中的 python 代码所做的)。

      【讨论】:

      • 谢谢你的帮助,我一定会看看 OpenGL。
      猜你喜欢
      • 2018-06-23
      • 2021-06-08
      • 2013-01-22
      • 2015-03-07
      • 1970-01-01
      • 1970-01-01
      • 2014-07-06
      • 2013-11-26
      • 1970-01-01
      相关资源
      最近更新 更多