2012-03-10 13 views
15

Próbuję stworzyć prosty interfejs do wykreślania wielomianów Lagrange'a. Do tego potrzebne są tylko 3 punkty (z każdą własną współrzędną x, y, z), które następnie interpoluje się za pomocą wielomianów Lagrange'a kwadratowego.Jak zrobić interaktywny dział MATLAB?

Łatwo jest utworzyć wersję statyczną lub nawet taką, która pozwala użytkownikowi wprowadzić 3 punkty przed wykreśleniem krzywej. Ale użytkownik powinien także móc przeciągnąć istniejący punkt w oknie wykresu do innej pozycji, a następnie ponownie narysować krzywą automatycznie, używając nowej pozycji tego punktu!

enter image description here

Tak w skrócie, użytkownik powinien być w stanie przeciągnąć te czarne kropki do innej lokalizacji. Następnie (lub podczas przeciągania) należy zaktualizować krzywą.

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); 

myślę, że albo trzeba użyć funkcji jak WindowButtonDownFcn, WindowButtonUpFcn i WindowButtonMotionFcn, lub ImPoint z obrazka Processing Toolbox. Ale jak?

[Edytuj] Powinien również działać w 3D, ponieważ chciałbym uogólnić tę koncepcję na tensor powierzchni produktu.

+0

Czy kiedykolwiek próbowałeś rozwiązać ten problem z linkdata? –

Odpowiedz

3

Świetne pytanie! Też miałem ten problem i zastanawiałem się, jak go rozwiązać wcześniej, ale nigdy nie zaglądałem w to. Moją pierwszą myślą było użyć ginput, a następnie zminimalizować odległość do linii i znaleźć najbliższy punkt. Myślałem, że to trochę hack, więc rozejrzałem się. Wygląda na to, że to jedyna rozsądna odpowiedź i tam potwierdzono 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) 

Nie wiem, jak to skaluje do 3D, ale myślałem, że to byłby dobry początek.

+0

Dzięki, nie znałem opcji _ginput_! Jednak nie można przeciągnąć punktu, czy też nie? Właśnie szukałem więcej informacji/przykładów na ** ImPoint ** i napisałem prosty skrypt. Opublikuję to jako odpowiedź, ale nie przyjmuję własnej odpowiedzi, ponieważ nie działa ona w 3D. Ale może niektórzy ludzie uznają to za przydatne. – Ailurus

12

OK, szukałem więcej informacji na temat opcji ImPoint z narzędzia Image Processing Toolbox i napisałem ten skrypt.

Od ImPoint działa tylko dla ustawienia 2D (i chciałbym uogólnić to na 3D, aby móc pracować z powierzchniami zamiast krzywymi), to nie jest naprawdę akceptowalna odpowiedź! Ale ktoś może odnieść z tego korzyści, lub uzyskać pomysł, jak to zrobić w 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); 

Dodałem komentarze w celu zwiększenia przejrzystości.

[Edytuj] W podglądzie podświetlanie składni nie wygląda najlepiej! Czy powinienem zdefiniować język, który ma być podświetlony?

+0

Aby przetestować ten skrypt, zapisz go jako ** Interact.m ** i wywołaj go bez argumentów wejściowych. – Ailurus

6

Lepszym rozwiązaniem (takim, które nie wymaga żadnych dodatkowych zestawów narzędzi) jest użycie zdarzeń. Pierwszy krok:

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

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

Następnym krokiem jest określenie funkcji, takich jak MouseClick, jest to miejsce, gdzie można realizować jak reagować na zdarzenia (na przykład przyciski myszy są kliknięciu przycisków jest wciśnięty).

W międzyczasie zaimplementowałem interaktywne środowisko B-splajn w MATLAB, kod źródłowy (wraz z zwięzłą instrukcją) można pobrać z https://github.com/pjbarendrecht/BsplineLab.

+0

Link już nie istnieje! – Arash

+0

@Arash Masz rację, moja stara uczelnia usunęła stronę kilka tygodni temu. Mogę utworzyć stronę GitHub dla ulepszonej wersji lub napisać coś podobnego dla Geogebra :) – Ailurus

+0

dziękuje, czekamy :) – Arash

Powiązane problemy