@@ -16,14 +16,16 @@ not shapes of nonzero size.)
16
16
"""
17
17
mutable struct KDTree{K,S<: Shape{K} }
18
18
s:: Vector{S}
19
+ s_index:: Vector{Int}
19
20
ix:: Int
20
21
x:: Float64
21
22
left:: KDTree{K,S} # shapes ≤ x in coordinate ix
22
23
right:: KDTree{K,S} # shapes > x in coordinate ix
23
- KDTree {K,S} (s:: AbstractVector{S} ) where {K,S<: Shape{K} } = new (s, 0 )
24
+ KDTree {K,S} (s:: AbstractVector{S} ) where {K,S<: Shape{K} } = new (s, collect (eachindex (s)), 0 )
25
+ KDTree {K,S} (s:: AbstractVector{S} ,s_index:: Vector{<:Int} ) where {K,S<: Shape{K} } = new (s, s_index, 0 )
24
26
function KDTree {K,S} (ix:: Integer , x:: Real , left:: KDTree{K,S} , right:: KDTree{K,S} ) where {K,S<: Shape{K} }
25
27
1 ≤ ix ≤ K || throw (BoundsError ())
26
- new (S[], ix, x, left, right)
28
+ new (S[], Int[], ix, x, left, right)
27
29
end
28
30
end
29
31
@@ -38,8 +40,15 @@ Construct a K-D tree (`KDTree`) representation of a list of
38
40
When searching the tree, shapes that appear earlier in `s`
39
41
take precedence over shapes that appear later.
40
42
"""
43
+
41
44
function KDTree (s:: AbstractVector{S} ) where {K,S<: Shape{K} }
42
- (length (s) ≤ 4 || K == 0 ) && return KDTree {K,S} (s)
45
+ # If no list of indicies is provided, simply enumerate by the number of
46
+ # shapes in `s`.
47
+ return KDTree (s,collect (eachindex (s)))
48
+ end
49
+
50
+ function KDTree (s:: AbstractVector{S} , s_index:: AbstractVector{<:Integer} ) where {K,S<: Shape{K} }
51
+ (length (s) ≤ 4 || K == 0 ) && return KDTree {K,S} (s, s_index)
43
52
44
53
# figure out the best dimension ix to divide over,
45
54
# the dividing plane x, and the number (nl,nr) of
@@ -61,22 +70,26 @@ function KDTree(s::AbstractVector{S}) where {K,S<:Shape{K}}
61
70
end
62
71
63
72
# don't bother subdividing if it doesn't reduce the # of shapes much
64
- 4 * max (nl,nr) > 3 * length (s) && return KDTree {K,S} (s)
73
+ 4 * max (nl,nr) > 3 * length (s) && return KDTree {K,S} (s,s_index )
65
74
66
75
# create the arrays of shapes in each subtree
67
76
sl = Vector {S} (undef, nl)
77
+ sl_idx = Vector {Int} (undef, nl)
68
78
sr = Vector {S} (undef, nr)
79
+ sr_idx = Vector {Int} (undef, nr)
69
80
il = ir = 0
70
81
for k in eachindex (s)
71
82
if b[k][1 ][ix] ≤ x
72
83
sl[il += 1 ] = s[k]
84
+ sl_idx[il] = s_index[k]
73
85
end
74
86
if b[k][2 ][ix] > x
75
87
sr[ir += 1 ] = s[k]
88
+ sr_idx[ir] = s_index[k]
76
89
end
77
90
end
78
91
79
- return KDTree {K,S} (ix, x, KDTree (sl), KDTree (sr))
92
+ return KDTree {K,S} (ix, x, KDTree (sl,sl_idx ), KDTree (sr,sr_idx ))
80
93
end
81
94
82
95
depth (kd:: KDTree ) = kd. ix == 0 ? 0 : max (depth (kd. left), depth (kd. right)) + 1
@@ -104,7 +117,7 @@ function Base.findfirst(p::SVector{N}, s::Vector{S}) where {N,S<:Shape{N}}
104
117
for i in eachindex (s)
105
118
b = bounds (s[i])
106
119
if all (b[1 ] .< p .< b[2 ]) && p ∈ s[i] # check if p is within bounding box is faster
107
- return s[i]
120
+ return i
108
121
end
109
122
end
110
123
return nothing
@@ -118,7 +131,12 @@ function Base.findfirst(p::SVector{N}, kd::KDTree{N}) where {N}
118
131
return findfirst (p, kd. right)
119
132
end
120
133
else
121
- return findfirst (p, kd. s)
134
+ idx = findfirst (p, kd. s)
135
+ if isnothing (idx)
136
+ return idx
137
+ else
138
+ return kd. s_index[idx]
139
+ end
122
140
end
123
141
end
124
142
0 commit comments