文章目录

  • 一、问题描述
  • 二.MATLAB代码
  • 三.LUA代码
  • 四.C++代码
  • 五.参考博文

一、问题描述

  给定平面nnn个点,计算最小覆盖圆,使得所有给定点均在圆周以内(包括在圆周上)。博主commonc详细给出了最小覆盖圆算法步骤、算法时间复杂度及其证明、空间复杂度。博主Howe_Young书写的代码简洁、形式优雅,本文在其代码上做了小修改:(1)通过判断距离的平方而非距离,来判断点是否在圆内,从而避免平方根运算,有效提升计算速度 (2)尽量采用乘法代替除法,提升计算速度。下面是改进后的最小覆盖圆算法的MATLAB、LUA、C++完整代码。
  2个点示例:

  3个点示例:

  10个点示例:

  100个点示例:

二.MATLAB代码

%{Function: get_sign
Description: 求实数x的符号
Input: 实数x
Output: 实数x的符号y
Author: Marc Pony(marc_pony@163.com)
%}
function y = get_sign(x)
if abs(x) < 1.0e-8y = 0;
elseif x < 0.0y = -1;elsey = 1;end
end
end
%{Function: get_distance_square
Description: 求平面两点之间距离的平方
Input: 平面两点a,b
Output: 平面两点之间距离的平方
Author: Marc Pony(marc_pony@163.com)
%}
function distanceSquare = get_distance_square(a, b)
distanceSquare = (a(1) - b(1))^2 + (a(2) - b(2))^2;
end
%{Function: get_circle_center
Description: 求三角形外接圆的圆心
Input: 平面三个点a,b,c
Output: 三角形外接圆的圆心center
Author: Marc Pony(marc_pony@163.com)
%}
function center = get_circle_center(a, b, c)
center = zeros(2, 1);
a1 = b(1) - a(1);
b1 = b(2) - a(2);
c1 = 0.5 * (a1 * a1 + b1 * b1);
a2 = c(1) - a(1);
b2 = c(2) - a(2);
c2 = 0.5 * (a2 * a2 + b2 * b2);
d = a1 * b2 - a2 * b1;
center(1) = a(1) + (c1 * b2 - c2 * b1) / d;
center(2) = a(2) + (a1 * c2 - a2 * c1) / d;
end
%{Function: min_cover_circle
Description: 求平面pointCount个点的最小覆盖圆
Input: 平面pointCount个点的坐标(x,y),点个数pointCount
Output: 平面pointCount个点的最小覆盖圆圆心center,半径radius
Author: Marc Pony(marc_pony@163.com)
%}
function [center, radius] = min_cover_circle(x, y, pointCount)
p = [x(:)'; y(:)'];
p = p(:, randperm(pointCount)); %随机打乱数据
center = p(:, 1);
radiusSquare = 0.0;
for i = 2 : pointCountif get_sign(get_distance_square(p(:, i), center) - radiusSquare) > 0center = p(:, i);radiusSquare = 0.0;for j = 1 : iif get_sign(get_distance_square(p(:, j), center) - radiusSquare) > 0center = 0.5 * (p(:, i) + p(:, j));radiusSquare = get_distance_square(p(:, j), center);for k = 1 : jif get_sign(get_distance_square(p(:, k), center) - radiusSquare) > 0center = get_circle_center(p(:, i), p(:, j), p(:, k));radiusSquare = get_distance_square(p(:, i), center);endendendendend
end
radius = sqrt(radiusSquare);
end
%{Function: draw_circle
Description: 画圆周
Input: 圆心center,圆周半径radius,线型/颜色等设置参数options
Output: 无
Author: Marc Pony(marc_pony@163.com)
%}
function draw_circle(center, radius, options)
theta = 0.0 : 0.001 : 2.0 * pi;
x = center(1) + radius * cos(theta);
y = center(2) + radius * sin(theta);
plot(x, y, options)
end
clc
clear
close all
for pointCount = [1, 2, 3, 10, 100]x = randi([-100, 100], pointCount, 1);y = randi([-100, 100], pointCount, 1);[center, radius] = min_cover_circle(x, y, pointCount);figure('color', 'w')draw_circle(center, radius, 'k--')hold onplot(x, y, 'r+')axis equal off
end

三.LUA代码

