Draw circle with 100 points - matlab

I have to draw a circle using only 100 points. The center's coordinates are like (1,1), (1,2), (2,2) etc. The circle should be inscribed within 0.6×0.6 square. I figured out I can use something like:
th= linspace(0,2*pi)
to get 100 points, and
x = cos(th)
y = sin(th)
to get x and y coordinates to be used in plot(x,y).
However, I do not know how to get the exact coordinates or 0.6×0.6 square. If there was not np requirement of exactly 100 points I could use circleplot syntax...

You could do it like this (for each circle):
th = linspace(0, 2*pi);
x = sin(th) * .3 + cX;
y = cos(th) * .3 + cY;
plot(x,y);
where cX and cY are the center of the circle.

Related

Calculate volume of hollow tilted cylinder inside cube, without a grid

I have a hollow cylinder with inner radius r1 and outer radius r2. This cylinder is tilted from the Z axis towards the X axis, then rotated around the Z axis and then translated along X and along Y. I also have a cube between a range of X and Y values. I then want to calculate how large a volume of the hollow cylinder is inside the cube.
%set variables
r1 = 0.9; r2 = 1.0;
z1 =-1.0; z2 = 1.0;
beta = pi/4; gamma = pi/8;
%create inner surface
[X,Y,Z] = cylinder(r1, 100);
%outer surface
[Xx,Yy,Zz] = cylinder(r2, 100);
%fix coordinates
X = [X,Xx]; Y = [Y,Yy]; Z = [Z,Zz];
Z(1,:) = z1; Z(2,:) = z2;
%elongate in first rotation direction
X = X/cos(beta);
%shift top and bottom accordingly
X(1,:) = X(1,:) + z2/tan(beta);
X(2,:) = X(2,:) + z1/tan(beta);
%also perform another rotation in XY plane
Xnu = X*cos(gamma) + -Y*sin(gamma);
Y = X*sin(gamma) + Y*cos(gamma);
X = Xnu;
%translation not included for this example
surf(X,Y,Z); axis equal
%try to make a cube from its nodes/corners
ix=-1;iy=-1;dx=0.5;dy=dx;
[X,Y,Z] = ndgrid( ix*dx+[-dx/2, dx/2] , iy*dy+[-dy/2, dy/2] , [z1, z2] );
X = reshape(X, 2, []);Y = reshape(Y, 2, []);Z = reshape(Z, 2, []);
%failed
surf(X,Y,Z); axis equal
The hollow cylinder seems OK. Just no 'cap' on the top of the edge.
The cube looks nothing like a cube, but at least the volume between the corners should be correct.
My question is, how do I get the intersection of these two shapes and then calculate the volume?
I actually need to iterate over many of these tubes and cubes, but once I have this single case fixed then it should be easy. Each cube represents a measured pixel from an experiment and each hollow cylinder a physical object that was in the experiment. When simulating this on a meshgrid itself I encounter memory issues very fast.

Matlab - Subtracting two 3D figures with surf and min function

