Рабочее, но очень медленное решение - искать каждую точку в pc2 для ближайшего соседа:
function [ pc ] = pcaddcloud( pc1, pc2, res )
limits = overlapRange(pc2, pc1);
pc1idx = findPointsInROI(pc2, limits);
pc2Overlap = select(pc2, pc1idx);
idx = findPointsInROI(pc1, limits);
pc1Overlap = select(pc1, idx);
endi = pc2Overlap.Count;
pc2Overlap = pc2Overlap.Location;
for i=1:endi
[idx, ~] = findNeighborsInRadius(pc1Overlap, pc2Overlap(i,:), res);
% keep only indices of redundant points to delete them later
if isempty(idx)
pc1idx(i) = 0;
end
end
pc1idx(pc1idx==0) = [];
pc2 = pc2.Location;
pc2(pc1idx,:) = [];
pc = pointCloud([pc1.Location; pc2]);
end
% Compute the bounding box of overlapped region (from pcmerge)
function rangeLimits = overlapRange(pcA, pcB)
xlimA = pcA.XLimits;
ylimA = pcA.YLimits;
zlimA = pcA.ZLimits;
xlimB = pcB.XLimits;
ylimB = pcB.YLimits;
zlimB = pcB.ZLimits;
if (xlimA(1) > xlimB(2) || xlimA(2) < xlimB(1) || ...
ylimA(1) > ylimB(2) || ylimA(2) < ylimB(1) || ...
zlimA(1) > zlimB(2) || zlimA(2) < zlimB(1))
% No overlap
rangeLimits = [];
else
rangeLimits = [ min(xlimA(1),xlimB(1)), max(xlimA(2),xlimB(2)); ...
min(ylimA(1),ylimB(1)), max(ylimA(2),ylimB(2)); ...
min(zlimA(1),zlimB(1)), max(zlimA(2),zlimB(2))];
end
end
У меня есть более быстрое решение (все еще медленное, но быстрее, чем решение 1), работающее с альфа-фигурами: я определяю оболочку вокруг pc1 и решаю, находятся ли точки pc2 внутри или нет. Недостаток: точки, которые только "немного снаружи" (то есть близко к точкам pc1, но не находятся внутри альфа-формы), не распознаются как избыточные.
function [ pc ] = pcaddcloud( pc1, pc2 )
limits = overlapRange(pc2, pc1);
pc2 = pc2.Location;
pc1 = pc1.Location;
%seems to be faster than findPointsInROI:
pc2Overlap = pc2(pc2(:,1)>=limits(1,1)&pc2(:,1)<=limits(1,2) ...
&pc2(:,2)>=limits(2,1)&pc2(:,2)<=limits(2,2)...
&pc2(:,3)>=limits(3,1)&pc2(:,3)<=limits(3,2),:);
pc2idx = find(pc2(:,1)>=limits(1,1)&pc2(:,1)<=limits(1,2) ...
&pc2(:,2)>=limits(2,1)&pc2(:,2)<=limits(2,2)...
&pc2(:,3)>=limits(3,1)&pc2(:,3)<=limits(3,2));
pc1Overlap = pc1(pc1(:,1)>=limits(1,1)&pc1(:,1)<=limits(1,2) ...
&pc1(:,2)>=limits(2,1)&pc1(:,2)<=limits(2,2)...
&pc1(:,3)>=limits(3,1)&pc1(:,3)<=limits(3,2),:);
shape = alphaShape(double(pc1Overlap));
in = inShape(shape, double(pc2Overlap));
pc2idx(~in) = [];
pc2(pc2idx,:) = [];
pc = pointCloud([pc1; pc2]);
end
% Compute the bounding box of overlapped region (from pcmerge)
function rangeLimits = overlapRange(pcA, pcB)
xlimA = pcA.XLimits;
ylimA = pcA.YLimits;
zlimA = pcA.ZLimits;
xlimB = pcB.XLimits;
ylimB = pcB.YLimits;
zlimB = pcB.ZLimits;
if (xlimA(1) > xlimB(2) || xlimA(2) < xlimB(1) || ...
ylimA(1) > ylimB(2) || ylimA(2) < ylimB(1) || ...
zlimA(1) > zlimB(2) || zlimA(2) < zlimB(1))
% No overlap
rangeLimits = [];
else
rangeLimits = [ min(xlimA(1),xlimB(1)), max(xlimA(2),xlimB(2)); ...
min(ylimA(1),ylimB(1)), max(ylimA(2),ylimB(2)); ...
min(zlimA(1),zlimB(1)), max(zlimA(2),zlimB(2))];
end
end