--[[-----------------------
Function: get_sign
Description: 求实数x的符号
Input: 实数x
Output: 实数x的符号
Author: Marc Pony(marc_pony@163.com)
--]]------------------------
function get_sign(x)if math.abs(x) < 1.0e-8 thenreturn 0elseif x < 0.0 thenreturn -1elsereturn 1endend
end--[[-----------------------
Function: get_distance_square
Description: 求平面两点之间距离的平方
Input: 平面两点a,b
Output: 平面两点之间距离的平方
Author: Marc Pony(marc_pony@163.com)
--]]------------------------
function get_distance_square(a, b)return (a[1] - b[1])^2 + (a[2] - b[2])^2
end--[[-----------------------
Function: get_circle_center
Description: 求三角形外接圆的圆心
Input: 平面三个点a,b,c
Output: 三角形外接圆的圆心center
Author: Marc Pony(marc_pony@163.com)
--]]------------------------
function get_circle_center(a, b, c)local center = {}local a1 = b[1] - a[1]local b1 = b[2] - a[2]local c1 = 0.5 * (a1 * a1 + b1 * b1)local a2 = c[1] - a[1]local b2 = c[2] - a[2]local c2 = 0.5 * (a2 * a2 + b2 * b2)local d = a1 * b2 - a2 * b1center[1] = a[1] + (c1 * b2 - c2 * b1) / dcenter[2] = a[2] + (a1 * c2 - a2 * c1) / dreturn center
end--[[-----------------------
Function: get_random_array
Description: 将数组随机排列
Input: 数组array,数组起始索引startIndex,结束索引endIndex
Output: 随机排列后数组randomArray
Author: Marc Pony(marc_pony@163.com)
--]]------------------------
function get_random_array(array, startIndex, endIndex)local i, index, lengthlocal randomArray = {}math.randomseed(tostring(os.time()) : reverse() : sub(1, 7))    --设置时间种子length = endIndex - startIndex + 1for i = 1, endIndex - startIndex + 1 doindex = math.floor(startIndex + (endIndex - startIndex + 1 - i) * math.random() + 0.5)     --执行round功能randomArray[length] = array[index]array[index] = array[length]length = length - 1endreturn randomArray
end--[[-----------------------
Function: min_cover_circle
Description: 求平面pointCount个点的最小覆盖圆
Input: 平面pointCount个点的坐标(x,y),点个数pointCount
Output: 平面pointCount个点的最小覆盖圆圆心center,半径radius
Author: Marc Pony(marc_pony@163.com)
--]]------------------------
function min_cover_circle(x, y, pointCount)local i, j, k, radius, radiusSquarelocal center = {}local p_i = {}local p_j = {}local p_k = {}local xx = {}local yy = {}local array = {}local randomArray = {}--将坐标随机排列for i = 1, pointCount doarray[i] = ixx[i] = x[i]yy[i] = y[i]endrandomArray = get_random_array(array, 1, pointCount)for i = 1, pointCount dox[i] = xx[randomArray[i]]y[i] = yy[randomArray[i]]endcenter[1] = x[1]center[2] = y[1]radiusSquare = 0.0for i = 2, pointCount dop_i[1] = x[i]p_i[2] = y[i]if get_sign(get_distance_square(p_i, center) - radiusSquare) > 0 then center[1] = p_i[1]center[2] = p_i[2]radiusSquare = 0.0for j = 1, i dop_j[1] = x[j]p_j[2] = y[j]if get_sign(get_distance_square(p_j, center) - radiusSquare) > 0 thencenter[1] = 0.5 * (p_i[1] + p_j[1])center[2] = 0.5 * (p_i[2] + p_j[2])radiusSquare = get_distance_square(p_j, center)for k = 1, j dop_k[1] = x[k]p_k[2] = y[k]if get_sign(get_distance_square(p_k, center) - radiusSquare) > 0 thencenter = get_circle_center(p_i, p_j, p_k)radiusSquare = get_distance_square(p_i, center)endendendendendendradius = math.sqrt(radiusSquare)return center, radius
end-- Test random array
local array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
local startIndex = 1
local endIndex = 10
local randomArray = get_random_array(array, startIndex, endIndex)-- Test min cover circle
local x = {-63, 35, 35, 17, -74, 38, -97, -78, 91, -49}
local y = {91, 2, -12, -51, 74, -22, -82, -34, 56, 66}
local n = 10
local radius
local center = {}
center, radius = min_cover_circle(x,y, n)
print("min cover circle's center : (", center[1], ", ", center[2], ")")
print("min cover circle's radius : ", radius)

