Matlab imline snapping

≯℡__Kan透↙ 提交于 2019-12-22 22:39:32

问题


Is there a way to make the ends of a line created by imline snap to the nearest data point on a curve?

I'm trying to measure the slope between two points on a curve. The imline is great, but the ends of the line created by it do not snap to data points on a curve.

I'm wondering if I can drag the line around while both ends of the line remained on the curve.


回答1:


It can be done using the 'PositionConstraintFcn' property of imline. Its value specifies a function handle that is called whenever the line is dragged using the mouse:

'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 [...]

The form of new_position is a 2x2 matrix, where each row is an endpoint of the line; and columns represent x and y respectively.

So all you have to do is specify a function that finds the closest point for each end and returns that constrained position. This can be done in two steps:

  1. Create a function to do the actual job, using as inputs the new position (2x2 matrix) and the set of allowed positions (Nx2, where N represents the number of points of the curve). The output is a 2x2 matrix with the constrained position.

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

    Define this function in its own m-file (imline_snap.m) and place it where Matlab can find it, for example in the current folder.

    Here's how it works. The function receives the two points selected by the mouse (new_pos) and the set of points defining the curve (positions). It computes the distance from the first mouse point to each point in the curve (sum(bsxfun(@minus, new_pos(1,:), positions).^2, 2)), and gets the index of the point in the curve with minimum distance (ind1). The same is done for the second point (giving the index ind2). Finally, those indices are used for selecting the appropriate curve points and building the ouput (constr_pos).

  2. The above imline_snap function needs to be particularized with the allowed positions corresponding to the points of the curve. This is necessary because the PositionConstraintFcn must accept only one input, namely the first input of imline_snap. This can be done via an anonymous function (see the example below, line fcn = ...); whose handle is then passed to imline.

Example code:

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

It should be noted that the code snaps to actual curve points. It doesn't for example interpolate between curve points. That could be done modifying the imline_snap function accordingly (but could result in sluggish movement if the number of operations is large).

Here's the above example at work (in Matlab R2010b). The righmost endpoint of the curve was dragged arbitrarily with the mouse, but it is seen to be snapped to the curve.

As a bonus, it would be easy to modify the function to display the slope in the figure title. Just add the following line at the end of the imline_snap function:

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

Example showing slope:



来源:https://stackoverflow.com/questions/32467969/matlab-imline-snapping

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!