2017-06-18 65 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

現在的問題是概括這種方法對任意表面。這當然有可能,但需要一點工作。