-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathqueryset.m
109 lines (88 loc) · 3.5 KB
/
queryset.m
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
function [qi,qp,qj] = queryset(tr,tm,fn,varargin)
%QUERYSET spatial queries for AABB-indexed collections.
% [QI,QP,QJ] = QUERYSET(TR,TM,FN) computes a spatial query
% on an indexed collection. TR is the AABB-tree built to
% index the collection, TM is the query-to-tree mapping
% structure, and FN is the intersection "kernel" function,
% called to compute actual intersections.
%
% A set of intersecting objects is returned for each item,
% such that for each query item QI(II), a list of interse-
% cting objects QJ(QP(II,1):QP(II,2)) is returned.
%
% [PK,CK] = FN(PJ,CJ,A1,...,AN) is an intersection kernel
% function called for each non-empty node in the tree TR.
% PJ,CJ are Nx1 and Mx1 arrays of query- and obj.-indices
% to compare against each other. These lists represent a
% "localised" O(N*M) "tile" of pairwise comparisons. PK,CK
% are lists of matching objects. A1,...,AN are a set of
% optional user-defined arguments that are passed to the
% kernel function FN internally. Optional arguments can be
% passed to FN via calls to QUERYSET(..., A1,...AN).
%
% See also MAPVERT, MAPRECT, MAKETREE
% Darren Engwirda : 2017 --
% Email : de2363@columbia.edu
% Last updated : 07/10/2017
qi = []; qp = []; qj = [];
%---------------------------------------------- basic checks
if (nargin <= +2)
error('queryset:incorrectNumInputs', ...
'Incorrect number of inputs.');
end
%---------------------------------------------- empty inputs
if (isempty(tr)), return; end
%---------------------------------------------- basic checks
if (~isempty(tr) && ~isstruct(tr) )
error('queryset:incorrectInputClass', ...
'Incorrect input class.') ;
end
if (~isempty(tm) && ~isstruct(tm) )
error('queryset:incorrectInputClass', ...
'Incorrect input class.') ;
end
%---------------------------------- check existing aabb-tree
if (~isfield(tm,'ii') || ...
~isfield(tm,'ll') )
error('queryset:incorrectAABBstruct', ...
'Invalid aabb-maps obj.') ;
end
%---------------------------------- check existing aabb-tree
if (~isfield(tr,'xx') || ...
~isfield(tr,'ii') || ...
~isfield(tr,'ll') )
error('queryset:incorrectAABBstruct', ...
'Invalid aabb-tree obj.') ;
end
%------------------------------ spatial query over tree-node
ic = cell(size(tm.ii,1),1) ;
jc = cell(size(tm.ii,1),1) ;
for ip = 1 : size(tm.ii,1)
%-------------------------- extract items/query per tile
ni = tm.ii(ip,1) ; % node (in tree)
%-------------------------- do O(n*m) search within tile
[qi,qj] = feval(fn, ...
tm.ll{ip,1}, ... % query in tile
tr.ll{ni,1}, ... % items in tile
varargin {:} ) ;
%-------------------------- push loc. item-query matches
ic{ip} = qi(:) ;
jc{ip} = qj(:) ;
end
%-------------------------------- concat matches into arrays
qi = vertcat(ic{:});
qj = vertcat(jc{:});
if (isempty(qj)),return; end
%-------------------------------- form sparse-style indexing
[qi,ix] = sort (qi) ;
qj = qj(ix);
ix = find(diff(qi));
ni = length (qi) ;
qi = qi([ix;ni]) ;
nj = length (qj) ;
ni = length (qi) ;
%------------------------------ each list is IP(I,1):IP(I,2)
qp = zeros(ni,2) ;
qp(:,1) = [+1; ix+1] ;
qp(:,2) = [ix; nj+0] ;
end