如何在图中相对于另一个轴定位轴? [英] How to position an axes in a figure relative to another axes?

查看:195
本文介绍了如何在图中相对于另一个轴定位轴?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在MATLAB中布置图形时,键入轴等于可确保无论维度是什么,将永远是正方形:





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



所以,我的问题是:


  1. 有没有人知道如何通过指定相对于另一个轴的位置来定位图中的轴?

  2. 假设我可以做1,即使我调整数字大小,我怎么能让这些新轴保持在同一个位置?


解决方案

轴 / IMAGESC 通过显式设置'XData'来运行并绘制小图像, 'YData'适当移动和缩放图像的属性。这样做的好处是它需要单轴,并且不必处理调整大小问题。



这是一个示例实现:

 %#创建扇形坐标
[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);

%#每个点的图像(它们不必相同)
img = imread('coins.png');
img = repmat({img},[num 1]);

%#plot scatter of images
SCALE = 0.2; %#图像大小沿最大维度

表示i = 1:num
%#calcome每个图像的XData / YData向量
[hw] = size(img {i });
如果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:我们使用函数
image的低级语法('XData',xx,'YData',yy,'CData',img {i}, 'CDataMapping','scaled')
结束
轴图像,轴ij
colormap灰色,colorbar
set(gca,'CLimMode','auto')


When laying out a figure in MATLAB, typing axis equal ensures that no matter what the figure dimensions, the axes will always be square:

My current problem is that I want to add a second axes to this plot. Usually, that's no problem; I would just type axes([x1 y1 x2 y2]), and a new square figure would be added with corners at (x1, y1), (x2, y2), which is a fixed location relative to the figure. The problem is, I want this new axes to be located at a fixed location relative to the first axes.

So, my questions are:

  1. Does anyone know how I can position an axes in a figure by specifying the location relative to another axes?
  2. Assuming I can do 1, how can I have this new axes remain in the same place even if I resize the figure?

解决方案

An axis position property is relative to its parent container. Therefore, one possibility is to create a transparent panel with the same size as the first axis, then inside it create the second axis, and set its location and size as needed. The position specified would be as if it were relative to the first axis.

Now we need to always maintain the panel to be the same size/location as the first axis. Usually this can be done using LINKPROP which links a property of multiple graphic objects (panel and axis) to be the same, namely the 'Position' property.

However, this would fail in your case: when calling axis image, it fixes the data units to be the same in every direction by setting aspect ratio properties like 'PlotBoxAspectRatio' and 'DataAspectRatio'. The sad news is that the 'Position' property will not reflect the change in size, thus breaking the above solution. Here is an example to illustrate the problem: if you query the position property before/after issuing the axis image call, it will be the same:

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

Fortunately for us, there is a submission on FEX (plotboxpos) that solves this exact issue, and returns the actual position of the plotting region of the axis. Once we have that, it's a matter of syncing the panel position to the axis position. One trick is to create a event listener for when the axis changes size (it appears that the 'TightInset' property changes unlike the 'Position' property, so that could be the trigger in our case).

I wrapped the above in a function AXESRELATIVE for convenience: you call it as you would the builtin AXES function. The only difference is you give it as first argument the handle to the axis you want to relatively-position the newly created axis against. It returns handles to both the new axis and its containing panel.

Here is an example usage:

%# 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')

And the function implementation:

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


On a completely different note: before you recent edit, I got the impression that you were trying to produce a scatter plot of images (i.e like a usual scatter plot, but with full images instead of points).

What you suggested (from what I understand) is creating one axis for each image, and setting its position corresponding to the x/y coordinates of the point.

My solution is to use the IMAGE/IMAGESC functions and draw the small images by explicitly setting the 'XData' and 'YData' properties to shift and scale the images appropriately. The beauty of this is it require a single axis, and doesn't suffer from having to deal with resizing issues..

Here is a sample implementation for that:

%# 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')

这篇关于如何在图中相对于另一个轴定位轴?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