我正在使用patch
将椭圆内部绘制成我在gui环境中创建的图形。
通常,我会得到数字'点击(坐标)点击(使用回调函数)。当我想抓住的点不在我之前绘制的椭圆内时(应用patch
),它可以正常工作。
在应用patch
之后我应该怎么做才能在绘制之后得到一个椭圆内的点?非常感谢!
答案 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