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.
|
// NewPlane returns a new Plane.
|
||||||
|
//
|
||||||
|
// Points in p must not be infinitely distant, otherwise NewPlane will panic.
|
||||||
func NewPlane(p []Particle2) *Plane {
|
func NewPlane(p []Particle2) *Plane {
|
||||||
|
for _, l := range p {
|
||||||
|
if isInfR2(l.Coord2()) {
|
||||||
|
panic("barneshut: point at infinity")
|
||||||
|
}
|
||||||
|
}
|
||||||
q := Plane{Particles: p}
|
q := Plane{Particles: p}
|
||||||
q.Reset()
|
q.Reset()
|
||||||
return &q
|
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
|
// Reset reconstructs the Barnes-Hut tree. Reset must be called if the
|
||||||
// Particles field or elements of Particles have been altered, unless
|
// Particles field or elements of Particles have been altered, unless
|
||||||
// ForceOn is called with theta=0 or no data structures have been
|
// ForceOn is called with theta=0 or no data structures have been
|
||||||
|
@@ -47,12 +47,23 @@ type Volume struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewVolume returns a new Volume.
|
// NewVolume returns a new Volume.
|
||||||
|
//
|
||||||
|
// Points in p must not be infinitely distant, otherwise NewVolume will panic.
|
||||||
func NewVolume(p []Particle3) *Volume {
|
func NewVolume(p []Particle3) *Volume {
|
||||||
|
for _, l := range p {
|
||||||
|
if isInfR3(l.Coord3()) {
|
||||||
|
panic("barneshut: point at infinity")
|
||||||
|
}
|
||||||
|
}
|
||||||
q := Volume{Particles: p}
|
q := Volume{Particles: p}
|
||||||
q.Reset()
|
q.Reset()
|
||||||
return &q
|
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
|
// Reset reconstructs the Barnes-Hut tree. Reset must be called if the
|
||||||
// Particles field or elements of Particles have been altered, unless
|
// Particles field or elements of Particles have been altered, unless
|
||||||
// ForceOn is called with theta=0 or no data structures have been
|
// 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
|
// 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
|
// provides the source of randomness for vantage point selection. If src is nil
|
||||||
// global rand package functions are used.
|
// 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 {
|
func New(p []Comparable, effort int, src rand.Source) *Tree {
|
||||||
var intn func(int) int
|
var intn func(int) int
|
||||||
var shuf func(n int, swap func(i, j 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)
|
choices := b.random(effort, s)
|
||||||
for _, p := range choices {
|
for _, p := range choices {
|
||||||
for i, q := 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)
|
variance := stat.Variance(b.work, nil)
|
||||||
if variance > bestVar {
|
if variance > bestVar {
|
||||||
best, bestVar = p, variance
|
best, bestVar = p, variance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if best == nil {
|
||||||
|
// This should never be reached.
|
||||||
|
panic("vptree: could not find vantage point")
|
||||||
|
}
|
||||||
return best
|
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) {
|
func (b *builder) partition(v Comparable, s []Comparable) (radius float64, closer, further []Comparable) {
|
||||||
b.work = b.work[:len(s)]
|
b.work = b.work[:len(s)]
|
||||||
for i, p := range 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})
|
sort.Sort(byDist{dists: b.work, points: s})
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user