create circles on a spline - matlab

I need a little information regarding creation of elements in the form of either circles or Hexagon along the entire spline as shown in below image in Matlab. Can you tell me how can i implement this in my code.
Please find the below code with respect to spline creation
x = -4:4;
y = [0 .15 1.12 2.36 2.36 1.46 .49 .06 0];
cs = spline(x,[0 y 0]);
xx = linspace(-4,4,101);
plot(x,y,'o',xx,ppval(cs,xx),'-');
Please let me know incase any additional information is required

Well since you already know the locations at which you want to plot the circles (the [x,y] array) you can replicate part of the plot code you used but this time use larger markers and a different color:
hold on
plot(x,y,'o',xx,ppval(cs,xx),'-');
plot(x,y,'o','MarkerSize',80,'Color','g');
which looks like this:
You can use the 'hexagram' marker as well (i.e. use h instead of o) to get an hexagon:
Or if you want each circle to look different or control their properties individually you can also plot a rectangle with a curvature of [1 1]:
radius = .5;
for k = 1:numel(x)
centerX = x(k);
centerY = y(k);
rectangle('Position',[centerX - radius, centerY - radius, radius*2, radius*2],...
'Curvature',[1 1],...
'EdgeColor','g','FaceColor','none');
end

Related

Plotting circles with complex numbers in MATLAB

