我有一个代表n个球体的nx4矩阵A
和一个代表m个点的mx3矩阵B
。我需要测试这些m点是否在任何球体内。我可以使用for
循环执行此操作,但是对于较大的n
和m
而言,此方法效率很低。如何将这个操作向量化?我目前的方法是
A = [0.8622 1.1594 0.7457 0.6925;
1.4325 0.2559 0.0520 0.4687;
1.8465 0.3979 0.2850 0.4259;
1.4387 0.8713 1.6585 0.4616;
0.2383 1.5208 0.5415 0.9417;
1.6812 0.2045 0.1290 0.1972];
B = [0.5689 0.9696 0.8196;
0.5211 0.4462 0.6254;
0.9000 0.4894 0.2202;
0.4192 0.9229 0.4639];
for i=1:size(B,1)
mask = vecnorm(A(:, 1:3) - B(i,:), 2, 2) < A(:, 4);
if sum(mask) > 0
C(i) = true;
else
C(i) = false;
end %if
end %for
我测试了@LuisMendo建议的方法,似乎它只加快了相当小的m
和n
的计算速度,却加快了m
和n
的计算速度,例如,我的问题大约在10000左右,改进非常有限。但是@NickyMattsson给了我一些提示。由于matlab中的逻辑运算比vecnorm
更快,因此我首先使用粗略的检查来找到该点附近的球体,然后进行精细的检查:
A = [0.8622 1.1594 0.7457 0.6925;
1.4325 0.2559 0.0520 0.4687;
1.8465 0.3979 0.2850 0.4259;
1.4387 0.8713 1.6585 0.4616;
0.2383 1.5208 0.5415 0.9417;
1.6812 0.2045 0.1290 0.1972];
B = [0.5689 0.9696 0.8196;
0.5211 0.4462 0.6254;
0.9000 0.4894 0.2202;
0.4192 0.9229 0.4639];
ids = 1:size(A, 1);
for i=1:size(B,1)
% first a rough check
xbound = abs(A(:, 1) - B(i, 1)) < A(:, 4);
ybound = abs(A(:, 2) - B(i, 2)) < A(:, 4);
zbound = abs(A(:, 3) - B(i, 3)) < A(:, 4);
nears = ids(xbound & ybound & zbound);
if isempty(nears)
C(i) = false;
else
% then a fine check
mask = vecnorm(A(nears, 1:3) - B(i,:), 2, 2) < A(nears, 4);
if sum(mask) > 0
C(i) = true;
else
C(i) = false;
end
end
end
这可以将时间减少到1/2或1/3,这是可以接受的,并且如果我将m
和n
分成批处理,则可能会更快,而不会增加内存负担。 @CrisLuengo提到了R * -tree方法,但是似乎XD的实现非常复杂
答案 0 :(得分:3)
这使用implicit expansion计算点与球心之间的所有距离,然后将其与球半径进行比较:
select (multiple: true)
这可能比循环方法要快,但也要占用更多的内存,因为要计算一个中间UserTaxonomy
×nested_form
×C = any(vecnorm(permute(B, [1 3 2]) - permute(A(:,1:3), [3 1 2]), 2, 3) < A(:,4).', 2);
数组。