2017-06-18 47 views
2

我必须绘制一个具有无意义负值的3d函数(它们不应出现在图中)。它必须是情节的功能是这样的:Matplotlib忽略三维图中的负值

def constraint_function(x, y): 
    return min(
     (1800 - 0.3 * x - 0.5 * y)/0.4, 
     (500 - 0.1 * x - 0.08 * y)/0.12, 
     (200 - 0.06 * x - 0.04 * y)/0.05 
    ) 

我计算功能的方式如下:

xs = np.linspace(0, 3600, 1000) 
ys = np.linspace(0, 3600, 1000) 
zs = np.empty(shape=(1000, 1000)) 
for ix, x in enumerate(xs): 
    for iy, y in enumerate(ys): 
     zs[ix][iy] = constraint_function(x, y) 
xs, ys = np.meshgrid(xs, ys) 

功能大多在广场[0, 3600]x[0, 3600]有效值。第一种方法我已经被设定轴界限适合我的需要:

fig = plt.figure() 

ax = fig.add_subplot(111, projection='3d') 
ax.azim = 20 
ax.set_xlim(0, 3500) 
ax.set_ylim(0, 3500) 
ax.set_zlim(0, 4500) 
ax.plot_surface(xs, ys, zs) 

plt.show() 

导致以下情节:

enter image description here 它只是忽略的限制,做反正绘制。第二种方法是定义负值为np.nan改变功能是为:

def constraint_function(x, y): 
    temp = min(
     (1800 - 0.3 * x - 0.5 * y)/0.4, 
     (500 - 0.1 * x - 0.08 * y)/0.12, 
     (200 - 0.06 * x - 0.04 * y)/0.05 
    ) 
    return temp if temp >= 0 else np.nan 

和设置无效值的阿尔法为零:

plt.cm.jet.set_bad(alpha=0.0) 
ax.azim = 20 
ax.set_xlim(0, 3500) 
ax.set_ylim(0, 3500) 
ax.set_zlim(0, 4500) 

ax.plot_surface(xs, ys, zs) 

plt.show() 

enter image description here 它给我留下了锯状这也是我不想拥有的边界。当情节转为负面时,是否有办法摆脱这些边缘并获得平滑线条?

回答

1

首先,你的Z值阵列轴是相反的;它应该是zs[iy][ix]而不是zs[ix][iy]。正因为如此,你的情节被翻转左右。

其次,通过在Python中迭代构建您的z数组要慢得多;你应该改为numpy,如下所示:

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

# create axis sample 
xs = np.linspace(0, 3600, 1000) 
ys = np.linspace(0, 3600, 1000) 

# create mesh samples 
xxs, yys = np.meshgrid(xs, ys) 

# create data 
zzs = np.min([ 
    ((1800 - 0.30 * xxs - 0.50 * yys)/0.40), 
    ((500 - 0.10 * xxs - 0.08 * yys)/0.12), 
    ((200 - 0.06 * xxs - 0.04 * yys)/0.05) 
], axis=0) 

# clip data which is below 0.0 
zzs[zzs < 0.] = np.NaN 

NumPy矢量化操作速度快很多倍。

第三,除了采样分辨率太低以外,代码没有什么特别的错误;将其设置较高,

fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 
ax.azim = 20 
ax.set_xlim(0, 3500) 
ax.set_ylim(0, 3500) 
ax.set_zlim(0, 4500) 
ax.plot_surface(xxs, yys, zzs, rcount=200, ccount=200) 

plt.show() 

产生

enter image description here

0

从技术上讲,可以歪斜网格,使得栅格,这将导致一个济科-扎克图案的点被移位这样,即他们躺在一条线上。

这如下所示。

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

x=np.linspace(-5,5,6) 
X,Y = np.meshgrid(x,x) 
Z = X+Y 

X[Z==-2] = X[Z==-2]+1 
Y[Z==-2] = Y[Z==-2]+1 
Z[Z==-2] = 0 
Z[Z<0] = np.nan 

fig = plt.figure() 
ax = fig.add_subplot(111, projection='3d') 

ax.set_zlim(0, 12) 
ax.plot_surface(X, Y, Z) 

plt.show() 

enter image description here

现在的问题是概括这种方法对任意表面。这当然有可能,但需要一点工作。