Как нарисовать орфографическую проекцию из равнопромежуточной проекции

У меня есть это изображение: https://raw.githubusercontent.com/Mihara/RasterPropMonitor/master/GameData/JSI/RasterPropMonitor  /Библиотека/Компоненты/NavBall/NavBall000.png

Я не знаю точно, какой он по проекции, по форме, наверное, равноугольный или меркаторский. Это текстура для индикатора ориентации, b.

Я хочу нарисовать ортографическую проекцию, b или, возможно, Общая перспектива проекция (какой из них выглядит лучше) в соответствии с вектором направления, определяемым двумя углами (курс и тангаж). Это направление определяет точку на сфере, эта точка должна быть центром проекции.

Я хочу, чтобы это выглядело с точки зрения пилота, поэтому должна быть нарисована только половина сферы.

Я использую python и еще не выбрал графическую библиотеку, но, вероятно, буду использовать pygame.

Я нашел что-то похожее: http://www.pygame.org/project-Off-Center+Map+Projections-2881-.html, но он использует OpenGL, и у меня нет опыта работы с ним, но я могу попробовать, если это необходимо.

Как мне это сделать? Я, вероятно, могу нарисовать его вручную, рассчитав каждый пиксель по формулам расчета, но я думаю, что есть какие-то библиотечные инструменты, позволяющие сделать это эффективно (возможно, с аппаратным ускорением?).


person luxcem    schedule 15.05.2015    source источник


Ответы (2)


Для решения, полностью основанного на 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 действительно является местом для такого рода обработки пикселей, особенно если это что-то интерактивное.

person timday    schedule 16.05.2015

Я взглянул на код в материалах "Off-Center Map Projections", которые вы связали...

В качестве отправной точки я бы сказал, что это было довольно хорошо, особенно если вы хотите достичь этого с какой-либо эффективностью в PyGame, поскольку перенос любых попиксельных операций на OpenGL будет много быстрее, чем когда-либо в Python.

Очевидно, что для дальнейшего продвижения вам необходимо понимать OpenGL; проекция реализована в коде main.py GLSL (материал в строке, переданной mod_program.ShaderFragment) - атан и асин не должны быть сюрпризом, если вы читали о равнопромежуточных проекциях.

Однако, чтобы получить то, что вы хотите, вам нужно выяснить, как визуализировать сферу вместо четырехугольника, заполняющего область просмотра (рендерится в main.py по адресу glBegin(GL_QUADS);). Или, в качестве альтернативы, придерживайтесь четырехугольника, заполняющего экран, и также выполняйте пересечение лучевой сферы в коде шейдера (что фактически делает код Python в моем другом ответе).

person timday    schedule 15.05.2015
comment
Спасибо за помощь, обязательно посмотрю на OpenGL. - person luxcem; 16.05.2015