Skip to content

Commit 991b79d

Browse files
committed
feature 优化性能修复bug
1 parent 99f2018 commit 991b79d

5 files changed

Lines changed: 355 additions & 194 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# rtreego
2-
https://github.com/dhconnelly/rtreego 精度进行了更改,改为float32
2+
https://github.com/dhconnelly/rtreego 精度进行了更改,改为float32。依据版本是主线分支 2024-02-18 版本。此版本对1.2进行了bug修复。而1.2 对1.1进行了性能提升。
33

geom.go

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
)
1212

1313
// DimError represents a failure due to mismatched dimensions.
14+
//
15+
// 表示由于维度不匹配导致的失败。
1416
type DimError struct {
1517
Expected int
1618
Actual int
@@ -22,46 +24,60 @@ func (err DimError) Error() string {
2224

2325
// DistError is an improper distance measurement. It implements the error
2426
// and is generated when a distance-related assertion fails.
27+
//
28+
// 表示不正确的距离测量。它实现了 `error` 接口,并在距离相关的断言失败时生成。
2529
type DistError float32
2630

2731
func (err DistError) Error() string {
2832
return "rtreego: improper distance"
2933
}
3034

3135
// Point represents a point in n-dimensional Euclidean space.
36+
//
37+
// 表示 n 维欧几里得空间中的一个点。
3238
type Point []float32
3339

40+
func (p Point) Copy() Point {
41+
result := make(Point, len(p))
42+
copy(result, p)
43+
return result
44+
}
45+
3446
// Dist computes the Euclidean distance between two points p and q.
47+
//
48+
// 计算 p 和 q 两点之间的欧几里得距离。就是两点间 每个维度上的差值平方和的平方根
3549
func (p Point) dist(q Point) float32 {
3650
if len(p) != len(q) {
3751
panic(DimError{len(p), len(q)})
3852
}
39-
sum := 0.0
53+
sum := float32(0.0)
4054
for i := range p {
4155
dx := p[i] - q[i]
42-
sum += float64(dx * dx)
56+
sum += dx * dx
4357
}
44-
return float32(math.Sqrt(sum))
58+
return float32(math.Sqrt(float64(sum)))
4559
}
4660

4761
// minDist computes the square of the distance from a point to a rectangle.
4862
// If the point is contained in the rectangle then the distance is zero.
4963
//
5064
// Implemented per Definition 2 of "Nearest Neighbor Queries" by
5165
// N. Roussopoulos, S. Kelley and F. Vincent, ACM SIGMOD, pages 71-79, 1995.
52-
func (p Point) minDist(r *Rect) float32 {
66+
//
67+
// 计算从一个点到一个矩形的距离的平方。如果该点包含在矩形内,则距离为零。
68+
func (p Point) minDist(r Rect) float64 {
5369
if len(p) != len(r.p) {
5470
panic(DimError{len(p), len(r.p)})
5571
}
5672

57-
sum := float32(0.0)
73+
sum := 0.0
5874
for i, pi := range p {
5975
if pi < r.p[i] {
6076
d := pi - r.p[i]
61-
sum += d * d
77+
sum += float64(d) * float64(d)
6278
} else if pi > r.q[i] {
6379
d := pi - r.q[i]
64-
sum += d * d
80+
sum += float64(d) * float64(d)
6581
} else {
6682
sum += 0
6783
}
@@ -75,7 +91,9 @@ func (p Point) minDist(r *Rect) float32 {
7591
//
7692
// Implemented per Definition 4 of "Nearest Neighbor Queries" by
7793
// N. Roussopoulos, S. Kelley and F. Vincent, ACM SIGMOD, pages 71-79, 1995.
78-
func (p Point) minMaxDist(r *Rect) float32 {
94+
//
95+
// 计算从`p`到`r`上各点的最大距离中的最小值。如果`r`是某些几何对象的边界框,那么在`r`中至少有一个对象位于`p`的minMaxDist(p, r)范围内
96+
func (p Point) minMaxDist(r Rect) float64 {
7997
if len(p) != len(r.p) {
8098
panic(DimError{len(p), len(r.p)})
8199
}
@@ -101,18 +119,18 @@ func (p Point) minMaxDist(r *Rect) float32 {
101119
// This formula can be computed in linear time by precomputing
102120
// S = sum{1<=i<=n}(|pi - rMi|^2).
103121

104-
S := float32(0.0)
122+
S := 0.0
105123
for i := range p {
106124
d := p[i] - rM(i)
107-
S += d * d
125+
S += float64(d) * float64(d)
108126
}
109127

110128
// Compute MinMaxDist using the precomputed S.
111-
min := float32(math.MaxFloat32)
129+
min := math.MaxFloat64
112130
for k := range p {
113131
d1 := p[k] - rM(k)
114132
d2 := p[k] - rm(k)
115-
d := S - d1*d1 + d2*d2
133+
d := S - float64(d1)*float64(d1) + float64(d2)*float64(d2)
116134
if d < min {
117135
min = d
118136
}
@@ -128,17 +146,19 @@ type Rect struct {
128146
}
129147

130148
// PointCoord returns the coordinate of the point of the rectangle at i
131-
func (r *Rect) PointCoord(i int) float32 {
149+
//
150+
// 返回矩形在索引 i 处的坐标。
151+
func (r Rect) PointCoord(i int) float32 {
132152
return r.p[i]
133153
}
134154

135155
// LengthsCoord returns the coordinate of the lengths of the rectangle at i
136-
func (r *Rect) LengthsCoord(i int) float32 {
156+
func (r Rect) LengthsCoord(i int) float32 {
137157
return r.q[i] - r.p[i]
138158
}
139159

140160
// Equal returns true if the two rectangles are equal
141-
func (r *Rect) Equal(other *Rect) bool {
161+
func (r Rect) Equal(other Rect) bool {
142162
for i, e := range r.p {
143163
if e != other.p[i] {
144164
return false
@@ -152,7 +172,7 @@ func (r *Rect) Equal(other *Rect) bool {
152172
return true
153173
}
154174

155-
func (r *Rect) String() string {
175+
func (r Rect) String() string {
156176
s := make([]string, len(r.p))
157177
for i, a := range r.p {
158178
b := r.q[i]
@@ -164,8 +184,7 @@ func (r *Rect) String() string {
164184
// NewRect constructs and returns a pointer to a Rect given a corner point and
165185
// the lengths of each dimension. The point p should be the most-negative point
166186
// on the rectangle (in every dimension) and every length should be positive.
167-
func NewRect(p Point, lengths []float32) (r *Rect, err error) {
168-
r = new(Rect)
187+
func NewRect(p Point, lengths []float32) (r Rect, err error) {
169188
r.p = p
170189
if len(p) != len(lengths) {
171190
err = &DimError{len(p), len(lengths)}
@@ -183,26 +202,32 @@ func NewRect(p Point, lengths []float32) (r *Rect, err error) {
183202
}
184203

185204
// NewRectFromPoints constructs and returns a pointer to a Rect given a corner points.
186-
func NewRectFromPoints(minPoint, maxPoint Point) (r *Rect, err error) {
205+
func NewRectFromPoints(minPoint, maxPoint Point) (r Rect, err error) {
187206
if len(minPoint) != len(maxPoint) {
188207
err = &DimError{len(minPoint), len(maxPoint)}
189208
return
190209
}
191210

192-
//checking that min and max points is swapping
211+
// check that min and max point coordinates require swapping
212+
copied := false
193213
for i, p := range minPoint {
194214
if minPoint[i] > maxPoint[i] {
215+
if !copied {
216+
minPoint = minPoint.Copy()
217+
maxPoint = maxPoint.Copy()
218+
copied = true
219+
}
195220
minPoint[i] = maxPoint[i]
196221
maxPoint[i] = p
197222
}
198223
}
199224

200-
r = &Rect{p: minPoint, q: maxPoint}
225+
r = Rect{p: minPoint, q: maxPoint}
201226
return
202227
}
203228

204229
// Size computes the measure of a rectangle (the product of its side lengths).
205-
func (r *Rect) Size() float32 {
230+
func (r Rect) Size() float32 {
206231
size := float32(1.0)
207232
for i, a := range r.p {
208233
b := r.q[i]
@@ -212,7 +237,7 @@ func (r *Rect) Size() float32 {
212237
}
213238

214239
// margin computes the sum of the edge lengths of a rectangle.
215-
func (r *Rect) margin() float32 {
240+
func (r Rect) margin() float32 {
216241
// The number of edges in an n-dimensional rectangle is n * 2^(n-1)
217242
// (http://en.wikipedia.org/wiki/Hypercube_graph). Thus the number
218243
// of edges of length (ai - bi), where the rectangle is determined
@@ -230,7 +255,7 @@ func (r *Rect) margin() float32 {
230255
}
231256

232257
// containsPoint tests whether p is located inside or on the boundary of r.
233-
func (r *Rect) containsPoint(p Point) bool {
258+
func (r Rect) containsPoint(p Point) bool {
234259
if len(p) != len(r.p) {
235260
panic(DimError{len(r.p), len(p)})
236261
}
@@ -247,7 +272,7 @@ func (r *Rect) containsPoint(p Point) bool {
247272
}
248273

249274
// containsRect tests whether r2 is is located inside r1.
250-
func (r *Rect) containsRect(r2 *Rect) bool {
275+
func (r Rect) containsRect(r2 Rect) bool {
251276
if len(r.p) != len(r2.p) {
252277
panic(DimError{len(r.p), len(r2.p)})
253278
}
@@ -257,6 +282,7 @@ func (r *Rect) containsRect(r2 *Rect) bool {
257282
// enforced by constructor: a1 <= b1 and a2 <= b2.
258283
// so containment holds if and only if a1 <= a2 <= b2 <= b1
259284
// for every dimension.
285+
// float32精度不够高,精确到第六位就行了
260286
if a1-a2 > 0.000001 || b2-b1 > 0.000001 {
261287
return false
262288
}
@@ -267,7 +293,7 @@ func (r *Rect) containsRect(r2 *Rect) bool {
267293

268294
// intersect computes the intersection of two rectangles. If no intersection
269295
// exists, the intersection is nil.
270-
func intersect(r1, r2 *Rect) bool {
296+
func intersect(r1, r2 Rect) bool {
271297
dim := len(r1.p)
272298
if len(r2.p) != dim {
273299
panic(DimError{dim, len(r2.p)})
@@ -312,19 +338,18 @@ func intersect(r1, r2 *Rect) bool {
312338
}
313339

314340
// ToRect constructs a rectangle containing p with side lengths 2*tol.
315-
func (p Point) ToRect(tol float32) *Rect {
341+
func (p Point) ToRect(tol float32) Rect {
316342
dim := len(p)
317343
a, b := make([]float32, dim), make([]float32, dim)
318344
for i := range p {
319345
a[i] = p[i] - tol
320346
b[i] = p[i] + tol
321347
}
322-
return &Rect{a, b}
348+
return Rect{a, b}
323349
}
324350

325351
// boundingBox constructs the smallest rectangle containing both r1 and r2.
326-
func boundingBox(r1, r2 *Rect) (bb *Rect) {
327-
bb = new(Rect)
352+
func boundingBox(r1, r2 Rect) (bb Rect) {
328353
dim := len(r1.p)
329354
bb.p = make([]float32, dim)
330355
bb.q = make([]float32, dim)
@@ -345,16 +370,3 @@ func boundingBox(r1, r2 *Rect) (bb *Rect) {
345370
}
346371
return
347372
}
348-
349-
// boundingBoxN constructs the smallest rectangle containing all of r...
350-
func boundingBoxN(rects ...*Rect) (bb *Rect) {
351-
if len(rects) == 1 {
352-
bb = rects[0]
353-
return
354-
}
355-
bb = boundingBox(rects[0], rects[1])
356-
for _, rect := range rects[2:] {
357-
bb = boundingBox(bb, rect)
358-
}
359-
return
360-
}

geom_test.go

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,13 @@ func TestNewRectFromPointsWithSwapPoints(t *testing.T) {
5959

6060
rect, err := NewRectFromPoints(q, p)
6161
if err != nil {
62-
t.Errorf("Error on NewRect(%v, %v): %v", p, q, err)
62+
t.Errorf("Error on NewRect(%v, %v): %v", q, p, err)
6363
}
6464

65-
// we must swap p and q because in function it was swapped
66-
if d := p.dist(rect.q); d > EPS {
67-
t.Errorf("Expected p == rect.p")
65+
if d := p.dist(rect.p); d > EPS {
66+
t.Errorf("Expected p == rect.")
6867
}
69-
if d := q.dist(rect.p); d > EPS {
68+
if d := q.dist(rect.q); d > EPS {
7069
t.Errorf("Expected q == rect.q")
7170
}
7271
}
@@ -148,9 +147,9 @@ func TestRectMargin(t *testing.T) {
148147
p := Point{1.0, -2.5, 3.0}
149148
lengths := []float32{2.5, 8.0, 1.5}
150149
rect, _ := NewRect(p, lengths)
151-
size := float32(4*2.5 + 4*8.0 + 4*1.5)
150+
size := 4*2.5 + 4*8.0 + 4*1.5
152151
actual := rect.margin()
153-
if size != actual {
152+
if float32(size) != actual {
154153
t.Errorf("Expected %v.margin() == %v, got %v", rect, size, actual)
155154
}
156155
}
@@ -336,20 +335,6 @@ func TestBoundingBoxContains(t *testing.T) {
336335
}
337336
}
338337

339-
func TestBoundingBoxN(t *testing.T) {
340-
rect1, _ := NewRect(Point{0, 0}, []float32{1, 1})
341-
rect2, _ := NewRect(Point{0, 1}, []float32{1, 1})
342-
rect3, _ := NewRect(Point{1, 0}, []float32{1, 1})
343-
344-
exp, _ := NewRect(Point{0, 0}, []float32{2, 2})
345-
bb := boundingBoxN(rect1, rect2, rect3)
346-
d1 := bb.p.dist(exp.p)
347-
d2 := bb.q.dist(exp.q)
348-
if d1 > EPS || d2 > EPS {
349-
t.Errorf("boundingBoxN(%v, %v, %v) != %v, got %v", rect1, rect2, rect3, exp, bb)
350-
}
351-
}
352-
353338
func TestMinDistZero(t *testing.T) {
354339
p := Point{1, 2, 3}
355340
r := p.ToRect(1)
@@ -360,16 +345,16 @@ func TestMinDistZero(t *testing.T) {
360345

361346
func TestMinDistPositive(t *testing.T) {
362347
p := Point{1, 2, 3}
363-
r := &Rect{Point{-1, -4, 7}, Point{2, -2, 9}}
348+
r := Rect{Point{-1, -4, 7}, Point{2, -2, 9}}
364349
expected := float32((-2-2)*(-2-2) + (7-3)*(7-3))
365-
if d := p.minDist(r); math.Abs(float64(d-expected)) > EPS {
350+
if d := p.minDist(r); math.Abs(d-float64(expected)) > EPS {
366351
t.Errorf("Expected %v.minDist(%v) == %v, got %v", p, r, expected, d)
367352
}
368353
}
369354

370355
func TestMinMaxdist(t *testing.T) {
371356
p := Point{-3, -2, -1}
372-
r := &Rect{Point{0, 0, 0}, Point{1, 2, 3}}
357+
r := Rect{Point{0, 0, 0}, Point{1, 2, 3}}
373358

374359
// furthest points from p on the faces closest to p in each dimension
375360
q1 := Point{0, 2, 3}

0 commit comments

Comments
 (0)