MATLAB surface from rotated closed curves - matlab

Essentially I am trying to create a volume by rotating a closed curve. I have attempted to use cylinder to achieve this, but I am getting undesirable results. I also have tried directly using surf. Here are those two attempts (newEl defined below).
elPatternPlot = plot3(newEl(:,1),newEl(:,2),newEl(:,3),'gr-','LineWidth',0.5);
xlabel('x')
ylabel('y')
zlabel('z')
grid on
Next, I rotate the 2D closed curve to the correct angle.
rotate(elPatternPlot, [1 0 0], 90);
To generate data points in the desired volume, I use rotate:
% Now rotate around z and store in the data
axObjs = azElFig.Children;
dataObjs = axObjs.Children;
xElData = dataObjs(1).XData;
yElData = dataObjs(1).YData;
zElData = dataObjs(1).ZData;
for a1=1:5:180
rotate(elPatternPlot, [0 0 1], a1);
axObjs = azElFig.Children;
dataObjs = axObjs.Children;
xElData = [xElData dataObjs(1).XData];
yElData = [yElData dataObjs(1).YData];
zElData = [zElData dataObjs(1).ZData];
end
plot3(xElData,yElData,zElData,'r-','LineWidth',0.5)
And the result:
This this yields the correct outside geometry, but I am seeking to create a volume. From here I use surf:
xv = linspace(min(xElData), max(xElData), 150);
yv = linspace(min(yElData), max(yElData), 150);
[X, Y] = meshgrid(xv, yv);
Z = griddata(xElData,yElData,zElData,X,Y);
figure; surf(X,Y,Z);
The output is:
Using cylinder,
[x,y,z] = cylinder(Z);
figure; surf(x,y,z)
I obtain:
The desired surface should look more like (from the bottom):
And from the side, a filled in version of this:
newEl =
-906.5000 -36.5000 0
-909.5000 -65.5000 0
-903.5000 -91.5000 0
-891.5000 -139.5000 0
-877.5000 -203.5000 0
-863.5000 -238.5000 0
-855.5000 -254.5000 0
-847.5000 -269.5000 0
-839.5000 -284.5000 0
-784.5000 -369.5000 0
-771.5000 -384.5000 0
-746.5000 -406.5000 0
-733.5000 -421.5000 0
-695.5000 -457.5000 0
-668.5000 -479.5000 0
-641.5000 -496.5000 0
-614.5000 -513.5000 0
-600.5000 -525.5000 0
-573.5000 -544.5000 0
-561.5000 -549.5000 0
-549.5000 -553.5000 0
-488.5000 -579.5000 0
-474.5000 -585.5000 0
-460.5000 -592.5000 0
-446.5000 -599.5000 0
-417.5000 -603.5000 0
-388.5000 -607.5000 0
-293.5000 -611.5000 0
-277.5000 -608.5000 0
-246.5000 -597.5000 0
-231.5000 -593.5000 0
-187.5000 -578.5000 0
-160.5000 -553.5000 0
-133.5000 -528.5000 0
-120.5000 -512.5000 0
-85.5000 -478.5000 0
-61.5000 -428.5000 0
-56.5000 -411.5000 0
-47.5000 -359.5000 0
-42.5000 -342.5000 0
-33.5000 -289.5000 0
-28.5000 -271.5000 0
-19.5000 -220.5000 0
-14.5000 -202.5000 0
-5.5000 -149.5000 0
-0.5000 -132.5000 0
4.5000 -128.5000 0
9.5000 -161.5000 0
18.5000 -194.5000 0
23.5000 -226.5000 0
32.5000 -261.5000 0
37.5000 -293.5000 0
42.5000 -324.5000 0
51.5000 -359.5000 0
56.5000 -390.5000 0
65.5000 -426.5000 0
70.5000 -455.5000 0
125.5000 -517.5000 0
138.5000 -528.5000 0
165.5000 -556.5000 0
178.5000 -567.5000 0
192.5000 -578.5000 0
207.5000 -585.5000 0
251.5000 -596.5000 0
267.5000 -604.5000 0
298.5000 -611.5000 0
393.5000 -607.5000 0
422.5000 -602.5000 0
451.5000 -597.5000 0
465.5000 -592.5000 0
479.5000 -586.5000 0
493.5000 -580.5000 0
530.5000 -565.5000 0
542.5000 -559.5000 0
554.5000 -552.5000 0
592.5000 -534.5000 0
619.5000 -515.5000 0
646.5000 -496.5000 0
673.5000 -477.5000 0
725.5000 -430.5000 0
738.5000 -419.5000 0
776.5000 -379.5000 0
789.5000 -368.5000 0
801.5000 -353.5000 0
811.5000 -336.5000 0
836.5000 -292.5000 0
844.5000 -279.5000 0
852.5000 -268.5000 0
860.5000 -253.5000 0
881.5000 -200.5000 0
886.5000 -184.5000 0
891.5000 -167.5000 0
895.5000 -146.5000 0
902.5000 -104.5000 0
907.5000 -90.5000 0
909.5000 -46.5000 0
904.5000 6.5000 0
899.5000 58.5000 0
897.5000 60.5000 0
875.5000 126.5000 0
867.5000 142.5000 0
828.5000 208.5000 0
820.5000 224.5000 0
763.5000 276.5000 0
750.5000 289.5000 0
712.5000 319.5000 0
699.5000 332.5000 0
686.5000 341.5000 0
659.5000 360.5000 0
632.5000 378.5000 0
605.5000 396.5000 0
578.5000 416.5000 0
566.5000 431.5000 0
517.5000 496.5000 0
505.5000 509.5000 0
436.5000 567.5000 0
407.5000 587.5000 0
377.5000 603.5000 0
361.5000 604.5000 0
345.5000 606.5000 0
329.5000 607.5000 0
313.5000 608.5000 0
282.5000 610.5000 0
236.5000 606.5000 0
221.5000 601.5000 0
151.5000 567.5000 0
111.5000 547.5000 0
100.5000 533.5000 0
89.5000 520.5000 0
79.5000 500.5000 0
60.5000 477.5000 0
46.5000 454.5000 0
27.5000 427.5000 0
13.5000 403.5000 0
-10.5000 403.5000 0
-24.5000 423.5000 0
-38.5000 444.5000 0
-52.5000 465.5000 0
-66.5000 486.5000 0
-75.5000 502.5000 0
-96.5000 531.5000 0
-107.5000 548.5000 0
-147.5000 566.5000 0
-174.5000 581.5000 0
-202.5000 591.5000 0
-217.5000 600.5000 0
-262.5000 611.5000 0
-309.5000 607.5000 0
-325.5000 607.5000 0
-341.5000 606.5000 0
-357.5000 604.5000 0
-373.5000 603.5000 0
-403.5000 587.5000 0
-432.5000 566.5000 0
-501.5000 511.5000 0
-513.5000 494.5000 0
-525.5000 478.5000 0
-537.5000 463.5000 0
-587.5000 407.5000 0
-628.5000 380.5000 0
-655.5000 361.5000 0
-682.5000 341.5000 0
-708.5000 320.5000 0
-721.5000 311.5000 0
-759.5000 277.5000 0
-797.5000 244.5000 0
-807.5000 237.5000 0
-816.5000 224.5000 0
-824.5000 213.5000 0
-832.5000 199.5000 0
-871.5000 124.5000 0
-882.5000 104.5000 0
-887.5000 98.5000 0
-894.5000 72.5000 0
-896.5000 37.5000 0
-899.5000 34.5000 0
-901.5000 1.5000 0
-906.5000 -36.5000 0

