找到两个非连续向量的公共段

时间:2013-12-26 10:18:21

标签: matlab

我正在寻找一种快速而优雅的方式来解决这个问题: 我有两条非连续线,就像这张图片中的黑线一样: enter image description here

对于每一个,我有两个向量 - 一个定义每个段的起点,另一个定义终点。

我正在寻找一个MATLAB脚本,它将为blue行提供起点和终点,这是两条线的交叉点。

当然,我可以创建两个向量,每个向量包含黑色线条中的所有元素,然后使用“相交”。但是,由于这里的数字是数十亿,这些矢量的大小将是巨大的,交叉点将需要很长时间。

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

好问题!

这是一个无循环的解决方案,用于组合 n 不连续的行 n 在原始帖子中为2 )。

考虑 n 不连续线,每条线由其起点和终点定义。还要考虑任意测试点P.设S表示解,即,定义为所有输入线的交点的不连续线。关键的想法是: P在S中,当且仅当P左边的起点数减去P左边的停止点数等于n(考虑所有线的所有点)

这个想法可以通过矢量化操作紧凑地应用:

start = {[1 11 21], [2 10 15 24]}; %// start points
stop  = {[3 14 25], [3 12 18 27]}; %// stop points
  %// start and stop are cell arrays containing n vectors, with n arbitrary

n = numel(start);
start_cat = horzcat(start{:}); %// concat all start points
stop_cat = horzcat(stop{:}); %// concat all stop points
m = [ start_cat stop_cat; ones(1,numel(start_cat)) -ones(1,numel(stop_cat)) ].';
  %'// column 1 contains all start and stop points.
  %//  column 2 indicates if each point is a start or a stop point
m = sortrows(m,1); %// sort all start and stop points (column 1),
  %// keeping track of whether each point is a start or a stop point (column 2)
ind = find(cumsum(m(:,2))==n); %// test the indicated condition
result_start = m(ind,1).'; %'// start points of the solution
result_stop = m(ind+1,1).'; %'// stop points of the solution

根据以上数据,结果是

result_start =
     2    11    24

result_stop =
     3    12    25

答案 1 :(得分:0)

您对离散化的想法很好,但我没有使用固定步长,而是将其缩小到相关点。联合的起点或终点是其中一个输入的起点或终点。

%first input
v{1}=[1,3,5,7;2,4,6,8];
%second input
v{2}=[2.5,6.5;4,8];
%solution can only contain these values:
relevantPoints=union(v{1}(:),v{2}(:));

%logical matrix: row i column j is true if input i contains segment j
%numel(relevantPoints) Points = numel(relevantPoints)-1 Segments
bn=false(size(v,2),numel(relevantPoints)-1);
for vector=1:numel(v)
    c=v{vector};
    for segment=1:size(c,2)
        thissegment=c(:,segment);
        %set all segments of bn to true, which are covered by the input segment
        bn(vector,find(relevantPoints==thissegment(1)):find(relevantPoints==thissegment(2))-1)=true;
    end
end
%finally the logic we want to apply
resultingSegments=and(bn(1,:),bn(2,:));
seg=[relevantPoints(find(resultingSegments))';relevantPoints(find(resultingSegments)+1)'];