2017-07-31 7 views
2

いくつかの値を持つ行列Zがあるとします。その値をZの高さでプロットすることで説明します。最初の解決策は表面だと思いますが、surfと同様の機能を小さな行列で使用すると、見栄えが悪くなります。3Dバープロットのバーに任意の色を設定する方法は?

私はbar3の3Dバープロットのようなものを使うことを考えました。しかし問題は、この関数は常に高さではなくグループによって色を設定することであり、そうすることはできません。私はbar3(のようなCDataFaceColor)によって返されたハンドルでの色の性質を探してみましたが、すべての値とどのように失われてしまった

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

:ここ

は一例です彼らはバー自体に関連しています。

最終的に、私は2つの行列ZCのために、私はZCによって与えられた色で所定の高さにあるバーで、3D棒グラフを作成することができ、一般的な解決策を持っていると思います。

どうすればいいですか?

答えて

3

一つのグループ内のすべてのバーが本質的に1「破損」面としてプロットされているので、表面オブジェクト、各群(各色用すなわち、1種)のための1つを返すbar3機能。これはthis answerで非常によく説明されているので、ここではこれを繰り返さないでください。

代わりに、私はこの特定の問題の解決策に着きます。表面の関連する特性はCDataである。棒グラフを作成すると、各サーフェスのCDataには、あるサイズのマトリックスが割り当てられます(ここではこれを取得します)。これはすべて同じ値です。各サーフェスごとに異なる値。これは、Figure全体がカラーマップをグループの色に変換する方法です。

各グループはサーフェスで表現されているため、サーフェスの各ポイントで色を定義するためには全体の行列が必要です(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 *数です。これは、領域オブジェクト(最後の頂点は最初の頂点のようなもの)で1つの閉じた矩形を作成するために5つの頂点を必要とし、1つの線が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

は、私はそれがinterp'' ' ''にFaceColor'を設定する方が簡単だと思う:() 'の図。 hS =サーフ(ピーク(50)、「エッジカラー」、「なし」); hS.FaceColor = 'interp'; '。私の答えの中のリンクをたどって、どのような補間色が 'bar3'のように見えるかを見ることができます。 –

+0

@ Dev-iL確かに、私は関数呼び出しを半分行ったのと、別の関数呼び出しを半分行った理由は全く分かりません。 –

2

これは部分的な答えです。

バーの高さを色として使用する場合は、公式MATLAB documentationに記載されています。あなたが後でする必要があるすべてはcolormapが希望のものであることを確認している

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

:基本的にサンプルコードは、に沸きます。

enter image description here

+0

私は2番目のオプションが好きだと思うint彼は共有リンクします –

+0

私はこれらのドキュメントしかし、私はループがなければそれが良いのが好きで、私はそこに何が起こっているのかについてもう少し説明をすると思います(色付けのために別のデータを使うという選択肢は別です)。 – EBH

関連する問題