Plotting A Large Number Of Patches

12 views (last 30 days)
There are a few older topics on this, but nothing I could find which is directly relevent I don't think. I'm utilising a modified version of: Olivier (2020). PLOTCUBE ( https://www.mathworks.com/matlabcentral/fileexchange/15161-plotcube ), MATLAB Central File Exchange to plot some images of a cubic discretisation e.g:
function PLOTTER(Coords,objprop)
for index = 1:length(Coords.Lo.X(:))
plotcube([Coords.dX;Coords.dY;Coords.dZ]'...
,[Coords.Lo.X(index);Coords.Lo.Y(index);Coords.Lo.Z(index)]',...
.5,objprop(index)); hold on;
%Object Prop Defines Colormap
end
end
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);
I'm encountering two issues, both which I believe are related to the fact I'm rendering this using many patches.
First, if I have a large number of cubes, I'm no longer able to interact with the figure (but there's no obvious CPU/GPU strain either: 4690K 4.7GHz overclock + GTX 1060).
Secondly, when I'm comparing a large number of algorithms i.e producing many plots, I'm finding MATLAB crashes or encounters low-level graphics errors once I reach around 30 plots (216 cubes per plot).
I think this is likely poor coding/utilisation of MATLAB visualisation abilities rather than a case of MATLAB being unable to achieve my intention. Any thoughts on a more efficient way to render these plots, particularily for larger numbers of cubes would be greatly appreciated, noting the transpancy of the cubes is important to be able to visulise any internal structures.

Accepted Answer

Kelly Kearney
Kelly Kearney on 16 Oct 2020
Creating a single multi-faceted patch is much, much more efficient than plotting lots of single-face patches. In the figure you show, you're plotting 216 cubes, with 6 faces each, for a total of 1296 faces. Using the code above, you're creating that many individual patch objects, and each one comes with a lot of graphics overhead.
Instead, plot one patch with 1296 faces:
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] ...
};
% Faces for a single unit cube (6 faces)
xcube = cat(1, XYZ{:,1})';
ycube = cat(1, XYZ{:,2})';
zcube = cat(1, XYZ{:,3})';
% Many cubes
[x0, y0, z0] = ndgrid(1:6); % corner coordinates
col = zeros(size(x0)); % color index
col(:,:,end) = 2;
xall = arrayfun(@(a) a+xcube, x0(:), 'uni', 0);
yall = arrayfun(@(a) a+ycube, y0(:), 'uni', 0);
zall = arrayfun(@(a) a+zcube, z0(:), 'uni', 0);
xall = cat(2, xall{:});
yall = cat(2, yall{:});
zall = cat(2, zall{:});
col = kron(col(:)', ones(1,6)); % expand colors to all 6 faces
% Plot
p = patch(xall, yall, zall, col, 'facealpha', 0.1);
view(3);
  3 Comments
Kelly Kearney
Kelly Kearney on 19 Oct 2020
Just looking at it quickly (haven't tested the code), I would suggest updating the xall/yall/zall equation to:
xall = arrayfun(@(a,b) a+xcube.*b, x0(:), dx(:), 'uni', 0);
where dx is an array the same size as x0, specifying the length of each cube in the x direction. And repeat the same for the y and z dimensions.
ADSW121365
ADSW121365 on 19 Oct 2020
Edited: ADSW121365 on 19 Oct 2020
Worked like a charm, thanks so much! I can plot 216000 cubes and still manipulate my figure!

Sign in to comment.

More Answers (0)

Categories

Find more on Graphics Object Programming in Help Center and File Exchange

Products


Release

R2020a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!