viernes, 28 de marzo de 2014

Gráficas en tres dimensiones en MATLAB (Superficies, Curvas en el espacio, Planos)


Superficies

Utilizando matrices

Una manera de graficar superficies es utilizar matrices y representarlas mediante funciones disponibles en MATLAB. Para ello debe definirse previamente una malla bidimensional utilizando el comando meshgrid, cuyos argumentos son los intervalos de las variables independientes, por ejemplo suponga que quiere graficarse la siguiente función:

$$f(x,y)=x^2+y^2$$

[X,Y]=meshgrid(-5:0.1:5);
Z=X.^2+Y.^2;
surf(X,Y,Z);


De forma simbólica

Otra forma de obtener el mismo resultado que el caso anterior, es proceder de manera simbólica. Una de las funciones que permite esto es ezsurf, cuya forma es la siguiente:

ezsurf('x^2+y^2',[-5 5]);


Como puede observarse, se necesitan menos líneas de código bajo este método.


Curvas en el espacio

Para graficar curvas en el espacio se dispone del comando plot3, cuyos argumentos son las ecuaciones paramétricas de la curva, tómese como ejemplo la siguiente curva (helice circular):

$$ x(t)=cos(t) \,\,\,\,\,\,\,\,\, y(t)=sin(t)  \,\,\,\,\,\,\,\,\, z(t)=t $$

t=linspace(0,10*pi,200);
x=cos(t);
y=sin(t);
z=t;
plot3(x,y,z,'linewidth',2);

Puede utilizar la forma simbólica para obtener un resultado similar al anterior con el comando ezplot3, tal como sigue:

ezplot3('cos(t)','sin(t)','t',[0 10*pi]);


Planos

El siguiente ejemplo muestra como graficar un plano $z=constante$, para ello se utiliza el comando fill3.

hold on
ezsurf('x^2+y^2',[-5 5]);
k=20;
A=[-5 -5 k];
B=[-5 5 k];
C=[5 5 k];
D=[5 -5 k];
X=[A(1) B(1) C(1) D(1)];
Y=[A(2) B(2) C(2) D(2)];
Z=[A(3) B(3) C(3) D(3)];
fill3(X,Y,Z,[0.7 0.7 0.7]);
view(3);




















jueves, 27 de marzo de 2014

Animación simple MATLAB


Código de la animación

x=0:0.1:10;
for k=1:0.05:10
    axis([0 10 -2 2]);
    y=cos(k*x);
    plot(x,y);
    drawnow;
end


viernes, 21 de marzo de 2014

Calculadora básica en MATLAB


Utilizando las siguientes líneas de código se puede crear una calculadora básica en MATLAB, lo cual suele ser una de las tareas iniciales en el desarrollo de GUIs. Se ha prescindido del entorno de desarrollo (GUIDE) en este caso.





function calculadora

% Calculadora básica
% $ Por: Jorge De Los Santos $
% $ http://matlab-typ.blogspot.com $
% $ Rev. 1.0.0 $ $ Fecha: 02/01/14 $

figure('MenuBar','none','NumberTitle','off','Name','Calculadora',...
    'position',[200 200 200 280],'resize','off');
centerfig(gcf);

p=uipanel(gcf,'units','pixels','position',[10 10 180 200]);

pantalla=uicontrol('style','text','string','',...
    'position',[10 230 180 40],'HorizontalAlignment','right',...
    'FontSize',20,'FontWeight','b','FontName','Courier');

% Botón AC (Limpiar)
uicontrol('style','push','string','AC','position',[60 195 40 15],...
    'backgroundcolor','r','callback',@acFcn,'foregroundcolor','w',...
    'fontweight','b');

% Botón OFF (Apagar)
uicontrol('style','push','string','OFF','position',[100 195 40 15],...
    'backgroundcolor','b','callback',@offFcn,'foregroundcolor','w',...
    'fontweight','b');

% Controles numéricos y operadores
uicontrol(p,'style','push','string','0','position',[8 8 35 35]);
uicontrol(p,'style','push','string','.','position',[51 8 35 35]);
uicontrol(p,'style','push','string','=','position',[94 8 35 35]);
uicontrol(p,'style','push','string','+','position',[137 8 35 35]);
uicontrol(p,'style','push','string','1','position',[8 51 35 35]);
uicontrol(p,'style','push','string','2','position',[51 51 35 35]);
uicontrol(p,'style','push','string','3','position',[94 51 35 35]);
uicontrol(p,'style','push','string','-','position',[137 51 35 35]);
uicontrol(p,'style','push','string','4','position',[8 94 35 35]);
uicontrol(p,'style','push','string','5','position',[51 94 35 35]);
uicontrol(p,'style','push','string','6','position',[94 94 35 35]);
uicontrol(p,'style','push','string','*','position',[137 94 35 35]);
uicontrol(p,'style','push','string','7','position',[8 137 35 35]);
uicontrol(p,'style','push','string','8','position',[51 137 35 35]);
uicontrol(p,'style','push','string','9','position',[94 137 35 35]);
uicontrol(p,'style','push','string','/','position',[137 137 35 35]);
set(findobj('parent',p),'callback',@calcFcn,'FontSize',14);

