我想绘制一个3D直方图(带有gnuplot或octave)以表示我的数据。 假设我有一个以下形式的数据文件:
2 3 4
8 4 10
5 6 7
我想在集合[1,3] x [1,3]中绘制九个彩色条(矩阵的大小),这样条的颜色与酒吧的高度。我怎么能这样做?
答案 0 :(得分:12)
以下是我实施的一项功能,可以作为bar3
替换(部分)。
在我的版本中,通过创建patch graphics object来渲染条形图:我们构建了一个vertex coordinates and a list of faces connecting those vertices的矩阵。
这个想法是首先构建一个单一的“立方体”#34;作为模板,然后复制它为我们有多少个酒吧。每个栏都根据其位置和高度进行移动和缩放。
顶点/面矩阵以矢量化方式构造(看起来没有循环!),结果是为所有条形绘制的单个patch
object,而不是每个条形一个多个补丁(这是在graphics performance)方面效率更高。
可以通过使用XData
,YData
,ZData
和CData
属性而不是{Vertices
,Faces
,bar3
和bar3
属性指定形成多边形的连接顶点的坐标来实现此功能。 {1}}和function pp = my_bar3(M, width)
% MY_BAR3 3D bar graph.
%
% M - 2D matrix
% width - bar width (1 means no separation between bars)
%
% See also: bar3, hist3
%% construct patch
if nargin < 2, width = 0.8; end
assert(ismatrix(M), 'Matrix expected.')
% size of matrix
[ny,nx] = size(M);
% first we build a "template" column-bar (8 vertices and 6 faces)
% (bar is initially centered at position (1,1) with width=? and height=1)
hw = width / 2; % half width
[X,Y,Z] = ndgrid([1-hw 1+hw], [1-hw 1+hw], [0 1]);
v = [X(:) Y(:) Z(:)];
f = [
1 2 4 3 ; % bottom
5 6 8 7 ; % top
1 2 6 5 ; % front
3 4 8 7 ; % back
1 5 7 3 ; % left
2 6 8 4 % right
];
% replicate vertices of "template" to form nx*ny bars
[offsetX,offsetY] = meshgrid(0:nx-1,0:ny-1);
offset = [offsetX(:) offsetY(:)]; offset(:,3) = 0;
v = bsxfun(@plus, v, permute(offset,[3 2 1]));
v = reshape(permute(v,[2 1 3]), 3,[]).';
% adjust bar heights to be equal to matrix values
v(:,3) = v(:,3) .* kron(M(:), ones(8,1));
% replicate faces of "template" to form nx*ny bars
increments = 0:8:8*(nx*ny-1);
f = bsxfun(@plus, f, permute(increments,[1 3 2]));
f = reshape(permute(f,[2 1 3]), 4,[]).';
%% plot
% prepare plot
if exist('OCTAVE_VERSION','builtin') > 0
% If running Octave, select OpenGL backend, gnuplot wont work
graphics_toolkit('fltk');
hax = gca;
else
hax = newplot();
set(ancestor(hax,'figure'), 'Renderer','opengl')
end
% draw patch specified by faces/vertices
% (we use a solid color for all faces)
p = patch('Faces',f, 'Vertices',v, ...
'FaceColor',[0.75 0.85 0.95], 'EdgeColor','k', 'Parent',hax);
view(hax,3); grid(hax,'on');
set(hax, 'XTick',1:nx, 'YTick',1:ny, 'Box','off', 'YDir','reverse', ...
'PlotBoxAspectRatio',[1 1 (sqrt(5)-1)/2]) % 1/GR (GR: golden ratio)
% return handle to patch object if requested
if nargout > 0
pp = p;
end
end
属性。实际上这就是bar3
内部所做的事情。这种方法通常需要更大的数据来定义补丁(因为我们不能在补丁面上有共享点,尽管我在实现中并不关心它)。这是一个related post,我试图解释由subplot(121), bar3(magic(7)), axis tight
subplot(122), my_bar3(magic(7)), axis tight
构建的数据的结构。
bar3
以下是将其与MATLAB中的内置M = membrane(1); M = M(1:3:end,1:3:end);
h = my_bar3(M, 1.0);
% 6 faces per bar
fvcd = kron((1:numel(M))', ones(6,1));
set(h, 'FaceVertexCData',fvcd, 'FaceColor','flat', 'CDataMapping','scaled')
colormap hsv; axis tight; view(50,25)
set(h, 'FaceAlpha',0.85) % semi-transparent bars
函数进行比较的示例:
M = 9^2 - spiral(9);
h = my_bar3(M, 0.8);
% use Z-coordinates as vertex colors (indexed color mapping)
v = get(h, 'Vertices');
fvcd = v(:,3);
set(h, 'FaceVertexCData',fvcd, 'FaceColor','interp')
axis tight vis3d; daspect([1 1 10]); view(-40,20)
set(h, 'EdgeColor','k', 'EdgeAlpha',0.1)
请注意,我选择使用单一纯色(与hist3
函数的输出相似)为所有条形图着色,而MATLAB强调矩阵的列具有匹配的颜色。
虽然很容易customize the patch;以下是使用coloring mode匹配colorbar
indexed color mapping (scaled)的示例:
jet
或者说您想使用gradient according to their heights:
为条形设置颜色membrane
请注意,在上一个示例中,"Renderer" property of the figure会影响渐变的外观。在MATLAB中,&#39; OpenGL&#39;渲染器将沿RGB颜色空间插入颜色,而其他两个渲染器(&#39; Painters&#39;和ZBuffer&#39;)将在所使用的当前颜色映射的颜色之间进行插值(因此直方图条看起来如此比如迷你spiral
穿过{{1}}调色板,而不是从底部的蓝色到任何颜色在定义高度的渐变,如上所示)。有关详细信息,请参阅this post。
我已经在Windows上运行的Octave 3.6.4和3.8.1中测试了该功能,并且运行正常。如果您运行我上面显示的示例,您会发现某些高级3D功能尚未在Octave中正确实现(这包括透明度,照明等等)。此外,我还使用了{{1}}和{{1}}等Octave中不可用的函数来构建样本矩阵,但这些函数对代码并不重要,只需将它们替换为您自己的数据:)
答案 1 :(得分:3)
我无法访问Octave,但我相信这应该可以解决问题:
Z = [2 3 4
8 4 10
5 6 7];
[H W] = size(Z);
h = zeros( 1, numel(Z) );
ih = 1;
for ix = 1:W
fx = ix-.45;
tx = ix+.45;
for iy = 1:W
fy = iy-.45;
ty = iy+.45;
vert = [ fx fy 0;...
fx ty 0;...
tx fy 0;...
tx ty 0;...
fx fy Z(iy,ix);...
fx ty Z(iy,ix);...
tx fy Z(iy,ix);...
tx ty Z(iy,ix)];
faces = [ 1 3 5;...
5 3 7;...
7 3 4;...
7 8 4;...
5 6 7;...
6 7 8;...
1 2 5;...
5 6 2;...
2 4 8;...
2 6 8];
h(ih) = patch( 'faces', faces, 'vertices', vert, 'FaceVertexCData', Z(iy,ix),...
'FaceColor', 'flat', 'EdgeColor','none' );
ih = ih+1;
end
end
view( 60, 45 );
colorbar;
答案 2 :(得分:3)
我认为以下应该可以解决问题。我没有使用比colormap
,surf
和patch
更复杂的东西,据我所知,这些都应该在Octave中按原样运行。
代码:
%# Your data
Z = [2 3 4
8 4 10
5 6 7];
%# the "nominal" bar (adjusted from cylinder())
n = 4;
r = [0.5; 0.5];
m = length(r);
theta = (0:n)/n*2*pi + pi/4;
sintheta = sin(theta); sintheta(end) = sqrt(2)/2;
x0 = r * cos(theta);
y0 = r * sintheta;
z0 = (0:m-1)'/(m-1) * ones(1,n+1);
%# get data for current colormap
map = colormap;
Mz = max(Z(:));
mz = min(Z(:));
% Each "bar" is 1 surf and 1 patch
for ii = 1:size(Z,1)
for jj = 1:size(Z,2)
% Get color (linear interpolation through current colormap)
cI = (Z(ii,jj)-mz)*(size(map,1)-1)/(Mz-mz) + 1;
fC = floor(cI);
cC = ceil(cI);
color = map(fC,:) + (map(cC,:) - map(fC,:)) * (cI-fC);
% Translate and rescale the nominal bar
x = x0+ii;
y = y0+jj;
z = z0*Z(ii,jj);
% Draw the bar
surf(x,y,z, 'Facecolor', color)
patch(x(end,:), y(end,:), z(end,:), color)
end
end
结果:
我如何生成&#34;标称栏&#34;基于MATLAB&#39; cylinder()
的代码。一个很酷的事情就是你可以很容易地制作出更加时髦的酒吧:
这是通过更改
生成的n = 4;
r = [0.5; 0.5];
进入
n = 8;
r = [0.5; 0.45; 0.2; 0.1; 0.2; 0.45; 0.5];
答案 3 :(得分:3)
解决方案仅使用OCTAVE中提供的功能,使用octave-online
进行测试 此解决方案以类似于Matlabs hist3d
函数内部的方式生成表面。
简而言之:
对于以包含bin高度的矩阵形式给出的数据(代码中的bin_values):
<强>代码强>
bin_values=rand(5,4); %some random data
bin_edges_x=[0:size(bin_values,2)];
x=kron(bin_edges_x,ones(1,5));
x=x(4:end-2);
bin_edges_y=[0:size(bin_values,1)];
y=kron(bin_edges_y,ones(1,5));
y=y(4:end-2);
mask_z=[0,0,0,0,0;0,1,1,0,0;0,1,1,0,0;0,0,0,0,0;0,0,0,0,0];
mask_c=ones(5);
z=kron(bin_values,mask_z);
c=kron(bin_values,mask_c);
surf(x,y,z,c)
<强>输出强>
答案 4 :(得分:2)
稍微调整一下:
Z=[2 3 4
8 4 10
5 6 7]; % input data
figure;
h = bar3(Z); % get handle to graphics
for k=1:numel(h),
z=get(h(k),'ZData'); % old data - need for its NaN pattern
nn = isnan(z);
nz = kron( Z(:,k),ones(6,4) ); % map color to height 6 faces per data point
nz(nn) = NaN; % used saved NaN pattern for transparent faces
set(h(k),'CData', nz); % set the new colors
end
colorbar;
这就是你最后得到的: