Как сделать сюжет MATLAB интерактивным? - PullRequest
15 голосов
/ 10 марта 2012

Я пытаюсь создать простой интерфейс для построения квадратичных полиномов Лагранжа.Для этого вам нужно всего 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 ]

12 голосов
/ 11 марта 2012

Хорошо, я искал дополнительную информацию о опции 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);

Я добавил некоторые комментарии для ясности.

[Редактировать] В предварительном просмотре подсветка синтаксиса выглядит не очень хорошо! Должен ли я определить язык, который будет выделен где-то?

6 голосов
/ 17 апреля 2014

Лучшее решение (не требующее дополнительных наборов инструментов) - использовать события. Первый шаг:

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, это место, где вы реализуете, как реагировать на события (например, нажатие кнопок мыши, нажатие клавиш).

Тем временем я внедрил интерактивную среду B-сплайна в MATLAB, исходный код (вместе с кратким руководством) можно загрузить с https://github.com/pjbarendrecht/BsplineLab.

3 голосов
/ 10 марта 2012

Отличный вопрос!Я тоже имел эту проблему и задавался вопросом, как ее решить раньше, но никогда не изучал ее.Моей первой мыслью было использовать ginput, а затем минимизировать расстояние до линии и найти ближайшую точку.Я подумал, что это было немного взломать, поэтому я оглянулся.Похоже, что это единственный разумный ответ, который был подтвержден здесь с помощью этого кода в качестве примера.

%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, но я думал, чтохорошее начало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...