% Guarda y evalua los cálculos
    function calcFcn(src,~)
        global cnum ceval
        % cnum - Guarda cadena numérica
        % ceval - Guarda cadena a evaluar
        pres=get(src,'str');
        if ~any(strcmp(pres,{'*','/','+','-','='}))
            cnum=[cnum,pres];
            set(pantalla,'str',cnum);
        elseifany(strcmp(pres,{'+','-','*','/'}))
            ceval=[ceval,cnum,pres];
            cnum='';
        elseif strcmp(pres,'=')
            ceval=[ceval,cnum];
            set(pantalla,'str',str2num(ceval));
            ceval=get(pantalla,'str');
            cnum='';
        end
    end

% Borra pantalla y restaura variables
    function acFcn(~,~)
        global cnum ceval
        cnum='';
        ceval='';
        set(pantalla,'str','0');
    end

% "Apaga" la calculadora
    function offFcn(~,~)
        clearvars('-global','cnum','ceval');
        set(pantalla,'str','');
    end
end


miércoles, 19 de marzo de 2014

Puntos aleatorios dentro de una circunferencia


Esta función permite dibujar puntos distribuidos aleatoriamente dentro de una región delimitada por una circunferencia. El radio de la circunferencia y el número de puntos son los argumentos de entrada.


function circ_punt(r,N)
% Donde:
%   r : radio del círculo
%   N : número de puntos aleatorios
%
% Ej:   >> circ_punt(10,200);

t=linspace(0,2*pi,1000);
x=r*cos(t);
y=r*sin(t);
hold on
plot(x,y,'linewidth',2);
k=1;
while k <= N
    px=randi([-100*r,100*r])/100;
    py=randi([-100*r,100*r])/100;
    ifsqrt(px^2+py^2)<r
        plot(px,py,'.r')
        k=k+1;
    end
    axis([-(r+1) r+1 -(r+1) r+1]);
    axis('square');
end    
end


La siguiente imagen es el resultado de la ejecución con r=10 y N=200:





martes, 18 de marzo de 2014

Centrar una GUI


Quizá sea uno de los cuestionamientos más frecuentes cuando se inicia en el mundo de las interfaces gráficas en MATLAB, dado que esto proporciona una mejor visualización y presentación de nuestras GUI.

Para tal fin bastará con utilizar las instrucciones "movegui" o bien "centerfig" y colocarlas en el OpeningFcn de la GUI (en el caso de utilizar GUIDE). Para utilizar la primera es necesario pasarle como argumento la opción "center", como se muestra enseguida:

movegui('center');

Y para el segundo caso simplemente puede escribirse la instrucción sin argumentos o bien utilizar gcf (handle  de la figura actual), como se indica:

centerfig;
centerfig(gcf);


sábado, 8 de marzo de 2014

Crear imágenes con degradado (Lineal y Radial)


Será ésta la primera entrada del blog orientada al procesamiento de imágenes, por lo cual es aún muy básica.

Vamos a crear cuatro tipo de degradados (lineal de derecha a izquierda, lineal de izquierda a derecha, radial de adentro hacia afuera y radial de afuera hacia adentro) en imágenes en escala de grises, utilizando ciclos for simples y anidados.

Lineal de derecha izquierda

Definimos primeramente las variables ancho y alto que determinarán el tamaño de la imagen. Con el ciclo for creamos la matriz A, agregando cada elemento de ella en una ejecución, como puede observarse la variación de valores se da sólo en una dirección. Recuerde que el tipo de dato comúnmente utilizado en imágenes es el uint8 (entero sin signo de 8 bits) y por ello debe hacerse la conversión explícita dado que MATLAB por defecto considera como tipo double cualquier valor numérico introducido. Se especifica que el valor tomado debe ser ancho-i para que mientras i aumenta el valor decrezca. Tome en cuenta que los valores próximos a 0 tienden a ser negros y que entre más próximos a 255 serán en un tono más claro o blanco. Finalmente, la instrucción imshow permite mostrar la imagen en una ventana.

ancho = 250;
alto = 250;
for i=1:ancho
    A(1:alto,i)=uint8(ancho-i);
end
imshow(A);



Lineal de izquierda a derecha


ancho = 250;
for i=1:ancho
    A(1:alto,i)=uint8(i);
end
imshow(A);




Radial de adentro hacia afuera

Como en el caso lineal se definen las variables ancho y alto, pero ahora se necesitarán dos ciclos for anidados dado que la variación será en ambas direcciones. El punto de referencia no será ninguno de los extremos, sino el punto medio dado por $ ancho/2 $ y $ alto/2 $. La variación del valor asignado depende de la variable "distr", que es la distancia desde el punto medio a cada uno de los puntos o pixeles que componen la imagen, o en términos más amables:

$$ \sqrt{(ancho/2\,-\,i)^2+(alto/2\,-\,j)^2} $$

ancho = 250;
alto = 250;
for i=1:ancho
    for j=1:alto
        distr = sqrt((ancho/2-i)^2+(alto/2-j)^2);
        A(j,i)=uint8(distr);
    end
end
imshow(A);



Radial de afuera hacia adentro


ancho = 250;
alto = 250;
for i=1:ancho
    for j=1:alto
        distr = sqrt((ancho/2-i)^2+(alto/2-j)^2);
        A(j,i)=uint8(0.5*ancho-distr);
    end
end
imshow(A);