2016-06-03 2 views
1

Matplotlib을 사용하여 3 차원 일러스트레이션을 디자인하고 있습니다. 모두 (녹색) 파라 메트릭 서페이스가 완전히 올바르게 그려지는 동안 (빨간색) 파라 메트릭 커브가 잘못된 zorder를 얻는 것을 제외하고는 모두 잘 작동합니다. 아래의 코드에 의해 생성Matplotlib의 3D 파라 메트릭 곡선은 zorder를 존중하지 않습니다. 해결 방법은 무엇입니까?

출력 : Output generated by code below

내가하기 matplotlib 정확하게 개체의 zOrder를 계산 제한된 기능을 가지고 있다는 것을 알고 있지만 파라 메트릭 표면을 위해 그것을 할 수 있기 때문에, 그것을하기 matplotlib에서 벌레처럼 보인다.

즉, 빠르게 작동하도록 올바른 z- 순서를 지정하는 방법이 있습니까? 내가 말할 수 있어야하는 것은 올바른 투명한 푸른 색 비행기가 다른 모든 것 위에 있다는 것입니다. 그러나 zorder 인수를 PolyCollection에 넣는 것은 아무 효과가없는 것처럼 보입니다. 명시 적 zorder 인수를 읽기 선을 그리는 플롯 기능에 넣으면 녹색 표면을 기준으로 한 순서가 엉망이됩니다.

모든 것 위에 오른쪽 파란색 투명면을 적용 할 수있는 방법이 있습니까?

#!/bin/env python3 

from pylab import * 
from mpl_toolkits.mplot3d import * 

from matplotlib.collections import PolyCollection 
from matplotlib.colors import colorConverter 
from matplotlib.patches import FancyArrowPatch 

rc('text', usetex=True) 
rc('font', size=20) 

fig = figure(figsize=(11,6)) 
ax = fig.gca(projection='3d') 

ax.set_axis_off() 

def f(x,t): 
    return t/2 * 0.55*(sin(2*x)+0.4*x**2-0.65) 

c_plane = colorConverter.to_rgba('b', alpha=0.15) 

N = 50 
y = linspace(-1,1,N) 
t = linspace(0,2,N) 
yy, tt = meshgrid(y, t) 
zz = f(yy,tt) 

ax.plot(0*ones(y.shape), y, f(y,0), '-g', linewidth=3) 
ax.plot(2*ones(y.shape), y, f(y,2), '-g', linewidth=3) 

yt = 0.7*y 
zt = f(yt, t) + 0.2*t 

ax.plot(t, yt, zt, '-r', linewidth=3) 
ax.plot((0,2), (yt[0], yt[-1]), (zt[0], zt[-1]), 'or') 

ax.plot([2,2,2], [-1,yt[-1],yt[-1]], [zt[-1],zt[-1],-1], 'k--') 
ax.plot(2*ones(y.shape), yt, f(yt,2)+0.1*(y+1), 'g:', linewidth=2) 
ax.plot((2,2), 
(yt[0], yt[-1]), 
(f(yt[0], 2), f(yt[-1], 2) + 0.1*(y[-1]+1)), 'og') 
ax.plot((0,2,2), 
(-1,-1,zt[-1]), 
(0,yt[-1],-1), 'ok') 

ax.text(0, -1.1, 0, r'$p(0)=0$', ha='right', va='center') 
ax.text(2, -1.05, zt[-1], r'$p(T)$', ha='right', va='center') 
ax.text(0, -1.0, 1, r'$p$', ha='right', va='bottom') 
ax.text(0, 1, -1.1, r'$q$', ha='center', va='top') 
ax.text(0, -1, -1.1, r'$t=0$', ha='right', va='top') 
ax.text(2, -1, -1.1, r'$t=T$', ha='right', va='top') 
ax.text(2, yt[-1]-0.05, -1.05, r'$q(T)=q^*$', ha='left', va='top') 
ax.text(0, 0.5, 0.05, r'$\mathcal{M}(0)$', ha='center', va='bottom') 
ax.text(2, 0.1, -0.8, r'$\mathcal{M}(T)$', ha='center', va='bottom') 

arrowprops = dict(mutation_scale=20, 
linewidth=2, 
arrowstyle='-|>', 
color='k') 

