【问题标题】:What is the best way to determine an intersection between 2D shapes on a cartesian grid?确定笛卡尔网格上二维形状之间交集的最佳方法是什么?
【发布时间】:2022-01-17 09:34:10
【问题描述】:

下面的函数应该确定movingBall结构的两个对象是否相互“接触”

 bool areBallstouching(movingBall one, movingBall two)
{
    int xMin, xMax, yMin, yMax;
    int TxMin, TxMax, TyMin, TyMax;
    xMin = one.xPosition - one.radius;
    xMax = one.xPosition + one.radius;
    yMin = one.yPosition - one.radius;
    yMax = one.yPosition + one.radius;
    //===================================
    TxMin = two.xPosition - two.radius;
    TxMax = two.xPosition + two.radius;
    TyMin = two.yPosition - two.radius;
    TyMax = two.yPosition + two.radius;
    //=======================================

    vector <int> xrange, yrange, Txrange, Tyrange;
    bool xtouch = false; bool ytouch = false;
    for (int i = xMin; i < xMax; i++)
    {
        xrange.push_back(i);
    }
    for (int i = yMin; i < yMax; i++)
    {
        yrange.push_back(i);
    }
    for (int i = TxMin; i < TxMax; i++)
    {
        Txrange.push_back(i);
    }
    for (int i = TyMin; i < TyMax; i++)
    {
        Tyrange.push_back(i);
    }
    for (int i = 0; i < xrange.size(); i++)
        for (int j = 0; j < Txrange.size(); j++)
            if (xrange[i] == Txrange[j])
                xtouch = true;

    for (int i = 0; i < yrange.size()-1; i++)
        for (int j = 0; j < Tyrange.size()-1; j++)
            if (yrange[i] == Tyrange[j])
                ytouch = true;
    if (xtouch == true && ytouch == true)
    {
        return true;
    }
    else
    {
        return false;
    }
}

我推断只有当球共享任意两个坐标时,它们才能相互接触。如果它们只共享一个 x 坐标,它们将垂直对齐,但最上面的球的底部不会接触到最底部的球的顶部。如果它们只共享一个 y 坐标,它们将水平对齐,但最左边的球的最右边的点不会接触到最右边的球的最左边的点。

附图说明了这个推理。当我实现代码时,并没有达到我想要的结果。程序无法正确检测两个圆之间的交点。

【问题讨论】:

  • 这是一种非常复杂的测试两个圆是否接触的方法。为什么不只测试它们的中心之间的距离是否小于或等于 r1 + r2?或者更好的是,距离的平方小于或等于 r1*r1 + r2*r2... 所以你不需要计算任何平方根。
  • 更正:sq(dist) &lt;= sq(r1 + r2)

标签: c++ arrays vector graphics geometry


【解决方案1】:

从数学上讲,两个圆相交的点将它们的中心位置分开的距离等于两个半径之和。如下:

  • 如果中心之间的距离小于半径之和,则圆相交;
  • 如果圆心之间的距离大于半径之和,则圆不会相交(或接触)。

因此,您只需要使用基本的毕达哥拉斯进行简单的距离计算。

float dx = two.xPosition - one.xPosition;
float dy = two.yPosition - one.yPosition;
float distsq = dx * dx + dy * dy;   // square distance between centers
float r = one.radius + two.radius;  // sum of radii
float rsq = r * r;

bool intersect_or_touch = (distsq <= rsq);

请注意,上面我们可以在平方距离和平方半径的域中进行操作,以避免需要使用sqrt 计算。

【讨论】:

  • 请注意,我在计算中使用了float,但由于您的所有值显然都是整数并且我们不需要做平方根,那么所有的math 也适用于整数,前提是您没有超出整数的有效范围。
  • 您好,稻田,感谢您的回复。如果你不介意,我还有一个问题要问。这是我得到的计算 x 重叠的方程: cos(tan^-1(two.yPosition - one.yPosition/two.xPosition-one.xPosition))*((dy^2+dx^2)/2 )-(one.radius+two.radius/2)。这是正确的吗?
  • 最好提出一个新问题,以扩大影响范围(而不是让我成为您的私人导师)和清晰(使用格式并提供在评论范围内不可能提供的额外细节)。当您提出这个问题时,我建议您准确定义“x 重叠”的含义。对我来说,这意味着两个圆相交的 两个 x 位置(如果它们完全接触,则为 一个)。你可以用毕达哥拉斯、向量数学或求解二次方程来做到这一点。要回答您的方程式,您为什么不实际尝试并设计测试和/或数学证明。
  • 哦,我还要补充一点,当你问这个问题时,请说出你真正希望用它实现什么。请注意,您对这个问题的回答与您尝试解决问题的方式完全不同。可能和你现在的想法一样。例如,如果您尝试计算圆碰撞后的反弹方向,则正确的做法是使用矢量数学,而不是三角函数。
猜你喜欢
  • 2010-09-10
  • 2012-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-29
  • 2014-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多