-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathaabbdemo.m
More file actions
387 lines (298 loc) · 10.7 KB
/
Copy pathaabbdemo.m
File metadata and controls
387 lines (298 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
function aabbdemo(varargin)
%AABBDEMO run a series of aabb-tree demos.
% AABBDEMO(II) runs the II-th demo, where +1 <= II <= +3.
% Demos illustrate the functionallity of the MAKETREE
% routine -- performing spatial queries on collections of
% bounding-boxes.
%
% See also MAKETREE, DRAWTREE, QUERYSET, MAPVERT, MAPRECT
% Darren Engwirda : 2014 --
% Email : darren.engwirda@columbia.edu
% Last updated : 09/03/2018
if (nargin>=1)
id = varargin{1};
else
id = +1;
end
%------------------------------------------------- call demo
switch (id)
case 1, demo1;
case 2, demo2;
case 3, demo3;
otherwise
error('aabbdemo:invalidInput','Invalid demo selection.');
end
end
function demo1
%-----------------------------------------------------------
fprintf(1,[...
' AABBTREE offers d-dimensional aabb-tree construction &\n',...
' search for collections of spatial objects. These trees\n',...
' are useful when seeking to implement efficient spatial\n',...
' queries -- determining intersections between collecti-\n',...
' ons of spatial objects. \n\n',...
' Given a collection of spatial objects, an aabb-tree p-\n',...
' artitions the bounding-boxes of the elements in the c-\n',...
' ollection (the aabb''s) into a "tree" (hierarchy) of \n',...
' rectangular "nodes". In contrast to other types of ge-\n',...
' ometric trees (quadtrees, kd-trees, etc) the nodes in \n',...
' an aabb-tree enclose aabb''s -- not points -- and may \n',...
' overlap as a result. Objects in the collection are co-\n',...
' ntained in a single node only. \n\n']);
filename = mfilename('fullpath');
filepath = fileparts( filename );
addpath([filepath,'/mesh-file']);
[geom] = loadmsh([filepath,'/test-data/airfoil.msh']);
pp = geom.point.coord(:,1:2);
tt = geom.tria3.index(:,1:3);
bi = pp(tt(:,1),:); bj = pp(tt(:,1),:);
for ii = 2 : size(tt,2)
bi = min(bi,pp(tt(:,ii),:)) ;
bj = max(bj,pp(tt(:,ii),:)) ;
end
tr = maketree([bi,bj]) ;
fc = [.95,.95,.55];
ec = [.25,.25,.25];
figure;
subplot(1,2,1); hold on;
patch('faces',tt,'vertices',pp,'facecolor',fc,...
'edgecolor',ec,'facealpha',+.3);
axis image off;
set(gca,'units','normalized','position',[0.01,0.05,.48,.90]);
subplot(1,2,2); hold on;
drawtree(tr);
axis image off;
set(gca,'units','normalized','position',[0.51,0.05,.48,.90]);
end
function demo2
%-----------------------------------------------------------
fprintf(1,[...
' AABBTREE is a d-dimensional library, storing objects \n',...
' and performing search operations in R^d. AABBTREE sim-\n',...
' ply requires an description of the d-dimensional boun-\n',...
' ding-boxes of a given collection. It is not limited to\n',...
' simplexes (triangles, tetrahedrons, etc).\n\n']);
filename = mfilename('fullpath');
filepath = fileparts( filename );
addpath([filepath,'/mesh-file']);
[geom] = loadmsh([filepath,'/test-data/veins.msh']);
pp = geom.point.coord(:,1:3);
tt = geom.tria3.index(:,1:3);
bi = pp(tt(:,1),:); bj = pp(tt(:,1),:);
for ii = 2 : size(tt,2)
bi = min(bi,pp(tt(:,ii),:)) ;
bj = max(bj,pp(tt(:,ii),:)) ;
end
op.vtol = .67;
tr = maketree([bi,bj],op) ;
fc = [.95,.95,.55];
ec = [.25,.25,.25];
figure;
subplot(1,2,1); hold on;
patch('faces',tt,'vertices',pp,'facecolor',fc,...
'edgecolor',ec,'facealpha',+1.);
axis image off;
set(gca,'units','normalized','position',[0.01,0.05,.48,.90]);
view(80,15);
light; camlight;
subplot(1,2,2); hold on;
drawtree(tr);
axis image off;
view(80,15);
light; camlight;
set(gca,'units','normalized','position',[0.51,0.05,.48,.90]);
end
function demo3
%-----------------------------------------------------------
fprintf(1,[...
' AABBTREE facilitates efficient spatial queries through\n',...
' "localisation" -- reducing a large O(M*N) comparison \n',...
' to a sequence of small O(m*n) operations, where m<<M \n',...
' and n<<N. By partitioning the data about the aabb-tree\n',...
' itself, intersection tests can be carried out over sm-\n',...
' all local subsets, rather than between every pair of \n',...
' objects in the collection. \n\n',...
' In the following example, the intersections between a \n',...
' set of points and a set of circles is computed. \n',...
' The "slow" algorithm simply tests every point against \n',...
' every circle (an O(N^2) operation). \n\n',...
' The "fast" algorithm relies on an aabb-tree to partit-\n',...
' ion the data, and then computes the intersections loc-\n',...
' ally (an approx. O(N*log(N) operation)). The speed-up \n',...
' is around a factor of 10 (on my machine).\n\n',...
' The QUERYSET routine has been provided to compute such\n',...
' operations, taking an aabb-tree, a tree-query mapping,\n',...
' and a user-defined query function as inputs. See the \n',...
' DEMO-3 code in AABBDEMO.m for additional details.\n\n']);
nc = +10000;
np = +50000;
pc = randcirc(nc,2,0.02);
pi = rand(np,size(pc,2)-1);
fprintf(1,...
' "Slow" algorithm: \n');
tic
[ii_slow,ip_slow,cj_slow ] = slowfindcirc(pc,pi);
toc
fprintf(1,...
' "Fast" algorithm: \n');
tic
[ii_fast,ip_fast,cj_fast,tr] = fastfindcirc(pc,pi);
toc
fprintf(1,...
' Equivalent results? \n');
if (size(ii_slow) == size(ii_fast))
same = true ;
for ii = +1 : size(ip_slow,1)
c1 = ...
cj_slow(ip_slow(ii,1):ip_slow(ii,2));
c2 = ...
cj_fast(ip_fast(ii,1):ip_fast(ii,2));
c1 = sort (c1) ;
c2 = sort (c2) ;
if (length(c1) == length(c2))
if (any(c1 ~= c2))
same = false; break ;
end
else
same = false; break ;
end
end
else
same = false ;
end
if (same)
fprintf(1,' TRUE \n') ;
else
fprintf(1,' FALSE \n') ;
end
vp = ceil(linspace(+1,min(2500,np),2500));
vc = ceil(linspace(+1,min(5000,nc),5000));
figure;
subplot(1,2,1); hold on;
drawcirc(pc(vc,:));
plot(pi(vp,1),pi(vp,2),'r.');
axis image off;
set(gca,'units','normalized','position',[0.01,0.05,.48,.90]);
subplot(1,2,2); hold on;
drawtree(tr);
axis image off;
set(gca,'units','normalized','position',[0.51,0.05,.48,.90]);
end
function [ii,ip,cj] = slowfindcirc(pc,pi)
%SLOWFINDCIRC find the points enclosed by a set of circles.
% [II,IP,CJ] = SLOWFINDCIRC(PC,PI) computes the pairwise
% point-circle intersections between the points PI and
% the circles PC. PC(:,1:2) are the circle centres and
% PC(:,3) are the circle radii.
% [II,IP,CJ] is the set of intersections in compressed
% "sparse-style" indexing. Each point II(K) intersects
% with the list of circles CJ(IP(K,1):IP(K,2)).
%
% This is the "slow" brute-force variant.
ip = 1:size(pi,1);
ic = 1:size(pc,1);
[pj,cj] = incircle(ip,ic,pi,[pc(:,1:2),pc(:,3).^2]);
pj = pj( :);
cj = cj( :);
%-- re-index to the sparse-style representation
%-- of QUERYSET
[pj,ix] = sort (pj) ;
cj = cj(ix);
ix = find(diff(pj)>+0) ;
%-- the points in II intersect with >= 1 circle
ni = length (pj) ;
ii = pj([ix;ni]) ;
nj = length (cj) ;
ni = length (ii) ;
%-- the points in II intersect with the circles
%-- CJ(IP(K,1):IP(K,2)) {for point II(K)}.
ip = zeros(ni,2) ;
ip(:,1) = [+1; ix+1] ;
ip(:,2) = [ix; nj+0] ;
end
function [ii,ip,cj,tr] = fastfindcirc(pc,pi)
%FASTFINDCIRC find the points enclosed by a set of circles.
% [II,IP,CJ] = FASTFINDCIRC(PC,PI) computes the pairwise
% point-circle intersections between the points PI and
% the circles PC. PC(:,1:2) are the circle centres and
% PC(:,3) are the circle radii.
% [II,IP,CJ] is the set of intersections in compressed
% "sparse-style" indexing. Each point II(K) intersects
% with the list of circles CJ(IP(K,1):IP(K,2)).
%
% This is the "fast" aabb-indexed variant.
nd = size (pc,2)-1;
%-- compute the set of aabb's for circ.
bb = zeros(size(pc,1),nd*+2);
for id = +1 : nd
bb(:,id+nd*0) = ...
pc(:,id)-pc(:,nd+1) ;
bb(:,id+nd*1) = ...
pc(:,id)+pc(:,nd+1) ;
end
%-- compute aabb-tree for set of aabb's
op.nobj = +64;
tr = maketree(bb,op);
%-- compute tree-to-vert. indexing maps
tm = mapvert (tr,pi);
%-- the points in II intersect with >= 1 circle
%-- the points in II intersect with the circles
%-- CJ(IP(K,1):IP(K,2)) {for point II(K)}.
[ii,ip,cj] = ...
queryset(tr,tm,@incircle,pi,[pc(:,1:2),pc(:,3).^2]) ;
end
function [pj,cj] = incircle(ip,ic,pi,pc)
%INCIRCLE pairwise point-circle comparison kernel function.
% [PJ,CJ] = INCIRCLE(IP,IC,PI,PC) compute the pairwise in-
% tersections between the points PI(IP,:) and the circles
% PC(IC,:). PC(:,3) are the squared circle radii.
% [PJ,CJ] are pairs of intersections, such that the point
% PJ(K) intersects with the circle CJ(K).
li = cell(length(ic),1);
lj = cell(length(ic),1);
pt = pi(ip,:) ;
for ii = +1 : length(ic)
di = (pt(:,1)-pc(ic(ii),1)).^2 + ...
(pt(:,2)-pc(ic(ii),2)).^2 ;
li{ii} = find(di<=pc(ic(ii),3));
lj{ii} = ...
ii * ones(length(li{ii}),1);
end
pj = ip(vertcat(li{:})) ;
cj = ic(vertcat(lj{:})) ;
end
function [pc] = randcirc(nc,nd,rr)
%RANDCIRC make a set of NC randomised d-circles in R^ND with
%mean radius RR.
pc = [rand(nc,nd), rr*(rand(nc,1))];
end
function drawcirc(pc)
%DRAWCIRC draw a set of NC d-circles.
fc = [.95,.95,.55];
ec = [.25,.25,.25];
switch (size(pc,2))
case 3
%--------------------------------------------------- circles
tt = linspace(+.0,+2.*pi,24);
xx = cos(tt)';
yy = sin(tt)';
nt = length(tt);
ee = [(1:nt-1)',(2:nt-0)'];
xc = cell(size(pc,1),1);
yc = cell(size(pc,1),1);
jc = cell(size(pc,1),1);
for ic = +1 : size(pc,1)
xc{ic} = pc(ic,3)*xx + pc(ic,1);
yc{ic} = pc(ic,3)*yy + pc(ic,2);
jc{ic} = ee + (ic-1)*nt;
end
pp =[vertcat(xc{:}), ...
vertcat(yc{:})] ;
ff = vertcat(jc{:});
case 4
%--------------------------------------------------- spheres
%%!!todo:
end
patch('faces',ff,'vertices',pp,'facecolor',fc,...
'edgecolor',ec,'facealpha',+.3);
end