如何使MATLAB绘图交互?

时间:2012-03-10 11:45:13

标签: matlab

我正在尝试创建一个简单的界面来绘制二次拉格朗日多项式。为此,您只需要3个点(每个点都有自己的x,y,z坐标),然后使用二次拉格朗日多项式进行插值。

制作静态版本很容易,甚至可以在绘制曲线之前让用户输入3个点。但是,用户也应该可以将绘图窗口中的现有点拖动到另一个位置,然后使用此点的新位置自动重新绘制曲线!

enter image description here

简而言之,用户应该能够将这些黑点拖到另一个位置。之后(或拖动时),曲线应该更新。

function Interact()

% Interactive stuff here

figure();
hold on;
axis([0 7 0 5])

DrawLagrange([1,1; 3,4; 6,2])

function DrawLagrange(P)

plot(P(:,1), P(:,2), 'ko--', 'MarkerSize', 10, 'MarkerFaceColor', 'k')

t = 0:.1:2;
Lagrange = [.5*t.^2 - 1.5*t + 1; -t.^2 + 2*t; .5*t.^2 - .5*t];

CurveX = P(1,1)*Lagrange(1,:) + P(2,1)*Lagrange(2,:) + P(3,1)*Lagrange(3,:);
CurveY = P(1,2)*Lagrange(1,:) + P(2,2)*Lagrange(2,:) + P(3,2)*Lagrange(3,:);

plot(CurveX, CurveY);

我想我要么必须使用 WindowButtonDownFcn WindowButtonUpFcn WindowButtonMotionFcn 等功能,要么使用 ImPoint 图像处理工具箱。但是如何?

[编辑] 它也应该在3D中工作,因为我想将这个概念推广到张紧产品表面。

3 个答案:

答案 0 :(得分:12)

好的,我在图像处理工具箱中搜索了有关 ImPoint 选项的更多信息,并编写了此脚本。

由于 ImPoint 仅适用于2D设置(我想将其概括为3D以便能够使用曲面而不是曲线),这不是一个真正可以接受的答案!但有人可能会从中受益,或者想知道如何在3D中做到这一点。

% -------------------------------------------------
% This file needs the Image Processing Toolbox!
% -------------------------------------------------

function Interact(Pos)

% This part is executed when you run it for the first time.
% In that case, the number of input arguments (nargin) == 0.
if nargin == 0

    close all;
    clear all;
    clc;

    figure();
    hold on;
    axis([0 7 0 5])

    % I do not know how to do this without global variables?
    global P0 P1 P2

    % GCA = Get handle for Current Axis
    P0 = ImPoint(gca,1,1);
    setString(P0,'P0');
    P1 = ImPoint(gca,2,4);
    setString(P1,'P1');
    P2 = ImPoint(gca,6,2);
    setString(P2,'P2');

    % Call subfunction
    DrawLagrange(P0,P1,P2)

    % Add callback to each point
    addNewPositionCallback(P0,@Interact);
    addNewPositionCallback(P1,@Interact);
    addNewPositionCallback(P2,@Interact);

else

    % If there _is_ some input argument, it has to be the updated
    % position of a moved point.
    global H1 H2 P0 P1 P2

    % Display X and Y coordinates of moved point
    Pos

    % Important: remove old plots! Otherwise the graph will get messy.
    delete(H1)
    delete(H2)
    DrawLagrange(P0,P1,P2)

end

function DrawLagrange(P0,P1,P2)

P = zeros(3,2);
% Get X and Y coordinates for the 3 points.
P(1,:) = getPosition(P0);
P(2,:) = getPosition(P1);
P(3,:) = getPosition(P2);

global H1 H2
H1 = plot(P(:,1), P(:,2), 'ko--', 'MarkerSize', 12);

t = 0:.1:2;
Lagrange = [.5*t.^2 - 1.5*t + 1; -t.^2 + 2*t; .5*t.^2 - .5*t];

CurveX = P(1,1)*Lagrange(1,:) + P(2,1)*Lagrange(2,:) + P(3,1)*Lagrange(3,:);
CurveY = P(1,2)*Lagrange(1,:) + P(2,2)*Lagrange(2,:) + P(3,2)*Lagrange(3,:);

H2 = plot(CurveX, CurveY);

为了清楚起见,我添加了一些评论。

[编辑] 在预览中,语法高亮显示不太好!我应该定义要在某处突出显示的语言吗?

答案 1 :(得分:6)

更好的解决方案(不需要任何其他工具箱的解决方案)是使用事件。第一步:

H = figure('NumberTitle', 'off');
set(H, 'Renderer', 'OpenGL');

set(H, 'WindowButtonDownFcn', @MouseClick);
set(H, 'WindowButtonMotionFcn', @MouseMove);
set(H, 'WindowScrollWheelFcn', @MouseScroll);
set(H, 'KeyPressFcn', @KeyPress )

下一步是定义像MouseClick这样的函数,这是您实现如何对事件做出反应的地方(例如,点击鼠标按钮,按下按键)。

与此同时,我在MATLAB中实现了一个交互式B样条环境,源代码(以及简明的手册)可以从https://github.com/pjbarendrecht/BsplineLab下载。

答案 2 :(得分:3)

好问题!我也遇到过这个问题,并想知道如何解决它,但从未研究过它。我的第一个想法是使用ginput,然后最小化到线的距离并找到最近的点。我觉得这有点像黑客,所以我环顾四周。似乎这是唯一合理的答案,并得到确认here with this code as an example.

%minimum absolute differences kick in again
xx = 1:10; %xdata
yy = exp(xx);

plot(xx,yy);
[xm ym] = ginput(1); %xmouse, ymouse

%Engine
[~, xidx] = min(abs(xx-xm)); %closest index
[~, yidx] = min(abs(yy-ym));
x_closest = xx(xidx) %extract
y_closest = yy(yidx)

不确定它如何扩展到3D,但我认为这将是一个良好的开端。