我有一个带有以下数据数组的文件
7
1 2 3 120.12
4 5 8 70.25
6 11 12 111.20
2 6 10 90.39
3 2 1 120.12
10 6 2 90.39
11 2 3 87.12
9
1 2 3 110.12
4 5 8 70.25
6 11 12 111.20
2 6 10 60.39
3 2 1 110.12
10 6 2 60.39
11 2 3 87.12
20 1 9 156.48
3 2 11 87.12
...
文件由数十个数据块组成。每个数据块有一个顶部标题行(数据行数=数据块大小(,数据段有4列。这4列是3个点的角度。前三列是点编号或点索引。第4列是3个点的角度。因此,它是"ID1 ID2 ID3角度"。例如,"1 2 3 120.12"表示1-2-3的角度(本例中顶点为"2"(为120.12度。
问题是,存在重复元素。在第一帧中,有两个重复对:1 2 3和3 2 1,以及2 6 10和10 6 2。在第二帧中,有3个重复项,1 2 3和3 2 1,以及2 6 10和10 6 2,以及11 2 3和2 3 11。所有这些对都是相同的角度,但方向正好相反。
如何排除那些重复的元素,并为每个数据块只保留一个?我希望上面的例子变成这样:
5
1 2 3 120.12
4 5 8 70.25
6 11 12 111.20
2 6 10 90.39
11 2 3 87.12
6
1 2 3 110.12
4 5 8 70.25
6 11 12 111.20
2 6 10 60.39
11 2 3 87.12
20 1 9 156.48
...
我希望得到每个数据块的角度分布和法线PDF,以及所有角度,无论角度如何。但我不确定如何排除那些重复的组合。
幸运的是,在不同的组合中出现相同角度的可能性很小,所以我试图根据ID号排除重复元素,比如ID1 ID2 ID3由ID3 ID2 ID1重复。但我找不到任何合适的逻辑来处理if循环和循环或函数。。。
假设您已经分离了块,其中一个块存储为n-by-4双数组block
。
您需要的是对每行中的顶点进行排序,同时保持第二行的固定。这可以通过沿着行维度使用sort
来实现,如下
sort([block(:,1),block(:,3)],2);
第二个输入2
指定沿着列对所有行进行排序。
接下来,您需要添加回第二个顶点,并挑选出唯一的顶点组合。
unique([block(:,2),sort([block(:,1),block(:,3)],2)],'row');
'row'
意味着从整体上挑选出唯一的行,而不是唯一的单个元素。您可以添加'stable'
以保留现有订单。但你没有在问题中具体说明这种需求。所以我会选择它。
为了获得原始顶点顺序,我们使用唯一行的索引,如下所示。这里,您需要确保由有效顶点序列标识的重复角度具有相同的角度值。(否则,您需要在上述公式中添加block(:,4)
。(
[~, ind] = unique([block(:,2),sort([block(:,1),block(:,3)],2)],'row');
你的最终答案是:(只有下面两行(
[~, ind] = unique([block(:,2),sort([block(:,1),block(:,3)],2)],'row');
block(ind,:),
ans =
1.0000 2.0000 3.0000 120.1200
11.0000 2.0000 3.0000 87.1200
4.0000 5.0000 8.0000 70.2500
2.0000 6.0000 10.0000 90.3900
6.0000 11.0000 12.0000 111.2000
如果有人能用手动缓存写一个基于循环的答案,我很想看看以上和用手动缓存循环之间的区别,哪一个更快。
这是accumarray
的经典作业。由于您没有提供任何加载数据的代码,所以我只是用readmatrix
读取了它。如果您以另一种方式加载代码,则可能需要对其进行调整。
% given
DATA = readmatrix('data.txt','NumHeaderLines',0); % load data
DATA(:,end) = []; % remove last column, as only NaN
hl = any(isnan(DATA(:,2:end)),2); % identify header lines
subs = cumsum(hl); % indices for accumarray
% unqiue rows of chunks of data
y = accumarray(subs(:), ... % indices of chunks
1:numel(subs).', ... % numbering of rows
[], ... % not used
@(x) { ... % anonymous function
unique( ... % unique 'rows' of chunks
[sort( DATA(x,1:3), 2) DATA(x,4)], ... % first 3 columns sorted
'rows', 'stable' ... % stable -> do not change order
)});
y = cell2mat(y); % tranfsform back to array
y =
7.0000 NaN NaN NaN
1.0000 2.0000 3.0000 120.1200
4.0000 5.0000 8.0000 70.2500
6.0000 11.0000 12.0000 111.2000
2.0000 6.0000 10.0000 90.3900
2.0000 3.0000 11.0000 87.1200
9.0000 NaN NaN NaN
1.0000 2.0000 3.0000 110.1200
4.0000 5.0000 8.0000 70.2500
6.0000 11.0000 12.0000 111.2000
2.0000 6.0000 10.0000 60.3900
2.0000 3.0000 11.0000 87.1200
1.0000 9.0000 20.0000 156.4800