在文本框中显示由 imline 创建的直线的斜率

Displaying the slope of a line created by imline in a text box

此 post 是线程的延续:"Matlab imline snapping" 已解决。下面是将 imline object 捕捉到曲线的工作代码。

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 object。有许多具有不同参数的图形,因此数据必须从图中提取出来的。在给定的图形中,可以有多个objects:imline objects, text, and/or line;因此,calc_slope 函数的前七行。

imline objects 捕捉到曲线的最近数据点,它由 imline_snap 函数完美完成,这是 "Luis Mendo" 的答案。太感谢了。这一直是最头疼的问题。

现在的最后一个问题是在文本框(而不是标题或浮动框)中显示内切线的斜率 object。在disp_slope函数中尝试过(而且很惨)

我这样做 "delete(findobj(gca,'Type','text'));" 只是因为如果没有类似的东西,当 imline object 移动时,它将留下数百万个文本框。我只想展示一个最新的斜率计算。

"delete(findobj(gca,'Type','text'));" 存在多个问题。如果我停止移动线,它会很好地显示最后的斜率计算。但是,只要我放入另一个 imline object 并移动新的,第一个 imline object 中的文本框就会被删除,当然。

另一个问题是,即使我删除内嵌线object,关联的文本框也会保留。

综上所述,

  1. 我想在文本框中显示当前计算的斜率
  2. 我希望每个 imline object 的文本框保持不变,即使有多个 imline objects。
  3. 最后,我希望相应的文本框在删除特定的 imline object 时也消失。

这能做到吗?请帮忙

谢谢,

埃里克

不要每次都创建一个新的文本对象。最初创建一个

ht = text(.45, .85, ''); %// modify coordinates to place it where you want

然后 imline 更改时更新其内容 ('String' 属性)。要进行更新,请修改 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); 

举个例子,借用的曲线:

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 method and specify the event name and callback function. The callback function is specified by means of a function handle,它应该期望两个输入,分别对应于源对象和事件(这就是回调函数会知道 "why" 它正在被调用)。即使实际上不会使用这些输入,也需要以这种方式定义函数。

本例中,我们要监听的事件是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),从而删除文本对象。