我有一个矩形网格,表示为二维点的二维数组。这样的东西(C#-inspired伪代码):
Point2D[,] mesh = CreateSampleMesh();
mesh.Plot();
重要特征是:
我的问题是:考虑到候选人Point2D,我该如何找到“ 矩形“它在里面,如果有的话?这是我建议的方法签名:
GridPosition position = GetIndexOfBottomLeftRectangleContaining(Point2D candidatePoint);
if (position != null)
{
int pi = Position.I;
int pj = Positino.J;
}
答案 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)
你很幸运拥有单调链(折线),它们可以对飞机进行分类。
首先,设计一个程序,告诉您是否在垂直链的左侧或右侧。为此,您可以找到垂直面向点的线段,并绘制一条水平线。交叉点告诉您是左还是右。这需要在节点纵坐标之间进行二分法搜索。
使用此程序查找两侧最近的两条链,它们定义了一个点所在的条纹。现在,通过与水平边缘进行比较,此条纹中的最终二分法搜索将告诉您确切的图块。
对于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是否正确计算,并且它们不会振荡,否则退出条件可能永远不会成立。 否则,这应该很快找到你在网格中的点。
编辑:这种方法假定失真是良性的,这意味着节点不扭曲,使得它们移动到不同的方格(这要求网格线相交)。如果网格线可以交叉,那么这种方法不会起作用。