Lo que he aprendido: dibujar cubos en Matlab

Como ando jugando con elementos finitos en el curro, me vi en la circunstancia de tener que pintar un modelo mallado con cubos en Matlab. Esto, que parece una tontería a simple vista es una locura total porque el buen Matlab hace solo superficies. Esto significa que para pintar un mísero cubo hay que pintar 6 superficies, cosa que tampoco es especialmente sencilla.

Después de probar varias alternativas, me he quedado con la función fill3 que pinta polígonos en tres dimensiones. Hay que meterle los datos de manera completamente antiintuitiva (es Matlab, recordemos), pero consigue el objetivo de crear cubetes.

Así que escribí esta función con la idea de usarla de base para pintar todo el modelo:

function cubo(coord)
% Pintar un cubos a partir de las coordenadas definidas según el siguiente
% orden para cada cubo:
%
%    7-------8
%   /|      /|
%  / |     / |
% 5--|----6  |
% |  3----|--4
% | /     | /
% 1-------2

for k = 1:length(coord)/8

  X = coord(8*(k-1)+1:8*(k-1)+8,1);
  Y = coord(8*(k-1)+1:8*(k-1)+8,2);
  Z = coord(8*(k-1)+1:8*(k-1)+8,3);

  % Los puntos de cada cara se ordenan según el sentido antihorario
  caras = [1 2 4 3; 5 6 8 7; 1 3 7 5; 2 4 8 6; 1 2 6 5; 3 4 8 7];

  % size(X) = [4 6]
  % - cada columna hace referencia a los puntos de un plano
  % - hay 4 elementos en cada columna que se refieren a las coordenadas x de
  % cada punto del plano

  X = [X(caras(1,:)) X(caras(2,:)) X(caras(3,:)) X(caras(4,:)) X(caras(5,:)) X(caras(6,:))];
  Y = [Y(caras(1,:)) Y(caras(2,:)) Y(caras(3,:)) Y(caras(4,:)) Y(caras(5,:)) Y(caras(6,:))];
  Z = [Z(caras(1,:)) Z(caras(2,:)) Z(caras(3,:)) Z(caras(4,:)) Z(caras(5,:)) Z(caras(6,:))];

  alpha = 0.6; % transparencia de la cara
  colour ='blue'; % color de la cara

  fill3(X,Y,Z,colour,'FaceAlpha',alpha); % dibujar los cubos
  axis equal

  hold on

end

end

Se usa de la siguiente manera:

P = [1 0 0; 1 1 0; 0 0 0; 0 1 0; 1 0 1; 1 1 1; 0 0 1; 0 1 1];

cubo(P)

Y nos pinta este simpático cubo:

cubo

¡Ahora ya podía pintar mi modelo de elementos finitos! Peeero también podía crear arte. Está claro lo que hice, ¿verdad?

Modifiqué la función de tal manera que cogiese el color y la transparencia como parámetros de entrada y llamé a la función en bucle con un cubo que se iba cambiando de sitio aleatoriamente.

Aquí mi función modificada:

function cubo(coord, color, alfa)
% Pintar un cubos a partir de las coordenadas definidas según el siguiente
% orden para cada cubo:
%
%    7-------8
%   /|      /|
%  / |     / |
% 5--|----6  |
% |  3----|--4
% | /     | /
% 1-------2


for k = 1:length(coord)/8

    X = coord(8*(k-1)+1:8*(k-1)+8,1);
    Y = coord(8*(k-1)+1:8*(k-1)+8,2);
    Z = coord(8*(k-1)+1:8*(k-1)+8,3);

    % Estas son las caras si está numerado en orden, para usar la conectividad
    % hay que cambiar el orden de los nodos de cada cara según el del cubo
    % patrón

    % Los puntos de cada cara se ordenan según el sentido antihorario
    caras = [1 2 4 3; 5 6 8 7; 1 3 7 5; 2 4 8 6; 1 2 6 5; 3 4 8 7];


    % size(X) = [4 6]
    % - cada columna hace referencia a los puntos de un plano
    % - hay 4 elementos en cada columna que se refieren a las coordenadas x de
    %   cada punto del plano

    X = [X(caras(1,:)) X(caras(2,:)) X(caras(3,:)) X(caras(4,:)) X(caras(5,:)) X(caras(6,:))];
    Y = [Y(caras(1,:)) Y(caras(2,:)) Y(caras(3,:)) Y(caras(4,:)) Y(caras(5,:)) Y(caras(6,:))];
    Z = [Z(caras(1,:)) Z(caras(2,:)) Z(caras(3,:)) Z(caras(4,:)) Z(caras(5,:)) Z(caras(6,:))];

    fill3(X,Y,Z,color,'FaceAlpha',alfa); % dibujar los cubos
    axis equal 

    hold on

end

end

que llamo de la siguiente manera:

n = 100; % numero de cubos
color = parula(n); % n colores del mapa de colores parula
alfa = rand(n,1); % transparencia aleatoria

% Cubo unitario
coord = [1 0 0; 1 1 0; 0 0 0; 0 1 0; 1 0 1; 1 1 1; 0 0 1; 0 1 1];

for k = 1:n

    cubo(coord, color(k), alfa(k))

    X = coord(:,1);
    Y = coord(:,2);
    Z = coord(:,3);

    coord = [X+rand(1,1)-0.5 Y+rand(1,1)-0.5 Z+rand(1,1)-0.5];
end

¡Y me crea esto!

estructura

Se puede mover el cubo de miles de maneras, cambiarle el tamaño o lo que queráis, ya me enseñaréis si habéis fabricado cosas molonas. Yo ahora voy a cambiar la función para que coja la conectividad del modelo y las coordenadas de los nodos y me pinte mi placa con sus nodos perfectamente numerados. Que es lo que tenía que haber hecho desde el principio.

Referencias

3D Polygon – draw planes with Matlab

Plot cube in matlab en StackOverflow


Musiquilla ❤

2 pensamientos en “Lo que he aprendido: dibujar cubos en Matlab

  1. Indian

    ¡Cómo mola! El resultado final parece sacado de una demoscene : ), estaría curioso usarlo para generar un (l-system)[https://en.wikipedia.org/wiki/L-system “L-System”]. A ver si lo puedo replicar usando python y matplotlib.

    Responder
    1. Ondiz Autor de la entrada

      Me hacéis aprender unas cosas guapísimas, no sabía ni qué era un demoscene ni, por supuesto, el L-system 😀

      No creo que te resulte difícil de replicar, no dejan de ser unas superficies y eso con Matplotlib lo tienes chupao, ¡ya nos enseñarás cómo queda!

      Responder

¡Opina sin miedo! (Puedes usar Markdown)

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s