在扭曲的矩形网格中进行测试/查找交叉点

时间:2018-01-25 18:59:09

标签: collision-detection computational-geometry nearest-neighbor bounding-box hittest

我有一个矩形网格,表示为二维点的二维数组。这样的东西(C#-inspired伪代码):

Point2D[,] mesh = CreateSampleMesh();
mesh.Plot();

enter image description here

重要特征是:

  1. 网格在拓扑上是矩形的,但在图像显示时几何上是“不规则的”;
  2. 每一行的X坐标和每列的Y坐标是单调的(也就是说,它不是“反向”);
  3. 每个矩形都是凸的(项目2的必然结果,我猜);
  4. 我的问题是:考虑到候选人Point2D,我该如何找到“ 矩形“它在里面,如果有的话?这是我建议的方法签名:

    GridPosition position = GetIndexOfBottomLeftRectangleContaining(Point2D candidatePoint);
    if (position != null)
    {
        int pi = Position.I;
        int pj = Positino.J;
    }
    

3 个答案:

答案 0 :(得分:1)

您可能会发现查找point is inside a convex polygon or not是否有用的算法。请注意,第二个答案提出了一种方法,它在2D中花费四个点产品,假设乘法需要恒定时间,意味着时间复杂度为4 * O(D)= 4 * O(2)= O(1)。

现在你可能会疯狂并且并行检查你所拥有的所有多边形,当然这不是O(N 2 ),但可能仍然是过度杀伤。

因此,您需要使用您喜欢的任何数据结构对空间进行分区,其中每个分区都包含一个多边形。

A quadtree

  

是每个内部节点都有的树数据结构   正是四个孩子。四叉树是二维模拟的   八叉树并且最常用于划分二维空间   通过递归将其细分为四个象限或区域。

在这种情况下,

似乎派上用场,每个叶子都包含一个多边形(或者你选择的几个多边形)。

一旦查询落在一片叶子上,你就会去检查这个点是否在这片叶子的多边形内并给出答案。

特别是,我会尝试Region Quadtree,它“通过将区域分解为四个相等的象限,子点,等等来表示二维空间的分区,每个叶节点包含对应于特定的数据子区域“。

查询时间是对数的,或者在最坏的情况下是线性的,因为您可以阅读这些slides

答案 1 :(得分:1)

你很幸运拥有单调链(折线),它们可以对飞机进行分类。

首先,设计一个程序,告诉您是否在垂直链的左侧或右侧。为此,您可以找到垂直面向点的线段,并绘制一条水平线。交叉点告诉您是左还是右。这需要在节点纵坐标之间进行二分法搜索。

enter image description here

使用此程序查找两侧最近的两条链,它们定义了一个点所在的条纹。现在,通过与水平边缘进行比较,此条纹中的最终二分法搜索将告诉您确切的图块。

对于N²节点阵列,这需要时间与Log²N成比例,并且不需要额外的数据结构!

答案 2 :(得分:0)

您可以使用某种2D二进制搜索。

示例:如果您有一个点p(px,py)并且您的网格存储在5x5数组'网格[i,j]'中,您将从i = 5/2开始= 3和j = 5/2 = 3。以下是一些用于说明的基本示例代码:

int i = 3;
int j = 3;
int iOld = i
int jOld = j;
do {
    iOld = i
    jOld = j;

    Point m = mesh[i,j]; 
    //Compare p with m: 
    if (p.x > m.x) {
        i = (i+5)/2;
    } else {
        i = (i/2)/2;
    }
    if (p.y > m.y) {
        j = (j+5)/2;
    } else {
        j = (j/2)/2;
    }
} while (i != iOld && j != jOld);

此代码仅供参考!当您靠近节点时,您可能必须验证i和j是否正确计算,并且它们不会振荡,否则退出条件可能永远不会成立。 否则,这应该很快找到你在网格中的点。

编辑:这种方法假定失真是良性的,这意味着节点扭曲,使得它们移动到不同的方格(这要求网格线相交)。如果网格线可以交叉,那么这种方法不会起作用。