Plot points and polygon matlab - matlab

I am trying to plot a point, a circle surrounding a point with a given radius and polygons from array of coods as input. I have the following code implemented
plot(start(1),start(2))
axis([0,256,0,256]);
hold on;
%pdecirc(endp(1),endp(2),10);
for i = 1:size(X,1)
patch(X(i),Y(i),'r');
end
However, pdecirc is not working. it opens a new editor and thus I have commented it. X and Y are 2d arrays of dimensions (no.of points X 4). Thus X(i) has 4 X values and Y(i) has 4 X values. This code is not drawing the polygons as expected. Can you please tell me the best way of achieving what am trying to do? A code would be really helpful. Thanks in advance.

It appears that pdecirc is part of a matlab pde toolkit, not for generic circle drawing, here's something quick
r = 10;
theta = linspace(0, 2 * pi, 100);
x = r * cos(theta);
y = r * sin(theta);
plot(x, y);
does your patch command work?

Related

Draw a line with non-Cartesian coordinates in MATLAB

MATLAB's surf command allows you to pass it optional X and Y data that specify non-cartesian x-y components. (they essentially change the basis vectors). I desire to pass similar arguments to a function that will draw a line.
How do I plot a line using a non-cartesian coordinate system?
My apologies if my terminology is a little off. This still might technically be a cartesian space but it wouldn't be square in the sense that one unit in the x-direction is orthogonal to one unit in the y-direction. If you can correct my terminology, I would really appreciate it!
EDIT:
Below better demonstrates what I mean:
The commands:
datA=1:10;
datB=1:10;
X=cosd(8*datA)'*datB;
Y=datA'*log10(datB*3);
Z=ones(size(datA'))*cosd(datB);
XX=X./(1+Z);
YY=Y./(1+Z);
surf(XX,YY,eye(10)); view([0 0 1])
produces the following graph:
Here, the X and Y dimensions are not orthogonal nor equi-spaced. One unit in x could correspond to 5 cm in the x direction but the next one unit in x could correspond to 2 cm in the x direction + 1 cm in the y direction. I desire to replicate this functionality but drawing a line instead of a surf For instance, I'm looking for a function where:
straightLine=[(1:10)' (1:10)'];
my_line(XX,YY,straightLine(:,1),straightLine(:,2))
would produce a line that traced the red squares on the surf graph.
I'm still not certain of what your input data are about, and what you want to plot. However, from how you want to plot it, I can help.
When you call
surf(XX,YY,eye(10)); view([0 0 1]);
and want to get only the "red parts", i.e. the maxima of the function, you are essentially selecting a subset of the XX, YY matrices using the diagonal matrix as indicator. So you could select those points manually, and use plot to plot them as a line:
Xplot = diag(XX);
Yplot = diag(YY);
plot(Xplot,Yplot,'r.-');
The call to diag(XX) will take the diagonal elements of the matrix XX, which is exactly where you'll get the red patches when you use surf with the z data according to eye().
Result:
Also, if you're just trying to do what your example states, then there's no need to use matrices just to take out the diagonal eventually. Here's the same result, using elementwise operations on your input vectors:
datA = 1:10;
datB = 1:10;
X2 = cosd(8*datA).*datB;
Y2 = datA.*log10(datB*3);
Z2 = cosd(datB);
XX2 = X2./(1+Z2);
YY2 = Y2./(1+Z2);
plot(Xplot,Yplot,'rs-',XX2,YY2,'bo--','linewidth',2,'markersize',10);
legend('original','vector')
Result:
Matlab has many built-in function to assist you.
In 2D the easiest way to do this is polar that allows you to make a graph using theta and rho vectors:
theta = linspace(0,2*pi,100);
r = sin(2*theta);
figure(1)
polar(theta, r), grid on
So, you would get this.
There also is pol2cart function that would convert your data into x and y format:
[x,y] = pol2cart(theta,r);
figure(2)
plot(x, y), grid on
This would look slightly different
Then, if we extend this to 3D, you are only left with plot3. So, If you have data like:
theta = linspace(0,10*pi,500);
r = ones(size(theta));
z = linspace(-10,10,500);
you need to use pol2cart with 3 arguments to produce this:
[x,y,z] = pol2cart(theta,r,z);
figure(3)
plot3(x,y,z),grid on
Finally, if you have spherical data, you have sph2cart:
theta = linspace(0,2*pi,100);
phi = linspace(-pi/2,pi/2,100);
rho = sin(2*theta - phi);
[x,y,z] = sph2cart(theta, phi, rho);
figure(4)
plot3(x,y,z),grid on
view([-150 70])
That would look this way

affine2d in Octave

In MATLAB I make a cylinder r and shift it to the position I want which is Pos. In MATLAB I use affine2d and imwarp but unfortunately Octave doesn't have these functions.
Does anybody know how I can do this in Octave without affine2d and imwarp?
The MATLAB code is
% get image limits
limX = size(image,1)/2;
limY = size(image,2)/2;
steps = 1;
% add 30% to the inner diameter to make sure it covers the complete sparse area
largeradius = 1.5*diaStart/2;
smallradius = diaStart/2;
% generate x/y points
[x,y] = meshgrid(-limX:steps:limX,-limY:steps:limY);
% calculate the radius values:
r = sqrt(x.^2 + y.^2);
r(r>largeradius) = 0;
r(r<smallradius) = 0;
% Shift translate circle in place
r = im2bw(r);
xPos = (Pos(1)-limX);
yPos = Pos(2)-limY;
tform = affine2d([1 0 0; 0 1 0; xPos yPos 1]);
r_trans = imwarp(r,tform,'OutputView',imref2d(size(image)));
It should be easy to do. affine2d is not a problem, as it is a function that changes the data type, but doesn't modify anything.
imwarp does [x y 1] = [u v 1] * T (being T the affine transformation Matrix) for each of the pixels.
So, if you know that you want the values of the pixels in some specific locations in the transformed image, then its easy to know them
In other words: you have an image r (composed by [u v 1] pixels, a transformation tform and you know that you want to know how a new image is created by that. The new image r_trans is composed by [x y 1] pixels, and you know [x,y,1] values.
Basically, you want to get r(u,v) for each [u,v,1]=[x y 1]*T^(-1);.
x will be 1:size(r,1), and y=1:size(r,2).
Therefore computing [u,v,1]=[x y 1]*T^(-1); is not a problem.
Now, you want to access r(u,v), and u and v wont be integers, they will be floating point values. To be able to get ther` values you will need interpolation.
For that, you need to use this simple piece of code;
[X,Y]=meshgrid(1:size(r,1),1:size(r,2));
value=interp2(X,Y,r,ui,vi,method); %chose method from https://www.gnu.org/software/octave/doc/interpreter/Multi_002ddimensional-Interpolation.html
r_trans(xi,yi)=value;
I didn't give you the whole code, but hopefully you understand how to do it.

Rotating a 3D figure in MATLAB

I generated a 3D surface in matlab.
clear all;
close all;
clc;
x = [1:0.1:5];
y=[1:50];
[n1 n2] = size(x);
[m1, m2] = size(y);
for i = 1 : m2
for j = 1 : n2
z(i,j) = (x(1,j)) / (y(1,i));
end
end
[x, y] = meshgrid(x, y);
surf(y, x, z)
colorbar
xlabel('x')
ylabel('y')
zlabel('z')
I got the following plotted surface:
I am interested now to rotate the cube of a quarter turn in the clockwise direction. I know that I can use the "rotate3d on" and choose the best Az and EI, but I didn't understand what are Az and EI and how should be equal to respond to my need?
For example:
There also another function called camroll(). But I don't know what must the value in () in order to rotate the cube of a quarter turn in the clockwise direction. Does 90 degree is the correct answer?
Any help will be very appreciated!
To rotate the figure axis you can use the view command:
surf(rand(20))
for az = 360:-1:-0
view(az, 30)
pause(0.01)
end
Azimus has values in between 0° and 360°. To turn the axis figure by 90° in counter-clockwise direction you oculd choose the azimuths of: [270, 180, 90, 0]
as #ASantosRibeiro mentioned, the rotate function will produce the output you want. As an aside, here is a vectorized version of your code, which you might find useful if you have a significantly larger data set.
x = 1:0.1:5;
y=1:50;
X = repmat(x',1,size(y,2)).';
Y = repmat(y',1,size(x,2));
Z = X./Y;
figure
hSurf = surf(Y,X,Z);
rotate(hSurf,[1,0,0],45) % As proposed by #ASantosRibeiro
colorbar
xlabel('x')
ylabel('y')
zlabel('z')
The repmat function is used to replicate both x and y in order to form X and Y with correct sizes to be allowed to divide one by the other in order to form Z. This operation is quite similar to the call to meshgrid in your code. For a small dataset like the one in your example the running times are similar with both methods (on my laptop), however when I use x = 1:0.1:500 and y = 1:500 for example the vectorized version takes 3x less time, so it might be worthwhile to look at it.
Hope that helps you!

Extract cross sections from a plot of multiple spheres in Matlab

I know the locations of spheres (center and radius) in a box. I want to extract cross sections. I am able to plot the spheres placed in a cube using the following Matlab code:
[X,Y,Z] = sphere;
for SpNum = 1:NumSpheres
surf( X*Radius(SpNum)+Center(SpNum,1), Y*Radius(SpNum)+Center(SpNum,2), Z*Radius(SpNum)+Center(SpNum,3), ...
'FaceColor','r' );
%shading interp;
hold on;
end
axis tight; daspect([1 1 1]);
In the above code, each sphere could have different radius and they do not overlap (so the centers are also different).
The above code does not however generate cross sections. I want to extract cross sections similar to what we get from say X-ray CT data: a series of images in the Z-direction. I think 'interp2/interp3' and 'slice' functions are the relevant functions, but I am not sure how to use them to generate the cross sections. I would appreciate if anyone could give pointers or provide some sample code for my problem?
-- Thanks in advance.
Update:
I tried using meshgrid to generate the grid points followed by the function F(X,Y,Z) as follows:
[X,Y,Z] = meshgrid(1:100,1:100,1:100);
F = zeros(size(X),'uint8');
for SpNum = 1:NumSpheres
F( sqrt((X - Center(SpNum,1)).^2 + (Y - Center(SpNum,2)).^2 + (Z - Center(SpNum,3)).^2) <= Radius(SpNum) ) = 1;
end
surf(F);
followed by:
z = 1;
I = interp3(X, Y, Z, X*Radius(SpNum)+Center(SpNum,1), Y*Radius(SpNum)+Center(SpNum,2), Z*Radius(SpNum)+Center(SpNum,3), z, 'spline');
figure, imshow(I);
I know that interp3 is the function to use since it interpolates the values of the function F(X,Y,Z) which represent the spheres at different location within a bounded box (say 1:100, 1:100, 1:100). The interpolated values at particular 'z' (= 1, 2, 3... 100) should give me 100 cross sections (in the form of 2-D images).
The flaw is in the function F itself, since 'surf' throws an error saying that F should be an array - "CData must be an M-by-N matrix or M-by-N-by-3 array".
Can anyone please help.
I finally figured it. For the benefit of others, here is the code.
% A 3-D matrix 'F' which has its value at particular coordinate set to 255 if it belongs to any one of the spheres and 0 otherwise.
[X,Y,Z] = meshgrid(1:100,1:100,1:100);
F = zeros(size(X));
for SpNum = 1:NumSpheres
F( sqrt((X - Center(SpNum,1)).^2 + (Y - Center(SpNum,2)).^2 + (Z - Center(SpNum,3)).^2) <= Radius(SpNum) ) = 255;
end
% Extract cross sections from F using interp3 function along the z-axis.
I = zeros(size(X));
for z = 1:100
I(:,:,z) = interp3(X, Y, Z, F, 1:100, (1:100)', z, 'spline');
end
implay(I,4);
You could test and visualize the output by setting Center (a 3-D vector) and Radius of each sphere (some arbitrary NumSpheres) to some random values. The above code will display a window with cross-sections.
Previously, I was trying to use 'surf' to render the spheres which is not right. To render, you have to use the first code snippet. Another mistake I made was using a row vector for the 6th argument instead of column vector.
Hope this helps.
--
Cheers,
Ram.

MATLAB: find intersection points with "solve" [circle + linear equation]

I would like to find the two (2) intersection points when a linear line goes through a circle's centrum (x,y).
r = 13 radius
x = 0 x-coordinate
y = 7 y-coordinate
k = 9 slope value(?) y=kx+m y=9x+m
So first I'm drawing a circle with r=13 and a centrum of (0,7).
r=13
x=0
y=7
k=9
hold on
z = 0:pi/50:2*pi;
xunit = r * cos(z) + x;
yunit = r * sin(z) + y;
plot(xunit, yunit);
I'm wondering if it would be possible to plot up a circle in an easier way? Something like
(x−cx)^2 + (y −cy)^2 = r^2
(x-0)^2 + (y-7) = 13^2
I've tried this
plot((x−cx)^2 + (y −cy)^2 = r^2)
It doesn't do anything at all so the code must be incorrect.
Well, then I'm drawing the linear equation by calculating
y=kx+m
k=9
the line goes thorugh (0,7)
7=9*0+m
m=7
y=9x+7
so since I'm new to MatLab it took me a while to actually draw the line. I didn't find any easy function to plot it so I plotted a line like this:
I took some random values for x or y and calculated some coordinates.
(0,7)
(2,25)
(-2,-11)
plot([-2,2],[-11,25])
Result image: http://i.imgur.com/ag6HJlm.jpg
So now I just need to solve the intersection points with "solve" function. So well I would really appreciate some help!
best regards
Here is one approach to it:
%Place your lines and figures on the grid
linexypos = eye(100);
shapexypos = flipud(eye(100)) ;
% Guess where they come together
intersection = filter2(ones(3),linexypos + shapexypos);
[quality, loc] = max(intersection(:))
Note that you have to guess, as two lines with widths of 1 pixel may not have exactly the same location. (consider [1 0; 0 1] and [0 1;1 0], they cross but never exactly overlap).
If you want to visualize the situation, try contour(intersection)