这是一个经典的最小覆盖圆算法,但对某些情况存在不能全覆盖的漏洞,所以本然添加了输出最舵覆盖的备用选项,希望能有点用。
clear;
clc;
close all;
%%
xx=rand(10,2);
bianyuan=xx;
z=xx(:,1);
y=xx(:,2);
%grid on%
if length(z)==2 %判定是否只有两个点,如果只有两个点则直接画圆
cc=sqrt(((z(1)-z(2))^2+(y(1)-y(2))^2));
r=cc/2;
a=(z(1)+z(2))/2;
b=(y(1)+y(2))/2;
R=[a b r]
alpha=0:pi/20:2*pi;%角度[0,2*pi]
plot(a+r*cos(alpha),b+r*sin(alpha),'--r');%中心点在(a,b)半径为r的圆
axis equal;
else % 当存在三个及三个以上的点时
[s,d]=size(xx);
for i=1:1:s
for j=i:1:s
summ=0;
for k=1:1:d
summ=summ+(xx(i,k)-xx(j,k))^2; %计算数据集中的点间距,
end
DistanceBO(i,j)=sqrt(summ); %构造出点间距矩阵DistanceBO
end
end
fprintf('算完每个点距离了\n');
for i=1:1:s %找到各个点间距离
for j=i:1:s
DD(i,j)=DistanceBO(i,j);
end
end
aaa=DD(:);
TempSortDistanceBO=sort(aaa); %将距离进行排序
bbb=fliplr(TempSortDistanceBO');
fprintf('排完序号了\n');
%下边找出3个距离最远的点
maxfrist=[];
maxsecond=[];
maxtwo=[];
allmaxfrist=[];
finalpoints=[];
for i=1:1:s %找到相互距离最大的第一个点
for j=i:1:s
if DD(i,j)==bbb(1)
maxfrist=[i j];
end
end
end
fprintf('找到最大距离对应的两个点了\n');
rSet=zeros(10,4);
flag=0;
for i=1:1:s %找到各个点间距离
if i~=maxfrist(1) && i~=maxfrist(2)
finalpoints=[maxfrist i];% 循环取点,直到找到可以全部覆盖的点
A=[z(finalpoints(1)) y(finalpoints(1))];
B=[z(finalpoints(2)) y(finalpoints(2))];
C=[z(finalpoints(3)) y(finalpoints(3))];
R=minCirclePoints3(A,B,C);
rSet(i,:)=[R,i];
rSet=sortrows(rSet,3);%按照半径排序
cr=[R(1),R(2)];
r=zeros(1,length(z));
for i=1:length(z)
r(i)=sqrt((z(i)-cr(1))^2+(y(i)-cr(2))^2);
end
maxValue=max(r); %或者N=max(r(:))
[mc]=find(maxValue==r);%找到最大距离对应的点
if (r(mc)-R(3)<=0.000001)%没有点在圆外,结束回家吃饭去
flag=1;
figure(1)
set(gcf,'color','white');%白色
plot(z,y,'*');hold on;
alpha=0:pi/20:2*pi;%角度[0,2*pi]
plot(R(1)+R(3)*cos(alpha),R(2)+R(3)*sin(alpha),'--r');%中心点在(R(1),R(2))半径为R(3)的圆
axis equal;
title('最小覆盖圆图示')
break
%所有点都被圆覆盖
end
end
end
if flag==0
figure(2)
set(gcf,'color','white');%白色
plot(z,y,'b*');hold on;
alpha=0:pi/20:2*pi;%角度[0,2*pi]
for i=1:length(rSet)
r(i)=rSet(i,3);
end
maxValue=max(r); %或者N=max(r(:))
[n]=find(maxValue==r);%找到最大距离对应的点
plot(rSet(n,1)+rSet(n,3)*cos(alpha),rSet(n,2)+rSet(n,3)*sin(alpha),'--r');%中心点在(R(1),R(2))半径为R(3)的圆
axis equal;
title('备用最小覆盖圆图示')
end
end