I'm new to MATLAB and have a fundamental problem that I'm having issues finding online resources for. I have an equation for a circle: C = center + (radius*cos(theta)) + (radius*sin(theta)). I want to graph this circle IN ADDITION to other things I'm graphing beforehand...all in 3D. I've tried using theta = linspace(0,2*pi) but then in constructing my equation for the circle it says matrix sizes don't agree! If you could offer any help that would be great!
Here's an example of plotting a circle with a given radius and center (and assuming the circle lies in the plane z = 0):
radius = 2; %# Define your radius
center = [1 2]; %# Define your circle center [Cx Cy]
theta = linspace(0,2*pi); %# Create an array of theta values
X = center(1)+radius.*cos(theta); %# Create the X values for the circle
Y = center(2)+radius.*sin(theta); %# Create the Y values for the circle
Z = zeros(size(X)); %# Create the Z values for the circle (needed
%# for 3D plotting)
hold on; %# Add to the current existing plot
plot3(X,Y,Z); %# Plot your circle in 3D
And here are some links to online resources that should be a good starting point for learning the basics of plotting in MATLAB:
Using Basic Plotting Functions in MATLAB
PLOT function documentation
PLOT3 function documentation
HOLD function documentation
Since circle is fundamentally a 2D entity, you'll need to generate the points representing it to some known 2D plane embedded in 3D space. Then you'll be able to rotate, scale and translate it as you wish.
A simple demonstration code hopefully makes it clear:
n= 78; theta= linspace(0, 2* pi, n); c= [1 2 3]'; r= sqrt(2);
points= r*[cos(theta); sin(theta); zeros(1, n)]+ repmat(c, 1, n);
plot3(points(1,:), points(2,:), points(3,:), 's-')
axis equal, hold on
R= rref([rand(3) eye(3)]); R= R(:, 4: 6);
points= R* points;
plot3(points(1,:), points(2,:), points(3,:), 'ro')
I am not sure what you are trying to do, but consider this example:
theta = linspace(0,2*pi,100);
C = [0;0];
r = 1;
p = bsxfun(#plus, r.*[cos(theta);sin(theta)], C);
plot(p(1,:), p(2,:), '.-')
axis equal
Related
I am trying to plot a circle's equation-regression on x and y, but I do not know how to proceed. Any suggestions? (I want a circle to connect the points thru least square solution)
x = [5; 4; -1; 1];
y = [3; 5; 2; 1];
% circle's equation: x^2+y^2 = 2xc1+2yc2+c3
a = [2.*x,2.*y,ones(n,3)]
b = [x.^2 + y.^2];
c = a\b;
How do I plot the circle after this
There are a couple of ways how to plot a circle in matlab:
plot a line where the data points form a circle
use the 'o' marker in plot and the 'MarkerSize' name-value pair to set the radius of the circle
you can plot a circle image using the vscircle function
In your case, I would go with the first option, since you maintain in control of the circle size.
use the rectangle(...,'Curvature',[1 1]) function [EDITED: thx to #Cris Luengo]
So here is a plotting function
function circle(x,y,r)
%x and y are the coordinates of the center of the circle
%r is the radius of the circle
%0.01 is the angle step, bigger values will draw the circle faster but
%you might notice imperfections (not very smooth)
ang=0:0.01:2*pi+.01;
xp=r*cos(ang);
yp=r*sin(ang);
plot(x+xp,y+yp);
end
So with your (corrected) code, it looks like this
x = [5; 4; -1; 1];
y = [3; 5; 2; 1];
% circle's equation: x^2+y^2 = 2xc1+2yc2+c3
a = [2.*x,2.*y,ones(length(x),1)];
b = [x.^2 + y.^2];
c = a\b;
x_m = c(1)/2;
y_m = c(2)/2;
r = sqrt(x_m^2 + y_m^2 -c(3));
% plot data points
plot(x,y,'o')
hold on
% plot center
plot(x_m,y_m,'+')
% plot circle
circle(x_m,y_m,r)
hold off
I have polar coordinates, radius 0.05 <= r <= 1 and 0 ≤ θ ≤ 2π. The radius r is 50 values between 0.05 to 1, and polar angle θ is 24 values between 0 to 2π.
How do I interpolate r = 0.075 and theta = pi/8?
I dunno what you have tried, but interp2 works just as well on polar data as it does on Cartesian. Here is some evidence:
% Coordinates
r = linspace(0.05, 1, 50);
t = linspace(0, 2*pi, 24);
% Some synthetic data
z = sort(rand(50, 24));
% Values of interest
ri = 0.075;
ti = pi/8;
% Manually interpolate
rp = find(ri <= r, 1, 'first');
rm = find(ri >= r, 1, 'last');
tp = find(ti <= t, 1, 'first');
tm = find(ti >= t, 1, 'last');
drdt = (r(rp) - r(rm)) * (t(tp) - t(tm));
dr = [r(rp)-ri ri-r(rm)];
dt = [t(tp)-ti ti-t(tm)];
fZ = [z(rm, tm) z(rm, tp)
z(rp, tm) z(rp, tp)];
ZI_manual = (dr * fZ * dt.') / drdt
% Interpolate with MATLAB
ZI_MATLAB = interp2(r, t, z', ri, ti, 'linear')
Result:
ZI_manual =
2.737907208525297e-002
ZI_MATLAB =
2.737907208525298e-002
Based on comments you have the following information
%the test point
ri=0.53224;
ti = pi/8;
%formula fo generation of Z
g=9.81
z0=#(r)0.01*(g^2)*((2*pi)^-4)*(r.^-5).*exp(-1.25*(r/0.3).^-4);
D=#(t)(2/pi)*cos(t).^2;
z2=#(r,t)z0(r).*D(t) ;
%range of vlaues of r and theta
r=[0.05,0.071175,0.10132,0.14422,0.2053, 0.29225,0.41602,0.5922,0.84299,1.2];
t=[0,0.62832,1.2566,1.885, 2.5133,3.1416,3.7699,4.3982,5.0265,5.6549,6.2832];
and you want interplation of the test point.
When you sample some data to use them for interpolation you should consider how to sample data according to your requirements.
So when you are sampling a regular grid of polar coordinates ,those coordinates when converted to rectangular will form a circular shape that
most of the points are concentrated in the center of the cricle and when we move from the center to outer regions distance between the points increased.
%regular grid generated for r and t
[THETA R] = meshgrid(t ,r);
% Z for polar grid
Z=z2(R,THETA);
%convert coordinate from polar to cartesian(rectangular):
[X, Y] = pol2cart (THETA, R);
%plot points
plot(X, Y, 'k.');
axis equal
So when you use those point for interpolation the accuracy of the interpolation is greater in the center and lower in the outer regions where the distance between points increased.
In the other word with this sampling method you place more importance on the center region related to outer ones.
To increase accuracy density of grid points (r and theta) should be increased so if length of r and theta is 11 you can create r and theta with size 20 to increase accuracy.
In the other hand if you create a regular grid in rectangular coordinates an equal importance is given to each region . So accuracy of the interpolation will be the same in all regions.
For it first you create a regular grid in the polar coordinates then convert the grid to rectangular coordinates so you can calculate the extents (min max) of the sampling points in the rectangular coordinates. Based on this extents you can create a regular grid in the rectangular coordinates
Regular grid of rectangular coordinates then converted to polar coordinated to get z for grid points using z2 formula.
%get the extent of points
extentX = [min(X(:)) max(X(:))];
extentY = [min(Y(:)) max(Y(:))];
%sample 100 points(or more or less) inside a region specified be the extents
X_samples = linspace(extentX(1),extentX(2),100);
Y_samples = linspace(extentY(1),extentY(2),100);
%create regular grid in rectangular coordinates
[XX YY] = meshgrid(X_samples, Y_samples);
[TT RR] = cart2pol(XX,YY);
Z_rect = z2(RR,TT);
For interpolation of a test point say [ri ti] first it converted to rectangular then using XX ,YY value of z is interpolated
[xi yi] = pol2cart (ti, ri);
z=interp2(XX,YY,Z_rect,xi,yi);
If you have no choice to change how you sample the data and only have a grid of polar points as discussed with #RodyOldenhuis you can do the following:
Interpolate polar coordinates with interp2 (interpolation for gridded data)
this approach is straightforward but has the shortcoming that r and theta are not of the same scale and this may affect the accuracy of the interpolation.
z = interp2(THETA, R, Z, ti, ri)
convert polar coordinates to rectangular and then apply an interpolation method that is for scattered data.
this approach requires more computations but result of it is more reliable.
MATLAB has griddata function that given scattered points first generates a triangulation of points and then creates a regular grid on top of the triangles and interpolates values of grid points.
So if you want to interpolate value of point [ri ti] you should then apply a second interpolation to get value of the point from the interpolated grid.
With the help of some information from spatialanalysisonline and Wikipedia linear interpolation based on triangulation calculated this way (tested in Octave. In newer versions of MATLAB use of triangulation and pointLocation recommended instead of delaunay and tsearch ):
ri=0.53224;
ti = pi/8;
[THETA R] = meshgrid(t ,r);
[X, Y] = pol2cart (THETA, R);
[xi yi] = pol2cart (ti, ri);
%generate triangulation
tri = delaunay (X, Y);
%find the triangle that contains the test point
idx = tsearch (X, Y, tri, xi, yi);
pts= tri(idx,:);
%create a matrix that repesents equation of a plane (triangle) given its 3 points
m=[X(pts);Y(pts);Z(pts);ones(1,3)].';
%calculate z based on det(m)=0;
z= (-xi*det(m(:,2:end)) + yi*det([m(:,1) m(:,3:end)]) + det(m(:,1:end-1)))/det([m(:,1:2) m(:,end)]);
More refinement:
Since it is known that the search point is surrounded by 4 points we can use only those point for triangulation. these points form a trapezoid. Each diagonal of trapezoid forms two triangles so using vertices of the trapezoid we can form 4 triangles, also a point inside a trapezoid can lie in at least 2 triangles.
the previous method based on triangulation only uses information from one triangle but here z of the test point can be interpolated two times from data of two triangles and the calculated z values can be averaged to get a better approximation.
%find 4 points surrounding the test point
ft= find(t<=ti,1,'last');
fr= find(cos(abs(diff(t(ft+(0:1))))/2) .* r < ri,1,'last');
[T4 R4] = meshgrid(t(ft+(0:1)), r(fr+(0:1)));
[X4, Y4] = pol2cart (T4, R4);
Z4 = Z(fr+(0:1),ft+(0:1));
%form 4 triangles
tri2= nchoosek(1:4,3);
%empty vector of z values that will be interpolated from 4 triangles
zv = NaN(4,1);
for h = 1:4
pts = tri2(h,:);
% test if the point lies in the triangle
if ~isnan(tsearch(X4(:),Y4(:),pts,xi,yi))
m=[X4(pts) ;Y4(pts) ;Z4(pts); [1 1 1]].';
zv(h)= (-xi*det(m(:,2:end)) + yi*det([m(:,1) m(:,3:end)]) + det(m(:,1:end-1)))/det([m(:,1:2) m(:,end)]);
end
end
z= mean(zv(~isnan(zv)))
Result:
True z:
(0.0069246)
Linear Interpolation of (Gridded) Polar Coordinates :
(0.0085741)
Linear Interpolation with Triangulation of Rectangular Coordinates:
(0.0073774 or 0.0060992) based on triangulation
Linear Interpolation with Triangulation of Rectangular Coordinates(average):
(0.0067383)
Conclusion:
Result of interpolation related to structure of original data and the sampling method. If the sampling method matches pattern of original data result of interpolation is more accurate, so in cases that grid points of polar coordinates follow pattern of data result of interpolation of regular polar coordinate can be more reliable. But if regular polar coordinates do not match the structure of data or structure of data is such as an irregular terrain, method of interpolation based on triangulation can better represent the data.
please check this example, i used two for loops, inside for loop i used condition statement, if u comment this condition statement and run the program, u'll get correct answer, after u uncomment this condition statement and run the program, u'll get wrong answer. please check it.
% Coordinates
r = linspace(0.05, 1, 10);
t = linspace(0, 2*pi, 8);
% Some synthetic data
%z = sort(rand(50, 24));
z=zeros();
for i=1:10
for j=1:8
if r(i)<0.5||r(i)>1
z(i,j)=0;
else
z(i,j) = r(i).^3'*cos(t(j)/2);
end
end
end
% Values of interest
ri = 0.55;
ti = pi/8;
% Manually interpolate
rp = find(ri <= r, 1, 'first');
rm = find(ri >= r, 1, 'last');
tp = find(ti <= t, 1, 'first');
tm = find(ti >= t, 1, 'last');
drdt = (r(rp) - r(rm)) * (t(tp) - t(tm));
dr = [r(rp)-ri ri-r(rm)];
dt = [t(tp)-ti ti-t(tm)];
fZ = [z(rm, tm) z(rm, tp)
z(rp, tm) z(rp, tp)];
ZI_manual = (dr * fZ * dt.') / drdt
% Interpolate with MATLAB
ZI_MATLAB = interp2(r, t, z', ri, ti, 'linear')
Result:
z1 =
0.1632
ZI_manual =
0.1543
ZI_MATLAB =
0.1582
I have an arbitrary shape, of which the exterior boundary has been traced in MATLAB using bwboundaries. Using regionprops, I can calculate the total area enclosed by this shape.
However, I want to know the area for only the parts of the shape that fall within a circle of known radius R centered at coordinates [x1, y1]. What is the best way to accomplish this?
There are a few ways to approach this. One way you could alter the mask before performing bwboundaries (or regionprops) so that it only includes pixels which are within the given circle.
This example assumes that you already have a logical matrix M that you pass to bwboundaries.
function [A, boundaries] = traceWithinCircle(M, x1, y1, R);
%// Get pixel centers
[x,y] = meshgrid(1:size(M, 1), 1:size(M, 2));
%// Compute their distance from x1, y1
distances = sqrt(sum(bsxfun(#minus, [x(:), y(:)], [x1, y1]).^2, 2));
%// Determine which are inside of the circle with radius R
isInside = distances <= R;
%// Set the values outside of this circle in M to zero
%// This will ensure that they are not detected in bwboundaries
M(~isInside) = 0;
%// Now perform bwboundaries on things that are
%// inside the circle AND were 1 in M
boundaries = bwboundaries(M);
%// You can, however, get the area by simply counting the number of 1s in M
A = sum(M(:));
%// Of if you really want to use regionprops on M
%// props = regionprops(M);
%// otherArea = sum([props.Area]);
end
And as an example
%// Load some example data
data = load('mri');
M = data.D(:,:,12) > 60;
%// Trace the boundaries using the method described above
B = traceWithinCircle(M, 70, 90, 50);
%// Display the results
figure;
hax = axes();
him = imagesc(M, 'Parent', hax);
hold(hax, 'on');
colormap gray
axis(hax, 'image');
%// Plot the reference circle
t = linspace(0, 2*pi, 100);
plot(x1 + cos(t)*R, y1 + sin(t)*R);
%// Plot the segmented boundaries
B = bwboundaries(M);
for k = 1:numel(B)
plot(B{k}(:,2), B{k}(:,1), 'r');
end
I have a problem and maybe you will be able to help me. Like in the title i have cross section data of a symmetric lens - coordinates s=-100:1:100 and height y - and I would like to create 3D plot the whole lens (x,y,z). Is there any build in function that helps with that? Thanks for help in advance!
If I'm understanding correctly, you have a 1-D array that you'd effectively like to 'sweep' around a circle to produce a 3-D plot. Here is an example of how to do that
% Some dummy data
Npts = 100;
z = sin(linspace(0, pi, Npts));
Nreps = 100; % How many times to repeat around circle
% Create polar meshgrid and convert to Cartesian
[r, theta] = meshgrid( ...
linspace(-length(z)/2, length(z)/2, Npts), ...
linspace(0, pi, Nreps));
[X, Y] = pol2cart(theta, r);
% Copy data Nreps times
Z = repmat(z, Nreps, 1);
% Plot!
surf(X, Y, Z)
Without more specs (such as if your y is a 2D matrix or a 1D array), it's not possible to give you the exact answer. However here is how you draw a surface in Matlab:
% create a meshgrid used as the independent variables of your surface
[sx, sy] = meshgrid(-100:100);
% if you have your own 2D matrix, ignore this line.
% if you have a formula, replace this line with your own formula
y = cos(sqrt(((sx/100).^2+(sy/100).^2)/2)*(pi/2));
% draw the surface
surf(sx, sy, y);
To have the opposite side as well, draw another surf on the same figure:
hold on;
surf(sx, sy, -y);
I have a dataset that describes a point cloud of a 3D cylinder (xx,yy,zz,C):
and I would like to make a surface plot from this dataset, similar to this
In order to do this I thought I could interpolate my scattered data using TriScatteredInterp onto a regular grid and then plot it using surf:
F = TriScatteredInterp(xx,yy,zz);
max_x = max(xx); min_x = min(xx);
max_y = max(yy); min_y = min(yy);
max_z = max(zz); min_z = min(zz);
xi = min_x:abs(stepSize):max_x;
yi = min_y:abs(stepSize):max_y;
zi = min_z:abs(stepSize):max_z;
[qx,qy] = meshgrid(xi,yi);
qz = F(qx,qy);
F = TriScatteredInterp(xx,yy,C);
qc = F(qx,qy);
figure
surf(qx,qy,qz,qc);
axis image
This works really well for convex and concave objects but ends in this for the cylinder:
Can anybody help me as to how to achieve a nicer plot?
Have you tried Delaunay triangulation?
http://www.mathworks.com/help/matlab/ref/delaunay.html
load seamount
tri = delaunay(x,y);
trisurf(tri,x,y,z);
There is also TriScatteredInterp
http://www.mathworks.com/help/matlab/ref/triscatteredinterp.html
ti = -2:.25:2;
[qx,qy] = meshgrid(ti,ti);
qz = F(qx,qy);
mesh(qx,qy,qz);
hold on;
plot3(x,y,z,'o');
I think what you are loking for is the Convex hull function. See its documentation.
K = convhull(X,Y,Z) returns the 3-D convex hull of the points (X,Y,Z),
where X, Y, and Z are column vectors. K is a triangulation
representing the boundary of the convex hull. K is of size mtri-by-3,
where mtri is the number of triangular facets. That is, each row of K
is a triangle defined in terms of the point indices.
Example in 2D
xx = -1:.05:1; yy = abs(sqrt(xx));
[x,y] = pol2cart(xx,yy);
k = convhull(x,y);
plot(x(k),y(k),'r-',x,y,'b+')
Use plot to plot the output of convhull in 2-D. Use trisurf or trimesh to plot the output of convhull in 3-D.
A cylinder is the collection of all points equidistant to a line. So you know that your xx, yy and zz data have one thing in common, and that is that they all should lie at an equal distance to the line of symmetry. You can use that to generate a new cylinder (line of symmetry taken to be z-axis in this example):
% best-fitting radius
% NOTE: only works if z-axis is cylinder's line of symmetry
R = mean( sqrt(xx.^2+yy.^2) );
% generate some cylinder
[x y z] = cylinder(ones(numel(xx),1));
% adjust z-range and set best-fitting radius
z = z * (max(zz(:))-min(zz(:))) + min(zz(:));
x=x*R;
y=y*R;
% plot cylinder
surf(x,y,z)
TriScatteredInterp is good for fitting 2D surfaces of the form z = f(x,y), where f is a single-valued function. It won't work to fit a point cloud like you have.
Since you're dealing with a cylinder, which is, in essence, a 2D surface, you can still use TriScatterdInterp if you convert to polar coordinates, and, say, fit radius as a function of angle and height--something like:
% convert to polar coordinates:
theta = atan2(yy,xx);
h = zz;
r = sqrt(xx.^2+yy.^2);
% fit radius as a function of theta and h
RFit = TriScatteredInterp(theta(:),h(:),r(:));
% define interpolation points
stepSize = 0.1;
ti = min(theta):abs(stepSize):max(theta);
hi = min(h):abs(stepSize):max(h);
[qx,qy] = meshgrid(ti,hi);
% find r values at points:
rfit = reshape(RFit(qx(:),qy(:)),size(qx));
% plot
surf(rfit.*cos(qx),rfit.*sin(qx),qy)