matlab - quiver3 color de flecha correspondiente a la magnitud
matlab-figure (2)
En el antiguo sistema de gráficos (R2014a y anterior) esto no es posible utilizando el objeto de
quiver
incorporado.
Puede obtener fácilmente todos los objetos de trazado que se utilizan para componer el trazado de
quiver
q = quiver(1:5, 1:5, 1:5, 1:5);
handles = findall(q, ''type'', ''line'');
Pero todas las colas están representadas por un objeto de trazado y las puntas de flecha están representadas por otro. Como tal, no puede alterar el color de cada cabeza / cola individualmente .
set(handles(1), ''Color'', ''r'')
set(handles(2), ''Color'', ''g'')
Sin embargo, con la introducción de HG2 (R2014b y posterior), puede obtener acceso a
dos
objetos
LineStrip
(no documentados) (
matlab.graphics.primitive.world.LineStrip
) (uno representa las cabezas y el otro las colas).
Estos son accesibles a través de las propiedades ocultas
Tail
y
Head
.
q = quiver(1, 1, 1, 1);
headLineStrip = q.Head;
tailLineStrip = q.Tail;
Luego puede modificar las propiedades de color de estos objetos para hacer que cada flecha tenga un color diferente.
La idea basica
Para hacer esto, primero calculo la magnitud de todas las flechas de carcaj (esto funciona tanto para
quiver
como para
quiver3
)
mags = sqrt(sum(cat(2, q.UData(:), q.VData(:), ...
reshape(q.WData, numel(q.UData), [])).^2, 2));
Luego uso el mapa de colores actual para asignar cada magnitud a un valor RGB.
A la flecha más corta se le asigna el color más bajo en el mapa de colores y a la flecha más larga se le asigna el color más alto en el mapa de colores.
histcounts
funciona muy bien para asignar a cada magnitud un índice que se puede pasar a
ind2rgb
junto con el mapa de
ind2rgb
en sí.
Tenemos que multiplicar por 255 porque necesitamos que el color sea RGB como un entero de 8 bits.
% Get the current colormap
currentColormap = colormap(gca);
% Now determine the color to make each arrow using a colormap
[~, ~, ind] = histcounts(mags, size(currentColormap, 1));
% Now map this to a colormap
cmap = uint8(ind2rgb(ind(:), currentColormap) * 255);
La propiedad
LineStrip
ColorData
(cuando se especifica como
truecolor
) también debe tener un canal alfa (que estableceremos en 255, que significa opaco).
cmap(:,:,4) = 255;
En este punto, podemos establecer la propiedad
ColorBinding
para
interpolated
lugar de
object
(para desacoplarla del objeto
quiver
) y establecer la propiedad
ColorData
de
q.Head
y
q.Tail
a los colores que creamos arriba, dando a cada flecha su propio color .
Solución completa
NOTA:
Esta solución funciona
tanto
para
quiver
como para
quiver3
y el código no tiene que adaptarse en absoluto.
%// Create a quiver3 as we normally would (could also be 2D quiver)
x = 1:10;
y = 1:10;
[X,Y] = meshgrid(x, y);
Z = zeros(size(X));
U = zeros(size(X));
V = zeros(size(X));
W = sqrt(X.^2 + Y.^2);
q = quiver3(X, Y, Z, U, V, W);
%// Compute the magnitude of the vectors
mags = sqrt(sum(cat(2, q.UData(:), q.VData(:), ...
reshape(q.WData, numel(q.UData), [])).^2, 2));
%// Get the current colormap
currentColormap = colormap(gca);
%// Now determine the color to make each arrow using a colormap
[~, ~, ind] = histcounts(mags, size(currentColormap, 1));
%// Now map this to a colormap to get RGB
cmap = uint8(ind2rgb(ind(:), currentColormap) * 255);
cmap(:,:,4) = 255;
cmap = permute(repmat(cmap, [1 3 1]), [2 1 3]);
%// We repeat each color 3 times (using 1:3 below) because each arrow has 3 vertices
set(q.Head, ...
''ColorBinding'', ''interpolated'', ...
''ColorData'', reshape(cmap(1:3,:,:), [], 4).''); %''
%// We repeat each color 2 times (using 1:2 below) because each tail has 2 vertices
set(q.Tail, ...
''ColorBinding'', ''interpolated'', ...
''ColorData'', reshape(cmap(1:2,:,:), [], 4).'');
Y aplicado a un objeto de
quiver
2D
Si no necesariamente desea escalar las flechas a todo el rango del mapa de colores, puede usar la siguiente llamada a
histcounts
(en lugar de la línea anterior) para mapear las magnitudes usando los límites de color de los ejes.
clims = num2cell(get(gca, ''clim''));
[~, ~, ind] = histcounts(mags, linspace(clims{:}, size(currentColormap, 1)));
Quiero que el color de cada flecha en un gráfico de
quiver3
de MATLAB corresponda a la magnitud de cada flecha.
¿Hay alguna forma de hacer eso?
Vi algunos ejemplos en línea que pueden hacer esto para el
quiver
2D, sin embargo ninguno de ellos funciona para la variante 3D,
quiver3
.
Tengo el siguiente diagrama y quiero reemplazar las flechas azules con un color correspondiente a su magnitud.
Si usa una versión posterior a r2014b, puede usar funciones no documentadas para cambiar el color de cada línea y encabezado:
figure
[x,y] = meshgrid(-2:.5:2,-1:.5:1);
z = x .* exp(-x.^2 - y.^2);
[u,v,w] = surfnorm(x,y,z);
h=quiver3(x,y,z,u,v,w);
s = size(x);
nPoints = s(1)*s(2);
% create a colour map
cmap = parula(nPoints);
% x2 because each point has 2 points, a start and an end.
cd = uint8(repmat([255 0 0 255]'', 1, nPoints*2));
count = 0;
% we need to assign a colour per point
for ii=1:nPoints
% and we need to assign a colour to the start and end of the
% line.
for jj=1:2
count = count + 1;
cd(1:3,count) = uint8(255*cmap(ii,:)'');
end
end
% set the colour binding method and the colour data of the tail
set(h.Tail, ''ColorBinding'',''interpolated'', ''ColorData'',cd)
% create a color matrix for the heads
cd = uint8(repmat([255 0 0 255]'', 1, nPoints*3));
count = 0;
% we need to assign a colour per point
for ii=1:nPoints
% and we need to assign a colour to the all the points
% at the head of the arrow
for jj=1:3
count = count + 1;
cd(1:3,count) = uint8(255*cmap(ii,:)'');
end
end
% set the colour binding method and the colour data of the head
set(h.Head, ''ColorBinding'',''interpolated'', ''ColorData'',cd)
Nota: No he hecho nada inteligente con la magnitud y simplemente cambio el color de cada carcaj en función del orden en la matriz original, pero debería poder hacerse una idea de cómo usar esta "función"