将点矢量化为线/段/光线距离函数(matlab)

时间:2018-03-09 15:21:40

标签: matlab line vectorization point raytracing

我正在使用here中的函数来计算多个光线到空间中多个点的距离。我现在这样做的方法是在下面的代码中注意到形成两个for循环,因为distancePoint2Line()函数没有向量化。然而,当我必须通过大约2000-3000光线的光线并在空间中找到6000-7000点的距离时,这需要花费很多时间。因此,我希望尽可能矢量化distancePoint2Line()以优化处理时间。

现有distancePoint2Line()函数的输入是起点,线,段或光线的终点,空间中的独立点和线的类型,简要给出:

function [d, C, t0] = distancePoint2Line(A, B, P, varargin)
% - lineType definition
if (nargin < 4)
    lineType = 'line';
lineType = 'line';
else
    lineType = varargin{1};
end
%% Algorithm

% Direction vector 
% M = B - A;
M = B;

% Running parameter t0 defines the intersection point of line through A and B
% and the perpendicular through P
t0  = dot(M, P - A) / dot(M, M);

% Intersection point of the perpendicular and line through A and B
intersectPnt = A + t0 * M;

switch lower(lineType)
    case 'line'
        % Line: intersection point is always closest.
        C   = intersectPnt;

    case 'segment'
        % Line segment
        if t0 < 0
            % Start point is closest.
            C   = A;
        elseif t0 > 1
            % End point is closest.
            C   = B;
        else
            % Intersection point is closest.
            C   = intersectPnt;
        end     

    case 'ray'
        % Ray
        if t0 < 0
            % Start point is closest.
            C   = A;
        else
            % Intersection point is closest.
            C   = intersectPnt;
        end

end

% Distance between independent point and closest point
d   = norm(P-C);

end

所以如果我认为我有下图:

enter image description here

绿点是我的起源,蓝色光线是从原点投射到空间的光线,红色点是空间中的各个点,我想用它测量它们与每条光线的距离。到目前为止如下:

origin = [10 10 0];
rays = [ 0.0420891179448099 -0.246431544552697  0.968245836551854;
         0.310536647204174   0.682690992135673  0.661437827766148;
        -0.746496065726383  -0.0724128707829756 0.661437827766148;
         0.435959418522208  -0.610278121352698 0.661437827766148];
mypts = [4579 4246 1962;
         3961 4670 3277;
         4796 3393  856;
         3277 3787 3529;
          179 3713  160];

for j=1:size(rays,1)
    for i=1:size(mypts,1)
        [D(i,j), C(i,j,:), t0(i,j)] = distancePoint2Line(origin, rays(j,:), mypts(j,:), 'ray');
    end
end

然而,正如我所说,当光线数量和个别点数增加时,上述实施太慢了。

因此,我尝试修改distancePoint2Line()函数,以便我对处理进行矢量化并将原点,所有结束点和所有单个点一次作为参数传递。

[d, c, tt0] = distancePoint2LineVec(origin, rays, mypts, 'ray');

以下是我的修改,直到获得交叉点:

function [d, C, t0] = distancePoint2LineVec(A, B, P, varargin)
% - lineType definition
if (nargin < 4)
    lineType = 'line';
lineType = 'line';
else
    lineType = varargin{1};
end
%% Algorithm

% Direction vector 
% M = B - A;
% M = bsxfun(@minus, B, A); 
M = B;

% Running parameter t0 defines the intersection point of line through A and B
% and the perpendicular through P
% t0  = dot(M, P - A) / dot(M, M);
K = bsxfun(@minus, P, A);
V = M*K.';
U = M*M.';
t0 = bsxfun(@rdivide, V, diag(U));
t0 = t0(:);

% Intersection point of the perpendicular and line through A and B
% intersectPnt = A + t0 * M;
mul = M.*repmat(t0, [1 size(M,1)]); <---- Getting matrix dimension error here
intersectPnt = bsxfun(@plus,A,mul);

switch lower(lineType)
    case 'line'
        % Line: intersection point is always closest.
        C   = intersectPnt;

    case 'segment'
        % Line segment
        if t0 < 0
            % Start point is closest.
            C   = A;
        elseif t0 > 1
            % End point is closest.
            C   = B;
        else
            % Intersection point is closest.
            C   = intersectPnt;
        end     

    case 'ray'
        % Ray
        if t0 < 0
            % Start point is closest.
            C   = A;
        else
            % Intersection point is closest.
            C   = intersectPnt;
        end

end

% Distance between independent point and closest point
d   = norm(P-C);

end

但关键是我在那里得到一个错误,因为尺寸与乘法不匹配。我搜索了一下,似乎没有直接的方法来做到这一点。任何想法如何有效地解决它?

感谢。

1 个答案:

答案 0 :(得分:0)

好的,这是我结束的第一个解决方案,看起来非常快:

function [d, C, t0] = distancePoint2LineVec(A, B, P, varargin)
% - lineType definition
if (nargin < 4)
    lineType = 'line';
else
    lineType = varargin{1};
end
%% Algorithm

% find if the origin point is withing the points and initialize it to Inf
[~,indx]=ismember(A,P,'rows');

if indx ~= 0
    P(indx,:) = Inf;
end

% Direction vector 
% M = B - A;
% M = bsxfun(@minus, B, A); 
M = B;

% Running parameter t0 defines the intersection point of line through A and B
% and the perpendicular through P
% t0  = dot(M, P - A) / dot(M, M);
K = bsxfun(@minus, P, A);
V = M*K.';
U = M*M.';
t0 = bsxfun(@rdivide, V, diag(U));
t0 = t0(:);

% Intersection point of the perpendicular and line through A and B
% intersectPnt = A + t0 * M;
mul = bsxfun(@times, repmat(M, [size(P,1) 1]), t0);
intersectPnt = bsxfun(@plus, repmat(A, [size(t0,1) 1]), mul);

C = intersectPnt;

idx = find(t0<0);
idx2 = find(t0>1);
% C(idx,:) = repmat(A,[size(idx,1) 1]);

switch lower(lineType)
    case 'line'
        % Line: intersection point is always closest.
        C   = intersectPnt;

    case 'segment'
        % Line segment
%         if t0 < 0
            % Start point is closest.
%             C   = A;
            C(idx,:) = repmat(A,[size(idx,1) 1]);
%         elseif t0 > 1
            % End point is closest.
%             C   = B;
            C(idx2,:) = repmat(B,[size(idx2,1) 1]);
%         else
            % Intersection point is closest.
%             C   = intersectPnt;
%         end     

    case 'ray'
        % Ray
%         if t0 < 0
            % Start point is closest.
%             C   = A;
%             C   = Inf;
%         else
            % Intersection point is closest.
%             C   = intersectPnt;
%         end
        C(idx,:) = repmat([Inf Inf Inf],[size(idx,1) 1]);

end

% Distance between independent point and closest point
% d   = norm(P-C);
d = pdist2(P,C);
d = d(sub2ind(size(d), repmat((1:size(d,1)).', 1, size(B,1)), (1:size(B,1))+((1:size(B,1):size(d,2))-1).'));


C = permute(reshape(C, size(B,1), size(P,1), []), [2 1 3]);
t0 = reshape(t0, size(B,1), size(P,1))';

end

如果对更多改进有任何意见或建议,我很乐意听到。再次感谢。