给定一组大的(数万到数百万)无序点表示为3D笛卡尔向量,用于制作包含所有点的常规方形网格(用户定义的间距)的好算法是什么?一些约束:
为了在2D中进行说明,给出了这一点:
对于某些网格间距X,算法的一个可能的返回值是这些红点的坐标(虚线仅用于说明目的):
对于网格间距X / 2,算法的一个可能的返回值是这些红点的坐标(虚线仅用于说明目的):
对于任何有兴趣的人来说,我正在使用的无序点是大蛋白分子的原子坐标,就像你可以从.pdb文件中得到的那样。
Python是解决方案的首选,尽管伪代码也很好。
编辑:我认为我对所需内容的第一次描述可能有点模糊,所以我添加了一些约束和图像以澄清事情。答案 0 :(得分:4)
我建议你制作k-d tree。它快速,简单,易于实现:
维基百科代码:
class Node: pass
def kdtree(point_list, depth=0):
if not point_list:
return
# Select axis based on depth so that axis cycles through all valid values
k = len(point_list[0]) # assumes all points have the same dimension
axis = depth % k
# Sort point list and choose median as pivot element
point_list.sort(key=lambda point: point[axis])
median = len(point_list) // 2 # choose median
# Create node and construct subtrees
node = Node()
node.location = point_list[median]
node.left_child = kdtree(point_list[:median], depth + 1)
node.right_child = kdtree(point_list[median + 1:], depth + 1)
return node
但是,您必须稍微修改它,以适应您的约束。
答案 1 :(得分:2)
Voronoi Diagram怎么样?它可以使用Fortunes algorithm在O(n log n)
中生成。
我不知道它是否解决了你的问题,但Voronoi Diagrams非常“自然”。它们在本质上非常普遍。
示例(来自维基百科):
答案 2 :(得分:2)
因为您要求使用用户指定间距的常规方格,所以听起来似乎是一种相当简单的方法。
首先通过数据来计算每个维度中的最小和最大坐标。计算出覆盖最大值和最小值之间距离所需的用户指定间距的步数。
再次通过数据,将每个点分配到网格中的单元格,使用每个坐标最小点和指定间距的网格(例如X_cell = Math.floor((x_i - x_min) /间距))。使用字典或数组记录每个单元格中的点数。
现在打印出细胞的坐标,其中至少有一个点。
你确实有一些我没有尝试优化的自由:除非最小坐标和最大坐标之间的距离是网格间距的精确倍数,否则会有一些允许你滑动网格的斜率它包含所有点:此时网格从最低点的位置开始,但它可能在最高点之前结束,因此您有足够的空间在每个维度上向下移动一点。当你这样做时,一些点将从一个单元移动到另一个单元,并且被占用的单元的数量将改变。
如果您一次只考虑一个维度的移动,您可以合理有效地计算出会发生什么。计算每个点与其单元格维度中的最大坐标之间的维度距离,然后对这些值进行排序。当您向下移动网格时,距离最大坐标最小的点将首先交换单元格,您可以按排序顺序逐个遍历这些点。如果您在执行此操作时更新单元格中的点数,则可以确定哪个位移最小化了已占用单元格的数量。
当然,您需要担心三个方面。您可以逐个处理它们,直到您减少单元格数量。这是当地的最低要求,但可能不是全球最低要求。寻找其他局部最小值的一种方法是从随机选择的起点重新开始。
答案 3 :(得分:1)
找到包含所有点的最小面积平方。将每个方块重复细分为4个子方块(因此从1到4到16到64到......)。在其中一个方块变空之前停止。不难证明得到的网格最多是最佳解决方案的四倍(关键洞察力:保证空方格至少包含任意网格中的一个方格至少两倍)。
可能通过引入随机翻译可以减少常量。
答案 4 :(得分:1)
我有2D网格聚类的经验,并在C#代码中实现了一个例子。 http://kunuk.wordpress.com/2011/09/15/clustering-grid-cluster/
这可以处理步骤处理步骤1,2和4。 您必须修改代码并将其更新为3D空间。希望这会给你一些想法。
代码在O(m * n)中运行,其中m是网格数,n是点数。
答案 5 :(得分:0)