# For arrows, see 
# https://stackoverflow.com/questions/29188612/arrows-in-matplotlib-using-mplot3d 
class Arrow3D(FancyArrowPatch): 
    def __init__(self, xs, ys, zs, *args, **kwargs): 
     FancyArrowPatch.__init__(self, (0,0), (0,0), *args, **kwargs) 
     self._verts3d = xs, ys, zs 

    def draw(self, renderer): 
     xs3d, ys3d, zs3d = self._verts3d 
     xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M) 
     self.set_positions((xs[0],ys[0]),(xs[1],ys[1])) 
     FancyArrowPatch.draw(self, renderer) 

a = Arrow3D([0,2], [-1,-1], [-1,-1], **arrowprops) 
ax.add_artist(a) 
a = Arrow3D([0,0], [-1,-1], [-1,1], **arrowprops) 
ax.add_artist(a) 
a = Arrow3D([0,0], [-1,1], [-1,-1], **arrowprops) 
ax.add_artist(a) 

# For surface illumination, see 
# http://physicalmodelingwithpython.blogspot.de/2015/08/illuminating-surface-plots.html 

# Get lighting object for shading surface plots. 
from matplotlib.colors import LightSource 

# Get colormaps to use with lighting object. 
from matplotlib import cm 

# Create an instance of a LightSource and use it to illuminate the surface. 
light = LightSource(70, -120) 
white = np.ones((zz.shape[0], zz.shape[1], 3)) 
illuminated_surface = light.shade_rgb(white*(0,1,0), zz) 

ax.plot_surface(tt, yy, zz, 
cstride=1, rstride=1, 
alpha=0.3, facecolors=illuminated_surface, 
linewidth=0) 

verts = [array([(-1,-1), (-1,1), (1,1), (1,-1), (-1,-1)])] 

poly = PolyCollection(verts, facecolors=c_plane) 
ax.add_collection3d(poly, zs=[0], zdir='x') 
poly = PolyCollection(verts, facecolors=c_plane) 
ax.add_collection3d(poly, zs=[2], zdir='x') 

ax.set_xlim3d(0, 2) 
ax.view_init(elev=18, azim=-54) 

show() 

답변

2

Axes3Dzorder을 무시하고 그들이해야 생각하는 순서대로 모든 예술가을 그립니다 : 여기에 지금까지 가지고있는 코드입니다. 그러나 빨간색 선은 zorder=0, 녹색 선은 zorder=-1 (또는 그 반대)으로 설정하면 오른쪽 파란색 패널 뒤에 놓을 수 있습니다.

내 결과 : 당신은 알고있다

enter image description here

: 축에 대한

기본 그리기 순서가 패치, 선, 텍스트입니다. 이 순서는 zorder 속성에 의해 결정됩니다. 다음 기본값 나는 좀 더 시행 착오 후 Line2D의 양쪽/LineCollection 2

텍스트 3

+0

하지만, 아주 정확하지 않습니다. 빨간 커브는 이제 녹색 서페이스 아래에 있습니다 (오른쪽 그림에서는 게시 한 그림의 뒤쪽에서 매우 보입니다).사실, plot_surface는 zorder 속성을 완전히 무시하는 것처럼 보입니다. 그렇지 않은 경우, 왼쪽 파란색 비행기로 문제가 생길 것 같지만 명시적인 zorder 사양으로 해결할 수 있다고 가정합니다. – mjo

1

아티스트 Z 순서

패치/PatchCollection 1

을 설정 해결책을 찾았습니다. plot_surface 빨간 곡선의 zorder를 변경하면 오른쪽 평면이 그려지기 때문에 matplotlib는 객체의 전체 순서를 올바르게 가져옵니다. 재미 있은만큼 비행기의 색은 PolyCollection 또는 plot_surface을 통해 그려지기 때문에 약간 변경되므로 동일한 기능을 사용하여 두 비행기를 모두 그려야합니다. 따라서 mplot3d의 zorder 처리는 다소 일관성이 없지만 최종 결과는 꽤 좋아 보입니다. I post it here for reference

여기에 최종 코드

: 나는이 시도했다

#!/bin/env python3 

from pylab import * 
from mpl_toolkits.mplot3d import * 

from matplotlib.collections import PolyCollection 
from matplotlib.colors import colorConverter 
from matplotlib.patches import FancyArrowPatch 

rc('text', usetex=True) 
rc('font', size=20) 

fig = figure(figsize=(11,6)) 
ax = fig.gca(projection='3d') 

ax.set_axis_off() 

def f(x,t): 
    return t/2 * 0.55*(sin(2*x)+0.4*x**2-0.65) 

c_plane = colorConverter.to_rgba('b', alpha=0.15) 

