2016-04-12 3 views
4

Я искал ответы на вопросы, но я не могу понять, почему в моем коде я не могу заставить проецируемые контуры появляться «позади» поверхности.Отображение контуров перед поверхностью в matplotlib

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

fig = plt.figure() 
ax = fig.gca(projection='3d') 
X = np.array([[200,800,1500,2000,3000],[200,700,1500,2000,3000],[200,800,1500,2000,3000],[200,800,1500,2000,3000]]) 
Y = np.array([[50,50,50,50,50],[350,350,350,350,350],[500,500,500,500,500],[1000,1000,1000,1000,1000]]) 
Z = np.array([[0,0,33,64,71],[44,62,69,74,76],[59,67,72,75,77],[63,68,73,76,77]]) 

ax.plot_surface(X, Y, Z, rstride=1, cstride=1, alpha=0.5) 
cset = ax.contourf(X, Y, Z, zdir='z', offset=0, cmap=cm.coolwarm) 
cset = ax.contourf(X, Y, Z, zdir='x', offset=200, cmap=cm.coolwarm) 
cset = ax.contourf(X, Y, Z, zdir='y', offset=1000, cmap=cm.coolwarm) 

ax.set_xlabel('X') 
ax.set_xlim(200, 3000) 
ax.set_ylabel('Y') 
ax.set_ylim(0, 1000) 
ax.set_zlabel('Z') 
ax.set_zlim(0, 100) 

plt.show() 

Я использую один из Заполненные изополей с этой страницы в качестве матрицы: http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#scatter-plots

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

Любые советы были бы очень желанными!

+0

Ваш код не запускается: 'Неизвестная проекция '3d'' – Chiel

+1

Я просто добавил' из mpl_toolkits.mplot3d import Axes3D', чтобы сделать это mwe работать. – WWhisperer

+0

Извинения за это ... Я отредактировал вопрос. – Sorade

ответ

2

Проблема, с которой вы столкнулись, - это хорошо известный bug/missing feature в matplotlib. Цитирование a co-lead developer of matplotlib:

Как я понимаю, это все трехмерное построение как часть взлома.

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

Можно было бы подумать, что установка zorder свойств для различных объектов могут повлиять на результат, но this is not the case, так как

дробя зарисовки является то, что «выше» и «снизу» определяются в некоторых, что аркан способ

in other words

Axes3D игнорирует ZOrder и привлекает художников в порядке он думает, что они должны быть.

Это проявляется во всех видах 3D-графиков, например, когда plotting text with surfaces, plotting complicated surfaces, или даже plotting 3d bar plots (даже если можно было бы ожидать, что легче определить порядок построения графиков в рамках одного вызова функции).

Для поверхностей, нанесенных с использованием одной команды (то есть тех, которые содержат один Poly3DCollection), вы можете использовать метод set_zsort(), чтобы дать очень грубый намек на matplotlib относительно предпочтительного порядка построения. Помимо этого, ваш единственный вариант - перемещать ваши поверхности и углы обзора вокруг (если это вообще возможно) таким образом, чтобы проблема не была видна или, по крайней мере, не была полностью очевидна. Другой вариант, предложенный @tcaswell, - это to use mayavi вместо mplot3d (но я этого никогда не делал).