I want to make a figure in MATLAB as described in the following image
What I did is the following:
x = [1 2 3];
y = [2 2 4];
radius = [1 1.2 2.2];
theta = [-pi 0 pi];
figure;
scatter(x,y,radius)
How do I add an angle theta to the plot to represent a complex number z = radius.*exp(1j*theta) at every spacial coordinates?
Technically speaking, those are only circles if x and y axes are scaled equally. That is because scatter always plots circles, independently of the scales (and they remain circles if you zoom in nonuniformly. + you have the problem with the line, which should indicate the angle...
You can solve both issues by drawing the circles:
function plotCirc(x,y,r,theta)
% calculate "points" where you want to draw approximate a circle
ang = 0:0.01:2*pi+.01;
xp = r*cos(ang);
yp = r*sin(ang);
% calculate start and end point to indicate the angle (starting at math=0, i.e. right, horizontal)
xt = x + [0 r*sin(theta)];
yt = y + [0 r*cos(theta)];
% plot with color: b-blue
plot(x+xp,y+yp,'b', xt,yt,'b');
end
having this little function, you can call it to draw as many circles as you want
x = [1 2 3];
y = [2 2 4];
radius = [1 1.2 2.2];
theta = [-pi 0 pi];
figure
hold on
for i = 1:length(x)
plotCirc(x(i),y(i),radius(i),theta(i))
end
I went back over scatter again, and it looks like you can't get that directly from the function. Hopefully there's a clean built-in way to do this, and someone else will chime in with it, but as a backup plan, you can just add the lines yourself.
You'd want a number of lines that's the same as the length of your coordinate set, from the center point to the edge at the target angle, and fortunately 'line' does multiple lines if you feed it a matrix.
You could just tack this on to the end of your code to get the angled line:
x_lines = [x; x + radius.*cos(theta)];
y_lines = [y; y + radius.*sin(theta)];
line(x_lines, y_lines, 'Color', 'b')
I had to assign the color specifically, since otherwise 'line' makes each new line cycle through the default colors, but that also means you could easily change the line color to stand out more. There's also no center dot, but that'd just be a second scatter plot with tiny radius. Should plot most of what you're looking for, at least.
(My version of Matlab is old enough that scatter behaves differently, so I can only check the line part, but they have the right length and location.)
Edit: Other answer makes a good point on whether scatter is appropriate here. Probably better to draw the circle too.

Moving the "anchor point" of patches in Matlab surf-plots

MWE below
I'm plotting an energy surface using Matlabs surf function. I first create my data points at various azimuthal and elevation angles, and next I convert these to an (x,y,z)-coordinate using the usual spherical-to-cartesian equations, and reshape the coordinates into a matrix.
However, when I plot this, I find that all data points are represented as the lower left corner of a "patch" of color, instead of centrally in the patch of color.
However, when I am scaling the radius of the surface to reflect the energy at that point, any dimples in the surface has all messed up colors due to this effect, i.e. any symmetry of the data is lost in the visualization. I would like this dimple to have roughly symmetrical color around the deepest point here.
The example shown is with the conversion from spherical to cartesian coordinates shifted by half the angular difference between two data points - this means that patches are centered around the right spot, but the coloring is still off.
Is there a way to "center" the colored patches on the exact direction that the data was taken?
scaling = 100;
min_val = 0.5
count = 1;
azstep = 10;
elstep = 10;
az = 0:azstep:360;
el = -90:elstep:90;
for ii = 1:length(az)
for jj = 1:length(el)
if any(az(ii) == [260 270 280]) && any(el(jj) == [-10 0 10])
r_output(count) = 0.8;
else
r_output(count) = 1;
end
c(count) = r_output(count);
r(count) = 1 + scaling.*(r_output(count)/min_val) - scaling;
x(count) = (r(count)) .* cosd(el(jj)) .* cosd(az(ii));
y(count) = (r(count)) .* cosd(el(jj)) .* sind(az(ii));
z(count) = (r(count)) .* sind(el(jj));
count = count + 1;
end
end
X = reshape(x,length(el),length(az));
Y = reshape(y,length(el),length(az));
Z = reshape(z,length(el),length(az));
C = reshape(c,length(el),length(az));
figure
hold on
surf(X,Y,Z,C)
colorbar
axis equal
xlabel('X axis'); ylabel('Y axis'); zlabel('Z axis');
Result from code above
Change the shading!
Adding shading interp in the end of your code produces the following image:
if you want the lines, then change the surf call to:
h=surf(X,Y,Z,C)
colorbar
shading interp
set(h','edgecolor','k')
as shading will remove them.
Note that you still get some artefacts in some corners. They seem to be generated by floating point errors when interpolating, so the only way of improving them seems to be just making a more densely populated sphere.

Rotating a Plot About the Y Axis

I have a vector of values that I want to plot as brightness on a circle through the radius of it (I.e. If it was 0 3 1 5 I'd want a circle that was dark at the centre, then a bright ring around it, then a slightly darker ring, then a brighter ring).
To do this I've attempted to rotate my radial vector (E) around the y axis, as such
[X,Y,Z] = cylinder(E);
h = surf(X,Y,Z),
However I'm clearly not doing it right, as this appears to be rotating my curve around the x axis. I've tried just swapping X and Y, but it still rotates it around the x axis. Any help would be greatly appreciated.
One way would be to rotate your vector and create a surface. The Z data of the surface (your rotated vector) will be color coded according to the colormap you choose, if you display the surface from the top you get your circles at the different brightness.
If you are really only interested from the "top view" of this surface, then no need to create a full surface, a simple pcolor will do the job.
example:
%% // input data (and assumptions)
E=[0 3 1 5 2 7];
nBrightness = 10 ; %// number of brightness levels
r = (0:numel(E)) ; %// radius step=1 by default for consecutive circles
%// otherwise define different thickness for each circle
So if I use stairs([E 0]) you get your different brightness levels:
I had to add a last 0 to the vector to "close" the last level, we'll have to do that again in the solution below.
Now to rotate/replicate that around Y, color code the height, and look at it from the top:
%% // replicate profile around axis
ntt = 50 ; %// define how many angular division for the plot
theta = linspace(0,2*pi,ntt) ; %// create all the angular divisions
[rr,tt]=meshgrid(r,theta) ; %// generate a grid
z = repmat( [E 0] , ntt , 1 ) ; %// replicate our "E" vector to match the grid
[xx,yy,zz] = pol2cart(tt,rr,z) ; %// convert everything to cartesian coordinates
pcolor(xx,yy,zz) %// plot everything
colormap(gray(nBrightness)) %// make sure we use only "nBrightness" colors (Shades of gray)
caxis([0 nBrightness])
shading flat ; axis equal %// refine the view (axis ratio and "spokes" not visible) etc...
colorbar
axis off
will yield the following :
Note that your problem was not fully defined, I had to take assumptions on:
What radius each brightness circle should have ? (I made them all the same but you can modify that)
How many brightness levels you want ? (You can also modify that easily though).
Have you tried the rotate function?
direction = [0 1 0];
rotate(h,direction,90);
In this example a 90 degree rotation is performed around the y axis.
Using this library http://www.mathworks.com/matlabcentral/fileexchange/45952-circle-plotter
%http://www.mathworks.com/matlabcentral/fileexchange/45952-circle-plotter
x0 = 0;
y0 = 0;
colors = [0 3 1 5];
maxC = max(colors);
sz = numel(colors);
for i=fliplr(1:sz)
c = colors(i);
circles(x0,y0,i,'facecolor',[c/maxC c/maxC 0]) % http://au.mathworks.com/help/matlab/ref/colorspec.html
end

3d plot with axes of same length

I have some 3D trajectories I want to plot.
Since they vary a lot in XY, but much less in Z, the default plot3 is misleading, because it automatically scales axes.
I've been told to use axes equal but it has no effect (see the commented line where I used it).
I came up with this code, which in my opinion is very long to achieve a so simple task:
[D,rate]=read_vicon_ascii('csvdata/a1-0.csv');
% or replace above line with D=csvread('stackoverflow-31289872.csv');
% get stackoverflow-31289872.csv at https://drive.google.com/file/d/0B5GjKiDZk3F5UHlVQUxKeFo4SG8/view?pli=1
% indices of X,Y,Z columns
X = 1+(2:3:14);
Y = 2+(2:3:14);
Z = 3+(2:3:14);
Bounds = [ min(min(D(:,X))) max(max(D(:,X)))
min(min(D(:,Y))) max(max(D(:,Y)))
min(min(D(:,Z))) max(max(D(:,Z))) ];
MaxDelta = max(Bounds(:,2)-Bounds(:,1));
SquareBounds = Bounds;
for xyz=1:3
Delta = SquareBounds(xyz,2) - SquareBounds(xyz,1);
SquareBounds(xyz,:) = SquareBounds(xyz,:) + (MaxDelta - Delta) * [-0.5 0.5];
end
figure
hold on
for i=1:5
plot3(D(:,X(i)),D(:,Y(i)),D(:,Z(i)),'r-')
end
xlim(SquareBounds(1,:))
ylim(SquareBounds(2,:))
zlim(SquareBounds(3,:))
%axes equal
hold off
Is there any way to make it better. (or a correct usage of axes equal if that does what is supoosed to do?)

Programmatically producing polar or quasi-polar plots with a variable for color in matlab

I would like to create plots using matlab that represent a numerical assessment of quality in a radial fashion.
The best method I've found seems to not work properly. One runs the following code:
theta = (0 : (360/11) : 360)*pi/180;
r = 0 : 2 : 20 ;
[TH,R] = meshgrid(theta,r);
[X,Y] = pol2cart(TH,R);
Z = meshgrid(Data);
surf(X,Y,Z);
Data is a vector of data containing 11 numbers, an example dataset being the following:
Data = 0.884, 0.882, 0.879, 0.880, 0.8776, 0.871, 0.8587, 0.829, 0.811, 0.803, 0.780
the output of surf here is this:
I would like to produce a more refined version of this type of image:
which I have generated with the following code:
for theta = 0 : pi/100 : pi;
v = [InterpolatedImageHeight;LengthVector];
x_center = InterpolatedImageHeight((HorizontalRes+1)/2);
y_center = 0; %InterpolatedImageHeight((HorizontalRes+1)/2);
center = repmat([x_center; y_center], 1, length(InterpolatedImageHeight));
R = [cos(theta) -sin(theta); sin(theta) cos(theta)];
vo = R*(v - center) + center;
x_rotated = vo(1,:);
y_rotated = vo(2,:);
scatter(x_rotated,y_rotated,DotSize,InterpolatedData,'filled'); %x,y,area,color,properties
end
The issue with this is that it is a scatter plot where I am essentially using plot(r,Data), plotting many many copies, and increasing the dot size. The graphic itself has many seams, this takes an enormous amount of memory, and is time intensive where surf or mesh will run extremely fast and take minimal memory.
How does one produce concentric rings with a variable input for color?
There are two completely different plots in your question. The first one represents the data as rays from the origin towards the outside of the circle. The data-points are placed anti-clockwise. A refined version of this can be achieved like this:
Data = [0.884, 0.882, 0.879, 0.880, 0.8776, 0.871,...
0.8587, 0.829, 0.811, 0.803, 0.780];
theta = linspace(0,2*pi,length(Data));
r = linspace(0,20,length(Data));
[TH,R] = meshgrid(theta,r);
Z = meshgrid(Data);
[X,Y,Z] = pol2cart(TH,R,Z);
surf(X,Y,Z);
view(2);
shading interp
Note that I used linspace to generate theta and r to always match the length of Data. Z is also passed trough pol2cart. Then you can use shading interp to remove the lines between the patches and interpolate the color. With view(2) you can set the perspective as you would have a 2d-plot.
This is the result:
It's relatively easy to get a result like in your second example. There the data-points represent concentric circles around the origin and are placed from the origin towards the outside. Therefore, just transpose the meshgrid of Z by using the following line:
Z = meshgrid(Data)';
This is the result then:
based on the code by Darren Rowland in this thread I have come up with the following solution:
x = interp1(1:length(data),datax,(datax(1):datax(end)/f:datax(end)),'linear');
y = interp1(1:length(datay),datay,datay(1):datay(end)/f:datay(end),'spline');
theta = linspace(0,2*pi,n);
xr = x.'*cos(theta);
zr = x.'*sin(theta);
yr = repmat(y.',1,n);
figure;
surf(xy,yr,zr,zr*numcolors);
which is elegant, runs quickly, and produces beautiful figures. This is a sample of the output with some extra chart elements: