具有单独的 x、y、高度和宽度值的 Bar3 图
Bar3 plot with seperate x,y,height and width values
Solution posted below function to plot bar 3 with separate x, y values and separate width and height values
bar3(x,y,z,xWidth,yWidth)
我们目前正在进行一个项目,该项目允许人们可视化 3d 函数 f(x,y) 下的区域。这样做的目的是演示条形如何切割 3d 表面。间接可视化所需的积分。
我们希望条形与表面网格的间隔相匹配。
下面是这个想法的粗略演示。
bar3 只有 x 值的输入 bar3(x,z),而 surf 有 x 和 y 的输入 surf( x,y,z)
不幸的是,这就是我们得到的结果。 - 这是因为 bar3 不能根据 x 和 y
代码:
clc;
cla;
d=eval(get(handles.edtOuterUpperB,'string'));
c=eval(get(handles.edtOuterLowerB,'string'));
b=eval(get(handles.edtInnerUpperB,'string'));
a=eval(get(handles.edtInnerLowerB,'string'));
n=eval(get(handles.edtInnerInterval,'string'));
m=eval(get(handles.edtOuterInterval,'string'));
h=(b-a)/n;
k=(d-c)/m;
[x,y] = meshgrid(a:h:b, c:k:d);
f=eval(get(handles.edtFunc,'string'));
surf(x,y,f);
hold on
bar3(f,1);
如果仔细观察,您会发现 XData
和 YData
从网格到 3D 条形图是不同的。这是因为您的网格使用 "real" x 和 y 值,而条形图使用索引作为 x 和 y 值。
要解决此问题,您需要更改其中一个。对于您的情况,最容易改变的是表面。实际上,您可以省略 x
和 y
输入,并且在生成表面时默认情况下将使用索引的 x
和 y
值。
surf(f);
来自 surf
的文档:
surf(Z)
creates a three-dimensional shaded surface from the z components in matrix Z
, using x = 1:n
and y = 1:m
, where [m,n] = size(Z)
. The height, Z
, is a single-valued function defined over a geometrically rectangular grid. Z
specifies the color data, as well as surface height, so color is proportional to surface height.
更新
如果要在 x 轴和 y 轴上保留非索引值,则需要转换 bar3
图。不幸的是,MATLAB 提供了一种方法来指定 x 轴 bot 而不是 y 轴。您可以采用以下两种方法之一。
改变XData
您可以获取结果条形对象的XData
属性,并将其更改为您想要的数据。
x = a:h:b;
y = c:k:d;
%// Anonymous function to scale things for us
scaler = @(vals)x(1) + ((vals-1) * (x(end) - x(1)) / (numel(x) - 1));
%// Create the bar plot
bars = bar3(y, f);
%// Change the XData
xdata = get(bars, 'XData');
xdata = cellfun(scaler, xdata, 'uni', 0);
set(bars, {'XData'}, xdata);
set(gca, 'xtick', x)
%// Now plot the surface
surf(x,y,f);
并且只是为了演示它的作用:
x = linspace(0.5, 1.5, 5);
y = linspace(2.5, 4.5, 4);
f = rand(4,5);
scaler = @(vals)x(1) + ((vals-1) * (x(end) - x(1)) / (numel(x) - 1));
bars = bar3(y, f);
set(bars, {'XData'}, cellfun(scaler, get(bars, 'XData'), 'uni', 0))
set(gca, 'xtick', x)
axis tight
改变XTickLabels
无需更改 实际 数据,您只需将显示的值更改为您希望的值,而不是索引值。
x = a:h:b;
y = c:k:d;
labels = arrayfun(@(x)sprintf('%.2f', x), x, 'uni', 0);
bar3(y, f);
set(gca, 'xtick', 1:numel(x), 'xticklabels', labels);
hold on
%// Make sure to use the INDEX values for the x variable
surf(1:numel(x), y, f);
我们发现了一个用户贡献的函数 scatterbar3,它以不同于 bar3 使用的方式做我们想要的事情:
http://www.mathworks.com/matlabcentral/fileexchange/1420-scatterbar3
然而,我们不得不纠正一个小问题:
hold on
scatterbar3(x,y,f,h);
scatterbar3 没有单独的条形宽度和高度输入,因此当间隔彼此不相等时会出现较大的间隙。如下所示。
因此,我们编辑了 scatterbar3 函数,以便将条形的宽度和高度都作为输入:
已编辑的 scatterbar3 函数:
function scatterbar3(X,Y,Z,widthx,widthy)
[r,c]=size(Z);
for j=1:r,
for k=1:c,
if ~isnan(Z(j,k))
drawbar(X(j,k),Y(j,k),Z(j,k),widthx/2,widthy/2)
end
end
end
zlim=[min(Z(:)) max(Z(:))];
if zlim(1)>0,zlim(1)=0;end
if zlim(2)<0,zlim(2)=0;end
axis([min(X(:))-widthx max(X(:))+widthx min(Y(:))-widthy max(Y(:))+widthy zlim])
caxis([min(Z(:)) max(Z(:))])
function drawbar(x,y,z,widthx,widthy)
h(1)=patch([-widthx -widthx widthx widthx]+x,[-widthy widthy widthy -widthy]+y,[0 0 0 0],'b');
h(2)=patch(widthx.*[-1 -1 1 1]+x,widthy.*[-1 -1 -1 -1]+y,z.*[0 1 1 0],'b');
h(3)=patch(widthx.*[-1 -1 -1 -1]+x,widthy.*[-1 -1 1 1]+y,z.*[0 1 1 0],'b');
h(4)=patch([-widthx -widthx widthx widthx]+x,[-widthy widthy widthy -widthy]+y,[z z z z],'b');
h(5)=patch(widthx.*[-1 -1 1 1]+x,widthy.*[1 1 1 1]+y,z.*[0 1 1 0],'b');
h(6)=patch(widthx.*[1 1 1 1]+x,widthy.*[-1 -1 1 1]+y,z.*[0 1 1 0],'b');
set(h,'facecolor','flat','FaceVertexCData',z)
最终可行的解决方案:
hold on
scatterbar3(x,y,f,h,k);
Solution posted below function to plot bar 3 with separate x, y values and separate width and height values
bar3(x,y,z,xWidth,yWidth)
我们目前正在进行一个项目,该项目允许人们可视化 3d 函数 f(x,y) 下的区域。这样做的目的是演示条形如何切割 3d 表面。间接可视化所需的积分。
我们希望条形与表面网格的间隔相匹配。 下面是这个想法的粗略演示。
bar3 只有 x 值的输入 bar3(x,z),而 surf 有 x 和 y 的输入 surf( x,y,z)
不幸的是,这就是我们得到的结果。 - 这是因为 bar3 不能根据 x 和 y
代码:
clc;
cla;
d=eval(get(handles.edtOuterUpperB,'string'));
c=eval(get(handles.edtOuterLowerB,'string'));
b=eval(get(handles.edtInnerUpperB,'string'));
a=eval(get(handles.edtInnerLowerB,'string'));
n=eval(get(handles.edtInnerInterval,'string'));
m=eval(get(handles.edtOuterInterval,'string'));
h=(b-a)/n;
k=(d-c)/m;
[x,y] = meshgrid(a:h:b, c:k:d);
f=eval(get(handles.edtFunc,'string'));
surf(x,y,f);
hold on
bar3(f,1);
如果仔细观察,您会发现 XData
和 YData
从网格到 3D 条形图是不同的。这是因为您的网格使用 "real" x 和 y 值,而条形图使用索引作为 x 和 y 值。
要解决此问题,您需要更改其中一个。对于您的情况,最容易改变的是表面。实际上,您可以省略 x
和 y
输入,并且在生成表面时默认情况下将使用索引的 x
和 y
值。
surf(f);
来自 surf
的文档:
surf(Z)
creates a three-dimensional shaded surface from the z components in matrixZ
, usingx = 1:n
andy = 1:m
, where[m,n] = size(Z)
. The height,Z
, is a single-valued function defined over a geometrically rectangular grid.Z
specifies the color data, as well as surface height, so color is proportional to surface height.
更新
如果要在 x 轴和 y 轴上保留非索引值,则需要转换 bar3
图。不幸的是,MATLAB 提供了一种方法来指定 x 轴 bot 而不是 y 轴。您可以采用以下两种方法之一。
改变XData
您可以获取结果条形对象的XData
属性,并将其更改为您想要的数据。
x = a:h:b;
y = c:k:d;
%// Anonymous function to scale things for us
scaler = @(vals)x(1) + ((vals-1) * (x(end) - x(1)) / (numel(x) - 1));
%// Create the bar plot
bars = bar3(y, f);
%// Change the XData
xdata = get(bars, 'XData');
xdata = cellfun(scaler, xdata, 'uni', 0);
set(bars, {'XData'}, xdata);
set(gca, 'xtick', x)
%// Now plot the surface
surf(x,y,f);
并且只是为了演示它的作用:
x = linspace(0.5, 1.5, 5);
y = linspace(2.5, 4.5, 4);
f = rand(4,5);
scaler = @(vals)x(1) + ((vals-1) * (x(end) - x(1)) / (numel(x) - 1));
bars = bar3(y, f);
set(bars, {'XData'}, cellfun(scaler, get(bars, 'XData'), 'uni', 0))
set(gca, 'xtick', x)
axis tight
改变XTickLabels
无需更改 实际 数据,您只需将显示的值更改为您希望的值,而不是索引值。
x = a:h:b;
y = c:k:d;
labels = arrayfun(@(x)sprintf('%.2f', x), x, 'uni', 0);
bar3(y, f);
set(gca, 'xtick', 1:numel(x), 'xticklabels', labels);
hold on
%// Make sure to use the INDEX values for the x variable
surf(1:numel(x), y, f);
我们发现了一个用户贡献的函数 scatterbar3,它以不同于 bar3 使用的方式做我们想要的事情: http://www.mathworks.com/matlabcentral/fileexchange/1420-scatterbar3
然而,我们不得不纠正一个小问题:
hold on
scatterbar3(x,y,f,h);
scatterbar3 没有单独的条形宽度和高度输入,因此当间隔彼此不相等时会出现较大的间隙。如下所示。
因此,我们编辑了 scatterbar3 函数,以便将条形的宽度和高度都作为输入:
已编辑的 scatterbar3 函数:
function scatterbar3(X,Y,Z,widthx,widthy)
[r,c]=size(Z);
for j=1:r,
for k=1:c,
if ~isnan(Z(j,k))
drawbar(X(j,k),Y(j,k),Z(j,k),widthx/2,widthy/2)
end
end
end
zlim=[min(Z(:)) max(Z(:))];
if zlim(1)>0,zlim(1)=0;end
if zlim(2)<0,zlim(2)=0;end
axis([min(X(:))-widthx max(X(:))+widthx min(Y(:))-widthy max(Y(:))+widthy zlim])
caxis([min(Z(:)) max(Z(:))])
function drawbar(x,y,z,widthx,widthy)
h(1)=patch([-widthx -widthx widthx widthx]+x,[-widthy widthy widthy -widthy]+y,[0 0 0 0],'b');
h(2)=patch(widthx.*[-1 -1 1 1]+x,widthy.*[-1 -1 -1 -1]+y,z.*[0 1 1 0],'b');
h(3)=patch(widthx.*[-1 -1 -1 -1]+x,widthy.*[-1 -1 1 1]+y,z.*[0 1 1 0],'b');
h(4)=patch([-widthx -widthx widthx widthx]+x,[-widthy widthy widthy -widthy]+y,[z z z z],'b');
h(5)=patch(widthx.*[-1 -1 1 1]+x,widthy.*[1 1 1 1]+y,z.*[0 1 1 0],'b');
h(6)=patch(widthx.*[1 1 1 1]+x,widthy.*[-1 -1 1 1]+y,z.*[0 1 1 0],'b');
set(h,'facecolor','flat','FaceVertexCData',z)
最终可行的解决方案:
hold on
scatterbar3(x,y,f,h,k);