Save data at each iteration of for loop when looping through sub-matrices of 3D matrix

2 views (last 30 days)
I have a 3D matrix 24*3*776 called 'vert'. Each sub-matrix (eg 24*3) of the 3D matrix contains 24 XYZ points describing positions of cube vertices essentially representing the corners of connected cube faces. In this way the positions and boundaries of 776 cubes are defined.
I want to loop through the 24*3*776 matrix and determine which points from another matrix variable 'nodes' lie inside each cube (i.e. 24*3). 'Nodes' is a 302083*3 with XYZ positions in each respective column. Essentially, I want to see which points from 'nodes' fall within the boundaries of each 24*3 matrix (i.e. each cube) and then save those points as individual sets. This would leave me with 776 new 'node' sets.
My problem is that I cannot work out how to save a new node set at each iteration of the loop. I have the following code which works to a point but I only end up with just one node set being saved (from the first 24*3 matrix in the 3D matrix).
nodesx = nodes(:,2);
nodesy = nodes(:,3);
nodesz = nodes(:,4);
for k = 1:size(vert,3)
vert_cubes(:,:,(k)) = vert(:,:,(k));
for i = 1:length(nodes)
if nodesx(i) >min(vert_cubes(:,1)) & nodesx(i) <max(vert_cubes(:,1)) && nodesy(i) >min(vert_cubes(:,2)) & nodesy(i) <max(vert_cubes(:,2))&& nodesz(i) >min(vert_cubes(:,3)) & nodesz(i) <max(vert_cubes(:,3))
nodes_set1(i) = nodesx(i);
nodes_set_2(i) = nodesy(i);
nodes_set_3(i) = nodesz(i);
end
end
end
If I first take and define just one of the 24*3 matrices from the 3D matrix 'vert' and then run my loop, it works just fine (see code below) but I am hoping to avoid having to type this out 776 times! I also have 4 other samples with a similar amount of cubes so it would involve typing the same loop out over 3500 times and I feel there must be a better way!
vert1 = (vert(:,:,1));
for i = 1:length(nodes)
if nodesx(i)>min(vert1(:,1)) & nodesx(i)<max(vert1(:,1)) && nodesy(i)>min(vert1(:,2)) & nodesy(i)<max(vert1(:,2))&& nodesz(i)>min(vert1(:,3)) & nodesz(i)<max(vert1(:,3))
nodes_set_1(i) = nodesx(i);
nodes_set_2(i) = nodesy(i);
nodes_set_3(i) = nodesz(i);
end
end
I hope I've explained myself well enough and any help would be hugely appreciated. I've tried to alter my code in a number of ways but it doesn't work and I think I'm missing something simple (maybe not!).
  6 Comments
DC
DC on 2 Dec 2016
Hi Guillaume, because the same vertices are being used to define multiple faces so vertices are used more than once. Each face has 4 vertices so 6*4 is 24.

Sign in to comment.

Accepted Answer

Guillaume
Guillaume on 2 Dec 2016
Edited: Guillaume on 2 Dec 2016
If I understood correctly, you don't need a single for loop. However, I'm unclear why you have 24 vertices by cube, when only 8 are needed.
vert = randi([1 100], [24 3 776]); %demo random data
nodes = randi([1 100], [302083 3]); %demo random data
minbounds = min(vert); %minimum of vertices of each cube, produces a 1x3xncubes matrix
maxbounds = max(vert); %maximum of vertices of each cube, produces a 1x3xncubes matrix
isinbounds = squeeze(all(nodes > minbounds & nodes < minbounds, 2)); %In R2016b
%in previous versions:
%isinbounds = squeeze(all(bsxfun(@gt, nodes, minbounds) & bsxfun(@lt, nodes, maxbounds), 2));
The isinbounds matrix is a Npoints x Ncubes matrix, where 1 indicates that the point is in the cube and 0 it is not
  1 Comment
DC
DC on 2 Dec 2016
Hi Guillaume, your solution worked perfectly and is much nicer than my own attempt - thank you for the help, you've saved me a very prolonged headache! I understand your confusion about the cube vertices - it confused me initially too. I've essentially created a plot of cubes using the cube_plot function and extracted the coordinate data direct from the cube plot figure using handles = get(gca,'children'); vertices = get(handles,'Vertices');. So the '24*3' figure is basically just an artefact of the way this outputs the data. It is easier to just use the 24*3 defining each cube than it is to manipulate and condense the data first before doing other things to it. I hope that makes a little more sense

Sign in to comment.

More Answers (1)

KSSV
KSSV on 2 Dec 2016
How about this?
clc; clear all;
vert1 = (vert(:,:,1));
nodes_set_x = zeros(776,1) ;
nodes_set_y = zeros(776,1) ;
nodes_set_z = zeros(776,1) ;
count = 0 ;
for i = 1:length(nodes)
if nodesx(i)>min(vert1(:,1)) & nodesx(i)<max(vert1(:,1)) && nodesy(i)>min(vert1(:,2)) & nodesy(i)<max(vert1(:,2))&& nodesz(i)>min(vert1(:,3)) & nodesz(i)<max(vert1(:,3))
count = count+1 ;
nodes_set_x(count) = nodesx(i);
nodes_set_y(count) = nodesy(i);
nodes_set_z(count) = nodesz(i);
end
end
  1 Comment
DC
DC on 2 Dec 2016
Thanks for the help KSSV. Unfortunately your code produces the same output as mine... the node sets that are saved relate only to vert(:,:,1) rather than having multiple node sets relating to vert(:,:,1) through to vert(:,:,776). I will see if I can play with your code to see if it can do that...

Sign in to comment.

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!