8

在 MATLAB 中布置图形时,键入axis equal可确保无论图形尺寸如何,始终是方形的:

在此处输入图像描述

我目前的问题是我想在这个图中添加第二个轴。通常,这没问题。我只需键入axes([x1 y1 x2 y2]),就会添加一个新的方形图形,其角为,这是相对于图形(x1, y1), (x2, y2)的固定位置。问题是,我希望这个新轴位于相对于第一个轴的固定位置。

所以,我的问题是:

  1. 有谁知道如何通过指定相对于另一个轴的位置来在图中定位轴?
  2. 假设我可以做 1,即使我调整了图形的大小,我怎样才能让这个新轴保持在同一个地方?
4

2 回答 2

13

位置属性相对于其父容器。因此,一种可能性是创建一个与第一个轴相同大小的透明面板,然后在其中创建第二个轴,并根据需要设置其位置和大小。指定的位置就好像它相对于第一个轴一样。

现在我们需要始终保持面板与第一个轴的大小/位置相同。通常这可以使用LINKPROP来完成,它将多个图形对象(面板和轴)的属性链接为相同,即'Position'属性。

但是,这在您的情况下会失败:当调用 时,它会通过设置纵横比属性(如和axis image)将数据单元在各个方向上固定为相同。可悲的是,该属性不会反映大小的变化,从而打破了上述解决方案。这是一个说明问题的示例:如果您在发出调用之前/之后查询 position 属性,它将是相同的:'PlotBoxAspectRatio''DataAspectRatio''Position'axis image

figure, plot(1:10,1:10)
get(gca,'Position')
pause(1)
axis image
get(gca,'Position')

对我们来说幸运的是,FEX ( plotboxpos )上的一个提交解决了这个确切的问题,并返回轴的绘图区域的实际位置。一旦我们有了它,这就是将面板位置与轴位置同步的问题。一个技巧是为轴改变大小时创建一个事件侦听器(看起来属性的'TightInset'变化与'Position'属性不同,因此在我们的例子中这可能是触发器)。

为了方便起见,我将上面的内容包装在一个函数AXESRELATIVE中:您可以像调用内置AXES函数一样调用它。唯一的区别是你给它作为第一个参数你想要相对定位新创建的轴的轴的句柄。它返回新轴及其包含面板的句柄。

这是一个示例用法:

%# automatic resize only works for normalized units
figure
hParentAx = axes('Units','normalized');
axis(hParentAx, 'image')

%# create a new axis positioned at normalized units with w.r.t the previous axis
%# the axis should maintain its relative position on resizing the figure
[hAx hPan] = axesRelative(hParentAx, ...
    'Units','normalized', 'Position',[0.7 0.1 0.1 0.1]);
set(hAx, 'Color','r')

以及功能实现:

function [hAx hPan] = axesRelative(hParentAx, varargin)
    %# create panel exactly on top of parent axis
    s = warning('off', 'MATLAB:hg:ColorSpec_None');
    hPan = uipanel('Parent',get(hParentAx, 'Parent'), ...
        'BorderType','none', 'BackgroundColor','none', ...
        'Units',get(hParentAx,'Units'), 'Position',plotboxpos(hParentAx));
    warning(s)

    %# sync panel to always match parent axis position
    addlistener(handle(hParentAx), ...
        {'TightInset' 'Position' 'PlotBoxAspectRatio' 'DataAspectRatio'}, ...
        'PostSet',@(src,ev) set(hPan, 'Position',plotboxpos(hParentAx)) );

    %# create new axis under the newly created panel
    hAx = axes('Parent',hPan, varargin{:});
end

轴相对


完全不同的一点是:在您最近编辑之前,我的印象是您试图生成图像的散点图(即像通常的散点图,但使用完整图像而不是点)。

您的建议(据我了解)是为每个图像创建一个轴,并将其位置设置为与该点的 x/y 坐标相对应。

我的解决方案是使用IMAGE / IMAGESC'XData'函数并通过显式设置and'YData'属性来适当地移动和缩放图像来绘制小图像。这样做的美妙之处在于它需要一个单轴,并且不必处理调整大小的问题。

这是一个示例实现:

%# create fan-shaped coordinates
[R,PHI] = meshgrid(linspace(1,2,5), linspace(0,pi/2,10));
X = R.*cos(PHI); Y = R.*sin(PHI);
X = X(:); Y = Y(:);
num = numel(X);

%# images at each point (they don't have to be the same)
img = imread('coins.png');
img = repmat({img}, [num 1]);

%# plot scatter of images
SCALE = 0.2;             %# image size along the biggest dimension
figure
for i=1:num
    %# compute XData/YData vectors of each image
    [h w] = size(img{i});
    if h>w
        scaleY = SCALE;
        scaleX = SCALE * w/h;
    else
        scaleX = SCALE; 
        scaleY = SCALE * h/w;
    end
    xx = linspace(-scaleX/2, scaleX/2, h) + X(i);
    yy = linspace(-scaleY/2, scaleY/2, w) + Y(i);

    %# note: we are using the low-level syntax of the function
    image('XData',xx, 'YData',yy, 'CData',img{i}, 'CDataMapping','scaled')
end
axis image, axis ij
colormap gray, colorbar
set(gca, 'CLimMode','auto')

image_scatter

于 2011-08-24T00:00:57.917 回答
4

这通常是您可以通过自定义图形来处理的事情'ResizeFcn',它将调整较小轴相对于较大轴的位置和大小。这是一个调整大小函数的示例,它保持子轴的大小,使其始终是较大方轴大小的 15%,并位于右下角:

function resizeFcn(src,event,hAxes,hSubAxes)

  figurePosition = get(get(hAxes,'Parent'),'Position');
  axesPosition = get(hAxes,'Position').*figurePosition([3 4 3 4]);
  width = axesPosition(3);
  height = axesPosition(4);
  minExtent = min(width,height);
  newPosition = [axesPosition(1)+(width-minExtent)/2+0.8*minExtent ...
                 axesPosition(2)+(height-minExtent)/2+0.05*minExtent ...
                 0.15*minExtent ...
                 0.15*minExtent];
  set(hSubAxes,'Units','pixels','Position',newPosition);

end

这是它的使用示例:

hFigure = figure('Units','pixels');  %# Use pixel units for figure
hAxes = axes('Units','normalized');  %# Normalized axes units so it auto-resizes
axis(hAxes,'image');                 %# Make the axes square
hSubAxes = axes('Units','pixels');   %# Use pixel units for subaxes
set(hFigure,'ResizeFcn',{@resizeFcn,hAxes,hSubAxes});  %# Set resize function
于 2011-08-23T14:10:41.653 回答