Как сделать интерактивный сюжет 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, так как я хотел бы обобщить это понятие на тензорные поверхности продукта.
Ответы
Ответ 1
Хорошо, я искал дополнительную информацию о параметре ImPoint в Image Processing Toolbox и написал этот script.
Так как 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);
Я добавил некоторые комментарии для ясности.
[Изменить] В предварительном просмотре подсветка синтаксиса выглядит не очень хорошо! Должен ли я определять язык, который нужно выделить где-нибудь?
Ответ 2
Лучшее решение (которое не нуждается в дополнительных инструментах) - это использование событий. Первый шаг:
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
Отличный вопрос! У меня тоже была эта проблема, и я подумал, как ее решить раньше, но никогда не рассматривал ее. Моя первая мысль заключалась в том, чтобы использовать 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, но я думал, что это будет хорошее начало.