此帖是该主题的延续:“Matlab imline snapping”已经解决。以下是将imline对象捕捉到曲线的工作代码。
function calc_slope(handle,event)
axis_h = findobj(gcf,'Type','axes');
obj_h = get(axis_h,'Children');
obj_type = get(obj_h,'Type');
if ~iscell(obj_type),obj_type = cellstr(obj_type);end
for i=1:length(obj_type)
if strcmpi(obj_type{i},'line'),data = obj_h(i);end
end
xdata = get(data,'XData');
ydata = get(data,'YData');
on = get(handle,'State');
if strcmpi(on,'on') || strcmpi(on,'off'),
fcn_constr = @(pos) imline_snap(pos, [xdata(:) ydata(:)]);
xy = imline(axis_h, 'PositionConstraintFcn', fcn_constr);
addNewPositionCallback(xy,@(pos) disp_slope(pos));
end
function constr_pos = imline_snap(new_pos, positions)
[~, ind1] = min(sum(bsxfun(@minus, new_pos(1,:), positions).^2, 2));
[~, ind2] = min(sum(bsxfun(@minus, new_pos(2,:), positions).^2, 2));
constr_pos = [positions(ind1,:); positions(ind2,:)];
function disp_slope(pos)
delete(findobj(gca,'Type','text'));
text((pos(1)+pos(2))/2,(pos(3)+pos(4))/2,['\DeltaY/\DeltaX = ',num2str((pos(4)-pos(3))/(pos(2)-pos(1))),...
' [\DeltaX = ',num2str(pos(2)-pos(1)),', \DeltaY = ',num2str((pos(4)-pos(3))),']']);
每次图形工具栏上的切换按钮切换(打开和关闭)时,都会抛出一个新的imline对象。有许多图形具有不同的参数,因此必须从图中提取数据。在给定的图中,可以有多个对象:imline对象,文本和/或行;因此,calc_slope函数中的前七行。
imline对象捕捉到曲线的最近数据点,它由imline_snap函数完美地完成,这是“Luis Mendo”的答案。非常感谢。这是一个最头痛的问题。
现在最后一个问题是在文本框中显示imline对象的斜率(而不是标题或浮动框)。它是在disp_slope函数中尝试的(而且很悲惨)。
我正在做“删除(findobj(gca,'Type','text'));”只是因为没有这样的东西,当imline对象被移动时,它将留下数百万个文本框。我只想显示一个最新的斜率计算。
“删除(findobj(gca,'Type','text'));”有多个问题。“如果我停止移动线,它将很好地显示最后的斜率计算。但是,只要我抛出另一个imline对象并移动新的imline对象,第一个imline对象中的文本框就会被删除,当然。
另一个问题是,即使我删除了imline对象,相关的文本框也会保留。
总之,
可以这样做吗?请帮助。
谢谢,
埃里克
答案 0 :(得分:2)
每次都不要创建新的文本对象。最初创建一个
ht = text(.45, .85, ''); %// modify coordinates to place it where you want
然后在'String'
更改时更新其内容(imline
属性)。要进行更新,请修改imline_snap
函数以接受ht
作为第三个输入,并在结尾处添加以下行:
set(ht, 'String', ...
num2str((constr_pos(2,2)-constr_pos(1,2))/(constr_pos(2,1)-constr_pos(1,1))));
因此功能变为
function constr_pos = imline_snap(new_pos, positions, ht)
[~, ind1] = min(sum(bsxfun(@minus, new_pos(1,:), positions).^2, 2));
[~, ind2] = min(sum(bsxfun(@minus, new_pos(2,:), positions).^2, 2));
constr_pos = [positions(ind1,:); positions(ind2,:)];
set(ht, 'String', ...
num2str((constr_pos(2,2)-constr_pos(1,2))/(constr_pos(2,1)-constr_pos(1,1))));
然后,在定义fcn_contr
时,将引用ht
传递给文本对象:
fcn_constr = @(pos) imline_snap(pos, [xdata(:) ydata(:)], ht);
这是一个例子,借用my previous answer的曲线:
h = plot(0:.01:1, (0:.01:1).^2); %// example curve. Get a handle to it
a = gca; %// handle to current axes
ht = text(.45, .85, ''); %// create text
xdata = get(h,'XData'); %// x values of points from the curve
ydata = get(h,'YData'); %// y values of points from the curve
fcn_constr = @(pos) imline_snap(pos, [xdata(:) ydata(:)], ht); %// particularize function
imline(a, 'PositionConstraintFcn', fcn_constr); %// create imline
您还可以更新文字位置('Position'
属性)。只需更改imline_snap
的最后一个语句即可包含该语句。例如:
set(ht, 'String', ...
num2str((constr_pos(2,2)-constr_pos(1,2))/(constr_pos(2,1)-constr_pos(1,1))), ...
'Position', ...
mean(constr_pos) + [.03 -.03]); %// manually adjust offset if needed
偏移量[.03 -.03]
旨在避免文本与行重叠。您可能需要更改它。此外,使用粗体创建文本对象可能会有所帮助。该行成为
ht = text(.45, .85, '', 'Fontweight', 'bold'); %// create text, in boldface
以下是更新文字位置的示例:
在您删除所需的imline
对象和event listener时删除关联的文本对象。这是一个具有三个主要属性的对象:源对象的单元数组,事件和回调函数。当指定的事件发生在其中一个源对象上时,执行事件监听器的回调函数。
要为imline
对象的删除创建事件侦听器,请使用该对象的addEventListener
方法并指定事件名称和回调函数。回调函数是通过function handle指定的,它应该有两个输入,它们对应于源对象和事件(这就是回调函数将如何知道"为什么"它&# 39;被称为)。即使这些输入实际上没有被使用,也需要以这种方式定义函数。
在这种情况下,我们要监听的事件是ObjectBeingDestroyed
,源对象是imline
对象,回调函数是delete(ht)
(删除文本对象) 。因此,上例中的代码变为
h = plot(0:.01:1, (0:.01:1).^2); %// example curve. Get a handle to it
a = gca; %// handle to current axes
ht = text(.45, .85, '', 'Fontweight', 'bold'); %// create text, in boldface
xdata = get(h,'XData'); %// x values of points from the curve
ydata = get(h,'YData'); %// y values of points from the curve
fcn_constr = @(pos) imline_snap(pos, [xdata(:) ydata(:)], ht); %// particularize function
hi = imline(a, 'PositionConstraintFcn', fcn_constr); %// create imline and get a handle
addlistener(hi, 'ObjectBeingDestroyed', @(obj,event) delete(ht))
其中只有最后两行是新的。
现在每当删除imline
对象时,都会执行操作delete(ht)
,从而删除文本对象。