【问题标题】:Displaying the slope of a line created by imline in a text box在文本框中显示由 imline 创建的线的斜率
【发布时间】:2015-09-09 17:33:00
【问题描述】:

这篇文章是线程的延续:“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 对象被移动时,它会留下数百万个文本框。我只想显示一个最新的斜率计算。

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

另外一个问题是,即使我删除了imline对象,关联的文本框也会保留。

总之,

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

这可以吗?请帮忙。

谢谢,

埃里克

【问题讨论】:

    标签: matlab matlab-figure


    【解决方案1】:

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

    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); 
    

    这是一个例子,借用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 指定,它应该有两个输入,对应于源对象和事件(这是回调函数知道“为什么”它被调用的方式)。即使这些输入实际上不会被使用,也需要以这种方式定义函数。

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

    【讨论】:

    • 我每次移动imline时都创建文本框的原因是因为我希望文本框跟随imline而不是在图中的固定位置......
    • 但这不需要删除对象并创建一个新对象。只需更新其'position' 属性。查看已编辑的答案(最后一部分)
    • Luis,我不知道该如何感谢你,我真的很佩服你在 Matlab 方面的知识。我希望我能以某种方式向你学习 LOL 最后一项任务。删除imline对象时,使关联的文本框消失(右键单击/删除)。这个可以吗?
    • @Eric 感谢您的好心 cmets。是的,它可以通过事件监听器来完成。请查看编辑后的答案
    • 我是一位经验丰富的专业工程师,我对您印象深刻,就像我有时对工作中的技术人员一样。过去几周我在网上搜索了很多脚本,我试图将它们拼凑在一起以解决这些问题。在我的书中,有两种类型的解决方案:暴力破解(或粗略)和优雅。您的解决方案绝对优雅。我希望我能像你一样帮助别人。多么大的快乐!我真的希望有人为这些帮助你大赚一笔。如果你住在华盛顿,我会好好款待你的。我所有的问题都已经解决了。非常感谢。
    猜你喜欢
    • 2019-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-20
    • 2020-11-08
    • 1970-01-01
    • 2013-12-15
    • 1970-01-01
    相关资源
    最近更新 更多