Matlab 内嵌捕捉

Matlab imline snapping

有没有办法让 imline 创建的线的末端与曲线上最近的数据点对齐?

我正在尝试测量曲线上两点之间的斜率。 imline 很棒,但它创建的线的末端不会捕捉到曲线上的数据点。

我想知道是否可以拖动线,同时线的两端都保持在曲线上。

可以使用 imline'PositionConstraintFcn' 属性 来完成。它的值指定了一个 函数句柄,每当使用鼠标拖动该行时都会调用该函数句柄:

'PositionConstraintFcn': Function handle fcn that is called whenever the line is dragged using the mouse.

Whenever the object is moved because of a mouse drag, the constraint function is called using the syntax: constrained_position = fcn(new_position) where new_position is of the form [...]

new_position的形式是一个2x2的矩阵,每行是直线的一个端点;和列分别代表 xy

所以您所要做的就是指定一个函数来为每个端点找到最近的点,并returns限制位置。这可以分两步完成:

  1. 创建一个函数来完成实际工作,使用新位置(2x2 矩阵)和一组允许的位置(Nx2,其中N表示曲线的点数)。输出是具有约束位置的 2x2 矩阵。

    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,:)];
    

    在它自己的 m-file (imline_snap.m) 中定义这个函数,并将它放在 Matlab 可以找到它的地方,例如在当前文件夹中。

    这是它的工作原理。该函数接收鼠标选择的两个点 (new_pos) 和定义曲线的一组点 (positions)。它计算从第一个鼠标点到曲线中每个点的距离 (sum(bsxfun(@minus, new_pos(1,:), positions).^2, 2)),并获得曲线中距离最小的点的索引 (ind1)。第二点也是如此(给出索引ind2)。最后,这些索引用于选择适当的曲线点并构建输出 (constr_pos)。

  2. 上面的imline_snap函数需要特别说明允许的位置对应曲线的点。这是必要的,因为 PositionConstraintFcn 必须只接受一个输入,即 imline_snap 的第一个输入。这可以通过匿名函数完成(参见下面的示例,第 fcn = ... 行);然后将其句柄传递给 imline.

示例代码:

h = plot(0:.01:1, (0:.01:1).^2); %// example curve. Get a handle to it
a = gca; %// handle to current axes
X = get(h,'XData'); %// x values of points from the curve
Y = get(h,'YData'); %// y values of points from the curve
fcn = @(pos) imline_snap(pos, [X(:) Y(:)]); %// particularize function using curve points
imline(a, 'PositionConstraintFcn', fcn) %// create imline with that PositionConstraintFcn

需要注意的是,代码会捕捉到实际曲线点。例如,它不会在曲线点之间进行插值。这可以通过相应地修改 imline_snap 函数来完成(但如果操作数量很大,可能会导致移动缓慢)。

这是上面的例子(在 Matlab R2010b 中)。曲线的最右端点用鼠标任意拖动,但看到它被吸附到曲线上了。

作为奖励,很容易修改函数以在图形标题中显示斜率。只需在 imline_snap 函数的末尾添加以下行:

title(['Slope: ' num2str((constr_pos(2,2)-constr_pos(1,2))/(constr_pos(2,1)-constr_pos(1,1)))])

显示斜率的示例: