首页 > 解决方案 > MATLAB:如何获取相对于图形位置而不是图形轴的点击值

问题描述

作为一些背景,我想做的是在当前情节中添加一个插图。我已经完成了大部分工作。这是一个代码示例:

h = figure(1); %Arbitrary figure #1
plot(990000:1000000,990000:1000000,'--r');

g = figure(2); %Arbitary figure #2
plot(randn(100,1),randn(100,1),'.k');

figure(3); %Figure to combine the above two figures
new_fig=gcf;
main_fig = findobj(h,'Type','axes');
h_main = copyobj(main_fig,new_fig);
set(h_main,'Position',get(main_fig,'Position'))
inset_fig = findobj(g,'Type','axes');
h_inset = copyobj(inset_fig,new_fig);
ax=get(main_fig,'Position');

inset_size = 0.3;
X = 0.2; %Left position of inset hard-coded in
Y = 0.6; %Bottom position of inset hard-coded in

set(h_inset,'Position', [X Y inset_size inset_size])  

close(h); close(g);

在上面的代码示例中,我只是手动将插图的 X 和 Y 位置设置为 X = 0.2 和 Y = 0.6。

但是,我坚持的棘手部分是我希望 X 和 Y 位置由用户确定。我希望用户能够在某处单击该图,并且该单击点成为插图的中心点。

不幸的是,ginput 并没有按照我想要的方式工作,因为 [x,y] = ginput(1) 返回相对于图形轴的值 x 和 y。这是一个代码示例:

h = figure(1); %Arbitrary figure #1
plot(990000:1000000,990000:1000000,'--r');
[x,y] = ginput(1);

正如您在此处看到的,x 和 y 大约为 10^5,因为它们以绘图轴为参考。所以 (x,y) fromginput不匹配用于设置图形位置的 (X,Y)。

任何想法如何将 (x,y) 转换为 (X,Y)?

编辑:我尝试进行以下缩放,它“几乎”有效,但不太有效,任何关于如何改进的想法都值得赞赏:

h = figure(1); %Arbitrary figure #1
plot(990000:1000000,990000:1000000,'--r');
[x,y] = ginput(1);

limx = xlim;
limy = ylim;

g = figure(2); %Arbitary figure #2
plot(randn(100,1),randn(100,1),'.k');

figure(3); %Figure to combine the above two figures
new_fig=gcf;
main_fig = findobj(h,'Type','axes');
h_main = copyobj(main_fig,new_fig);
set(h_main,'Position',get(main_fig,'Position'))
inset_fig = findobj(g,'Type','axes');
h_inset = copyobj(inset_fig,new_fig);
ax=get(main_fig,'Position');

inset_size = 0.3;
% X = 0.2; %Left position of inset hard-coded in
% Y = 0.6; %Bottom position of inset hard-coded in

%CONVERT ginput (x,y) to axis position (X,Y)
X = (x-min(limx))/diff(limx)*ax(3);
Y = (y-min(limy))/diff(limy)*ax(4);

set(h_inset,'Position', [X Y inset_size inset_size])  

close(h); close(g);

标签: matlabuser-controlsmatlab-figureaxisginput

解决方案


我会使用一个小函数将单位从“标准化”转换为“数据”:

ax2norm = @(x,y,ax) [...
    ax.Position(3)*((x-ax.XLim(1))./range(ax.XLim))+ ax.Position(1)...
    ax.Position(4)*((y-ax.YLim(1))./range(ax.YLim))+ ax.Position(2)];
 %  white area * ((value - axis min)  / axis length)  + gray area

其中xy是归一化坐标,ax是要转换为其数据单位的坐标区句柄。

下面的示例与您想要实现的类似,但更简洁和通用:

% create the inset:
insetFig = figure('Visible','off');
plot(randn(100,2),'.k')
temp_ax = gca;

% create the main figure:
mainFig = figure;
plot(1:10,1:10,'--r')
main_ax = gca;

% get position for inset:
inset_size = 0.3;
[x,y] = ginput(1);
XY = ax2norm(x,y,main_ax);

% copy the inset to the position:
inset_ax = copyobj(temp_ax,mainFig);
close(insetFig);
set(inset_ax,'Position', [XY-inset_size/2 inset_size inset_size])  

特别是,以下是主要变化:

  1. 我不创建第三个图形,而是将插图复制到主要图形中
  2. 我首先在一个不可见的图形中制作插图,然后从用户那里获取位置,复制后我也关闭它
  3. gca用来获取轴手柄,因为它比findobj

其中一些更改可能不适合您的情况,但它们都不是示例工作的关键。答案的本质是上面的函数。


推荐阅读