四.C++代码

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>#define MAX_POINT_COUNT 100
using namespace std;struct point
{double x, y;
};/*************************************************
Function: get_sign
Description: 求实数x的符号
Input: 实数x
Output: 无
Return: 实数x的符号(0, -1, 1)
Author: Marc Pony(marc_pony@163.com)
*************************************************/
int get_sign(double x)
{if (fabs(x) < 1.0e-8){return 0;}else{return (x < 0) ? -1 : 1;}
}/*************************************************
Function: get_distance_square
Description: 求平面两点之间距离的平方
Input: 平面两点a,b
Output: 无
Return: 平面两点之间距离的平方
Author: Marc Pony(marc_pony@163.com)
*************************************************/
double get_distance_square(const point a, const point b)
{return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
}/*************************************************
Function: get_circle_center
Description: 求三角形外接圆的圆心
Input: 平面三个点a,b,c
Output: 无
Return: 三角形外接圆的圆心center
Author: Marc Pony(marc_pony@163.com)
*************************************************/
point get_circle_center(const point a, const point b, const point c)
{point center;double a1 = b.x - a.x;double b1 = b.y - a.y;double c1 = 0.5 * (a1 * a1 + b1 * b1);double a2 = c.x - a.x;double b2 = c.y - a.y;double c2 = 0.5 * (a2 * a2 + b2 * b2);double d = a1 * b2 - a2 * b1;center.x = a.x + (c1 * b2 - c2 * b1) / d;center.y = a.y + (a1 * c2 - a2 * c1) / d;return center;
}/*************************************************
Function: min_cover_circle
Description: 求平面pointCount个点的最小覆盖圆
Input: 平面pointCount个点的数组首元素地址p,点个数pointCount
Output: 平面pointCount个点的最小覆盖圆圆心center,半径radius
Return: 无
Author: Marc Pony(marc_pony@163.com)
*************************************************/
void min_cover_circle(point *p, int pointCount, point &center, double &radius)//找最小覆盖圆(这里没有用全局变量p[], 因为是为了封装一个函数便于调用)
{double radiusSquare;random_shuffle(p, p + pointCount);//随机函数,使用了之后使程序更快点,也可以不用center = p[0];radiusSquare = 0.0;for (int i = 1; i < pointCount; i++){if (get_sign(get_distance_square(p[i], center) - radiusSquare) > 0)//如果p[i]在当前圆的外面, 那么以当前点为圆心开始找{center = p[i];//圆心为当前点radiusSquare = 0.0;//这时候这个圆只包括他自己.所以半径为0for (int j = 0; j < i; j++)//找它之前的所有点{if (get_sign(get_distance_square(p[j], center) - radiusSquare) > 0)//如果之前的点有不满足的, 那么就是以这两点为直径的圆{center.x = 0.5 * (p[i].x + p[j].x);center.y = 0.5 * (p[i].y + p[j].y);radiusSquare = get_distance_square(p[j], center);for (int k = 0; k < j; k++){if (get_sign(get_distance_square(p[k], center) - radiusSquare) > 0)//找新作出来的圆之前的点是否还有不满足的, 如果不满足一定就是三个点都在圆上了{center = get_circle_center(p[i], p[j], p[k]);radiusSquare = get_distance_square(p[i], center);}}}}}}radius = sqrt(radiusSquare);
}int main()
{#define POINT_COUNT 10point p[MAX_POINT_COUNT], center;double radius;double x[POINT_COUNT] = { -63, 35, 35, 17, -74, 38, -97, -78, 91, -49 };double y[POINT_COUNT] = { 91, 2, -12, -51, 74, -22, -82, -34, 56, 66 };for (int i = 0; i < POINT_COUNT; i++){p[i].x = x[i];p[i].y = y[i];}min_cover_circle(p, POINT_COUNT, center, radius);printf("min cover circle's center: (%.4f, %.4f)\n", center.x, center.y);printf("min cover circle's radius: %.4f\n", radius);getchar();return 0;
}

五.参考博文

1.最小圆覆盖算法(commonc博主)
2.最小圆覆盖算法(Howe_Young博主)

