Create voxels from a sphere pack and store as boolean - voxel

I'm trying to convert my output file from my matlab code that has an output of position vectors and sphere radius. I intend to create voxels from these spheres and store in boolean form i.e 1 for sphere, 0 for void. Please how do you advise I go about this. Here's an example of the output.
Pos (x) , Pos (y), Pos (z) Radius
-0.34316 -0.18477 -0.00897 0.0900
-0.18425 -0.20463 0.08040 0.020
-0.46883 -0.49809 0.36954 0.020
0.24727 -0.19437 -0.28274 0.0876
0.39771 0.49293 -0.49469 0.0200
-0.04368 0.26251 -0.07504 0.0200
-0.34705 0.04092 0.37070 0.0200
Here's a snippet of the matlab code I'm working with. The spheres are originally in a lattice space.Thanks
coords=zeros(N,3); % list of the 3D positions of all particles
overlap=(6*phi/(pi*N))^(1/3);
% create initial, evenly-spaced lattice
numcell=(ceil(N^(1/3)));
cellside=1/numcell;
hh=linspace(-.5+.5*cellside,.5-.5*cellside,numcell);
for ii=1:N
coords(ii,1)=hh(ceil(ii/ceil(N/numcell)));
coords(ii,2)=hh(floor(mod(ii,ceil(N/numcell))/numcell)+1);
coords(ii,3)=hh(mod(ii,numcell)+1);
end
scatter3(coords(:,1),coords(:,2),coords(:,3),'filled');

Related

Matlab: adding multiple 3D cartesian coordinate axes within a 3D plot

Getting right to the question: How can I make my plot go from looking like this:
to something like this:
where a right-handed Cartesian coordinate system (with axis labels at the end of the arrows, e.g., in this example the x-axis label is = $x_1^G$)
Some elaboration and prefacing: First, I am new to matlab and "matrix math". I tried searching on this site for questions similar to what I have posed above but did not see anything (but I may have missed), so hopefully this is not a duplicate.
Here is the code I have used to develop my rotated ellipsoid (since I'm new to matlab I would appreciate any comments on my code):
%Insert the components of the 3x3 matrix (i.e. the scalar values of the 2nd-rank symmetric tensor)
Pmatrix = [115.9547 12.03765 4.68235; 12.03765 116.3702 -2.47985; 4.68235 -2.47985 134.5488];
[R,D]=eig(Pmatrix); %find the eigenvectors (R) and eigenvalues (D) of the 2nd-rank tensor
[x, y, z] =sphere; %generate coordinates of a sphere, using the sphere command
%Stretch the coordinates of the sphere to form the tensor's representation ellipsoid, do this by multiplying the x, y, z coordinates by the square-roots of the eigenvalues
x1 = x*sqrt(D(1,1));
y1 = y*sqrt(D(2,2));
z1 = z*sqrt(D(3,3));
figure;
hmesh = mesh(x1,y1,z1);
set(hmesh,'FaceColor',[0.5,0.5,0.5],'FaceAlpha',0.5) %set color to gray, make mostly transparent
axis equal; %Make tick mark increments on all axes equal
xlabel('x');
ylabel('y');
zlabel('z');
theta1 = -asind(R(3,1)); %rotation around y-axis in degrees
psi1 = atan2d(R(3,2)/cos(theta1),R(3,3)/cos(theta1)); %rotation around x-axis in degrees
phi1 = atan2d(R(2,1)/cos(theta1),R(1,1)/cos(theta1)); %rotation around z-axis in degress
direction = [1 0 0]; %rotate the surface plot psi1 degrees around its x-axis
rotate(hmesh,direction,psi1)
direction = [0 1 0]; %rotate the surface plot theta1 degrees around its y-axis
rotate(hmesh,direction,theta1)
direction = [0 0 1]; %rotate the surface plot phi1 degrees around its z-axis
rotate(hmesh,direction,phi1)
view([-36 18]); %Change the camera viewpoint
To add to my question, I would like to add other (similar) items to my plot, so that the final product would look like this:
In the development of the image above, a set of axes collinear with the ellipsoid's eigenvectors are added (the red, green, blue arrows):
Then these axes are extended in the opposite direction, through the origin, where these portions of the axes are shown as a dashed lines:
Then, the angles between the global coordinate axes (black arrows) and the ellipsoid's axes (colored arrows) are notated as shown here:
To comment on this last addition, someone has built some matlab code with these features (see youtube video here). In the video's description it says the matlab code can be found here. Being new to matlab, I don't see where the code is, e.g., I don't see where on this page (screenshot below) the code is to build that matlab plot seen in the youtube video. If you can guide me on how to navigate that mathworks-fileexchage page that would be appreciated.

Matlab, visualize 3D rotational matrix

I have a target coordinate (xyz) within a 3D rectangle. The target coordinate is set assuming the 3D rectangle is in a flat plane with x,y,z. The target coordinate is set to be on one terminal end of the rectangle, with the 'y' component set to be -2 from the top of the 3D square (Refer to image). However, in reality the 3D rectangle is not in a flat plane with x,y,z axes, it is skewed. We calculate the skew by measuring two reference points on the top surface of the rectangle and now want to recalculate the target coordinate. I do not know how to ensure I am computing the skew correctly or (more importantly) plot the old vs new 3D rectangle and target coordinate. Below is code to generate both the matrix and the target within said matrix.
For the two reference points used to calculate the skew of the 3D rectangle, we name one 'bregma' and one 'lamda'.
%% CONVENTIONS:
%1) numbers get lower when
% 1) going to left on x axis
% 2) going down y axis
% 3) going posterior (or towards you) on z axis,
% opposite of convention
%2) coordinate order is AP (anterior posterior), ML
%(medial lateral), DV
%(dorsal ventral)
%Bregma is the anterior reference point and
%Lambda is posterior reference point . The goal variables
%are the point in space I want to reach. I'm hoping the code creates new
%points for me as caused by a change in elevation between point "c" and "f"
%Note, for AP/ML/DV absolute values, the actual integers %are merely
%reference points in space. It is the delta between AP %and AP or ML and ML
%that is meaningful
%values a-f would be acquired from the stereotaxic frame
a= 43; %AP at bregma
b= 20; %ML at bregma
c= 22; %DV at bregma
d= 38.8; %AP at lambda
e= 20; %ML at Lambda
f= 21.5; %DV at lamda This variable causes the change %in which I want the rotation to correct
%Bregma =[b a c];
%Following three points are given relative to bregma, this is convention. So mathematically 'Bregma=[0 0 0];'
%These are also the coordinates I want altered from the rotation matrix
MLgoal=0; %ML to injection
APgoal=0; %AP to injection
DVgoal=-2.0; %DV to injection
DVgoal_zaxis_signconvention_correction = -DVgoal; %we want sign convention flipped for z axis[![enter image description here][1]][1]
A= a-d;
M= b-e;
D= c-f;
%Bregma =[0 0 0];
v = [A M D];
mv = norm(v);
u=[A 0 0]; %theoretical vector [ML,AP,DV] bregma to %lambda
mu = norm(u);
%angle in radians
X=acos(dot(u,v)/(mu*mv));
cu=cross(u,v);
w=cu/norm(cu); %unit vector
%rotate about this unit vector by angle X
wx=w(1);
wy=w(2);
wz=w(3);
%sustitute variables into general rotation for more %readable code
vx = 1-cos(X);
cx = cos(X);
sx = sin(X);
%rotation matrix about arbitrary unit vector [wx; wy; %wz] by angle X
r=[vx*wx*wx + cx, vx*wx*wy - wz*sx, vx*wx*wz + wy*sx;
vx*wx*wy + wz*sx, vx*wy*wy + cx, vx*wy*wz - wx*sx;
vx*wx*wz - wy*sx, vx*wy*wz + wx*sx, vx*wz*wz + cx];
%Newcoordinate output should tell you the change in %targeting coordinate
%after correcting for the output of rotational matrix. %The value for DV
%seems too large based on the subtle increase elevation %of reference point
%Bregma to reference point Lambda
Newcoordinates=r* [APgoal;MLgoal;DVgoal_zaxis_signconvention_correction]; %should give you the new coordinates for the injection %site

How to create a 2D image by rotating 1D vector of numbers around its center element?

I have 1D vector of numbers which represents a center cut of a circular symmetric object. The vector itself is symmetric around its center element. I want to create in MATLAB a 2D image of the original object by rotating the 1D vector around its center element.
I tried the following code (with a dummy original vector of numbers) , but the center cut I get from the generated 2D image does not match the original 1D vector, as can be seen if you run the code.
I'll appreciate any help !!!
close all; clc
my1D_vector=[ zeros(1,20) ones(1,15) zeros(1,20)]; % original vector
len=length(my1D_vector);
img=zeros(len, len);
thetaVec=0:0.1:179.9; % angles through which to rotate the original vector
numRotations=length(thetaVec);
% the coordinates of the original vector and the generated 2D image:
x=(1:len)-(floor(len/2)+1);
y=x;
[X,Y]=meshgrid(x,y);
for ind_rotations=1:numRotations
theta=pi/180*thetaVec(ind_rotations);
t_theta=X.*cos(theta)+Y.*sin(theta);
cutContrib=interp1(x , my1D_vector , t_theta(:),'linear');
img=img+reshape(cutContrib,len,len);
end
img=img/numRotations;
figure('name','original vector');plot(x,my1D_vector,'b.-')
figure('name','generated 2D image'); imagesc(x,y,img); colormap(gray) ;
figure('name','comparison between the original vector and a center cut from the generated 2D image');
plot(x,my1D_vector,'b.-')
hold on
plot(x,img(find(x==0),:),'m.-')
legend('original 1D vector','a center cut from the generated 2D image')
I didn't follow your code but how about this:
V = [ zeros(1,20) ones(1,15) zeros(1,20)]; % Any symmetrical vector
n = floor(numel(V)/2);
r = [n:-1:0, 1:n]; % A vector of distance (measured in pixels) from the center of vector V to each element of V
% Now find the distance of each element of a square 2D matrix from it's centre. #(x,y)(sqrt(x.^2+y.^2)) is just the Euclidean distance function.
ri = bsxfun(#(x,y)(sqrt(x.^2+y.^2)),r,r');
% Now use those distance matrices to interpole V
img = interp1(r(1:n+1),V(1:n+1),ri);
% The corners will contain NaN because they are further than any point we had data for so we get rid of the NaNs
img(isnan(img)) = 0; % or instead of zero, whatever you want your background colour to be
So instead of interpolating on the angle, I interpolate on the radius. So r represents a vector of the distance from the centre of each of the elements of V, in 1D. ri then represents the distance from the centre in 2D and these are the values we want to interpolate to. I then only use half of r and V because they are symmetrical.
You might want to set all the NaNs to 0 afterwards because you can't interpolate the corners because their radius is larger than the radius of your furthest point in V.
Using your plotting code I get
and
The blue and magenta curves overlap exactly.
Explanation
Imagine that your vector, V, was only a 1-by-5 vector. Then this diagram shows what r and ri would be:
I didn't mark it on the diagram but r' would be the middle column. Now from the code we have
ri = bsxfun(#(x,y)(sqrt(x.^2+y.^2)),r,r');
and according to the diagram r = [2,1,0,1,2] so now for each pixel we have the euclidean distance from the centre so pixel (1,1) is going to be sqrt(r(1).^2+r(1).^2) which is sqrt(2.^2+2.^2) which is sqrt(8) as shown in the diagram.
Also you will notice that I have "greyed" out the corners pixels. These pixels are further from the centre than any point we have data for because the maximum radius (distance from the centre) of our data is 2 but sqrt(8) > sqrt(5) > 2 so you can't interpolate those data, you would have to extrapolate to get values for them. interp1 returns NaN for these points.
Why does the interpolation work? Think of the position of each pixel as referring to the centre of the pixel. Now in this diagram, the red circle is what happens when you rotate the outer elements (i.e. r==2) and the green is rotating the elements 1 further in (i.e. r==1). You'll see that the pixel that gets the distance of sqrt(2) (blue arrow) lies between these two radii when we rotate them and so we have to interpolate that distance between those two pixels.

Delaunay() function MATLAB Purpose

I want to generate triangle meshes in MATLAB with the delaunay function in 2-D. So I declare
the X- and Y- values and set tri=delaunay(X,Y). Then I use triplot to plot it. However,
what does tri give me? Does it give each of my triangle a special designation number?
After reading through some of the MATLAB tutorials I still DON'T
understand it.
The delaunay function returns tri as an Mx3 matrix of triangle connectivity, where each of the M triangles is represented as an integer triplet that indexes into the X,Y vertex position arrays.
It's probably easier with a simple example:
%% a simple square box
X = [0.0; 1.0; 1.0; 0.0];
Y = [0.0; 0.0; 1.0; 1.0];
%% an example output from delaunay()
tri = [1,2,3 %% 1st triangle connects vertices 1,2,3
1,3,4 %% 2nd triangle connects vertices 1,3,4
];
The triangles are just numbered linearly - tri(1,:) is the first triangle, tri(n,:) is the nth triangle etc. If you wanted to re-order the list of traingles you could permute the array, but the indexing would always have to be linear - if there are M triangles the indexing must encompass 1:M.
Hope this helps.

Coloring sectors in MATLAB

I am trying to animate a ball bouncing but having trouble creating a basic multicolor ball i can then rotate as a whole in each frame. I have 512 points on the circumference of the ball split into 8 sectors, each a separate color. So far I have 2 matrices that are 8x64, representing the x and the y coordinates of points along the circumference of the ball, each of the rows being the its own sector.
I want to know how to fill these "ranges" along the circle such that it will look like a beach ball, creating a function to do this with the two x and y coordinate matrices as inputs. Your help would be greatly appreciated!
Basic skeleton function:
% Expects 8xN x and y point matrices
function draw_ball(x,y)
% Draw the 8 sectors filling them with unique colors
end
You want to create a PATCH with draw_ball. The nicest way to do this would require you to have the data stored as faces and vertices, but you if you like to keep your 8xN arrays, you can instead create 8 patches that describe the ball.
This way, your function would look like this:
function pH = drawBall(x,y)
%# count sectors
nSectors = size(x,1);
%# create a colormap
ballColors = jet(nSectors);
%# set hold-state of current axes to 'on'
set(gca,'nextPlot','add')
%# initialize array of plot handles
pH = zeros(nSectors,1);
%# add [0,0] to every sector
x = [x,zeros(nSectors,1)];
y = [y,zeros(nSectors,1)];
%# plot patches
for s = 1:nSectors
%# plot sectors with black lines. If there shouldn't be lines, put 'none' instead of 'k'
pH(s) = patch(x(s,:),y(s,:),ballColors(s,:),'EdgeColor','k');
end
The function could begin by transforming the (x,y) coordinate system (Cartesian) into the polar coordinate system, where an angle of each point is available. The associated matlab function is cart2pol
After tranforming to polar, you could use floor to split the points into 8 sectors... something along the line of floor(polar_anle_in_radians/(2*pi)*8)