【问题标题】:Ray-square intersection射线-方形交点
【发布时间】:2014-07-27 17:49:58
【问题描述】:

在 2D 中,我有一个起点 (x_1, y_1),一个终点 (x_2, y_2),以及代表正方形三个顶点(左上、右上和右下顶点)的三个点。

如果源自 (x_1, y_1) 并穿过 (x_2, y_2) 的射线与三个顶点给出的平面(或正方形)相交,我的目标是返回 true。最后,我想将其扩展到 3D - 与立方体的交集 - 这就是我目前使用 3D 向量的原因。

在查看了许多其他 SO 问题后,我提出了以下 Java 代码:

// Determines if a given ray intersects a given square
// R1, R2 are two points on the ray
// S1 (upper left vertex), S2 (upper right vertex), and S3 (lower left vertex)
public static boolean intersectRayWithSquare(Vector3 R1, Vector3 R2, Vector3 S1, Vector3 S2, Vector3 S3) {

    Vector3 dS21 = S2.sub(S1); // Subtract S1 from S2
    Vector3 dS31 = S3.sub(S1);
    Vector3 n = dS21.cross(dS31); // Take the cross product of two vectors
    Vector3 dR = R1.sub(R2);

    double ndotdR = n.dot(dR);

    if (Math.abs(ndotdR) < 1e-25f) {
        return false;
    }

    double t = -n.dot(R1.sub(S1)) / ndotdR;

    Vector3 M = R1.add(dR.scale(t));
    Vector3 dMS1 = M.sub(S1);

    double u = dMS1.dot(dS21);
    double v = dMS1.dot(dS31);

    return (u >= 0.0 && u <= dS21.dot(dS21)
    && v >= 0.0 && v <= dS31.dot(dS31));
}

这非常适用于确定穿过 R1 和 R2 的 LINE 是否与正方形相交。但是,请考虑以下情况:

UPDATED: More accurate picture to better demonstrate the problem

Direct link to imgur as I don't have enough rep to post images D:

如果我们调用这个函数两次,每个方块调用一次,它们都会返回 true。我需要调用 (R1, R2, S1) 返回 true,但调用 (R1, R2, S2) 返回 false。

PS:这是我的第一篇文章(但潜伏了很长时间),所以如果需要任何其他信息或者您有任何可以帮助我改进问题的 cmet,请告诉我。

【问题讨论】:

    标签: java geometry 2d raycasting


    【解决方案1】:

    基本上你的光线有一个起点和一个方向,但没有终点。

    您需要做的就是在检查后查看正方形中是否有任何点满足线检查方向是否正确的公式。

    即为简单起见,仅查看 x 维度:

    if (x1<x2) {
      points_in_square.x must be >= x1
    } else if (x1>x2) {
      points_in_square.x must be <= x1 
    } else {
      // line is vertical, handle this case
    }
    

    您可以查看类似事物的现有实现。例如,jMonkeyEngine 是一个开源 Java 3d 引擎,其中包含与轴对齐边界框的光线的交点 - 这基本上正是您正在寻找的。我没有方便的链接,但请尝试使用我刚刚提供的关键字进行搜索。

    【讨论】:

    • 我认为我的第一张照片可能有点误导。我已经用更准确的问题图片更新了帖子。
    【解决方案2】:

    所以这个问题可以通过为布尔语句添加额外的要求来解决。

    return (u >= 0.0 && u <= dS21.dot(dS21) && v >= 0.0 && v <= dS31.dot(dS31) && t < 0);
    // t < 0 to eliminate squares behind the ray
    

    【讨论】:

      猜你喜欢
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      • 2010-10-12
      • 2015-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多