N = 50 
y = linspace(-1,1,N) 
t = linspace(0,2,N) 
yy, tt = meshgrid(y, t) 
zz = f(yy,tt) 

ax.plot(0*ones(y.shape), y, f(y,0), '-g', linewidth=3) 
ax.plot(2*ones(y.shape), y, f(y,2), '-g', linewidth=3) 

yt = 0.7*y 
zt = f(yt, t) + 0.2*t 

ax.plot(t, yt, zt, '-r', linewidth=3, zorder = 1) 

ax.plot([2,2,2], [-1,yt[-1],yt[-1]], [zt[-1],zt[-1],-1], 'k--') 
ax.plot(2*ones(y.shape), yt, f(yt,2)+0.1*(y+1), 'g:', linewidth=2) 
ax.plot((2,2), 
     (yt[0], yt[-1]), 
     (f(yt[0], 2), f(yt[-1], 2) + 0.1*(y[-1]+1)), 'og') 
ax.plot((0,2,2), 
     (-1,-1,zt[-1]), 
     (0,yt[-1],-1), 'ok') 

ax.text(0, -1.1, 0, r'$p(0)=0$', ha='right', va='center') 
ax.text(2, -1.05, zt[-1], r'$p(T)$', ha='right', va='center') 
ax.text(0, -1.0, 1, r'$p$', ha='right', va='bottom') 
ax.text(0, 1, -1.1, r'$q$', ha='center', va='top') 
ax.text(0, -1, -1.1, r'$t=0$', ha='right', va='top') 
ax.text(2, -1, -1.1, r'$t=T$', ha='right', va='top') 
ax.text(2, yt[-1]-0.05, -1.05, r'$q(T)=q^*$', ha='left', va='top') 
ax.text(0, 0.5, 0.05, r'$\mathcal{M}(0)$', ha='center', va='bottom') 
ax.text(2, 0.1, -0.8, r'$\mathcal{M}(T)$', ha='center', va='bottom') 

arrowprops = dict(mutation_scale=20, 
        linewidth=2, 
        arrowstyle='-|>', 
        color='k') 

# For arrows, see 
# https://stackoverflow.com/questions/29188612/arrows-in-matplotlib-using-mplot3d 
class Arrow3D(FancyArrowPatch): 
    def __init__(self, xs, ys, zs, *args, **kwargs): 
     FancyArrowPatch.__init__(self, (0,0), (0,0), *args, **kwargs) 
     self._verts3d = xs, ys, zs 

    def draw(self, renderer): 
     xs3d, ys3d, zs3d = self._verts3d 
     xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M) 
     self.set_positions((xs[0],ys[0]),(xs[1],ys[1])) 
     FancyArrowPatch.draw(self, renderer) 

a = Arrow3D([0,2], [-1,-1], [-1,-1], **arrowprops) 
ax.add_artist(a) 
a = Arrow3D([0,0], [-1,-1], [-1,1], **arrowprops) 
ax.add_artist(a) 
a = Arrow3D([0,0], [-1,1], [-1,-1], **arrowprops) 
ax.add_artist(a) 

# For surface illumination, see 
# http://physicalmodelingwithpython.blogspot.de/2015/08/illuminating-surface-plots.html 

# Get lighting object for shading surface plots. 
from matplotlib.colors import LightSource 

# Get colormaps to use with lighting object. 
from matplotlib import cm 

# Create an instance of a LightSource and use it to illuminate the surface. 
light = LightSource(70, -120) 
white = ones((zz.shape[0], zz.shape[1], 3)) 
illuminated_surface = light.shade_rgb(white*(0,1,0), zz) 

ax.plot_surface(tt, yy, zz, 
       cstride=1, rstride=1, 
       alpha=0.3, facecolors=illuminated_surface, 
       linewidth=0, 
       zorder=10) 

verts = [array([(-1,-1), (-1,1), (1,1), (1,-1), (-1,-1)])] 

ax.plot_surface(((0,0),(0,0)), ((-1,-1),(1,1)), ((-1,1),(-1,1)), 
       color=c_plane) 

ax.plot_surface(((2,2),(2,2)), ((-1,-1),(1,1)), ((-1,1),(-1,1)), 
       color=c_plane) 

ax.plot((0,2), (yt[0], yt[-1]), (zt[0], zt[-1]), 'or') 

ax.set_xlim3d(0, 2) 
ax.view_init(elev=18, azim=-54) 

show() 
관련 문제