domingo, 7 de noviembre de 2010

Cómo dibujar la superficie de una curva en 3 dimensiones

En esta entrada, resumiré las opciones más importantes a la hora de dibujar una curva en 3D. En el ejemplo, utilizo la función de Rosenbrock siguiente:

z = (1-x)2 + 2·(y-x2)2

entre los siguientes límites

-2 < x < 2
-1 < y < 2.5




En primer lugar, defino la función que voy a dibujar en el archivo "f01.m":

function z = f01(x,y)
z = (1-x).^2 + 2*(y-x.^2).^2;

A continuación, creo tres matrices con los valores de "x" e "y", y los valores de la función. El comando meshgrid transforma los vectores "x" e "y" en dos matrices, que contienen todos los diferentes pares de puntos.

x = [-2:0.1:2];
y = [-1:0.1:2.5];

[X,Y] = meshgrid(x,y);
Z = f01(X,Y);

Nota: "x" es un vector de longitud 41. "y" es un vector de longitud 36. "X", "Y", y "Z" son matrices de tamaño 36x41.



La superficie la podemos dibujar directamente con el comando surf:

figure(1)
surf(X,Y,Z)
box on



Existen muchas opciones que se pueden configurar. Por ejemplo:


colormap spring % definimos el color (default, hot, spring, summer, autumn, winter...)
daspect([3 2.5 60]);
axis([-2 2 -1 2.5 0 60])
xlabel('x')
ylabel('y')
zlabel('z')
title('función de Rosenbrock')
set(gca,'XTick',[-2:1:2])
set(gca,'XTickLabel',{'-2','-1','0','1','2'})
set(gca,'YTick',[-1:0.5:2.5])
set(gca,'YTickLabel',{'-1.0','-0.5','0.0','0.5','1.0','1.5','2.0','2.5'})
set(gca,'ZTick',[0:20:60])
set(gca,'ZTickLabel',{'0','20','40','60'})
set(gca,'Fontsize',10)

Nota: Con "daspect" definimos la relación del tamaño de los ejes.


Podemos definir el punto de vista del observador con la función "view". Por ejemplo:

view([1 0 0])


También podemos poner un foco de luz, para que la figura se vea más bonita

light('Position',[0,2,50]) % Posición del foco de luz
lighting phong % Para suavizar la luz
material metal % Distintos tipos de brillo (shiny, dull, metal...)




En vez de usar el comando "surf", podemos usar otro tipo de funciones. Por ejemplo:

La función "mesh" muestra la superficie como una rejilla:

figure(1)
mesh(X,Y,Z)
box on


La función "contour" nos muestra el gráfico en dos dimensiones, con isolíneas. Como se ve a continuación, y donde "n" es el número de isolíneas.

n = 75;
figure(1)
contour(X,Y,Z,n)
box on
colormap autumn
axis([-2 2 -1 2.5])
xlabel('x')
ylabel('y')
title('función de Rosenbrock')
set(gca,'XTick',[-2:1:2])
set(gca,'xTickLabel',{'-2','-1','0','1','2'})
set(gca,'YTick',[-1:0.5:2.5])
set(gca,'YTickLabel',{'-1.0','-0.5','0.0','0.5','1.0','1.5','2.0','2.5'})
set(gca,'Fontsize',10)


Podemos añadir una barra lateral con el valor de los colores:

colorbar('EastOutside', 'YTick',[0:20:60], 'YTickLabel',{'0','20','40','60'},'Fontsize',10)

Nota: Como la barra la hemos puesto vertical, los números de la barra los definimos con 'YTick'. Si la hubiéramos puesto horizontal (con 'SouthOutside', deberíamos haber usado 'XTick'...)


En vez de isolíneas, también podríamos haber usado solo colores en una superficie, con el comando "surface":

figure(1)
surface(X,Y,Z)
box on
colormap default
axis([-2 2 -1 2.5])
xlabel('x')
ylabel('y')
title('función de Rosenbrock')
set(gca,'XTick',[-2:1:2])
set(gca,'xTickLabel',{'-2','-1','0','1','2'})
set(gca,'YTick',[-1:0.5:2.5])
set(gca,'YTickLabel',{'-1.0','-0.5','0.0','0.5','1.0','1.5','2.0','2.5'})
set(gca,'Fontsize',10)
colorbar('SouthOutside', 'XTick',[0:20:60], 'XTickLabel',{'0','20','40','60'},'Fontsize',10)


Si trabajmos con "surf" o "surface", podemos suavizar el degrado de colores:

figure(1)
surface(X,Y,Z)
shading interp
box on

No hay comentarios: