当点位于之前已被“修补”的区域内时,如何获得图形的点(使用GUI中的回调)?

时间:2014-08-10 14:21:51

标签: matlab matlab-figure matlab-guide

我正在使用patch将椭圆内部绘制成我在gui环境中创建的图形。

通常,我会得到数字'点击(坐标)点击(使用回调函数)。当我想抓住的点不在我之前绘制的椭圆内时(应用patch),它可以正常工作。

在应用patch之后我应该怎么做才能在绘制之后得到一个椭圆内的点?非常感谢!

1 个答案:

答案 0 :(得分:1)

以下是解决问题的方法:

首先我们绘制一个点,然后是一个补丁,"覆盖"它。在这个例子中,补丁是透明的,但仍然无法选择它背后的点。

(这部分代码来自MATLAB&patch的例子)

close all force; clear variables; clc;
h = plot(3,6,'o')
hold on;

xdata = [2     2     0     2     5;
         2     8     2     4     5;
         8     8     2     4     8];
ydata = [4     4     4     2     0;
         8     4     6     2     2;
         4     0     4     0     0];
cdata = [15     0     4     6    10;
         1     2     5     7     9;
         2     3     0     8     3];
p = patch(xdata,ydata,cdata,'Marker','o',...
          'FaceColor','flat')

如果您运行此代码,您应该获得以下行的输出:

h =
  174.0110

p =
  175.0105

显示分配给轴的每个子项的句柄。

要获得更多信息,请添加以下附加代码:

axes_children = get(gca,'Children')
disp(['Type of "point" plot: ' get(h,'type')]);
disp(['Type of "patch" plot: ' get(p,'type')]);

其输出为:

axes_children =

  175.0105
  174.0110

Type of "point" plot: line
Type of "patch" plot: patch

请注意元素的顺序: 175.0105 (即patch)在列表中较高 - 这非常重要,因为您无法选择被另一个物体遮挡的物体。

如果您有多个积分\补丁,只需使用以下内容重新定位patch以下point s:

for ind1=1:length(axes_children)
    if strcmp(get(axes_children(ind1),'type'),'patch')
        uistack(axes_children(ind1),'bottom');
    end
end

这将使点可选择,并保留补丁的顺序,以防它们相互重叠。

修改

这是我使用idea from UndocumentedMatlab为您的问题编译的一些鼠标跟踪代码的扩展示例。它可能会给你更多的想法...

function init()
close all force; clear variables; clc;
%// Initialize the figure with a listener:
h = figure('WindowButtonMotionFcn',@windowMotion);
%// Add a "static" text label:
col = get(h,'color');
uicontrol('Style','text', 'Pos',[0,0,300,30],'Tag','lbl',...
          'Background',col, 'HorizontalAlignment','left');

axes('units','pix'); hold all;
for i=1:3
    X = 5*rand(100,1);
    plot(X,rand*X + rand(100,1),'.');
end

    xdata = [2     2     0     2     5;
             2     8     2     4     5;
             8     8     2     4     8]/2;
    ydata = [4     4     4     2     0;
             8     4     6     2     2;
             4     0     4     0     0]/2;
    cdata = [5     0     4     6    10;
             1     2     5     7     9;
             2     3     0     8     3];
    patch(xdata,ydata,cdata,'Marker','o',...
              'FaceColor','interp');

drawnow;

datacursormode on;
end

function windowMotion(hObject,eventData,varargin)
   persistent inCallback;   
   %// If you want to do something complex inside the callback, the
   %// inCallback lines makes sure that only 1 instance of the callback is
   %// being executed at a time.
   if ~isempty(inCallback), return;  end
   inCallback = true;

   lbl = findobj('Tag','lbl');

   try
    currPos = get(gcf,'CurrentPoint');
    ax_pos = get(gca,'Position');

    %// Test if the mouse pointer is inside the axes:
    if (currPos(1)>ax_pos(1) && currPos(1)<ax_pos(1)+ax_pos(3)) && ...
       (currPos(2)>ax_pos(2) && currPos(2)<ax_pos(2)+ax_pos(4)) 

        %// Find all possible
        possible_points_obj = findobj(gca,'Type','line');
        %// SOME LOGIC TO FIND THE CORRECT points_obj
        %// In this example it will look only in the last-plotted group of
        %// points - RED. This can be extended to loop over all "line"
        %// objects and select the closest point of all.
        correct_points_obj = possible_points_obj(1);

        X=get(correct_points_obj,'XData')'; ...'
        Y=get(correct_points_obj,'YData')'; ...'
        XScale=diff(get(gca,'XLim'));
        YScale=diff(get(gca,'YLim'));

        currPosinAx = (currPos - ax_pos(1:2))./ax_pos(3:4).*[XScale YScale];

        r=(((X-currPosinAx(1))./XScale).^2+((Y-currPosinAx(2))./YScale).^2);
        [~,i]=min(r);

        %// Here you put whatever you want to do with the point you found
        set(lbl,'String',{['The closest point to the pointer is at: ('...
                            num2str(X(i)) ',' num2str(Y(i)) '),'];
        ['and belongs to handle: ' num2str(correct_points_obj)]});    
    else
        set(lbl,'String','Mouse is outside axes'); 
    end
   catch
       % error trapping here
   end
   drawnow;
   inCallback = [];
end  % myCallbackFcn1