【问题标题】:Trilateration algorithm to position 3 circles as close as possible without overlapping三边测量算法将 3 个圆尽可能靠近而不重叠
【发布时间】:2015-06-01 17:12:47
【问题描述】:

我有两个圆圈,它们完美地位于彼此的边界上。它们有位置 A 和 B(都是向量),以及半径 Ra 和 Rb。

现在我添加第三个半径为 Rc 的圆。如何找到三个圆尽可能靠近而不重叠的位置向量C?

我写这篇文章是为了我正在建立的网站的插图,所以效率加分:)

编辑: 当我最初发布时,我没有足够的代表来发布插图。 其中两个圆(B 和 C)将重叠,但与 A 相切。我想将 C 移出它与 B 共享的重叠区域,进入虚线。

编辑 2: 很抱歉,这太不清楚了,我创建了一个图表来试图解释我正在尝试做的事情。

我正在 Pixi.js 中创建一个插图,这是一个简单的 canvas/webGL 库。我正在使用 Vectors(通过 Victor.js)来定位圆圈并移动它们。

我随机生成一堆圆圈,然后我将最大的圆圈 (A) 放在容器的中间。之后,我想将 A 周围的所有圆圈聚集在一起,在发生碰撞时解决它们。这很重要,因为我将在用户点击或悬停单个圆圈时缩放它们。

对于没有碰撞的简单情况,矢量解决方案非常简单,如果可能,我想解决两个圆以相同方式碰撞的情况。

【问题讨论】:

  • 问题描述不清楚。
  • C有2个答案,你不能有1个答案
  • 圆圈是否相互接触?
  • 任何答案都可以,但最接近的答案会更好

标签: algorithm math geometry computational-geometry


【解决方案1】:

答案是找到形成边长为:Ra+Rb、Ra+Rc、Rb+Rc 的三角形的点。这就是所谓的三边求解,但你会得到 2 个可能的答案。

这里使用的基本公式是余弦定律:c^2 = a^2 + b^2 - 2ab*cos(gamma)

让我们定义我们的长度为:

  1. La = Ra+Rb
  2. Lb = Rb+Rc
  3. Lc = Rc+Ra

我们将首先找到 AB 和 AC 之间的角度。求解arccos(a) = (Lb^2 + Lc^2 - La^2) / 2*Lb*Lc
(如果此时你已经有了AB的坐标系角度,可以跳到第三步)

第二步,求AB相对于X轴的坐标系夹角。这是使用基本三角函数完成的。求高度h = Ay - By,角度为arcsin(b) = h / La

第三步是添加或减去(2 个答案!)角度 a 和 b,这是从点 A 开始的向量的方向,其中点 C 位于距离 Lc 处。要找到 C,请再次使用三角函数。

Cx = Ax + Lc * cos(a + b)
Cy = Ay + Lc * sin(a + b)

【讨论】:

  • 我希望 SO 允许 MathJax 格式。无论如何,这是正确的解决方案,因为您知道三个边并且正在寻找内角。
  • 嘿阿米特!我现在怎么联系你?我无法在 WhatsApp 上联系到您 这也是正确的!抱歉我没有注意到。但是,我希望找到一种巧妙的方法来解决许多昂贵的三角计算,因为我想尝试为转换设置动画。
  • @sindre - 对不起,你不能在 whatsapp 上联系我,一般来说,你不应该直接联系 SO 上的任何人。这个想法是您在网站本身上分享您的问题、更正、答案和其他所有内容(在需要时使用这些 cmets),以便其他人可以学习/评论所有内容。那么,您为什么害怕三角计算?对于一个圈子来说,它们并不“那么”贵。如果您想制作动画,请解释您要创建的动画...
  • @Amit 对不起,我以为你是我的一个同名的私人朋友,使用了类似的头像。他的号码似乎与 What's App 断开了连接。我的错,对此感到抱歉。我有多达 10 个圆在动画中可能同时发生碰撞,速度为 60fps 我担心浏览器中每个圆进行 4 次三角计算会导致性能不佳。我现在要试试这个,看看效果如何。
  • @sindre,没问题..有趣的巧合。我不确定我是否理解你的场景。你有 10 个圆圈,并且你正在为所有圆圈设置动画?从什么状态到什么状态?碰撞与找到最终位置有何关系? (顺便说一句,圆形碰撞检测比这简单得多)
【解决方案2】:

当圆相互接触时,圆心之间的距离称为半径之和。求解这个方程组并找到Cx,Cy 坐标。有两种可能的解决方案。将坐标原点放在一个圆的中心时解决方案更简单。

(Cx-Ax)^2 + (Cy-Ay)^2 = (Ra+Rc)^2
(Cx-Bx)^2 + (Cy-By)^2 = (Rb+Rc)^2

【讨论】:

    【解决方案3】:

    如果您假设第一个圆 (A) 的中心是 (0,0),而第二个圆 (B) 的中心在正的 x 轴上,那么问题就简化了。如果不是这种情况,您可以将A 的中心平移到(0,0),然后旋转平面使其成为这种情况。 (然后在最后反转这些操作以恢复原始配置。)

    那么C的中心距离A的中心距离A.R + C.RC的中心距离B的中心距离B.R + C.R,其中@987654333 @、B.RC.R 是圆的半径ABC。也就是说C的圆心在两个圆的交点上

          x^2 + y^2 = (A.R + C.R)^2
    (x-B.x)^2 + y^2 = (B.R + C.R)^2
    

    其中(B.x,0) 是圆心B。从第二个方程中减去第一个方程,我们得到

    -2*B.x*x + B.x^2 = B.R^2 + 2*B.R*C.R - A.R^2 - 2*A.R*C.R
    

    也就是说C的中心有x坐标

    C.x = (A.R^2 + 2*A.R*C.R + B.x^2 - B.R^2 - 2*B.R*C.R)/(2*B.x)
    

    现在我们有了C.x,我们可以很容易地计算出C.y

    C.y = plus or minus sqrt((A.R+C.R)^2 - C.x^2)
    

    现在反转您在开始时应用的转换,如果有的话(先反转旋转,然后反转平移),您将拥有C 的最终中心。

    如果您不想应用初始平移和旋转,当然,您仍然可以解决问题,但代数有点混乱。

    【讨论】:

    • 这似乎是我一直在寻找的,我会尝试实现它并回到这里。奥斯陆是晚上,所以我会在早上第一件事就是建造它。谢谢:)
    猜你喜欢
    • 2011-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    相关资源
    最近更新 更多