mirror of
https://github.com/gonum/gonum.git
synced 2025-10-05 23:26:52 +08:00
spatial/{barneshut,vptree}: refuse points at infinity
This commit is contained in:
@@ -47,12 +47,23 @@ type Plane struct {
|
||||
}
|
||||
|
||||
// NewPlane returns a new Plane.
|
||||
//
|
||||
// Points in p must not be infinitely distant, otherwise NewPlane will panic.
|
||||
func NewPlane(p []Particle2) *Plane {
|
||||
for _, l := range p {
|
||||
if isInfR2(l.Coord2()) {
|
||||
panic("barneshut: point at infinity")
|
||||
}
|
||||
}
|
||||
q := Plane{Particles: p}
|
||||
q.Reset()
|
||||
return &q
|
||||
}
|
||||
|
||||
func isInfR2(v r2.Vec) bool {
|
||||
return math.IsInf(v.X, 0) || math.IsInf(v.Y, 0)
|
||||
}
|
||||
|
||||
// Reset reconstructs the Barnes-Hut tree. Reset must be called if the
|
||||
// Particles field or elements of Particles have been altered, unless
|
||||
// ForceOn is called with theta=0 or no data structures have been
|
||||
|
@@ -47,12 +47,23 @@ type Volume struct {
|
||||
}
|
||||
|
||||
// NewVolume returns a new Volume.
|
||||
//
|
||||
// Points in p must not be infinitely distant, otherwise NewVolume will panic.
|
||||
func NewVolume(p []Particle3) *Volume {
|
||||
for _, l := range p {
|
||||
if isInfR3(l.Coord3()) {
|
||||
panic("barneshut: point at infinity")
|
||||
}
|
||||
}
|
||||
q := Volume{Particles: p}
|
||||
q.Reset()
|
||||
return &q
|
||||
}
|
||||
|
||||
func isInfR3(v r3.Vec) bool {
|
||||
return math.IsInf(v.X, 0) || math.IsInf(v.Y, 0) || math.IsInf(v.Z, 0)
|
||||
}
|
||||
|
||||
// Reset reconstructs the Barnes-Hut tree. Reset must be called if the
|
||||
// Particles field or elements of Particles have been altered, unless
|
||||
// ForceOn is called with theta=0 or no data structures have been
|
||||
|
@@ -64,6 +64,8 @@ type Tree struct {
|
||||
// The order of elements in p will be altered after New returns. The src parameter
|
||||
// provides the source of randomness for vantage point selection. If src is nil
|
||||
// global rand package functions are used.
|
||||
//
|
||||
// Points in p must not be infinitely distant, otherwise New will panic.
|
||||
func New(p []Comparable, effort int, src rand.Source) *Tree {
|
||||
var intn func(int) int
|
||||
var shuf func(n int, swap func(i, j int))
|
||||
@@ -118,13 +120,21 @@ func (b *builder) selectVantage(s []Comparable, effort int) Comparable {
|
||||
choices := b.random(effort, s)
|
||||
for _, p := range choices {
|
||||
for i, q := range choices {
|
||||
b.work[i] = p.Distance(q)
|
||||
d := p.Distance(q)
|
||||
if math.IsInf(d, 0) {
|
||||
panic("vptree: point at infinity")
|
||||
}
|
||||
b.work[i] = d
|
||||
}
|
||||
variance := stat.Variance(b.work, nil)
|
||||
if variance > bestVar {
|
||||
best, bestVar = p, variance
|
||||
}
|
||||
}
|
||||
if best == nil {
|
||||
// This should never be reached.
|
||||
panic("vptree: could not find vantage point")
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
@@ -139,7 +149,11 @@ func (b *builder) random(n int, s []Comparable) []Comparable {
|
||||
func (b *builder) partition(v Comparable, s []Comparable) (radius float64, closer, further []Comparable) {
|
||||
b.work = b.work[:len(s)]
|
||||
for i, p := range s {
|
||||
b.work[i] = v.Distance(p)
|
||||
d := v.Distance(p)
|
||||
if math.IsInf(d, 0) {
|
||||
panic("vptree: point at infinity")
|
||||
}
|
||||
b.work[i] = d
|
||||
}
|
||||
sort.Sort(byDist{dists: b.work, points: s})
|
||||
|
||||
|
Reference in New Issue
Block a user