我正在尝试确定最有效的方法来测试是否连接了两个单元格\体素。为简单起见,我将在2个方面讨论这个问题,并考虑图中的单元格......
现在我将问题限制在垂直轴上,称之为y轴。
每个单元格的左下角是它的坐标,它总是一个正整数(如果这有帮助)。
可以写出A和B的y轴边界,
A.y1 = 4
A.y2 = 8
B.y1 = 7
B.y2 = 8
现在测试A和B在y轴上连接/重叠的最有效方法是什么? 请注意,如果您在图表中切换A和B标签,它也应该有用。
这是我毫无疑问天真的尝试......
IF B.x2 == A.x1
IF (A.y1 <= B.y1) AND (A.y2 >= B.y2) THEN
connected = true
ELSE
IF (A.y1 >= B.y1) AND (A.y2 <= B.y2) THEN
connected = true
ELSE
connected = false
END
END
答案 0 :(得分:0)
假设通过连接你的意思是“分享一个非平凡的边界”,我会这样思考:如果它们共享两个不同的点,则其中两个字段是连接的。如果您坚持使用矩形字段,则只需检查每个单元格的角落,并查看两个角落中是否至少有两个角落。要使用此方法将平面分区解析为表示连接字段的图形,您还可以使用它来检查是否应插入边(假设这是您的最终目标),但您可能应该考虑某种排序方式因此,你不能在细胞数量上进行二次多次比较。
答案 1 :(得分:0)
仅使用几何检查,您就接近最佳状态。
您需要进行4次比较(在2d中)以确定哪个(如果有的话)边缘对是相邻的。如果找到邻接,则需要检测是否存在2d重叠。您正在使用&lt; =和&gt; =进行两次包含检查。你不会做得更好。如果真正的答案更可能是假的,那么首先要检查一个终点是否明确地包含在另一个边缘中可能是值得的。如果所有这些测试都失败了,逻辑必须通过最终检查相同的边缘。 (如果错误的答案很常见,这种额外的检查会使方法更加昂贵。)
如果为每个节点添加“深度”编号,则可以使用效率。这将告诉您哪个单元格更大或者它们是否相同,允许您只进行两个包含检查中的一个。单深度比较将避免多次边缘坐标比较。
最后,如果您将父指针放在节点中,那么您可以通过查找最不常见的祖先的路径来进行此比较。可以测试这些路径以获得答案。但是,由于查找和测试它们不太可能比你已经拥有的数值比较更快,我不会再深入研究它。
答案 2 :(得分:0)
您可以分析盒子在轴上的投影如何相互交叉(类似于@ coproc的答案)。但这次计算每个交叉点的“矢量”大小,然后检查是否所有都是非负的。然后检查只有拐角的角落,你可以要求至少有一个这样的长度为正。例如,有这样的东西(为了清楚起见,我重新安排了边界框结构):
typedef int axis_t; // some signed type
struct range { axis_t low, high; };
struct box { range x, y; }
axis_t overlap(const range &a, const range &b)
{
return min(a.high, b.high) - max(a.low, b.low);
}
bool overlap(const box &a, const box &b)
{
axis_t x_overlap = overlap(a.x, b.x);
axis_t y_overlap = overlap(a.y, b.y);
return x_overlap >= 0 && y_overlap >= 0 && x_overlap + y_overlap > 0;
}
这是最多7次比较和3次加法/减法,但有8个值要考虑,所以可能它并没有那么糟糕。
答案 3 :(得分:0)
据我所知,你的代码是最好的。
最多需要6次比较。
恐怕找到半径/距离/重叠涉及更多的计算。
一种替代方法是缓存。 如果在存储每个框坐标时缓存相邻节点, 稍后你可以查看B是否在A的相邻列表中,并且具有较少数量的比较。构建初始缓存是开销,但后来的性能可能会很好。
否则,我看不到更好的方法。