注意:我不相信你画的圆是最小的边界圆。它应该小一点,向上和向右,并且应该至少接触其周边的两个点。
接近问题
我们有一组点,我们想画一个包含所有点的圆。问题是您需要三个信息来定义一个圆:圆心的 X 和 Y 坐标,以及圆的半径。所以这个问题似乎并不简单。
但是,有一个更容易解决的相关问题。假设圆的中心是固定的。从那时起,我们使一个圆同心向外生长,使其变得越来越大。在某些时候,圆圈将包含我们集合中的一个点。随着它变大,它将包含第二个点和第三个点,直到我们集合中的所有点都落在我们的圈内。显然,一旦集合中的最后一个点落入我们的圆内,我们就有了包含所有点的最小圆,假设我们从固定圆的中心点开始。
此外,我们可以确定这个圆的半径是多少。它只是从集合中的任何点到圆心的最大距离,因为当最后一个点接触到我们扩大的圆的周长时,我们就停止了。
下一个问题是确定放置圆心的最佳起点是什么? 显然,如果起点远离我们集合中的所有点,那么半径必须非常大,甚至可以包含集合中的一个点。直观地说,它一定在我们点的“中间”某处。但是,具体在哪里?
使用fminsearch
我的建议是你想找到点 P(x, y) 最小化你必须扩大圆圈以包含集合中的所有点的大小。我们很幸运,我们可以用它fminsearch
来找到 P。
根据fminsearch
文档,您传入的函数必须是一个参数的函数(可能是一个数组),并且它必须返回一个标量。这个想法是您希望函数的输出尽可能小,并且您想找出哪些输入可以实现。
在我们的例子中,我们想编写一个函数来输出我们的圆的大小,给定圆的中心作为输入。这样,fminsearch
将找到仍然包含所有点的最小可能圆的中心。我将编写一个函数,输出包含给定中心点 P 的所有点所需的半径。
pointsX = [..]; % X-coordinates of points in the set
pointsY = [..]; % Y-coordinates of points in the set
function r = radiusFromPoint(P)
px = P(1);
py = P(2);
distanceSquared = (pointsX - px).^2 + (pointsY - py).^2;
r = sqrt(max(distanceSquared));
end
然后我们想用它fminsearch
来找到给我们最小半径的点。我只是天真地使用原点 (0, 0) 作为我的起始估计,但您可能有更好的主意(比如使用集合中的第一个点)
P0 = [0, 0]; % starting estimate
[P, radiusMin] = fminsearch(@radiusFromPoint, P0);
圆由其中心在P
和半径定义radiusMin
。
我将把它留给你来绘制输出并推广到 3D 案例!