5 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.

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

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.

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

Start Hunting!
## 0 Comments

Sign in to comment.