How to set a point to change color in colorbar

30 views (last 30 days)
I want to use scatter3 with particles and want to have different color for positive and negative values of charge or velocities. I use this code through a Simulink prototype " Spiral Galaxy Formation Simulation "
oldPlot = scatter3(points_x,points_y,points_z,psize,points_col,'filled')
cmap = [1 0 0 ; 0 1 0 ] ; %2 color bar
colorbar;
colormap(cmap)
but when positive or negative gets higher values, then 0 is not the point that the color changes, but it moves towards the middle of the min and max value.
I want all positive to be green and all negative to be red.
I tried this code
cm=colormap;
cm(0,:)= [1 0 0];
colorbar;
colormap(cm)
but it doesn't seem to work.
Christos Dimopoulos on 1 Jan 2018
I am not sure. I have tried that too, but it doesn't suit the project as you can see from the code...
for i = 1:n,
points_x(i) = bodies(i,2);
points_y(i) = bodies(i,3);
points_z(i) = bodies(i,4);
MassRange=(log10(abs(bodies(i,1)))-41.0)*500; % /SolarMass;
psize(i)=MassRange; % bodies(i,1)/(10e7*SolarMass);
points_col(i) = bodies(i,1)/SolarMass ; % MassRange
end
% Remove the old plot.
if isempty(oldPlot)
oldPlot = fig;
elseif ~isempty(foundFig)
cla
% delete(oldPlot);
end
oldPlot = scatter3(points_x,points_y,points_z,psize,points_col,'filled')
I think I need one plot because I compare particles, sizes, I have to make them interact between each other.

Image Analyst on 1 Jan 2018
Edited: Image Analyst on 1 Jan 2018
Try this:
% Initialization/clean up
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format short g;
format compact;
fontSize = 13;
numPoints = 100;
points_x = rand(1,numPoints) - 0.5;
points_y = rand(1,numPoints) - 0.5;
points_z = rand(1,numPoints) - 0.5;
psize = 40;
% User wants "all positive to be green and all negative to be red."
% First default to all black;
points_col = zeros(numPoints, 3);
% Now find where ALL 3 coords are positive;
allPosIndexes = points_x > 0 & points_y > 0 & points_z > 0;
% Set those to green.
points_col(allPosIndexes, 2) = 1;
% Now find where ALL 3 coords are negative;
allNegIndexes = points_x < 0 & points_y < 0 & points_z < 0;
% Set those to red.
points_col(allNegIndexes, 1) = 1;
% Now one octant will be red, one octant will be green
% and 6 octants will be black.
% Now plot.
oldPlot = scatter3(points_x,points_y,points_z,psize,points_col,'filled')
xlabel('X', 'FontSize', fontSize);
ylabel('Y', 'FontSize', fontSize);
zlabel('Z', 'FontSize', fontSize);
Image Analyst on 18 Jan 2018
I've added Simulink to the Product list on the right hand side, so that others don't have to waste their time if they don't (like me) have Simulink. I'd say a minority of people here even have Simulink, so when people have a Simulink program, or any program that requires function available only in a certain toolbox or product they list that in the Products section. You might also attach the .mdl file to your original question up top.

Christos Dimopoulos on 2 Jan 2018
Thank you. I tried to "embed" your code in mine, but it doesn't seem to work. Can you see what's wrong please?
function PlotAll(bodies)
persistent fig;
persistent oldPlot;
coder.extrinsic('findobj','get','set','figure','clf','hold','text',...
'colorbar','drawnow','getframe', 'VideoWriter', 'writeVideo',...
'open', 'M','num2str', 'cm');
n = size(bodies,1);
SpeedOfLight = 299792458; % in m/s
YearInSeconds = 365*24*60*60;
ShowStep = 20;
LightYear = SpeedOfLight*YearInSeconds;
Parsec = 3.26*LightYear;
SolarMass = 1.9891e+30;
foundFig = findobj('Tag','galaxyScreen');
if isempty(fig)||isempty(foundFig)
if isempty(foundFig)
fig = figure;
else
fig = figure(foundFig);
end;
clf(fig);
set(fig, 'Name', 'Simulation');
end
points_x = zeros(1,n);
points_y = zeros(1,n);
points_z = zeros(1,n);
points_mass = zeros(1,n);
psize = zeros(1,n);
% User wants "all positive to be green and all negative to be red."
% First default to all black;
points_col = zeros(n, 3);
for i = 1:n,
points_x(i) = bodies(i,2);
points_y(i) = bodies(i,3);
points_z(i) = bodies(i,4);
points_mass(i) = bodies(i,1);
MassRange=(log10(abs(bodies(i,1)))-41.0)*200; % /SolarMass;
if MassRange<=4,
MassRange=4;
end
psize(i)=MassRange; % bodies(i,1)/(10e7*SolarMass);
end
% Now find where ALL 3 coords are positive;
allPosIndexes = points_mass > 0 ;
% Set those to green.
points_col(allPosIndexes, 2) = 1;
% Now find where ALL 3 coords are negative;
allNegIndexes = points_mass < 0;
% Set those to red.
points_col(allNegIndexes, 1) = 1;
% Remove the old plot.
%
if isempty(oldPlot)
oldPlot = fig;
ShowStep=ShowStep+1;
elseif ~isempty(foundFig)
cla
ShowStep=ShowStep+1;
% delete(oldPlot);
end
oldPlot = scatter3(points_x,points_y,points_z,psize,points_col,'filled')
%colormap([repmat([0 1 0],-10e10,0); repmat([1 1 0],-10e10,0)]);
%cm=colormap;
%cm(0,:)= [1 1 1];
%cmap = [1 0 0 ; 0 1 0 ] ; %3 color bar
colorbar('color','w');
drawnow
It gives me error message...
Logical indexing requires support of variable-sized arrays, which is currently disabled.
Function 'Plot all bodies' (#521.2202.2215), line 89, column 12: "allPosIndexes"
And the same for "allNegIndexes"
_____
Isn't there any easy way to just put the limit to 0 for the 2 colors?
I think the new proposal is way too complicated.
But if we can make it work, it is worth the effort.