Bar3绘图具有单独的x,y,高度和宽度值

时间:2016-04-07 20:56:12

标签: matlab plot matlab-figure

  

解决方案发布在 功能下,以使用单独的x,y值和单独的宽度和高度值绘制条形图3

     

BAR3(X,Y,Z,xWidth,yWidth)

我们目前正在开发一个项目,允许用户可视化3d函数f(x,y)下的区域。这样做的目的是演示条形切割3d表面的方式。间接地可视化所需的积分。

我们希望条形图与曲面网格的间隔匹配。 下面是这个想法的粗略演示。

example of idea

bar3只有x值 bar3(x,z)的输入,其中surf有x和y的输入 surf(x,y,z)< /强>

不幸的是,这就是我们得到的。 - 这是因为bar3不能用x和y

gui

CODE:

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);

2 个答案:

答案 0 :(得分:0)

如果你仔细观察,你会发现XDataYData与网格到3D条形图不同。这是因为您的网格使用“实际”x和y值,而条形图使用x和y值的索引。

要解决此问题,您需要更改其中一个。对于您的情况,最容易改变的是表面。您实际上可以省略xy输入,并且在生成曲面时默认情况下将使用索引的xy值。

surf(f);

来自surf的文档:

  

surf(Z)使用Zx = 1:n,使用y = 1:m从矩阵[m,n] = size(Z)中的z个组件创建三维阴影曲面。高度Z是在几何矩形网格上定义的单值函数。 Z指定颜色数据以及表面高度,因此颜色与表面高度成比例。

更新

如果要在x轴和y轴上保留非索引值,则需要转换bar3图。不幸的是,MATLAB提供了一种指定x轴bot 而不是 y轴的方法。您可以采用以下两种方法之一。

更改XData

您可以获取生成的bar对象的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

enter image description here

更改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);

enter image description here

答案 1 :(得分:0)

我们找到了一个用户贡献的函数scatterbar3,它以我们想要的方式执行,其方式与bar3使用的方式不同: http://www.mathworks.com/matlabcentral/fileexchange/1420-scatterbar3

然而我们必须纠正一些轻微的打嗝:

  

坚持

     

scatterbar3(X,Y,F,H);

scatterbar3没有单独的条形宽度和高度输入,因此当间隔不相等时会出现大的间隙。演示如下。

GUI-error

我们编辑了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)

最后是行动解决方案:

  

坚持

     

scatterbar3(X,Y,F,H,K);

working GUI 1

working GUI 2