I'm trying to make a surf plot that looks like:
So far I have:
x = [-1:1/100:1];
y = [-1:1/100:1];
[X,Y] = meshgrid(x,y);
Triangle1 = -abs(X) + 1.5;
Triangle2 = -abs(Y) + 1.5;
Z = min(Triangle1, Triangle2);
surf(X,Y,Z);
shading flat
colormap winter;
hold on;
[X,Y,Z] = sphere();
Sphere = surf(X, Y, Z + 1.5 );% sphere with radius 1 centred at (0,0,1.5)
hold off;
This code produces a graph that looks like :
A pyramid with square base ([-1,1]x[-1,1]) and vertex at height c = 1.5 above the origin (0,0) is erected.
The top of the pyramid is hollowed out by removing the portion of it that falls within a sphere of radius r=1 centered at the vertex.
So I need to keep the part of the surface of the sphere that is inside the pyramid and delete the rest. Note that the y axis in each plot is different, that's why the second plot looks condensed a bit. Yes there is a pyramid going into the sphere which is hard to see from that angle.
I will use viewing angles of 70 (azimuth) and 35 (elevation). And make sure the axes are properly scaled (as shown). I will use the AXIS TIGHT option to get the proper dimensions after the removal of the appropriate surface of the sphere.
Here is my humble suggestion:
N = 400; % resolution
x = linspace(-1,1,N);
y = linspace(-1,1,N);
[X,Y] = meshgrid(x,y);
Triangle1 = -abs(X)+1.5 ;
Triangle2 = -abs(Y)+1.5 ;
Z = min(Triangle1, Triangle2);
Trig = alphaShape(X(:),Y(:),Z(:),2);
[Xs,Ys,Zs] = sphere(N-1);
Sphere = alphaShape(Xs(:),Ys(:),Zs(:)+2,2);
% get all the points from the pyramid that are within the sphere:
inSphere = inShape(Sphere,X(:),Y(:),Z(:));
Zt = Z;
Zt(inSphere) = nan; % remove the points in the sphere
surf(X,Y,Zt)
shading interp
view(70,35)
axis tight
I use alphaShape object to remove all unwanted points from the pyramid and then plot it without them:
I know, it's not perfect, as you don't see the bottom of the circle within the pyramid, but all my tries to achieve this have failed. My basic idea was plotting them together like this:
hold on;
Zc = Zs;
inTrig = inShape(Trig,Xs(:),Ys(:),Zs(:)+1.5);
Zc(~inTrig) = nan;
surf(Xs,Ys,Zc+1.5)
hold off
But the result is not so good, as you can't really see the circle within the pyramid.
Anyway, I post this here as it might give you a direction to work on.
An alternative to EBH's method.
A general algorithm from subtracting two shapes in 3d is difficult in MATLAB. If instead you remember that the equation for a sphere with radius r centered at (x0,y0,z0) is
r^2 = (x-x0)^2 + (y-y0)^2 + (z-z0)^2
Then solving for z gives z = z0 +/- sqrt(r^2-(x-x0)^2-(y-y0)^2) where using + in front of the square root gives the top of the sphere and - gives the bottom. In this case we are only interested in the bottom of the sphere. To get the final surface we simply take the minimum z between the pyramid and the half-sphere.
Note that the domain of the half-sphere is defined by the filled circle r^2-(x-x0)^2-(y-y0)^2 >= 0. We define any terms outside the domain as infinity so that they are ignored when the minimum is taken.
N = 400; % resolution
z0 = 1.5; % sphere z offset
r = 1; % sphere radius
x = linspace(-1,1,N);
y = linspace(-1,1,N);
[X,Y] = meshgrid(x,y);
% pyramid
Triangle1 = -abs(X)+1.5 ;
Triangle2 = -abs(Y)+1.5 ;
Pyramid = min(Triangle1, Triangle2);
% half-sphere (hemisphere)
sqrt_term = r^2 - X.^2 - Y.^2;
HalfSphere = -sqrt(sqrt_term) + z0;
HalfSphere(sqrt_term < 0) = inf;
Z = min(HalfSphere, Pyramid);
surf(X,Y,Z)
shading interp
view(70,35)
axis tight

How can I describe lines moving radially outwards from a center point?

