2012-03-10 17 views
15

Sto provando a creare un'interfaccia semplice per tracciare i polinomi di Lagrange quadratici. Per questo, sono necessari solo 3 punti (con le loro coordinate x, y, z), che vengono poi interpolati usando i polinomi di Lagrange quadratici.Come rendere interattivo un grafico MATLAB?

È facile creare una versione statica o anche una che consente all'utente di inserire i 3 punti prima di tracciare la curva. Ma dovrebbe anche essere possibile per l'utente trascinare un punto esistente nella finestra della trama in un'altra posizione, e quindi ri-tracciare la curva automaticamente usando la nuova posizione di questo punto!

enter image description here

Così, in breve, l'utente dovrebbe essere in grado di trascinare questi puntini neri in un'altra posizione. Dopo di ciò (o durante il trascinamento), la curva dovrebbe essere aggiornata.

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

penso sia dovuto usare funzioni come WindowButtonDownFcn, WindowButtonUpFcn e WindowButtonMotionFcn, o il ImPoint dalla Image Processing Toolbox. Ma come?

[Modifica] Dovrebbe funzionare anche in 3D, poiché mi piacerebbe generalizzare questo concetto alle superfici del prodotto tensoriale.

+0

hai mai provato a risolvere questo problema con linkdata? –

risposta

3

Ottima domanda! Anch'io ho avuto questo problema e mi sono chiesto come risolverlo prima, ma non l'ho mai esaminato. Il mio primo pensiero è stato quello di utilizzare ginput e quindi ridurre al minimo la distanza dalla linea e trovare il punto più vicino. Ho pensato che fosse un po 'un trucco, quindi mi sono guardato intorno. Sembra che l'unica risposta ragionevole là fuori e è stato confermato 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) 

Non sono sicuro di come si scale al 3D, ma ho pensato che questo sarebbe un buon inizio.

+0

Grazie, non conoscevo l'opzione _ginput_! Tuttavia, non è possibile trascinare un punto, o è? Ho appena cercato ulteriori informazioni/esempi su ** ImPoint ** e ho scritto un semplice script. Inserirò questo come risposta, ma non accetterò la mia risposta poiché non funziona per 3D. Ma forse alcune persone lo troveranno utile. – Ailurus

12

Ok, ho cercato altre informazioni sull'opzione ImPoint da Image Processing Toolbox e ho scritto questo script.

Dal ImPoint funziona solo per un'impostazione 2D (e mi piacerebbe generalizzare questo in 3D per poter lavorare con superfici anziché curve), non è davvero una risposta accettabile! Ma qualcuno potrebbe trarne beneficio o avere un'idea di come farlo in 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); 

Ho aggiunto alcuni commenti per maggiore chiarezza.

[Modifica] Nell'anteprima l'evidenziazione della sintassi non sembra molto buona! Devo definire la lingua da evidenziare da qualche parte?

+0

Quindi per testare questo script, salvarlo come ** Interact.m ** e invocarlo _without_ input argomenti. – Ailurus

6

Una soluzione migliore (quella che non richiede alcuna casella degli strumenti aggiuntiva) consiste nell'utilizzare gli eventi. Primo passo:

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

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

Il passo successivo è quello di definire le funzioni come MouseClick, questo è il posto in cui si implementa come reagire agli eventi (ad esempio, i pulsanti del mouse viene cliccato, i tasti premuti).

Nel frattempo ho implementato un ambiente B-spline interattivo in MATLAB, il codice sorgente (insieme a un manuale conciso) può essere scaricato da https://github.com/pjbarendrecht/BsplineLab.

+0

il link non esiste più! – Arash

+0

@Arash Hai ragione, la mia vecchia università ha rimosso la pagina un paio di settimane fa. Potrei creare una pagina GitHub per una versione migliorata o scrivere qualcosa di simile per Geogebra :) – Ailurus

+0

grazie, stiamo aspettando :) – Arash

Problemi correlati