【问题标题】:Finding all points common to two circles找到两个圆共有的所有点
【发布时间】:2010-04-28 15:37:49
【问题描述】:

在 Python 中,如何找到两个圆共有的所有整数点?

例如,想象一个维恩图式的两个(大小相同)圆的交集,中心点为(x1,y1)(x2,y2),半径为r1=r2。另外,我们已经知道圆的两个交点是(xi1,yi1)(xi2,yi2)

如何以一种有效的方式生成包含在两个圆圈中的所有点(x,y) 的列表?也就是说,绘制一个包含交叉点的框并遍历它会很简单,检查给定点是否在两个圆内,但是有更好的方法吗?

【问题讨论】:

  • 当您说所有点时,您的意思是所有整数点。从数学上讲,您谈论的是无限数量的点,因此列出它们会有点困难。
  • 是的,对不起,整数点。为清晰起见进行了编辑。

标签: python geometry intersection points


【解决方案1】:

请记住,这里有四种情况。

  1. 两个圆都不相交,这意味着“公共区域”是空的。
  2. 一个圆圈完全位于另一个圆圈内,这意味着“公共区域”是较小的/内部圆圈。另请注意,如果它们是相同的同心圆,则这种情况的退化情况必须是这种情况,因为它们是您指定的等直径圆。
  3. 两个圆相交于一个交点。
  4. 将有两个交点的“一般”情况。从那里,您有两条弧线来定义封闭区域。在这种情况下,画框方法现在可以工作,我不确定是否有更有效的方法来确定交叉点包含的内容。但是请注意,如果您只是对该区域感兴趣,可以使用 a formula

【讨论】:

  • 从问题中可以看出只有第4种情况适用
  • 陈述的假设暗示了这一点,但列出可能未能考虑的其他可能性有什么问题?
  • 另外,我们已经知道圆的两个交点是(xi1,yi1)(xi2,yi2)这怎么算暗示?
  • 谢谢!我只对案例#4 感兴趣。该区域并不重要——点列表就是我所追求的。
  • 并不意味着暗示任何关于 OP 的编码技能,但总是可以将数字插入公式中,而公式中没有插入任何业务。 xi1、yi1、xi2 和 yi2 的值的存在与实际意义的值无关。为确保它们有意义,首先需要对 Daniel 进行检查。澄清这一点永远不会受到伤害。
【解决方案2】:

您可能还想了解图形开发中使用的各种裁剪算法。我已经使用剪裁算法解决了很多与您在这里提出的问题类似的问题。

【讨论】:

    【解决方案3】:

    如果你的圆的位置和半径的变化粒度小于你的网格,那么你无论如何都会检查一堆点。

    您可以通过适当地定义搜索区域来最大限度地减少检查点的数量。它的宽度等于交点之间的距离,高度等于

    r1 + r2 - D

    D 是两个中心的分离。请注意,此矩形通常不与 X 和 Y 轴对齐。 (这也让你测试两个圆是否相交!)

    实际上,您只需要检查这些点的一半。如果半径相同,您只需要检查其中的四分之一。问题的对称性对您有帮助。

    【讨论】:

    • 正确,但是这个w X h 矩形是我试图避免使用的“盒子”。我确实喜欢你使用对称的想法,但我没有想到。
    【解决方案4】:

    你快到了。 迭代框中的点应该相当不错,但是如果对于第二个坐标直接在限制之间进行迭代,则可以做得更好。

    假设您首先沿 x 轴迭代,然后在 y 轴上迭代,而不是在边界框坐标之间进行迭代,找出每个圆与 x 线相交的位置,更具体地说,您对相交点的 y 坐标感兴趣,并且在它们之间迭代(注意四舍五入)

    当您这样做时,因为您已经知道自己在圈子内,所以您可以完全跳过检查。 如果您有很多积分,那么您可以跳过很多检查,您可能会获得一些性能改进。

    作为一项额外改进,您可以选择 x 轴或 y 轴,以尽量减少需要计算交点的次数。

    【讨论】:

      【解决方案5】:

      所以你想找到两个圆内的格点?

      您建议的绘制一个盒子并遍历盒子中所有点的方法对我来说似乎是最简单的。只要方框中的点数与交点中的点数相当,它可能会很有效。

      即使它不是尽可能高效,您也不应该尝试优化它,直到您有充分的理由相信它是一个真正的瓶颈。

      【讨论】:

      • 是的,格点是更合适的术语 - 让我们使用“位于两个相交圆中的矩形格点”。虽然它本身不是瓶颈,但这个功能正在以相当大的数量级重复。它将排除的点数会很大。
      【解决方案6】:

      我假设“所有点”是指“所有像素”。假设您的显示器是 NX x NY 像素。有两个数组

      int x0[NY], x1[NY]; initially full of -1.
      

      交叉点呈菱形,位于两条曲线之间。 沿每条曲线迭代 x,y 值。在每个 y 值处(即曲线与 y + 0.5 相交的位置),将 x 值存储在数组中。如果 x0[y] 为 -1,则将其存储在 x0 中,否则将其存储在 x1 中。

      还要跟踪 y 的最低和最高值。

      完成后,只需迭代 y 值,并在每个 y 处迭代 x0 和 x1 之间的 x 值,即 for (ix = x0[iy]; ix < x1[iy]; ix++)(或相反)。

      重要的是要理解像素不是 x 和 y 为整数的点。相反,像素是网格线之间的小方块。这将防止您遇到极端情况问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-20
        • 2020-06-20
        • 2019-09-12
        • 1970-01-01
        • 1970-01-01
        • 2019-11-11
        相关资源
        最近更新 更多