寻找一组点中距离某一个点距离为L的所有点,有没有什么好一点的方法?

我有一组点的三维坐标,想找到距离某一个点V距离为L的所有点,
我下面这个方法能用是能用,有什么更好的方法吗?

function findAtomsAroundVacancy(V::Array, xyz::Array)
        xDistance = [xyz[i, 1] - V[1] for i in 1:length(xyz[:, 1])]
        yDistance = [xyz[i, 2] - V[2] for i in 1:length(xyz[:, 2])]
        zDistance = [xyz[i, 3] - V[3] for i in 1:length(xyz[:, 3])]
        xCoor = findall(j -> (-L < j < L), xDistance)
        yCoor = findall(j -> (-L < j < L), yDistance)
        zCoor = findall(j -> (-L < j < L), zDistance)
        nearestCoor = intersect(xCoor,yCoor,zCoor)
    return nearestCoor
end

你这里算的不是距离为 L 的点,而是所有距离小于 L 的点在 xyz 中的索引。范数使用的是无穷阶范数。

findall(axes(xyz, 1)) do i
    U = xyz[i, :]
    return (-L < U[1] - V[1] < L) && (-L < U[2] - V[2] < L) && (-L < U[3] - V[3] < L)
end

如果已经 using LinearAlgebra,则可以考虑使用 norm 函数:

findall(axes(xyz, 1)) do i
    U = xyz[i, :]
    return norm(U - V, Inf) < L
end

最简单的方法就是计算所有点和V点的距离,然后和L+tol进行比较:

@. d = sqrt( (xyz[:,1]-V[1])^2 +  (xyz[:,2]-V[2])^2 + (xyz[:,3] -V[3])^2 )
return findall( L-1e-6 .< d .< L+1e-6 )

如果点很多,还要考虑效率的话,以V为中心定义外范围箱(边长2L)和内范围箱(边长2L/sqrt(3)),先把外范围箱外的点和内范围箱内的点先踢掉,然而再计算距离。

2 个赞