How to plot in circle instead of straight line axis in Matlab? - matlab

I have a set of 3 datasets which I want to plot in MATLAB, but the 'x' axis, I want to give in the form of a circle instead of of straight bottom line. Any idea on how to do it?
An example plot:
The normal command for plotting in MATLAB is plot(x, data1, x data2, x, data3), in that the x axis is taken as the straight line. I want the x axis taken as a circle. Does anyone know the command for it please.

#Alok asks if you want a polar plot. I tell you that you do want a polar plot ! See the Matlab documentation for the function polar() and its relations, such as cart2pol. Depending on your exact requirements (I haven't followed your link) you may find it relatively easy or quite difficult to produce exactly the plot you want.

The following is a complete example to show how to map the data from a line axis to a circle.
I show two ways of achieving the goal:
one where the three data series are overlapping (i.e all mapped to the same range)
the other option is to draw them superimposed (on different adjacent ranges)
The basic idea: if you have a series D, then map the points to a circle where the radius is equal to the values of the data using:
theta = linspace(0, 2*pi, N); %# divide circle by N points (length of data)
r = data; %# radius
x = r.*cos(theta); %# x-coordinate
y = r.*sin(theta); %# y-coordinate
plot(x, y, '-');
Option 1
%# some random data
K = 3;
N = 30;
data = zeros(K,N);
data(1,:) = 0.2*randn(1,N) + 1;
data(2,:) = 0.2*randn(1,N) + 2;
data(3,:) = 0.2*randn(1,N) + 3;
center = [0 0]; %# center (shift)
radius = [data data(:,1)]; %# added first to last to create closed loop
radius = normalize(radius',1)'+1; %# normalize data to [0,1] range
figure, hold on
%# draw outer circle
theta = linspace(5*pi/2, pi/2, 500)'; %# 'angles
r = max(radius(:)); %# radius
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
plot(x, y, 'k:');
%# draw mid-circles
theta = linspace(5*pi/2, pi/2, 500)'; %# 'angles
num = 5; %# number of circles
rr = linspace(0,2,num+2); %# radiuses
for k=1:num
r = rr(k+1);
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
plot(x, y, 'k:');
end
%# draw labels
theta = linspace(5*pi/2, pi/2, N+1)'; %# 'angles
theta(end) = [];
r = max(radius(:));
r = r + r*0.2; %# shift to outside a bit
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
str = strcat(num2str((1:N)','%d'),{}); %# 'labels
text(x, y, str, 'FontWeight','Bold');
%# draw the actual series
theta = linspace(5*pi/2, pi/2, N+1);
x = bsxfun(#times, radius, cos(theta)+center(1))';
y = bsxfun(#times, radius, sin(theta)+center(2))';
h = zeros(1,K);
clr = hsv(K);
for k=1:K
h(k) = plot(x(:,k), y(:,k), '.-', 'Color', clr(k,:), 'LineWidth', 2);
end
%# legend and fix axes
legend(h, {'M1' 'M2' 'M3'}, 'location', 'SouthOutside', 'orientation','horizontal')
hold off
axis equal, axis([-1 1 -1 1] * r), axis off
Option 2
%# some random data
K = 3;
N = 30;
data = zeros(K,N);
data(1,:) = 0.2*randn(1,N) + 1;
data(2,:) = 0.2*randn(1,N) + 2;
data(3,:) = 0.2*randn(1,N) + 3;
center = [0 0]; %# center (shift)
radius = [data data(:,1)]; %# added first to last to create closed loop
radius = normalize(radius',1)'; %# normalize data to [0,1] range
radius = bsxfun( #plus, radius, (1:2:2*K)' ); %# 'make serieson seperate ranges by addition
figure, hold on
%# draw outer circle
theta = linspace(5*pi/2, pi/2, 500)'; %# 'angles
r = max(radius(:))+1; %# radius
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
plot(x, y, 'k:');
%# draw mid-circles
theta = linspace(5*pi/2, pi/2, 500)'; %# 'angles
r = 1.5; %# radius
for k=1:K
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
plot(x, y, 'k:');
r=r+2; %# increment radius for next circle
end
%# draw labels
theta = linspace(5*pi/2, pi/2, N+1)'; %# 'angles
theta(end) = [];
r = max(radius(:))+1;
r = r + r*0.2; %# shift to outside a bit
x = r*cos(theta)+center(1);
y = r*sin(theta)+center(2);
str = strcat(num2str((1:N)','%d'),{}); %# 'labels
text(x, y, str, 'FontWeight','Bold');
%# draw the actual series
theta = linspace(5*pi/2, pi/2, N+1);
x = bsxfun(#times, radius, cos(theta)+center(1))';
y = bsxfun(#times, radius, sin(theta)+center(2))';
h = zeros(1,K);
clr = hsv(K);
for k=1:K
h(k) = plot(x(:,k), y(:,k), '.-', 'Color', clr(k,:), 'LineWidth', 2);
end
%# legend and fix axes
legend(h, {'M1' 'M2' 'M3'}, 'location', 'SouthOutside', 'orientation','horizontal')
hold off
axis equal, axis([-1 1 -1 1] * r), axis off
I should mention that normalize() is a custom function, it simply performs minmax normalization ((x-min)/(max-min)) defined as:
function newData = normalize(data, type)
[numInst numDim] = size(data);
e = ones(numInst, 1);
minimum = min(data);
maximum = max(data);
range = (maximum - minimum);
if type == 1
%# minmax normalization: (x-min)/(max-min) => x in [0,1]
newData = (data - e*minimum) ./ ( e*(range+(range==0)) );
end
%# (...)
end

You can find here all available MATLAB 2-D and 3-D plot functions.

Sorry, if it may be not a proper answer to your question (you already have plenty). I recently found very powerful tool to plot on circle - CIRCOS: http://mkweb.bcgsc.ca/circos/
Have a look, figures are really amazing. It's not Matlab-based, but Perl, and it's free. May be you will find it useful.

Related

Random Points in an n-Dimensional Hypersphere

This Matlab code,
creates a set of random points defined by Cartesian coordinates and
uniformly distributed over the interior of an n-dimensional
hypersphere of radius r with center at the origin.
the source is here.
clear all
clc
m = 20000;
n = 2;
r = 2;
%// generate circle boundary
C = [3 4]; %// center [x y]
t = linspace(0, 2*pi, 100);
x = r*cos(t) + C(1);
y = r*sin(t) + C(2);
C_rep = repmat( C,m,1);
X = randn(m,n);
s2 = sum(X.^2,2);
X = X.*repmat(r*(rand(m,1).^(1/n))./sqrt(s2),1,n)+ C_rep;
%% Plot
figure(1), clf
plot(x,y,'b')
hold on
plot(C(1),C(2),'r.', 'MarkerSize', 50) % center point
hold on
plot(X(:,1),X(:,2),'g.','markersize',2);
axis equal;zoom off; zoom on;drawnow;shg;
ax = axis;
This is the output:
which is not what I want.
How to make the points distributed around a center point C?
When n = 2, 3, 4, k dimentions
What does s2 mean?

hexagonal lattice which is randomly colored with black and white color

I am trying to draw a (10,000 x 10,000) hexagonal lattice which is randomly half black and half white.I don't know how to fill hexagons of this lattice randomly to black and white.(this is a sample of what i really want from this code but I couldn't make it.).here is the code(written in matlab):
clc
x=input('enter the value of x: ');
y=input('enter the value of y: ');
r=input('enter the value of R: ');
n=input('enter the value of N: ');
d=sqrt(3*n)*r
axis([0 x 0 y ])
c=r;
v=30:60:390;
cv=r*cosd(v);
sv=r*sind(v);
for y=0:2:y
for w=0:2:x
line(w*sqrt(3)/2*c+cv,y*1.5*c+sv,'tag','h');
end
end
for m=1:2:y
for k=1:2:x
line(k*sqrt(3)/2*c+cv,m*1.5*c+sv,'tag','h');
end
end
can anyone help me through this?
Not recommended!
You can achieve your desired output using fill and by coordinating through the lattice correctly:
m = 100; % horizontal count
n = 50; % vertical count
blackratio = 0.5; % here you can choose the ratio of black hexagons
% parametric definition of a hexagon
t = (1/12:1/6:1)'*2*pi;
x = cos(t);
y = sin(t);
blacks = rand(m, n) < blackratio;
d=sqrt(3)/2;
figure;
hold on
for ii = 1:m
for jj = 1:n
if blacks(ii, jj)
% draw a black hexagon
fill(x + d*(mod(2*ii+jj, 2*m)), y+1.5*jj, 'k', 'EdgeColor', 'None')
else
% draw a white hexagon
fill(x + d*(mod(2*ii+jj, 2*m)), y+1.5*jj, 'w', 'EdgeColor', 'None')
end
end
end
axis equal tight off
With this output:
Note that on my laptop for 100x50 it took 6 seconds to get the result. For 1000x1000 my computer crashed.
The second fill function in my code replaces the transparency with white color. If you are fine with having transparency instead of white filling, you can remove this part of the code and double the speed.
You can plot multiple filled polygons using patch. This approach is extremely faster than drawing hexagons with fill one by one in a loop.
m = 100; % horizontal count
n = 50; % vertical count
blackratio = 0.5; % here you can choose the ratio of black hexagons
blacks = rand(m, n) > blackratio;
hexcount = sum(blacks(:));
whitecount = m * n - hexcount;
% parametric definition of a hexagon
t = (1/12:1/6:1)' * 2 * pi;
x = cos(t);
y = sin(t);
% coordinates of all black hexagons
Xb = zeros(6, hexcount);
Yb = zeros(6, hexcount);
% coordinates of all white hexagons
Xw = zeros(6, whitecount);
Yw = zeros(6, whitecount);
d=sqrt(3)/2;
bcount = 0;
wcount = 0;
for ii = 1:m
for jj = 1:n
if blacks(ii, jj)
bcount = bcount + 1;
Xb(:, bcount) = x + d * (mod(2 * ii + jj, 2 * m));
Yb(:, bcount) = y + 1.5 * jj;
else
wcount = wcount + 1;
Xw(:, wcount) = x + d * (mod(2 * ii + jj, 2 * m));
Yw(:, wcount) = y + 1.5 * jj;
end
end
end
figure; hold on
patch(Xb, Yb, 'k', 'EdgeColor', 'None')
patch(Xw, Yw, 'w', 'EdgeColor', 'None')
axis equal off
This gives you the desired output:

Create random unit vector inside a defined conical region

I'm looking for a simple way for creating a random unit vector constrained by a conical region. The origin is always the [0,0,0].
My solution up to now:
function v = GetRandomVectorInsideCone(coneDir,coneAngleDegree)
coneDir = normc(coneDir);
ang = coneAngleDegree + 1;
while ang > coneAngleDegree
v = [randn(1); randn(1); randn(1)];
v = v + coneDir;
v = normc(v);
ang = atan2(norm(cross(v,coneDir)), dot(v,coneDir))*180/pi;
end
My code loops until the random generated unit vector is inside the defined cone. Is there a better way to do that?
Resultant image from test code bellow
Resultant frequency distribution using Ahmed Fasih code (in comments).
I wonder how to get a rectangular or normal distribution.
c = [1;1;1]; angs = arrayfun(#(i) subspace(c, GetRandomVectorInsideCone(c, 30)), 1:1e5) * 180/pi; figure(); hist(angs, 50);
Testing code:
clearvars; clc; close all;
coneDir = [randn(1); randn(1); randn(1)];
coneDir = [0 0 1]';
coneDir = normc(coneDir);
coneAngle = 45;
N = 1000;
vAngles = zeros(N,1);
vs = zeros(3,N);
for i=1:N
vs(:,i) = GetRandomVectorInsideCone(coneDir,coneAngle);
vAngles(i) = subspace(vs(:,i),coneDir)*180/pi;
end
maxAngle = max(vAngles);
minAngle = min(vAngles);
meanAngle = mean(vAngles);
AngleStd = std(vAngles);
fprintf('v angle\n');
fprintf('Direction: [%.3f %.3f %.3f]^T. Angle: %.2fº\n',coneDir,coneAngle);
fprintf('Min: %.2fº. Max: %.2fº\n',minAngle,maxAngle);
fprintf('Mean: %.2fº\n',meanAngle);
fprintf('Standard Dev: %.2fº\n',AngleStd);
%% Plot
figure;
grid on;
rotate3d on;
axis equal;
axis vis3d;
axis tight;
hold on;
xlabel('X'); ylabel('Y'); zlabel('Z');
% Plot all vectors
p1 = [0 0 0]';
for i=1:N
p2 = vs(:,i);
plot3ex(p1,p2);
end
% Trying to plot the limiting cone, but no success here :(
% k = [0 1];
% [X,Y,Z] = cylinder([0 1 0]');
% testsubject = surf(X,Y,Z);
% set(testsubject,'FaceAlpha',0.5)
% N = 50;
% r = linspace(0, 1, N);
% [X,Y,Z] = cylinder(r, N);
%
% h = surf(X, Y, Z);
%
% rotate(h, [1 1 0], 90);
plot3ex.m:
function p = plot3ex(varargin)
% Plots a line from each p1 to each p2.
% Inputs:
% p1 3xN
% p2 3xN
% args plot3 configuration string
% NOTE: p1 and p2 number of points can range from 1 to N
% but if the number of points are different, one must be 1!
% PVB 2016
p1 = varargin{1};
p2 = varargin{2};
extraArgs = varargin(3:end);
N1 = size(p1,2);
N2 = size(p2,2);
N = N1;
if N1 == 1 && N2 > 1
N = N2;
elseif N1 > 1 && N2 == 1
N = N1
elseif N1 ~= N2
error('if size(p1,2) ~= size(p1,2): size(p1,2) and/or size(p1,2) must be 1 !');
end
for i=1:N
i1 = i;
i2 = i;
if i > N1
i1 = N1;
end
if i > N2
i2 = N2;
end
x = [p1(1,i1) p2(1,i2)];
y = [p1(2,i1) p2(2,i2)];
z = [p1(3,i1) p2(3,i2)];
p = plot3(x,y,z,extraArgs{:});
end
Here’s the solution. It’s based on the wonderful answer at https://math.stackexchange.com/a/205589/81266. I found this answer by googling “random points on spherical cap”, after I learned on Mathworld that a spherical cap is this cut of a 3-sphere with a plane.
Here’s the function:
function r = randSphericalCap(coneAngleDegree, coneDir, N, RNG)
if ~exist('coneDir', 'var') || isempty(coneDir)
coneDir = [0;0;1];
end
if ~exist('N', 'var') || isempty(N)
N = 1;
end
if ~exist('RNG', 'var') || isempty(RNG)
RNG = RandStream.getGlobalStream();
end
coneAngle = coneAngleDegree * pi/180;
% Generate points on the spherical cap around the north pole [1].
% [1] See https://math.stackexchange.com/a/205589/81266
z = RNG.rand(1, N) * (1 - cos(coneAngle)) + cos(coneAngle);
phi = RNG.rand(1, N) * 2 * pi;
x = sqrt(1-z.^2).*cos(phi);
y = sqrt(1-z.^2).*sin(phi);
% If the spherical cap is centered around the north pole, we're done.
if all(coneDir(:) == [0;0;1])
r = [x; y; z];
return;
end
% Find the rotation axis `u` and rotation angle `rot` [1]
u = normc(cross([0;0;1], normc(coneDir)));
rot = acos(dot(normc(coneDir), [0;0;1]));
% Convert rotation axis and angle to 3x3 rotation matrix [2]
% [2] See https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
crossMatrix = #(x,y,z) [0 -z y; z 0 -x; -y x 0];
R = cos(rot) * eye(3) + sin(rot) * crossMatrix(u(1), u(2), u(3)) + (1-cos(rot))*(u * u');
% Rotate [x; y; z] from north pole to `coneDir`.
r = R * [x; y; z];
end
function y = normc(x)
y = bsxfun(#rdivide, x, sqrt(sum(x.^2)));
end
This code just implements joriki’s answer on math.stackexchange, filling in all the details that joriki omitted.
Here’s a script that shows how to use it.
clearvars
coneDir = [1;1;1];
coneAngleDegree = 30;
N = 1e4;
sol = randSphericalCap(coneAngleDegree, coneDir, N);
figure;plot3(sol(1,:), sol(2,:), sol(3,:), 'b.', 0,0,0,'rx');
grid
xlabel('x'); ylabel('y'); zlabel('z')
legend('random points','origin','location','best')
title('Final random points on spherical cap')
Here is a 3D plot of 10'000 points from the 30° spherical cap centered around the [1; 1; 1] vector:
Here’s 120° spherical cap:
Now, if you look at the histogram of the angles between these random points at the coneDir = [1;1;1], you will see that the distribution is skewed. Here’s the distribution:
Code to generate this:
normc = #(x) bsxfun(#rdivide, x, sqrt(sum(x.^2)));
mysubspace = #(a,b) real(acos(sum(bsxfun(#times, normc(a), normc(b)))));
angs = arrayfun(#(i) mysubspace(coneDir, sol(:,i)), 1:N) * 180/pi;
nBins = 16;
[n, edges] = histcounts(angs, nBins);
centers = diff(edges(1:2))*[0:(length(n)-1)] + mean(edges(1:2));
figure('color','white');
bar(centers, n);
xlabel('Angle (degrees)')
ylabel('Frequency')
title(sprintf('Histogram of angles between coneDir and random points: %d deg', coneAngleDegree))
Well, this makes sense! If you generate points from the 120° spherical cap around coneDir, of course the 1° cap is going to have very few of those samples, whereas the strip between the 10° and 11° caps will have far more points. So what we want to do is normalize the number of points at a given angle by the surface area of the spherical cap at that angle.
Here’s a function that gives us the surface area of the spherical cap with radius R and angle in radians theta (equation 16 on Mathworld’s spherical cap article):
rThetaToH = #(R, theta) R * (1 - cos(theta));
rThetaToS = #(R, theta) 2 * pi * R * rThetaToH(R, theta);
Then, we can normalize the histogram count for each bin (n above) by the difference in surface area of the spherical caps at the bin’s edges:
figure('color','white');
bar(centers, n ./ diff(rThetaToS(1, edges * pi/180)))
The figure:
This tells us “the number of random vectors divided by the surface area of the spherical segment between histogram bin edges”. This is uniform!
(N.B. If you do this normalized histogram for the vectors generated by your original code, using rejection sampling, the same holds: the normalized histogram is uniform. It’s just that rejection sampling is expensive compared to this.)
(N.B. 2: note that the naive way of picking random points on a sphere—by first generating azimuth/elevation angles and then converting these spherical coordinates to Cartesian coordinates—is no good because it bunches points near the poles: Mathworld, example, example 2. One way to pick points on the entire sphere is sampling from the 3D normal distribution: that way you won’t get bunching near poles. So I believe that your original technique is perfectly appropriate, giving you nice, evenly-distributed points on the sphere without any bunching. This algorithm described above also does the “right thing” and should avoid bunching. Carefully evaluate any proposed algorithms to ensure that the bunching-near-poles problem is avoided.)
it is better to use spherical coordinates and convert it to cartesian coordinates:
coneDirtheta = rand(1) * 2 * pi;
coneDirphi = rand(1) * pi;
coneAngle = 45;
N = 1000;
%perfom transformation preventing concentration of points around the pole
rpolar = acos(cos(coneAngle/2*pi/180) + (1-cos(coneAngle/2*pi/180)) * rand(N, 1));
thetapolar = rand(N,1) * 2 * pi;
x0 = rpolar .* cos(thetapolar);
y0 = rpolar .* sin(thetapolar);
theta = coneDirtheta + x0;
phi = coneDirphi + y0;
r = rand(N, 1);
x = r .* cos(theta) .* sin(phi);
y = r .* sin(theta) .* sin(phi);
z = r .* cos(phi);
scatter3(x,y,z)
if all points should be of length 1 set r = ones(N,1);
Edit:
since intersection of cone with sphere forms a circle first we create random points inside a circle with raduis of (45 / 2) in polar coordinates and as #Ahmed Fasih commented to prevent concentration of points near the pole we should first transform this random points, then convert polar to cartesian 2D coordinates to form x0 and y0
we can use x0 and y0 as phi & theta angle of spherical coordinates and add coneDirtheta & coneDirphi as offsets to these coordinates.
then convert spherical to cartesian 3D coordinates

How to plot a filled circle?

The below code plots circles in Matlab. How can I specify the MarkerEdgeColor and MarkerFaceColor in it.
function plot_model
exit_agents=csvread('C:\Users\sony\Desktop\latest_mixed_crowds\December\exit_agents.csv');
%scatter(exit_agents(:,2),exit_agents(:,3),pi*.25^2,'filled');
for ii =1:size(exit_agents,1),
circle(exit_agents(ii,2),exit_agents(ii,3),0.25);
end
end
function h = circle(x,y,r)
hold on
th = 0:pi/50:2*pi;
xunit = r * cos(th) + x;
yunit = r * sin(th) + y;
h = plot(xunit, yunit);
hold off
end
Using plot and scatter scales them weirdly when zooming. This is not what I wish for.
There are various options to plot circles. The easiest is, to actually plot a filled rectangle with full curvature:
%// radius
r = 2;
%// center
c = [3 3];
pos = [c-r 2*r 2*r];
r = rectangle('Position',pos,'Curvature',[1 1], 'FaceColor', 'red', 'Edgecolor','none')
axis equal
With the update of the graphics engine with R2014b this is really smooth:
If you have an older version of Matlab than R2014b, you will need to stick with your trigonometric approach, but use fill to get it filled:
%// radius
r = 2;
%// center
c = [3 3];
%// number of points
n = 1000;
%// running variable
t = linspace(0,2*pi,n);
x = c(1) + r*sin(t);
y = c(2) + r*cos(t);
%// draw filled polygon
fill(x,y,[1,1,1],'FaceColor','red','EdgeColor','none')
axis equal
The "resolution" can be freely scaled by the number of points n.
Your function could then look like
function h = circle(x,y,r,MarkerFaceColor,MarkerEdgeColor)
hold on
c = [x y];
pos = [c-r 2*r 2*r];
r = rectangle('Position',pos,'Curvature',[1 1], ...
'FaceColor', MarkerFaceColor, 'Edgecolor',MarkerEdgeColor)
hold off
end

In matlab, how to use k means to make 30 clusters with circle around each cluster and mark the center?

In matlab, if I have a code which draws a circle and generates 100 random points inside it. I want to use k means to cluster these 100 points into 30 clusters with a circle around each cluster to differentiate between the clusters and i want to mark the center if each cluster.this is the code of the circle and the 100 random points inside it . Any help please ?
%// Set parameters
R =250; %// radius
C = [0 0]; %// center [x y]
N = 100; %// number of points inside circle
%// generate circle boundary
t = linspace(0, 2*pi,100);
x = R*cos(t) + C(1);
y = R*sin(t) + C(2);
%// generate random points inside it
th = 2*pi*rand(N,1);
r = R*randnlimit(0, 1, 0.5, 1, [N 1]);
xR = r.*cos(th) + C(1);
yR = r.*sin(th) + C(2);
%// Plot everything
figure(1), clf, hold on
% subplot(1,N0,1);
plot(x,y,'b');
hold on
text(0,0,'C')
plot(xR,yR,'p')
axis equal
zR=cell(N,1);
for i=1:N
zR{i,1}= [xR(i) yR(i)];
end
m=cell2mat(zR);
function clusterCircle()
%// Set parameters
R = 250; %// radius
C = [0 0]; %// center [x y]
N = 100; %// number of points inside circle
k = 30; %// number of clusters
%// generate circle boundary
t = linspace(0, 2*pi, 100);
x = R*cos(t) + C(1);
y = R*sin(t) + C(2);
%// generate random points inside it
th = 2*pi*rand(N,1);
r = R*randnlimit(0, 1, 0.5, 1, [N 1]);
xR = r.*cos(th) + C(1);
yR = r.*sin(th) + C(2);
%// some simple k-means:
% initial centroids:
% -> use different method, if k > N
% -> can be done more reasonable (e.g. run k-Means for different
% seeds, select seeds equidistant, etc.)
xC = xR(1:k)';
yC = yR(1:k)';
% run:
clusters = zeros(N,1);
clusters_old = ones(N,1);
while sum((clusters - clusters_old).^2) > 0
clusters_old = clusters;
[~,clusters] = min((bsxfun(#minus,xR,xC)).^2 + ...
(bsxfun(#minus,yR,yC)).^2 , [] , 2);
for kIdx = 1:k
xC(kIdx) = mean(xR(clusters==kIdx));
yC(kIdx) = mean(yR(clusters==kIdx));
end
end
%// Plot everything
figure(1);
clf;
hold on;
% -> plot circle and center
text(C(1),C(2),'C');
plot(x,y,'k');
% -> plot clusters
co = hsv(k);
for kIdx = 1:k
% plot cluster points
plot(xR(clusters==kIdx),yR(clusters==kIdx),'p','Color',co(kIdx,:));
% plot cluster circle
maxR = sqrt(max((xR(clusters==kIdx)-xC(kIdx)).^2 + ...
(yR(clusters==kIdx)-yC(kIdx)).^2));
x = maxR*cos(t) + xC(kIdx);
y = maxR*sin(t) + yC(kIdx);
plot(x,y,'Color',co(kIdx,:));
% plot cluster center
text(xC(kIdx),yC(kIdx),num2str(kIdx));
end
axis equal
end
%// creates random numbers, not optimized!
function rn = randnlimit(a,b,mu,sigma,sz)
rn = zeros(sz);
for idx = 1:prod(sz)
searchOn = true;
while searchOn
rn_loc = randn(1) * sigma + mu;
if rn_loc >= a && rn_loc <= b
searchOn = false;
end
end
rn(idx) = rn_loc;
end
end