You almost had it right. The problem is within how you rotate inside the for loop.
Your code:
for a1=1:5:180
rotate(elPatternPlot, [0 0 1], a1);
...
end
a1 is incremented by 5 as it iterates. Therefore, you are not rotating it by a step of 5.
To fix this, simply change
rotate(elPatternPlot, [0 0 1], a1);
to
rotate(elPatternPlot, [0 0 1], 5);
To make it easier to plot your figures, you can keep your data in matrix form:
for a1=1:5:180
rotate(elPatternPlot, [0 0 1], 5);
xElData = [xElData; elPatternPlot.XData];
yElData = [yElData; elPatternPlot.YData];
zElData = [zElData; elPatternPlot.ZData];
end
To plot:
figure
plot3(xElData, yElData, zElData)
grid on; axis equal
figure
surf(xElData, yElData, zElData)
grid on; axis equal
figure
mesh(xElData, yElData, zElData)
grid on; axis equal

Related

solve a system of lineare equation gauss Jordan method in matlab

I try to solve system of lineare equation using the Gauss Jordan methode. I try my code with a smaller matrice and I got the rigth answer. Now I try it with a bigger matrice and I got NAN(not a number) as answer. I don't what I am doing wrong.
a = [-1 0 0 0 0 0 1 0 0 0 1 0 0 0;
0 -1 0 0 0 0 0 1 0 0 0 1 0 0 ;
1 0 -1 0 -1 0 0 0 0 0 0 0 0 0;
0 1 0 -1 0 -1 0 0 0 0 0 0 0 0;
0 0 0 0 1 0 0 0 0 0 -1 0 -1 0;
0 0 0 0 0 1 0 0 0 0 0 -1 0 -1;
0 0 1 0 0 0 -1 0 -1 0 0 0 0 0;
0 0 0 1 0 0 0 -1 0 -1 0 0 0 0;
-0.025 0 1 0 0 0 0 0 0 0 0 0 0 0;
0 -0.8 0 1 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 -0.04 0 0 0 0 0 1 0 0 0;
0 0 0 0 0 -0.96 0 0 0 0 0 1 0 0;
0 0 -0.04 0 0 0 0 0 1 0 0 0 0 0;
0 0 0 -0.96 0 0 0 0 0 1 0 0 0 0];
b = [-50;-50;0;0;0;0;0;0;0;0;0;0;0;0];
Gaussjordan(a,b);
% Function Gauss Jordan
function x=Gaussjordan(a,b)
ab=[a b];
[m,n]=size(ab); %size of matrix
for i=1:m
ab(i,:)=ab(i,:)/ab(i,i);
for j=1:m
if j==i; continue;
end
ab(j,:)=ab(j,:)-ab(j,i)*ab(i,:);
end;
end;
x=ab(:,length(b)+1);
end
with the samll matrix a = [1 1 1; 2 -3 4; 3 4 5]
b = [9; 13; 40], I got the answer ans = [1 3 5].
But with the bigger one upon in code I got ans = [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN]
Did someone has an idea?
Ps: I solve this systen of equation with fsolve to be sure that it exist an answer on the system equation

Store and plot two structures in MATLAB

I am working with structures that two of which are shown below; A and B. I need to store A and B in a way (possibly not using tables) that allows MATLAB to plot them similar to the images.
In my viewpoint, generating a sparse matrix and store the circles in it may be a solution. Here is a function which could generate a circle array in a sparse matrix with given structure & color. What you need is design a table which denotes the color of each item (0 means there a nothing in that position).
Function CircleArrays.m
function [Imgout] = CircleArrays(DataIn,r,s)
%%Draw a circle array with given colors
% Parameters:
% DataIn ---- structures & color
% r ---- the radius of each circle
% s ---- the sparsity of the data
% Demo:
% S=rand(10);
% r=20;
% sparsity=1;
% Img=CircleArrays(S,r,sparsity);
% figure()
% colormap(hot)
% imagesc(1-Img)
% axis equal
% axis off
%Define a pre-allocate sparse matrix
[m,n]=size(DataIn);
Imgout=spalloc(m*(2*r+1),n*(2*r+1),floor(n*(2*r+1)*m*(2*r+1)*s));
%Create the Mask
I = 1:(2*r+1); % Define the x and y coordinates of the basic mask
x = (I - r)-1;
y = (r - I)+1;
[X,Y] = meshgrid(x,y); % Create the mask
M = (X.^2 + Y.^2 <= r^2);
[xx,yy]=ind2sub(size(M),find(M == true));
%%Add circles into the matrix
for ii=1:m
for jj=1:n
if (DataIn(ii,jj) == 0)
continue;
else
MidX=(ii-1)*(2*r+1)+r+1;
MidY=(jj-1)*(2*r+1)+r+1;
Imgout(sub2ind(size(Imgout),MidX+xx-r-1,MidY+yy-r-1))=DataIn(ii,jj);
end
end
end
end
DEMO:
clc; clear;
%%Structures & configs
% define structures & color
S=[0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 1 0 0 0 0 0 0 1 0 0 0;
0 0 0 1 0 0 0 0 0 0 1 0 0 0;
0 0 0 1 0 0 0 0 0 0 1 0 0 0;
0 0 0 1 0 0 0 0 0 0 1 0 0 0;
0 0 0 1 0 0 0 0 0 0 1 0 0 0;
0 0 0 .6 0.6 .6 .6 .6 .6 .6 .6 0 0 0;
0 0 0 1 0 0 0 0 0 0 1 0 0 0;
0 0 0 1 0 0 0 0 0 0 1 0 0 0;
0 0 0 1 0 0 0 0 0 0 1 0 0 0;
0 0 0 1 0 0 0 0 0 0 1 0 0 0;
0 0 0 1 0 0 0 0 0 0 1 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0;];
%set the radius of each circle and the sparsity of the data
r=20;
sparsity=0.25;
%generate the Structures
Img=CircleArrays(S,r,sparsity);
%%Draw the picture
figure()
colormap(hot)
imagesc(1-Img)
axis equal
axis off
output by DEMO code:
output by DEMO code in the function:
Notes: I wrote this function based on one of my old answers, so the circle mask maybe not 100% perfect, you can change it to whatever you like.

How can i count number of particles in each grid box in this code?

how can i count number of particles in each grid box in this code
here is my code below:
xyRange=[1,5];
P=3;
vx=0.6;
vy=0.4;
X=[];
Y=[];
for day=1:5
X=[X;randi(xyRange,P,1)];
Y=[Y;randi(xyRange,P,1)];
X=X+vx;
Y=Y+vy;
end
plot(X,Y,'kd');
grid on;
axis([1,50,1,50]);
j = floor(X/5)+1;
k = floor(Y/5);
box = k*10+j;
If you have the Statistics Toolbox, the easiest way is to use hist3.
In your case, when I plotted the grid, it looks like each box was separated in units of 5. As such, the command is very simply this:
cnt = hist3([X,Y], {0:5:50 - 2.5, 0:5:50 - 2.5});
X and Y are your 2D data points, and the second element is a cell array of X and Y values which denote the centres of each of the points in each grid. Take note that the points that are defined are with respect to the origin being at the top left corner. If you want to make sure that the origin is at the bottom left corner, you would actually need to do this:
cnt = flipud(cnt.');
On my run I get this:
cnt =
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
0 1 6 0 0 0 0 0 0 0 0
0 5 3 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0
When producing your plot, I get this:
If you compare the counts in comparison to the grid produced at the top, you'll see that the match. However, because of the way I specified the centre of the bins, the first and last row, and the first and last column are meaningless, so you can safely eliminate these from your analysis.
If you want a nice pictorial example of this, call hist3 without any output arguments:
%// Plot 2D histogram with some transparency
hist3([X,Y], {(0:5:50) - 2.5, (0:5:50) - 2.5}, 'FaceAlpha', 0.65);
%// Set height of each bar coloured according to height
set(get(gca,'child'),'FaceColor','interp','CDataMode','auto');
view(-34,68); %// Change camera view for better look
We get this:

Finding the minimum of corresponding elements in four matrices

So I need to find the minimum value of corresponding elements in multiple matrices. I did find this page but I would like to extend my question a little further. My matrices has positive and negative values (and zeros) and I want to find the minimum values excluding zeros.
Example:
Z(:,:,1) = [-5 0 5
0 0 0
1 0 3];
Z(:,:,2) = [1 0 2
0 0 0
0 0 0];
Z(:,:,3) = [0 0 0
-9 0 4
0 0 0];
Z(:,:,4) = [0 0 0
-2 0 0
0 0 0];
Here's what I'm using as of now:
Zmin = min(Z,[],3);
But that gives me:
[-5 0 0
-9 0 0
0 0 0]
But I want my result to be:
[-5 0 2
-9 0 4
1 0 3]
Any ideas? When I use nonzeros, it messes up everything.
Here's a workaround:
Replace all the 0s in Z by NaN, calculate the min, then switch back to 0:
clear all
clc
close all
Z(:,:,1) = [-5 0 5
0 0 0
1 0 3];
Z(:,:,2) = [1 0 2
0 0 0
0 0 0];
Z(:,:,3) = [0 0 0
-9 0 4
0 0 0];
Z(:,:,4) = [0 0 0
-2 0 0
0 0 0];
%// Assign NaN to 0 elements
Z(Z ==0) = NaN;
Zmin = min(Z,[],3);
%// Switch back with 0
Zmin(isnan(Zmin)) = 0;
%// Same for Z;
Z(isnan(Z)) =0;
The output looks like this:
Zmin
Z
Zmin =
-5 0 2
-9 0 4
1 0 3
Z(:,:,1) =
-5 0 5
0 0 0
1 0 3
Z(:,:,2) =
1 0 2
0 0 0
0 0 0
Z(:,:,3) =
0 0 0
-9 0 4
0 0 0
Z(:,:,4) =
0 0 0
-2 0 0
0 0 0
One option is to set all zero elements to NaN that way:
Z(Z==0)=NaN;
And then use nanmean
Zmin = nanmin(Z,[],3);

MATLAB one liner for batch assignment in 2D matrix?

Say I have a matrix
A = zeros(5, 5);
Instead of looping with a for loop, I wish to batch-modify some of the elements. For example, I wish to change elements marked by pts_to_modify to 1, where
pts_to_modify=[[2 3]; [3 2]];
So I wish A to become
0 0 0 0 0
0 0 1 0 0
0 1 0 0 0
0 0 0 0 0
However, when I do
A(pts_to_modify(:, 1), pts_to_modify(:, 2)) = 1,
I get
A =
0 0 0 0 0
0 1 1 0 0
0 1 1 0 0
0 0 0 0 0
0 0 0 0 0
How can I do it correctly?
You can use sub2ind:
>> ind = sub2ind(size(A), pts_to_modify(1,:), pts_to_modify(2,:))
ind =
12 8
>> A(ind) = 1
A =
0 0 0 0 0
0 0 1 0 0
0 1 0 0 0
0 0 0 0 0
0 0 0 0 0
sub2ind
linear indexing