我有两组积分 A 和 B 。
我想在 B 中找到 r 到 A 的所有点,其中一点 b <如果至少有一个点 a ,则 B 在 r 到 A 的范围内在 A 中,其与 b 的(欧几里德)距离等于或小于r。
这两组点中的每一组都是一组连贯的点。它们是从两个不重叠的物体的体素位置生成的。
在1D这个问题相当容易: 的所有点[min( A ) - r max( A < / strong>)+ r ]
但我是3D。
这样做的最佳方式是什么?
我目前正在使用某种knn算法(即matlab的rangesearch)重复搜索 A 中 B 中所有点的每个点,然后统一所有这些集合。但我觉得应该有更好的方法来做到这一点。我更喜欢matlab中的高级/矢量化解决方案,但伪代码也很好:)
我还想过将所有点写入图像并使用半径为r的对象A上的图像扩张。但这听起来有点开销。
答案 0 :(得分:4)
您可以使用k-d tree存储A的所有点。
迭代B的点b,并且对于k-d树中的每个点 - find the nearest point in A(让它为a)。当且仅当距离d(a,b)
小于r
时,点b应包含在结果中。
复杂性为O(|B| * log(|A|) + |A|*log(|A|))
答案 1 :(得分:2)
我通过首先过滤掉 B 中与 A 中的所有点相距太远的点来增强@ amit的解决方案,从而进一步加速存档,因为它们太过分了甚至在一个维度上(有点跟随问题中提到的一维解决方案)。
这样做会将复杂性限制为O(|B|+min(|B|,(2r/res)^3) * log(|A|) + |A|*log(|A|))
,其中res
是两点之间的最小距离,从而将测试用例中的运行时间减少到5秒(从10秒开始,在其他情况下甚至更多)。
matlab中的示例代码:
r=5;
A=randn(10,3);
B=randn(200,3)+5;
roughframe=[min(A,[],1)-r;max(A,[],1)+r];
sortedout=any(bsxfun(@lt,B,roughframe(1,:)),2)|any(bsxfun(@gt,B,roughframe(2,:)),2);
B=B(~sortedout,:);
[~,dist]=knnsearch(A,B);
B=B(dist<=r,:);
答案 2 :(得分:0)
bsxfun()
是你的朋友。所以,假设你在 A 中有10分,在 B 中有3分。您希望对它们进行排列,以使单个维度位于行/列。我将随机生成它们进行演示
A = rand(10, 1, 3); % 10 points in x, y, z, singleton in rows
B = rand(1, 3, 3); % 3 points in x, y, z, singleton in cols
然后,所有点之间的距离可以分两步计算
dd = bsxfun(@(x,y) (x - y).^2, A, B); % differences of x, y, z in squares
d = sqrt(sum(dd, 3)); % this completes sqrt(dx^2 + dy^2 + dz^2)
现在,您有 A 和 B 中各点之间距离的数组。因此,例如, A 中的点3与 B 中的点2之间的距离应为d(3, 2)
。希望这会有所帮助。