-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrange.go
67 lines (53 loc) · 1.81 KB
/
range.go
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
/*
* gouda/kdtree/range: code implementing range search
*
* Copyright (C) 2018 Pawel Foremski <[email protected]>
* Licensed to you under GNU GPL v3
*/
package kdtree
import "github.com/pforemski/gouda/point"
// search() returns all node's points that match given query range
// world is an information on what the node and all children can contain
func (node *KDNode) search(query *point.Range, world *point.Range, out point.Points) point.Points {
// check if query intersects with world
switch query.Intersects(world) {
case 0: // no intersection
return out
case 1: // some intersection
// check if node's point is contained
if query.Contains(node.point) {
out = append(out, node.point)
}
// check in the left child
if node.left != nil {
out = node.left.search(query, node.world_left(world), out)
}
// check in the right child
if node.right != nil {
out = node.right.search(query, node.world_right(world), out)
}
case 2: // fully contained
out = node.dump(out)
}
return out
}
// world_left() updates worldview to reflect the left child of given node
func (parent *KDNode) world_left(world *point.Range) *point.Range {
r := point.Range{}
r.Min = world.Min // bottom limits don't change
// upper limits: leave all but parent.axis
r.Max = make([]float64, len(world.Max))
copy(r.Max, world.Max)
r.Max[parent.axis] = parent.point.V[parent.axis] // all elements < median
return &r
}
// world_right() updates worldview to reflect the right child of given node
func (parent *KDNode) world_right(world *point.Range) *point.Range {
r := point.Range{}
r.Max = world.Max // upper limits don't change
// botton limits: leave all but parent.axis
r.Min = make([]float64, len(world.Min))
copy(r.Min, world.Min)
r.Min[parent.axis] = parent.point.V[parent.axis] // all elements >= median
return &r
}