matlab - quiver3 arrow color corresponding to magnitude -


i want color of each arrow in quiver3 plot matlab correspond magnitude of each arrow. there way that?

i saw few examples online able 2d quiver, none of them work 3d variant, quiver3.

i have following plot , want replace blue arrows color corresponding magnitude.

enter image description here

in old graphics system (r2014a , earlier) not possible using built-in quiver object. can of plot objects used compose quiver plot

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

but tails represented 1 plot object, , arrow heads represented another. such, can't alter color of each head/tail individually.

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

enter image description here

however, introduction of hg2 (r2014b , later), can access two (undocumented) linestrip objects (matlab.graphics.primitive.world.linestrip) (one represents heads , 1 represents tails). these accessible via hidden properties tail , head.

q = quiver(1, 1, 1, 1); headlinestrip = q.head; taillinestrip = q.tail; 

you can alter color properties of these objects make each arrow different color.

the basic idea

to this, first compute magnitude of quiver arrows (this works both quiver , quiver3)

mags = sqrt(sum(cat(2, q.udata(:), q.vdata(:), ...             reshape(q.wdata, numel(q.udata), [])).^2, 2)); 

then use current colormap map each magnitude rgb value. shortest arrow assigned lowest color on colormap , longest arrow assigned highest color on colormap. histcounts works great assigning each magnitude index can passed ind2rgb along colormap itself. have multiply 255 because need color rgb 8-bit integer.

% current colormap currentcolormap = colormap(gca);  % determine color make each arrow using colormap [~, ~, ind] = histcounts(mags, size(currentcolormap, 1));  % map colormap cmap = uint8(ind2rgb(ind(:), currentcolormap) * 255); 

the linestrip colordata property (when specified truecolor) needs have alpha channel (which set 255 meaning opaque).

cmap(:,:,4) = 255; 

at point can set colorbinding property interpolated rather object (to decouple quiver object) , set colordata property of both q.head , q.tail colors created above giving each arrow it's own color.

full solution

note: solution works both quiver , quiver3 , code not have adapted @ all.

%// create quiver3 (could 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 magnitude of vectors mags = sqrt(sum(cat(2, q.udata(:), q.vdata(:), ...             reshape(q.wdata, numel(q.udata), [])).^2, 2));  %// current colormap currentcolormap = colormap(gca);  %// determine color make each arrow using colormap [~, ~, ind] = histcounts(mags, size(currentcolormap, 1));  %// map colormap rgb cmap = uint8(ind2rgb(ind(:), currentcolormap) * 255); cmap(:,:,4) = 255; cmap = permute(repmat(cmap, [1 3 1]), [2 1 3]);  %// 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).');   %'  %// 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

and applied 2d quiver object

enter image description here

if don't want scale arrows entire range of colormap use following call histcounts (instead of line above) map magnitudes using color limits of axes.

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

Comments

Popular posts from this blog

css - SVG using textPath a symbol not rendering in Firefox -

Java 8 + Maven Javadoc plugin: Error fetching URL -

node.js - How to abort query on demand using Neo4j drivers -