I have a point in 3d space (x,y,z). I want to move radially outward from that point discretely (say for r=1 and r=2). In the x,y plane I can simply move outward by stepping ((x+r cos(theta)), (y+r sin(theta)), z) with r = 1 or 2 and theta varying every, say 10 degrees.
However, I am unsure how to describe this movement if I want to have lines moving outward on a tilted plane and step my lines within this plane.
I thought it would be just using spherical coordinates. But if I'm drawing lines from a center point using (x=rho sin phi cos theta, y=..., z=...) won't that form a cone rather than a circle tilted on a plane?
P.S. Will be implementing this in MATLAB
You could first make the coordinates going outwards from P0 and then rotate the coordinates using a rotation matrix.
So you take points P for all R's and thetas, as MBo pointed out:
P = [ P0x + R * cos(theta); P0y + R * sin(theta); 0 ]
Then you make a rotation matrix that rotates the XY plane with the angles you want
If you multiply that with your coordinates you get the rotated coordinates. For example a 90 degree rotation about the Z axis for the point [1,0,0]:
However you probably want to rotate about the point P0 and not about the origin, then you have to make an affine matrix with the following translation:
tx = x- r00 * x - r01 * y - r02 * z
ty = y- r10 * x - r11 * y - r12 * z
tz = z- r20 * x - r21 * y - r22 * z
And then make an affine transformation matrix with T and R (designated as M in the figure, sorry):
In this figure Q are the old coordinates and Q' the new coordinates.
I had a similar problem and used this answer and adjusted it to your problem:
%input point and rotated plane
p0 = [10;10;10;1]; % the last entry is your homogeneous dimension
r0 = [45,45,45]; r0 = r0*pi/180;
%rotation to plane
Rx=[1 0 0 0;
0 cos(r0(1)) sin(r0(1)) 0;
0 -sin(r0(1)) cos(r0(1)) 0;
0 0 0 1];
Ry=[cos(r0(2)) 0 -sin(r0(2)) 0;
0 1 0 0;
sin(r0(2)) 0 cos(r0(2)) 0;
0 0 0 1];
Rz=[cos(r0(3)) sin(r0(3)) 0 0;
-sin(r0(3)) cos(r0(3)) 0 0;
0 0 1 0;
0 0 0 1];
R = Rz*Ry*Rx; A = R;
T = ( eye(3)-R(1:3,1:3) ) * p0(1:3); %calculate translation to rotate about the point P0
A(1:3,4) = T; % to rotate about the origin just leave out this line
%make coordinates for the points going outward from p0
nangles = 36; anglestep = 2*pi/nangles;
nradii = 2; radiistep = 1;
thetas = anglestep:anglestep:2*pi;
rs = radiistep:radiistep:nradii*radiistep;
npoints = nradii*nangles;
coordinates = zeros(4,npoints); curpoint = 0;
for itheta = 1:nangles; for iradius = 1:nradii;
curpoint = curpoint+1;
coordinates(:, curpoint) = p0+rs(iradius)*[cos(thetas(itheta));sin(thetas(itheta));0;0];
end; end
coordinates_tilted = A*coordinates; %rotate the coordinates to the new plane
Which results in this figure:
figure;
scatter3(coordinates_tilted(1,:),coordinates_tilted(2,:),coordinates_tilted(3,:), 'MarkerEdgeColor', 'green')
hold on
scatter3(coordinates(1,:),coordinates(2,:),coordinates(3,:), 'MarkerEdgeColor', 'red')
legend('tilted', 'original')
Or plot them as lines:
%or as lines
coorarray = reshape(coordinates, [4 nradii nangles]);
Xline = squeeze(coorarray(1,:,:));
Yline = squeeze(coorarray(2,:,:));
Zline = squeeze(coorarray(3,:,:));
coorarray_tilted = reshape(coordinates_tilted, [4 nradii nangles]);
Xline_tilted = squeeze(coorarray_tilted(1,:,:));
Yline_tilted = squeeze(coorarray_tilted(2,:,:));
Zline_tilted = squeeze(coorarray_tilted(3,:,:));
figure;
plot3(Xline,Yline,Zline, 'r');
hold on
plot3(Xline_tilted,Yline_tilted,Zline_tilted, 'g');
legend( 'original', 'tilted')
Does this answer your question? These are now points at all multiples of 36 degree angles at a distance of one and two from point P0 in the plane that is tilted 45 degrees on all axes around the point P0. If you need individual 'pixels' to designate your line (so integer coordinates) you can round the coordinates and that would be sort of a nearest neighbour approach:
coordinates_tilted_nearest = round(coordinates_tilted);
How is your tilted plane defined?
Define it with base point P0 and two perpendicular unit vectors U and V. It is not hard to get this representation from any other. For example, if normal vector of your plane have angles ax, ay, az with axes OX, OY, OZ respectively, it's normalized form is N = (nx, ny, nz) = (Cos(ax), Cos(ay), Cos(az)). You can choose arbitrary vector U (lying in the plane) as described here, and find V vector as vector product V = U x N
Then needed points are:
P = P0 + U * R * Cos(Theta) + V * R * Sin(Theta)

