Настройка положения просмотра в 3D-графике Matplotlib

У меня есть набор точек внутри 3d куба. Я хочу получить визуальную проекцию этих точек в 2d в зависимости от того, где находится наблюдатель. До сих пор я пытался построить свои точки в 3d и установить высоту и азимут так, чтобы я смотрел куб на стороне.

Это простой пример, но мне нужно иметь возможность обобщить мой код для любой (x,y,z) позиции наблюдателя. Вот что я пробовал до сих пор:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

coord = np.random.uniform(2.,4., (10000,3)) # cube points

los = np.array([10.,3.,3])  #observer position ( looking at side of cube)

center = np.array([3.,3.,3.]) #cube center

def elev(los, target):
    diff = target - los
    cosel = np.sum(los*diff)/np.sqrt(np.sum(los**2.) *  np.sum(diff**2.))
    el = np.degrees(np.arccos(cosel))
    return el

def azi(los, target):
    diff = target - los
    cosazi = (-los[2]*los[0]*diff[0] - los[2]*los[1]*diff[1] + \\
(los[0]**2.+los[1]**2)*diff[2]) / np.sqrt((los[0]**2.+los[1]**2.)* \\
(los[0]**2.+los[1]**2.+los[2]**2)*(diff[0]**2.+diff[1]**2.+diff[2]**2)) 
    sinazi = (-los[2]*diff[0] + los[0]*diff[1]) /  \\
np.sqrt((los[0]**2.+los[1]**2.)*(diff[0]**2.+diff[1]**2.+diff[2]**2.))
    tanazi = sinazi/cosazi
    azi = np.degrees(np.arctan(tanazi))
    return azi

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(coord[:,0], coord[:,1], coord[:,2], edgecolor = "none", alpha = 0.3)

ax.view_init(elev=elev(los, center), azim=azi(los,center))
plt.show()

Я должен видеть идеальный квадрат, но моя получающаяся точка обзора находится под углом. Что не так?

Я позаимствовал формулы высоты и азимута отсюда: https://gis.stackexchange.com/questions/58923/calculate-view-angle

1 ответ

Проблема заключается в том, что угол места и азимут в matplotlib относятся к началу координат осей, а не к центру нарисованного объекта. Затем необходимо преобразовать координаты объекта в начало координат и преобразовать точку зрения относительно объекта.

Тогда азимут и высоту очень легко получить путем преобразования положения наблюдателя в сферические полярные координаты https://en.wikipedia.org/wiki/Spherical_coordinate_system

Примечание: высота тета измеряется относительно плоскости отсчета, поэтому тета = arcsin(z/r) (вместо arccos). Азимут нужно будет скорректировать в зависимости от того, в каком квадранте находится наблюдатель.

Другие вопросы по тегам