平面点群最小包络圆模型与计算(含matlab源码)

版权声明:本文为博主原创文章,转载需注明出处 https://blog.csdn.net/skytruine/article/details/60882966

平面点群最小包络圆模型与计算

1 问题描述

很多材料与口头表述中出现了这样一个句子:“求多边形最小外接圆”。事实上这样的描述是不准确的,多边形的外接圆指与多边形各顶点都相交的圆,若多边形存在外接圆,则外接圆唯一。这句话想表明的意思切确的来说,应该解释为求一个最小的圆,能够覆盖整个多边形。在探讨任意多边形的覆盖问题时,用平面点群来取代多边形,则更具备普适性。因此可将原问题转化为:“求平面点群最小包络圆”。

 

2 数学模型

文字被编辑器吃掉了,我直接上图好了


3 模型求解

3.1 简单算法

不考虑计算的量的情况下,提出一种简单算法。其基本理论基础是①任意点群,相互距离最大的两点必在点群最小包络圆上②最小包络圆与点群至少有两个交点当交点只有两个时,小包络圆距离最大两点的连线为直径④若包络圆与点群中三个及三个以上的点相交包络圆为点群中某三点构成三角形的外接圆。

基于上述基础,算法思想为:先求点群距离最大两点,与其余点组合形成三角形,迭代判别三角形外接圆是否满足条件。

算法步骤如下所示:

STEP 1: 计算点群P的距离矩阵,选取距离最近两点,设为AB

STEP 2: 求以AB为直径的圆O,判断O是否能覆盖所有点,是则输出该圆,否则继续;

STEP 3: 计算所有点到AB的距离,并以距离降序排列点,得到新点群P’;

STEP 4: P中取出当前桟顶的点,与AB构成三角形T,求T的外接圆O,判断O能否覆盖点群P’中的所有点,是则输出当前圆,否则继续迭代,直到桟为空。

3.2 算法优化

上述算法复杂度高,大批量点群无法高效处理。作为一个最优化问题,可以考虑将上述迭代算法变更为遗传算法、牛顿迭代算法或者共轭梯度算法。

另外由于点群凸包的最小包络圆与点群包络圆一致,因此可以求点群的凸包,基于凸包点进行求解,这样可以大大简化计算量。

4 算例与结果

Matlab环境下,通过P=100*rand(100,2)产生100


参考文献

[1]用遗传算法求平面点列的最小包容圆[EB/OL]20170306:http://wenku.baidu.com/view/51e154284b73f242336c5f99.html

[2]知乎:用MATLAB画包络圆[EB/OL]20170306:https://www.zhihu.com/question/27569214

[3]Matlab求三角形外接圆[EB/OL]20170306:http://www.cnblogs.com/tiandsp/p/3995876.html

[4]多边形最小外接圆算法[EB/OL]20170306:

http://wenku.baidu.com/link?url=n-YNirK3qMweJGum3bbvBbBcV9hpnxww0oyyW0TIRqNEjLlodBDWV5PXR1lKkRCCxXe1h9OOHjKilTju89wje1-6shUmr85NcDrsVWA62Xi

[5]Matlab求矩阵最大元素的行列号[EB/OL]20170307:http://blog.csdn.net/llw01/article/details/9263545

附录(Matlab源代码

function [O,r]= main_calcu(P)

%by 武汉大学孙一璠20170307

%本函数是算法主程序用于体现逻辑

 

%计算距离矩阵,找到点群长轴两端点

[A,B]=findLongAxis(P);

%判断以长轴为直径的圆是否能够覆盖所有的点

O(1)=(A(1)+B(1))/2;

O(2)=(A(2)+B(2))/2;

r=sqrt((O(1)-A(1))^2+(O(2)-A(2))^2);

if isContain(P,O,r)

    T=[A;B];

    displayResult(P,O,r,T);

    return;

end

 

%遍历所有其他点,求与AB构成的三角形的外接圆,判断是否能够包含,如果能够包含

d=calcDistance(A,B,P);

P2=[P d];

sortrows(P2,-3);

[m,~]=size(P2);

for i=1:m

    tP=P2(i,1:2);

    T=[A;B;tP];

    [O,r]= triangleCircumcircle(T);

    if isContain(P,O,r)

        displayResult(P,O,r,T);

        return;

    end

end

 

 

end

 

function [A,B]=findLongAxis(P)

    [m,~]=size(P);

    d=ones(m);

    for i=1:m

        for j=1:m

            d(i,j)=sqrt((P(i,1)-P(j,1))^2+(P(i,2)-P(j,2))^2);

        end

    end

    %这里没有考虑多个距离一样的情况,一般情况也能用了

    [lie_max,hanghao]=max(d);

    [~,liehao]=max(lie_max);

    hanghao=hanghao(liehao);

    A=P(hanghao,:);

    B=P(liehao,:);

        

end

 

function flag=isContain(P,O,r)

%用于判断输入圆是否完整地包含了整个点群

[m,~]=size(P);

 flag=true;

 for i=1:m

     if sqrt((O(1)-P(i,1))^2+(O(2)-P(i,2))^2)>r

         flag=false;

         break;

     end

 end

end

 

function d=calcDistance(A,B,P)

%用于求某点与指定线段AB所在直线的距离

a=B(2)-A(2);

b=A(1)-B(1);

c=B(1)*A(2)-B(2)*A(1);

d=abs(a.*P(:,1)+b.*P(:,2)+c)./sqrt(a*a+b*b);

end

 

function displayResult(P,O,r,T)

%本函数用于绘制点群及其最小包络圆

figure;hold on;

rectangle('Position',[O(1)-r,O(2)-r,2*r,2*r],'Curvature',[1,1]);

plot(P(:,1),P(:,2),'markeredgecolor','k','marker','.','linestyle','none');

plot(O(:,1),O(:,2),'markeredgecolor','r','marker','*','linestyle','none');

plot(T(:,1),T(:,2),'markeredgecolor','b','marker','O','linestyle','none');

axis equal;

end

 

function[O,r]= triangleCircumcircle(T)

%本函数用于求解任意三角形的外接圆

%O为圆心,r为半径,T为传入三角形,如[1 2;3 4;5 6]

 

%三角形赋值

xa=T(1,1);ya=T(1,2);

xb=T(2,1);yb=T(2,2);

xc=T(3,1);yc=T(3,2);

%矩阵赋值

A=[xa-xb ya-yb;xa-xc ya-yc];

W=[(xa*xa-xb*xb+ya*ya-yb*yb)/2;(xa*xa-xc*xc+ya*ya-yc*yc)/2];

%求解

O=(A^(-1)*W)';

r=sqrt((O(1,1)-xa)^2+(O(1,2)-ya)^2);

end

猜你喜欢

转载自blog.csdn.net/skytruine/article/details/60882966