功能bar3
返回一个surface对象,每组一个(即每种颜色一个),因此一组中的所有条形基本上都绘制为一个“破碎”表面。这在中解释得很好这个答案,所以这里不再重复。
相反,我将找到这个特定问题的解决方案。曲面的相关性质为CData
。当我们创建条形图时,每个表面的CData
被分配了一个大小相同的矩阵(我们稍后会讲到这一点),该矩阵全部相等。每个表面都有不同的值。这就是整个图形将其颜色图转换为各组颜色的方式。
如上所述(并在链接答案),每个组由一个表面表示,因此需要整个矩阵来定义表面每个点的颜色。我们要做的第一件事是获取这个矩阵大小:
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](https://i.stack.imgur.com/3rHqU.png)
以上所有内容都可以归结为这个方便的功能:
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')
Result:
![enter image description here](https://i.stack.imgur.com/8ce6V.png)