Create Circle In 3-D Axes

I am newbie in matlab.
I want to draw something like below pic in 3-D axes and move it mouse move.
i do not have problem with second part(move objects on mouse move) ,
i do not know how to create this circle in 3-D axes
elevation = linspace(0,2*pi,100);
r = ones(1,100);
azimuth = .75 * pi *ones(1,100);
while 1
axis([-10 10 -10 10 -10 10])
view([20 20 5])
[newx newy] = ginput(1);
[x,y,z] = sph2cart(azimuth,elevation,r);
x = x + newx;
y = y + newy;
patch(x,y,z,[1 0 0],'EdgeColor','r');
axis([-10 10 -10 10 -10 10])
end
You can change the radius by r like r = .5 * ones(1,100);
But the coordinates of click doesn't seem to be right.
I think you have solved that problem in your previous question.
Note
Coordinates returned by ginput are scaled to the XLim and YLim bounds of the axes you click (data units).
The figure CurrentPoint property, by contrast, is always returned in figure Units, irrespective of axes Units or limits`

draw ellipse and ellipsoid in MATLAB

How do I draw an ellipse and an ellipsoid using MATLAB?
(x^2/a^2)+(y^2/b^2)=1
n=40;
a=0; b=2*pi;
c=0; d=2*pi;
for i=1:n
u=a+(b-a)*(i-1)/(n-1);
for j=1:m
v=a+(d-c)*(j-1)/(m-1);
x(i,j)=sin(u)*cos(v);
y(i,j)=sin(u)*sin(v);
z(i,j)=cos(u);
end
end
mesh(x,y,z);
But I want the shape?
Ellipse article on Wikipedia had a simple JavaScript code to draw ellipses.
It uses the parametric form:
x(theta) = a0 + ax*sin(theta) + bx*cos(theta)
y(theta) = b0 + ay*sin(theta) + by*cos(theta)
where
(a0,b0) is the center of the ellipse
(ax,ay) vector representing the major axis
(bx,by) vector representing the minor axis
I translated the code into a MATLAB function:
calculateEllipse.m
function [X,Y] = calculateEllipse(x, y, a, b, angle, steps)
%# This functions returns points to draw an ellipse
%#
%# #param x X coordinate
%# #param y Y coordinate
%# #param a Semimajor axis
%# #param b Semiminor axis
%# #param angle Angle of the ellipse (in degrees)
%#
narginchk(5, 6);
if nargin<6, steps = 36; end
beta = -angle * (pi / 180);
sinbeta = sin(beta);
cosbeta = cos(beta);
alpha = linspace(0, 360, steps)' .* (pi / 180);
sinalpha = sin(alpha);
cosalpha = cos(alpha);
X = x + (a * cosalpha * cosbeta - b * sinalpha * sinbeta);
Y = y + (a * cosalpha * sinbeta + b * sinalpha * cosbeta);
if nargout==1, X = [X Y]; end
end
and an example to test it:
%# ellipse centered at (0,0) with axes length
%# major=20, ,minor=10, rotated 50 degrees
%# (drawn using the default N=36 points)
p = calculateEllipse(0, 0, 20, 10, 50);
plot(p(:,1), p(:,2), '.-'), axis equal
The answers from Jacob and Amro are very good examples for computing and plotting points for an ellipse. I'll address some easy ways you can plot an ellipsoid...
First, MATLAB has a built-in function ELLIPSOID which generates a set of mesh points given the ellipsoid center and the semi-axis lengths. The following creates the matrices x, y, and z for an ellipsoid centered at the origin with semi-axis lengths of 4, 2, and 1 for the x, y, and z directions, respectively:
[x, y, z] = ellipsoid(0, 0, 0, 4, 2, 1);
You can then use the function MESH to plot it, returning a handle to the plotted surface object:
hMesh = mesh(x, y, z);
If you want to rotate the plotted ellipsoid, you can use the ROTATE function. The following applies a rotation of 45 degrees around the y-axis:
rotate(hMesh, [0 1 0], 45);
You can then adjust the plot appearance to get the following figure:
axis equal; %# Make tick mark increments on all axes equal
view([-36 18]); %# Change the camera viewpoint
xlabel('x');
ylabel('y');
zlabel('z');
Also, if you want to use the rotated plot points for further calculations, you can get them from the plotted surface object:
xNew = get(hMesh, 'XData'); %# Get the rotated x points
yNew = get(hMesh, 'YData'); %# Get the rotated y points
zNew = get(hMesh, 'ZData'); %# Get the rotated z points
I've adapted this excellent ellipse plotting script from MATLAB Central for your requirement of
function plotEllipse(a,b,C)
% range to plot over
%------------------------------------
N = 50;
theta = 0:1/N:2*pi+1/N;
% Parametric equation of the ellipse
%----------------------------------------
state(1,:) = a*cos(theta);
state(2,:) = b*sin(theta);
% Coordinate transform (since your ellipse is axis aligned)
%----------------------------------------
X = state;
X(1,:) = X(1,:) + C(1);
X(2,:) = X(2,:) + C(2);
% Plot
%----------------------------------------
plot(X(1,:),X(2,:));
hold on;
plot(C(1),C(2),'r*');
axis equal;
grid;
end
Note: change N to define the resolution of your ellipse
Here's an ellipse centered at (10,10) with a = 30 and b = 10
Ellipse article on Wikipedia and Rotation matrix.
Rewrite that functions:
rotate by rotAngle counter-clockwise around (0,0)
Coordinate transform to (cx, cy)
function [X,Y] = calculateEllipse(cx, cy, a, b, rotAngle)
%# This functions returns points to draw an ellipse
%#
%# #param x X coordinate
%# #param y Y coordinate
%# #param a Semimajor axis
%# #param b Semiminor axis
%# #param cx cetner x position
%# #param cy cetner y position
%# #param angle Angle of the ellipse (in degrees)
%#
steps = 30;
angle = linspace(0, 2*pi, steps);
% Parametric equation of the ellipse
X = a * cos(angle);
Y = b * sin(angle);
% rotate by rotAngle counter clockwise around (0,0)
xRot = X*cosd(rotAngle) - Y*sind(rotAngle);
yRot = X*sind(rotAngle) + Y*cosd(rotAngle);
X = xRot;
Y = yRot;
% Coordinate transform
X = X + cx;
Y = Y + cy;
end
and an example to test it:
[X,Y] = calculateEllipse(0, 0, 20, 10, 0);
plot(X, Y, 'b'); hold on; % blue
[X,Y] = calculateEllipse(0, 0, 20, 10, 45);
plot(X, Y, 'r'); hold on; % red
[X,Y] = calculateEllipse(30, 30, 20, 10, 135);
plot(X, Y, 'g'); % green
grid on;
Create two vectors, one of the x-coordinates of the points of the circumference of the ellipsoid, one of the y-coordinates. Make these vectors long enough to satisfy your accuracy requirements. Plot the two vectors as (x,y) pairs joined up. I'd drop the for loops from your code, much clearer if you use vector notation. Also I'd format your question using the SO markup for code to make it all clearer to your audience.
The simplest way might be to use the Matlab function
pdeellip(xc,yc,a,b,phi)
For example:
pdeellip(0,0,1,0.3,pi/4)
However, this is simple solution is good to have a quick glance how the ellipse looks like. If you want to have a nice plot, look at the other solutions.
I don't know in which version of Matlab this was added, but it's available at least from version R2012b on.