最小覆盖圆(附完整代码)相关推荐

  1. python代码手机壁纸_Python制作微信好友背景墙教程(附完整代码)

    引言 前段时间,微信朋友圈开始出现了一种晒照片新形式,微信好友墙,即在一张大图片中展示出自己的所有微信好友的头像. 效果如下图,出于隐私考虑,这里作了模糊处理. 是不是很炫,而且这还是独一无二的,毕竟 ...

  2. 用Python代码画一个足球(附完整代码)

    用Python代码画一个足球(附完整代码) C站举办了世界杯征文活动,本文用Python代码画一个足球. 实现方法介绍 本文的绘图工具使用Python的标准库turtle库,无需安装,导入即可使用. ...

  3. 基于MATLAB的二维与三维插值拟合运算(附完整代码)

    · 一. 一维插值 interp1函数在上个博客中(如下链接)已经更新了,此处再补充两个相关例题. 基于MATLAB的数据插值运算:Lagrange与Hermite算法(附完整代码)_唠嗑!的博客-C ...

  4. 最小二乘法圆拟合(附完整代码)

    文章目录 一.2D圆弧拟合 1.不经过给定起点与终点 2.精确经过给定起点与终点 二.3D圆弧拟合 一.2D圆弧拟合 1.不经过给定起点与终点   平面圆的一般方程为: x2+y2+ax+by+c=0 ...

  5. php 3d animation,css3D+动画的例子(附完整代码)

    本篇文章给大家带来的内容是关于css3D+动画的例子(附完整代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 前言 最近玩了玩用css来构建3D效果,写了几个demo,所以博客总 ...

  6. Py之pygame:有趣好玩—利用pygame库实现鱼儿自动实时目标跟踪(附完整代码)

    Py之pygame:有趣好玩-利用pygame库实现鱼儿自动实时目标跟踪(附完整代码) 目录 输出结果 实现代码 输出结果 实现代码 #Py之pygame:利用pygame库实现鱼儿自动实时目标跟踪i ...

  7. c++代码好玩_Py之pygame:有趣好玩—利用pygame库实现鱼儿自动实时目标跟踪(附完整代码)...

    Py之pygame:有趣好玩-利用pygame库实现鱼儿自动实时目标跟踪(附完整代码) 目录 输出结果 实现代码 输出结果 ​ 实现代码 #Py之pygame:利用pygame库实现鱼儿自动实时目标跟 ...

  8. OpenCV基本线性变换轨迹栏的实例(附完整代码)

    OpenCV基本线性变换轨迹栏的实例 OpenCV基本线性变换轨迹栏的实例 OpenCV基本线性变换轨迹栏的实例 OpenCV基本线性变换轨迹栏的实例(附完整代码) #include "op ...

  9. OpenCV差分二值化的实时场景文本检测的实例(附完整代码)

    OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例(附完整代 ...

最新文章

  1. 红帽收购混合云管理提供商NooBaa,混合云爆发节点临近!
  2. “java程序打成jar包 如何处理第三方jar包”
  3. 卢伟冰再怼荣耀9X 10W快充与五年前红米Note一代机型一致
  4. ORA-24042 ORA-12545 ORA-26714 bug(Bug 5623403)
  5. 【大数据部落】R语言如何使用rjags R2jags来建立贝叶斯模型
  6. 虚拟机安装CentOS系统详细步骤。
  7. 鸿蒙曰意心养翻译,文言文情话及翻译
  8. python画球面投影_使用opencv-python对图片进行球面投影
  9. php页面强制横屏,Css实现手机端页面强制横屏(仅适用与一屏页面)
  10. bigsur cdr文件_clover和oc的杂交-openclover,big sur也可以直接用clover来引导了,小白一步一步教你...
  11. python psutil模块 硬盘厂家芯片型号_python第三方模块—psutil模块
  12. C语言画直线~Bresenham方法
  13. matlab图上输入希腊字母,Matlab中给图形添加【希腊字母】
  14. 基于Web+App的快递公司物流管理信息系统设计与实现
  15. Chrome浏览器使用谷歌翻译插件的正确方法
  16. 西电 操作系统课设 在Ubuntu18.04安装pintos
  17. 让数据中台“飞“起来— Quick BI性能优化解决方案及实践
  18. Hessian矩阵以及在图像中的应用
  19. 求n的阶乘及1~n的阶乘之和
  20. 一张A4纸对折不了8次?

热门文章

  1. vue与微信开放标签,调起app
  2. Android开发:用adb命令安装apk到手机
  3. Ubuntu 几个常用的更新命令
  4. openssl base64 编、解码
  5. 19 、(5分)成绩的学分绩点计算
  6. 也说QQ“全民潜水”的怪相
  7. Ocelot 网关搭建(二)
  8. 失去苹果,正成为高通不可承受之重
  9. UG NX 12 曲面的偏置
  10. google安装vue插件