2017-07-31 85 views
2

假設我有一個帶有一些值的矩陣Z,我想通過繪製高度爲Z的值來說明它。首先想到的解決方案是一個表面,但使用surf和小矩陣的類似功能看起來不太好。如何在3D條形圖中爲條形圖設置任意顏色?

所以我想到了使用像bar3這樣的3D條形圖。但問題是這個函數總是按組來設置顏色,而不是按高度來設置顏色,我無法做到這一點。

下面是一個例子:

Z = peaks(5); 
subplot 121 
surf(Z) 
title('Surface look bad') 
subplot 122 
bar3(Z) 
title('The color is not by height') 

enter image description here

我試圖尋找由bar3(如CDataFaceColor)返回的句柄的顏色屬性,但所有的價值觀,以及如何迷路了他們涉及酒吧本身。

最後,我想有2點矩陣ZC我可以創建與ZC給定的顏色給予高度酒吧3D柱狀圖中的通用解決方案。

我該怎麼做?

回答

3

bar3返回表面對象,每個組(即,一個用於每種顏色),因此在一個組中的所有條基本上描繪爲一個「斷」表面的作用。這在this answer中有很好的解釋,所以我在這裏不再重複。

相反,我會找到針對這個特定問題的解決方案。表面的相關屬性是CData。當我們創建條形圖時,每個曲面的CData都被賦予一個大小爲矩陣的矩陣(我們將會得到這個),它們都是相同的一個值。每個表面的值不同。這就是整個圖形如何將其顏色圖轉化爲組的顏色。

如上所述(並在linked answer中詳細說明),每個組由一個表面表示,所以它需要一個整體矩陣來定義表面上每個點的顏色。我們要做的第一件事是讓這個矩陣大小:

Z = peaks(5); 
bar_h = bar3(Z); 
% we take only the first one, but they are all the same size: 
cdata_sz = size(bar_h(1).CData) 

cdata_sz = 
    30  4 

CData一向4列(見here爲什麼),和行數始終是6 *號的組。這是因爲需要5個頂點來創建一個帶有區域對象的閉合矩形(最後一個頂點與第一個頂點相似),一條線用於NaN之間的間距,因此它們看上去是分開的。

接下來,我們需要放大我們的原始顏色映射(與Z的尺寸相同),以正確的方式適合CData。基本上,我們只是想爲屬於同一個條的所有頂點重複相同的值。假設Z也是我們的顏色數據(即通過高度我們的顏色),我們這樣做:

z_color = repelem(Z,6,4) 

現在,我們需要我們的z_color不同的細胞分裂在我們組的數量。每個單元格將包含一個表面對象的着色數據:

z_color = mat2cell(z_color,cdata_sz(1),ones(1,size(Z,2))*cdata_sz(2)); 

最後,我們新的顏色數據適用於條形圖:

set(bar_h,{'CData'},z_color.') 

作爲獎勵,如果我們要刪除所有從我們的酒吧零個值,它可以很容易地將它們設置爲NaN完成:

Z(abs(Z)<eps) = nan; 
C(isnan(Z)) = nan; % if we use a colormap C different from Z 

demo2

上述所有可以歸結爲這樣方便的功能:

function bar_h = Cbar3(Z,C,b,y) 
% Z - The data 
% C - CData (if other then Z values) 
% b - Minimum absolute value to keep colored 
% y - y-axis values to order the data by 

if nargin<2, C = Z; end 
if nargin<3 || isempty(b), b = 0; end 
Z(abs(Z)<b) = nan; 
C(isnan(Z)) = nan; 
if nargin<4 
    bar_h = bar3(Z); 
else 
    bar_h = bar3(y,Z); 
end 
cdata_sz = size(bar_h(1).CData); 
z_color = repelem(C,6,4); 
z_color = mat2cell(z_color,... 
    cdata_sz(1),ones(1,size(Z,2))*cdata_sz(2)); 
set(bar_h,{'CData'},z_color.') 
end 

使用示例:

subplot 121 
Z = peaks(30); 
Cbar3(Z,Z,0.5); 
pbaspect auto 
shading flat % just to get a cleaner look 
title('Cbar3 using height as color') 

subplot 122 
Cbar3(Z,rand(size(Z)),0.5); 
pbaspect auto 
shading flat % just to get a cleaner look 
title('Cbar3 using random as color') 

結果:

enter image description here

0

雖然我覺得EBH的解決方案審美更愉悅,這裏有一個更簡單的解決方案:插值

z = peaks(5); 
[x,y]=meshgrid(1:0.1:size(z,1),1:0.1:size(z,2)); 
zn=interp2(z,x,y,'nearest'); 
% plot it 
surf(zn,'edgecolor','none','facecolor','interp') 

enter image description here

+0

我認爲它更易於設置'FaceColor'到''interp'':'圖(); hS = surf(高峯(50),'edgecolor','none'); hS.FaceColor ='interp';'。你可以通過我的答案中的鏈接看到'bar3'中的插值顏色。 –

+0

@ Dev-iL當然,我不知道爲什麼我做了一半的功能調用和一半的不同的調用 –

2

這是一個局部的答案。

官方MATLAB documentation涵蓋使用酒吧高度作爲顏色的情況。本質上,示例代碼歸結爲:

function q45423394 
hB = bar3(peaks(25)); colorbar; 
for indE = 1:numel(hB) 
    hB(indE).CData = hB(indE).ZData; 
end 

所有你需要事後做的就是確保colormap是你想要的。

enter image description here

+0

我想我更喜歡第二個選項int他鏈接你共享 –

+0

我不知道我怎麼想這些文檔,但我更喜歡沒有循環,並且我想給出一些更多的解釋(除了使用其他數據着色的選項外)。 – EBH