I have a large dataset (several hundred thousand 3D points (x,y,z). I wish to display these points as cubes in Matlab (v. R2016a) (using the (x,y,z) points as the cube centroids). (The data points also have other attributes: A,B; which I wish to use to both colour the cubes and also dictate the 'alpha' or transparency of the cubes).
I have (mildly) adapted Olivers' PlotCube code from:
http://au.mathworks.com/matlabcentral/fileexchange/15161-plotcube
to implement a variable colour and transparency for each cube already, however trying to plot even a subset of the data (say 20,000 points) takes forever on this computer (2.5GHz i7, 16GB RAM +4GB GPU, 64-bit Windows 10). Also, once it is finally plotted (in a new Matlab figure window), I cannot rotate the object in 3D; its too (RAM? GPU?) intensive.
I have tried increasing the Java Heap Memory (from 128MB to 4GB) in case that was a bottleneck (to no avail):
Matlab > Home > Preferences > Matlab > General > Java Heap Memory
If all of the input variables only have a range from 0-255 (say) is it possible to change all data types from the standard 'double' (floating point integers) into uint8 format? (and thus impove computing/ graphics-display speed I guess).
Is there a way to change the PlotCube code to allow this? (uint8 or uint16 variables)
Note that the 'alpha' (transparency) values must lie within the range 0-1. (so is there a way for matlab to only store/use a uint8 precision for each point, but in decimal format within this range? As soon as I convert it to a decimal it goes back to 'double' type e.g. by dividing each value (0-255 range) by 255 to 'normalise' it: 0-1 range.)
Note that all computations in the code can easily be performed in 'double' data type format on the whole dataset; it is only the final data points to be plotted that (may) need to be in a smaller data format (to reduce memory requirements to plot and rotate 3D objects).
If there is a smarter way to plot/display large datasets of points in matlab (other-than/as-well-as changing the data type) I would much appreciate any advice!
I have read that 'pre-allocating' arrays in Matlab loops grants huge time savings*, however in the main 'for' loop (below) which I am using to plot all the points I am not sure how to implement pre-initialising.
% Run for loop for every point; an origin for each unique point.
% Note that edges, alpha and colour are all constant here for every point.
for i = 1:length(origin)
plotcube(edges,origin(i,:),alpha,[0 0 1])
end
Thanks for any help/advice!
The code for PlotCube (taken from the first url above) is:
function plotcube(varargin)
% PLOTCUBE - Display a 3D-cube in the current axes
%
% PLOTCUBE(EDGES,ORIGIN,ALPHA,COLOR) displays a 3D-cube in the current axes
% with the following properties:
% * EDGES : 3-elements vector that defines the length of cube edges
% * ORIGIN: 3-elements vector that defines the start point of the cube
% * ALPHA : scalar that defines the transparency of the cube faces (from 0
% to 1)
% * COLOR : 3-elements vector that defines the faces color of the cube
%
% Example:
% >> plotcube([5 5 5],[ 2 2 2],.8,[1 0 0]);
% >> plotcube([5 5 5],[10 10 10],.8,[0 1 0]);
% >> plotcube([5 5 5],[20 20 20],.8,[0 0 1]);
% Default input arguments
inArgs = { ...
[10 56 100] , ... % Default edge sizes (x,y and z)
[10 10 10] , ... % Default coordinates of the origin point of the cube
.7 , ... % Default alpha value for the cube's faces
[1 0 0] ... % Default Color for the cube
};
% Replace default input arguments by input values
inArgs(1:nargin) = varargin;
% Create all variables
[edges,origin,alpha,clr] = deal(inArgs{:});
XYZ = { ...
[0 0 0 0] [0 0 1 1] [0 1 1 0] ; ...
[1 1 1 1] [0 0 1 1] [0 1 1 0] ; ...
[0 1 1 0] [0 0 0 0] [0 0 1 1] ; ...
[0 1 1 0] [1 1 1 1] [0 0 1 1] ; ...
[0 1 1 0] [0 0 1 1] [0 0 0 0] ; ...
[0 1 1 0] [0 0 1 1] [1 1 1 1] ...
};
XYZ = mat2cell(...
cellfun( @(x,y,z) x*y+z , ...
XYZ , ...
repmat(mat2cell(edges,1,[1 1 1]),6,1) , ...
repmat(mat2cell(origin,1,[1 1 1]),6,1) , ...
'UniformOutput',false), ...
6,[1 1 1]);
cellfun(@patch,XYZ{1},XYZ{2},XYZ{3},...
repmat({clr},6,1),...
repmat({'FaceAlpha'},6,1),...
repmat({alpha},6,1)...
);
view(3);
The final outcome is to get something like Ben has achieved in the diagram here: