2015-04-14 22 views
10

Voglio il colore di ogni freccia in un grafico quiver3 da MATLAB per corrispondere alla grandezza di ogni freccia. C'è un modo per farlo?quiver3 freccia colore corrispondente alla grandezza

Ho visto alcuni esempi online che sono in grado di farlo per il 2D quiver, tuttavia nessuno di essi funziona per la variante 3D, quiver3.

Ho il seguente grafico e voglio sostituire le frecce blu con un colore corrispondente alla loro grandezza.

enter image description here

+0

Temo che la cosa migliore sarebbe modificare l'invio [this] (http://www.mathworks.com/matlabcentral/fileexchange/3225-quiverc) allo scambio di file per gestire il caso 3D ... –

risposta

17

Nel vecchio sistema grafico (R2014a e precedenti) questo non è possibile utilizzare il built-in quiver oggetto. Si può facilmente ottenere tutti gli oggetti di scena che vengono utilizzati per comporre la trama quiver

q = quiver(1:5, 1:5, 1:5, 1:5); 
handles = findall(q, 'type', 'line'); 

Ma le code sono tutti rappresentati da un oggetto trama, e le punte di freccia sono rappresentate da un altro. Pertanto, non è possibile modificare il colore di ciascuna testa/coda singolarmente.

set(handles(1), 'Color', 'r') 
set(handles(2), 'Color', 'g') 

enter image description here

Tuttavia, con l'introduzione di HG2 (R2014b e successive), si può effettivamente ottenere l'accesso a due (senza documenti) LineStrip oggetti (matlab.graphics.primitive.world.LineStrip) (uno rappresenta le teste e uno rappresenta le code). Questi sono accessibili tramite le proprietà nascoste Tail e Head.

q = quiver(1, 1, 1, 1); 
headLineStrip = q.Head; 
tailLineStrip = q.Tail; 

È quindi possibile modificare le proprietà del colore di questi oggetti per rendere ogni freccia di un colore diverso.

L'idea di base

Per fare questo, in primo luogo ho computo la grandezza di tutte le frecce della faretra (questo funziona per entrambi quiver e quiver3)

mags = sqrt(sum(cat(2, q.UData(:), q.VData(:), ... 
      reshape(q.WData, numel(q.UData), [])).^2, 2)); 

Allora io uso il colormap corrente di mappare ogni grandezza a un valore RGB. Alla freccia più corta viene assegnato il colore più basso sulla mappa colori e alla freccia più lunga viene assegnato il colore più alto sulla mappa colori. histcounts funziona perfettamente per assegnare a ciascuna grandezza un indice che può essere passato a ind2rgb insieme alla mappa colori stessa. Dobbiamo moltiplicare per 255 perché abbiamo bisogno che il colore sia RGB come un intero a 8 bit.

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

Il LineStripColorData struttura (quando specificato come truecolor) deve anche avere un canale alfa (che verrà impostato su 255 significa opaco).

cmap(:,:,4) = 255; 

A questo punto si può quindi impostare la proprietà ColorBinding a interpolated anziché object (per disaccoppiare dall'oggetto quiver) e impostare la proprietà ColorData sia q.Head e q.Tail ai colori abbiamo creato sopra dando ciascuna freccia è il proprio colore

Soluzione completa

NOTA: Questa soluzione funziona per siaquiver e quiver3 e il codice non deve essere adattato a tutti.

%// 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).'); 

enter image description here

e applicato a un oggetto 2D quiver

enter image description here

Se non necessariamente vuole scalare le frecce per l'intera gamma della mappa di colori è possibile utilizzare la dopo la chiamata a histcounts (anziché la riga precedente) per mappare le magnitudini utilizzando i limiti di colore degli assi.

clims = num2cell(get(gca, 'clim')); 
[~, ~, ind] = histcounts(mags, linspace(clims{:}, size(currentColormap, 1))); 
6

Se la vostra utilizzando una versione post r2014b è possibile utilizzare funzioni non documentate per cambiare il colore di ogni linea e la testa:

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: io non ho fatto nulla di intelligente con la grandezza e semplicemente cambiare il colore di ogni faretra in base all'ordine nella matrice originale - ma si dovrebbe essere in grado di ottenere l'idea su come utilizzare questa "caratteristica"

enter image description here