当该点位于先前已“修补"的区域内时,如何获取图形的点(使用GUI中的回调)? [英] How to get point of a figure (using callbacks in GUI) when the point is inside a region that previously has been "patched"?

查看:77
本文介绍了当该点位于先前已“修补"的区域内时,如何获取图形的点(使用GUI中的回调)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用patch以便将椭圆形内部绘制到在gui环境中创建的图形中.

I am using patch in order to draw inside an ellipse into a figure I have created in gui environment.

通常,我通过单击(使用回调函数)来获得图形的点(坐标).当我要抓住的点不在先前绘制的椭圆内(应用patch)时,它可以正常工作.

Normally, I get figures' points (coordinates) by clicking (using callback functions). It works properly when the point I want to grab is not inside an ellipse that I have previously plotted (applying patch).

应用patch后如何做才能在绘制椭圆后得到某个椭圆内的点?非常感谢!

What should I do after applying patch in order to be able to get a point that is inside some ellipse after I have drawn it? Thanks a lot!

推荐答案

以下是解决问题的一种方法:

Here's a way to solve your problem:

首先,我们先画一个点,然后贴上一个覆盖"它的补丁.在此示例中,补丁是透明的,但仍无法选择其后面的点.

First we draw a point followed by a patch that "covers" it. In this example the patch is transparent, and still the point behind it cannot be selected.

(这部分代码取自MATLAB的 patch )

(this part of the code is taken from MATLAB's example for 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')

如果运行此代码,则应该得到如下输出:

If you run this code, you should get an output along the lines of:

h =
  174.0110

p =
  175.0105

其中显示了分配给轴的每个子轴的手柄.

Which shows the handles assigned to each child of the axes.

要获得更多见解,请添加以下附加代码:

To get some more insight, you add this additional code:

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)在列表中较高-这非常重要,因为您不能选择被另一个物体遮盖.

Notice the order of the elements: 175.0105 (i.e. the patch) is higher in the list - this is very important, because you cannot select an object that is obscured by another object.

如果您有多个点\补丁,则可以使用以下类似方法将patch es重新定位在point下方:

In case you have multiple points\patches you can simply reposition the patches below the points using something like this:

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

这将使各点成为可选点,并在补丁彼此重叠的情况下保留补丁的顺序.

This will make the point(s) selectable and also preserve the order of the patches in case they overlap each other.

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

Here's an extended example of the some mouse tracking code that I have compiled for your problem using idea from UndocumentedMatlab. It may give you some more ideas...

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

这篇关于当该点位于先前已“修补"的区域内时,如何获取图形的点(使用GUI中的回调)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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