Skip to content

Commit b834243

Browse files
committed
精简trace功能
1 parent 96a2789 commit b834243

3 files changed

Lines changed: 41 additions & 42 deletions

File tree

geom.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ func (p Point) minMaxDist(r Rect) float64 {
143143
// Rect represents a subset of n-dimensional Euclidean space of the form
144144
// [a1, b1] x [a2, b2] x ... x [an, bn], where ai < bi for all 1 <= i <= n.
145145
type Rect struct {
146-
p, q Point // Enforced by NewRect: p[i] <= q[i] for all i.
147-
parent *node
146+
p, q Point // Enforced by NewRect: p[i] <= q[i] for all i.
147+
traceBox []Rect
148148
}
149149

150150
// PointCoord returns the coordinate of the point of the rectangle at i
@@ -183,15 +183,11 @@ func (r Rect) String() string {
183183
return strings.Join(s, "x")
184184
}
185185

186-
func (r Rect) SetParent(parent *node) Spatial {
187-
r.parent = parent
186+
func (r Rect) AppendTraceBox(bb Rect) Spatial {
187+
r.traceBox = append(r.traceBox, bb)
188188
return r
189189
}
190190

191-
func (r Rect) GetParent() *node {
192-
return r.parent
193-
}
194-
195191
func (r Rect) Bounds() Rect {
196192
return r
197193
}

rtree.go

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,7 @@ func (e entry) String() string {
276276
// R树上存储对象的接口。以提供存储和查询功能。
277277
type Spatial interface {
278278
Bounds() Rect
279-
SetParent(parent *node) Spatial
280-
GetParent() *node
279+
AppendTraceBox(bb Rect) Spatial
281280
}
282281

283282
// Insertion
@@ -711,8 +710,8 @@ func (tree *Rtree) condenseTree(n *node) {
711710
// 内部实现涉及遍历和递归调用。
712711
// 其实现依据是 A. 古特曼(A. Guttman)所著《R - 树:一种用于空间搜索的动态索引结构》的第 3.1 节,
713712
// 该内容出自 1984 年美国计算机协会数据管理专业组(ACM SIGMOD)的会议论文集,第 47 至 57 页。
714-
func (tree *Rtree) SearchIntersect(bb Rect, filters ...Filter) []Spatial {
715-
return tree.searchIntersect([]Spatial{}, tree.root, bb, filters)
713+
func (tree *Rtree) SearchIntersect(bb Rect, needTrace bool, filters ...Filter) []Spatial {
714+
return tree.searchIntersect([]Spatial{}, tree.root, bb, needTrace, filters)
716715
}
717716

718717
// SearchIntersectWithLimit is similar to SearchIntersect, but returns
@@ -725,32 +724,34 @@ func (tree *Rtree) SearchIntersect(bb Rect, filters ...Filter) []Spatial {
725724
// (带限制的交集搜索) 与 “SearchIntersect(交集搜索)” 类似,
726725
// 但在找到前 k 个结果时会立即返回。当 k 为负数时,其行为与 “SearchIntersect” 完全一样,会返回所有结果。
727726
// 保留该功能是为了向后兼容,不过请使用带有 “LimitFilter(限制过滤器)” 的 “SearchIntersect” 来实现相应操作。
728-
func (tree *Rtree) SearchIntersectWithLimit(k int, bb Rect) []Spatial {
727+
func (tree *Rtree) SearchIntersectWithLimit(k int, bb Rect, needTrace bool) []Spatial {
729728
// backwards compatibility, previous implementation didn't limit results if
730729
// k was negative.
731730
if k < 0 {
732-
return tree.SearchIntersect(bb)
731+
return tree.SearchIntersect(bb, needTrace)
733732
}
734-
return tree.SearchIntersect(bb, LimitFilter(k))
733+
return tree.SearchIntersect(bb, needTrace, LimitFilter(k))
735734
}
736735

737736
// searchIntersect 搜索指定矩形 bb 在 n 节点中相交的所有对象。
738737
// 会涉及到遍历和递归调用
739-
func (tree *Rtree) searchIntersect(results []Spatial, n *node, bb Rect, filters []Filter) []Spatial {
738+
func (tree *Rtree) searchIntersect(results []Spatial, n *node, bb Rect, needTrace bool, filters []Filter) []Spatial {
740739
for _, e := range n.entries {
741740
if !intersect(e.bb, bb) {
742741
continue
743742
}
744743

745744
if !n.leaf {
746-
results = tree.searchIntersect(results, e.child, bb, filters)
745+
results = tree.searchIntersect(results, e.child, bb, needTrace, filters)
747746
continue
748747
}
749748

750749
refuse, abort := applyFilters(results, e.obj, filters)
751750
if !refuse {
752751
searchOut := e.obj
753-
// searchOut = searchOut.SetParent(n)
752+
if needTrace {
753+
searchOut = searchOut.AppendTraceBox(n.ComputeBoundingBox())
754+
}
754755
results = append(results, searchOut)
755756
}
756757

@@ -763,8 +764,8 @@ func (tree *Rtree) searchIntersect(results []Spatial, n *node, bb Rect, filters
763764

764765
// NearestNeighbor returns the closest object to the specified point.
765766
// Implemented per "Nearest Neighbor Queries" by Roussopoulos et al
766-
func (tree *Rtree) NearestNeighbor(p Point) Spatial {
767-
obj, _ := tree.nearestNeighbor(p, tree.root, math.MaxFloat64, nil)
767+
func (tree *Rtree) NearestNeighbor(p Point, needTrace bool) Spatial {
768+
obj, _ := tree.nearestNeighbor(p, tree.root, math.MaxFloat64, nil, needTrace)
768769
return obj
769770
}
770771

@@ -825,13 +826,16 @@ func pruneEntriesMinDist(d float64, entries []entry, minDists []float64) []entry
825826
return entries[:i]
826827
}
827828

828-
func (tree *Rtree) nearestNeighbor(p Point, n *node, d float64, nearest Spatial) (Spatial, float64) {
829+
func (tree *Rtree) nearestNeighbor(p Point, n *node, d float64, nearest Spatial, needTrace bool) (Spatial, float64) {
829830
if n.leaf {
830831
for _, e := range n.entries {
831832
dist := math.Sqrt(p.minDist(e.bb))
832833
if dist < d {
833834
d = dist
834835
nearest = e.obj
836+
if needTrace {
837+
nearest = nearest.AppendTraceBox(n.ComputeBoundingBox())
838+
}
835839
}
836840
}
837841
} else {
@@ -858,19 +862,18 @@ func (tree *Rtree) nearestNeighbor(p Point, n *node, d float64, nearest Spatial)
858862
continue
859863
}
860864

861-
subNearest, dist := tree.nearestNeighbor(p, e.child, d, nearest)
865+
subNearest, dist := tree.nearestNeighbor(p, e.child, d, nearest, needTrace)
862866
if dist < d {
863867
d = dist
864868
nearest = subNearest
865869
}
866870
}
867871
}
868-
nearest = nearest.SetParent(n)
869872
return nearest, d
870873
}
871874

872875
// NearestNeighbors gets the closest Spatials to the Point.
873-
func (tree *Rtree) NearestNeighbors(k int, p Point, filters ...Filter) []Spatial {
876+
func (tree *Rtree) NearestNeighbors(k int, p Point, needTrace bool, filters ...Filter) []Spatial {
874877
// preallocate the buffers for sortings the branches. At each level of the
875878
// tree, we slide the buffer by the number of entries in the node.
876879
maxBufSize := tree.MaxChildren * tree.Depth()
@@ -881,7 +884,7 @@ func (tree *Rtree) NearestNeighbors(k int, p Point, filters ...Filter) []Spatial
881884
dists := make([]float64, 0, k)
882885
objs := make([]Spatial, 0, k)
883886

884-
objs, _, _ = tree.nearestNeighbors(k, p, tree.root, dists, objs, filters, branches, branchDists)
887+
objs, _, _ = tree.nearestNeighbors(k, p, tree.root, dists, objs, filters, branches, branchDists, needTrace)
885888
return objs
886889
}
887890

@@ -918,7 +921,7 @@ func insertNearest(k int, dists []float64, nearest []Spatial, dist float64, obj
918921
return dists, nearest, false
919922
}
920923

921-
func (tree *Rtree) nearestNeighbors(k int, p Point, n *node, dists []float64, nearest []Spatial, filters []Filter, b []entry, bd []float64) ([]Spatial, []float64, bool) {
924+
func (tree *Rtree) nearestNeighbors(k int, p Point, n *node, dists []float64, nearest []Spatial, filters []Filter, b []entry, bd []float64, needTrace bool) ([]Spatial, []float64, bool) {
922925
var abort bool
923926
if n.leaf {
924927
for _, e := range n.entries {
@@ -935,7 +938,7 @@ func (tree *Rtree) nearestNeighbors(k int, p Point, n *node, dists []float64, ne
935938
branches = pruneEntriesMinDist(dists[l-1], branches, branchDists)
936939
}
937940
for _, e := range branches {
938-
nearest, dists, abort = tree.nearestNeighbors(k, p, e.child, dists, nearest, filters, b[len(n.entries):], bd[len(n.entries):])
941+
nearest, dists, abort = tree.nearestNeighbors(k, p, e.child, dists, nearest, filters, b[len(n.entries):], bd[len(n.entries):], needTrace)
939942
if abort {
940943
break
941944
}

rtree_test.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,7 @@ func TestSearchIntersect(t *testing.T) {
949949

950950
p := Point{2, 1.5}
951951
bb := mustRect(p, []float32{10, 5.5})
952-
q := rt.SearchIntersect(bb)
952+
q := rt.SearchIntersect(bb, false)
953953

954954
var expected []Spatial
955955
for _, i := range []int{1, 2, 3, 4, 6, 7} {
@@ -995,7 +995,7 @@ func TestSearchIntersectWithLimit(t *testing.T) {
995995
// Loop through all possible limits k of SearchIntersectWithLimit,
996996
// and test that the results are as expected.
997997
for k := -1; k <= len(things); k++ {
998-
q := rt.SearchIntersectWithLimit(k, bb)
998+
q := rt.SearchIntersectWithLimit(k, bb, false)
999999

10001000
if k == -1 {
10011001
ensureDisorderedSubset(t, q, expected)
@@ -1054,7 +1054,7 @@ func TestSearchIntersectWithTestFilter(t *testing.T) {
10541054
}
10551055

10561056
// this test filter will only pick the objects that are in expected
1057-
objects := rt.SearchIntersect(bb, func(results []Spatial, object Spatial) (bool, bool) {
1057+
objects := rt.SearchIntersect(bb, false, func(results []Spatial, object Spatial) (bool, bool) {
10581058
for _, exp := range expected {
10591059
if exp == object {
10601060
return false, false
@@ -1087,7 +1087,7 @@ func TestSearchIntersectNoResults(t *testing.T) {
10871087
rt := tc.build()
10881088

10891089
bb := mustRect(Point{99, 99}, []float32{10, 5.5})
1090-
q := rt.SearchIntersect(bb)
1090+
q := rt.SearchIntersect(bb, false)
10911091
if len(q) != 0 {
10921092
t.Errorf("SearchIntersect failed to return nil slice on failing query")
10931093
}
@@ -1132,10 +1132,10 @@ func TestNearestNeighbor(t *testing.T) {
11321132
t.Run(tc.name, func(t *testing.T) {
11331133
rt := tc.build()
11341134

1135-
obj1 := rt.NearestNeighbor(Point{0.5, 0.5})
1136-
obj2 := rt.NearestNeighbor(Point{1.5, 4.5})
1137-
obj3 := rt.NearestNeighbor(Point{5, 2.5})
1138-
obj4 := rt.NearestNeighbor(Point{3.5, 2.5})
1135+
obj1 := rt.NearestNeighbor(Point{0.5, 0.5}, true)
1136+
obj2 := rt.NearestNeighbor(Point{1.5, 4.5}, true)
1137+
obj3 := rt.NearestNeighbor(Point{5, 2.5}, true)
1138+
obj4 := rt.NearestNeighbor(Point{3.5, 2.5}, true)
11391139
rect1 := obj1.(Rect)
11401140
rect2 := obj2.(Rect)
11411141
rect3 := obj3.(Rect)
@@ -1269,14 +1269,14 @@ func TestNearestNeighborsAll(t *testing.T) {
12691269
p := Point{0.5, 0.5}
12701270
sort.Sort(byMinDist{things, p})
12711271

1272-
objs := rt.NearestNeighbors(len(things), p)
1272+
objs := rt.NearestNeighbors(len(things), p, false)
12731273
for i := range things {
12741274
if objs[i] != things[i] {
12751275
t.Errorf("NearestNeighbors failed at index %d: %v != %v", i, objs[i], things[i])
12761276
}
12771277
}
12781278

1279-
objs = rt.NearestNeighbors(len(things)+2, p)
1279+
objs = rt.NearestNeighbors(len(things)+2, p, false)
12801280
if len(objs) > len(things) {
12811281
t.Errorf("NearestNeighbors failed: too many elements")
12821282
}
@@ -1311,7 +1311,7 @@ func TestNearestNeighborsFilters(t *testing.T) {
13111311
p := Point{0.5, 0.5}
13121312
sort.Sort(byMinDist{expected, p})
13131313

1314-
objs := rt.NearestNeighbors(len(things), p, func(r []Spatial, obj Spatial) (bool, bool) {
1314+
objs := rt.NearestNeighbors(len(things), p, true, func(r []Spatial, obj Spatial) (bool, bool) {
13151315
for _, ex := range expected {
13161316
if ex == obj {
13171317
return false, false
@@ -1347,14 +1347,14 @@ func TestNearestNeighborsHalf(t *testing.T) {
13471347
t.Run(tc.name, func(t *testing.T) {
13481348
rt := tc.build()
13491349

1350-
objs := rt.NearestNeighbors(3, p)
1350+
objs := rt.NearestNeighbors(3, p, false)
13511351
for i := range objs {
13521352
if objs[i] != things[i] {
13531353
t.Errorf("NearestNeighbors failed at index %d: %v != %v", i, objs[i], things[i])
13541354
}
13551355
}
13561356

1357-
objs = rt.NearestNeighbors(len(things)+2, p)
1357+
objs = rt.NearestNeighbors(len(things)+2, p, false)
13581358
if len(objs) > len(things) {
13591359
t.Errorf("NearestNeighbors failed: too many elements")
13601360
}
@@ -1371,10 +1371,10 @@ func TestMinMaxDistFloatingPointRoundingError(t *testing.T) {
13711371
}
13721372
things := make([]Spatial, 0, len(rects))
13731373
for i := range rects {
1374-
things = append(things, &rects[i])
1374+
things = append(things, rects[i])
13751375
}
13761376
rt := NewTree(2, 1, 2, things...)
1377-
n := rt.NearestNeighbor(Point{1134851.8, 25570.8})
1377+
n := rt.NearestNeighbor(Point{1134851.8, 25570.8}, true)
13781378
rect := n.(Rect)
13791379
if !rect.Equal(rects[1]) {
13801380
t.Fatalf("wrong neighbor, expected %v, got %v", things[1], n)

0 commit comments

Comments
 (0)