¿Cómo hacer que un diagrama de MATLAB sea interactivo?

Estoy tratando de crear una interfaz simple para trazar polinomios cuadráticos de Lagrange. Para esto, solo necesita 3 puntos (cada uno con sus propias coordenadas x, y, z), que luego se interpolan usando los polinomios cuadráticos de Lagrange.

Es fácil hacer una versión estática, o incluso una que le permita al usuario ingresar los 3 puntos antes de trazar la curva. ¡Pero también debería ser posible para el usuario arrastrar un punto existente en la ventana de trazado a otra posición y luego volver a trazar la curva automáticamente usando la nueva posición de este punto!

enter image description here

En resumen, el usuario debería poder arrastrar estos puntos negros a otra ubicación. Después de eso (o mientras arrastra), la curva debe actualizarse.

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

Creo que tengo que usar funciones como VentanaBotónAbajoFcn, VentanaBotónArribaFcn y VentanaBotónMovimientoFcn, o el ImPoint de la Caja de herramientas de procesamiento de imágenes. ¿Pero cómo?

[Editar] También debería funcionar en 3D, ya que me gustaría generalizar este concepto para tensar superficies de productos.

preguntado el 10 de marzo de 12 a las 11:03

¿Alguna vez intentaste resolver esto con linkdata? -

3 Respuestas

Ok, busqué más información sobre el ImPoint de la Caja de herramientas de procesamiento de imágenes y escribió este script.

Como ImPoint solo funciona para una configuración 2D (y me gustaría generalizar esto a 3D para poder trabajar con superficies en lugar de curvas), ¡no es realmente una respuesta aceptable! Pero alguien podría beneficiarse o tener una idea de cómo hacer esto en 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);

Agregué algunos comentarios para mayor claridad.

[Editar] ¡En la vista previa, el resaltado de sintaxis no se ve muy bien! ¿Debo definir el idioma que se resaltará en alguna parte?

Respondido 05 Feb 13, 13:02

Entonces, para probar este script, guárdelo como Interactuar.m e invocarlo sin argumentos de entrada. - Ailurus

Una mejor solución (una que no necesita cajas de herramientas adicionales) es usar eventos. Primer paso:

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

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

El siguiente paso es definir las funciones como MouseClick, este es el lugar donde implementa cómo reaccionar a los eventos (por ejemplo, se hace clic en los botones del mouse, se presionan las teclas).

Mientras tanto, implementé un entorno B-spline interactivo en MATLAB, el código fuente (junto con un manual conciso) se puede descargar de https://github.com/pjbarendrecht/BsplineLab.

Respondido 18 Feb 17, 18:02

el enlace ya no existe! - Arash

@Arash Tienes razón, mi antigua universidad eliminó la página hace un par de semanas. Podría crear una página de GitHub para una versión mejorada o escribir algo similar para Geogebra :) - Ailurus

Gracias, pero ¿cómo puedo arrastrar nodos en él? - Arash

@Arash Haga clic derecho para seleccionar y luego presione G para tomar el nodo y moverlo (haga clic con el botón izquierdo nuevamente para liberar el nodo). Se basa en el flujo de trabajo de Blender (blender.org). Véase también el PDF adjunto. - Ailurus

¡Gran pregunta! También he tenido este problema y me preguntaba cómo resolverlo antes, pero nunca lo investigué. Mi primer pensamiento fue usar ginput y luego minimice la distancia a la línea y encuentre el punto más cercano. Pensé que era un truco, así que miré a mi alrededor. Parece que esa es la única respuesta razonable que existe y fue confirmada aquí con este código como ejemplo.

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

No estoy seguro de cómo escala a 3D, pero pensé que sería un buen comienzo.

respondido 10 mar '12, 16:03

gracias no sabia la opcion entrada! Sin embargo, no es posible arrastrar un punto, ¿o sí? Acabo de buscar más información/ejemplos en ImPoint y escribió un guión simple. Publicaré esto como respuesta, pero no aceptaré mi propia respuesta ya que no funciona para 3D. Pero tal vez algunas personas lo encontrarán útil. - Ailurus

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.