mirror of
https://github.com/gonum/gonum.git
synced 2025-10-07 16:11:03 +08:00
spatial/r2,all: harmonize r2.Vec API with r3.Vec API
Migration to the new API can be achieved with this rsc.io/rf script: ``` rf ex { import "gonum.org/v1/gonum/spatial/r2"; var p,q r2.Vec; var f float64; p.Add(q) -> r2.Add(p, q); p.Sub(q) -> r2.Sub(p, q); p.Scale(f) -> r2.Scale(f, p); p.Dot(q) -> r2.Dot(p, q); p.Cross(q) -> r2.Cross(p, q); p.Rotate(f, q) -> r2.Rotate(p, f, q); } ``` Updates gonum/gonum#1553.
This commit is contained in:
@@ -84,7 +84,7 @@ func (u *EadesR2) Update(g graph.Graph, layout LayoutR2) bool {
|
|||||||
}
|
}
|
||||||
var updated bool
|
var updated bool
|
||||||
for i, p := range u.particles {
|
for i, p := range u.particles {
|
||||||
f := plane.ForceOn(p, u.Theta, barneshut.Gravity2).Scale(-u.Repulsion)
|
f := r2.Scale(-u.Repulsion, plane.ForceOn(p, u.Theta, barneshut.Gravity2))
|
||||||
// Prevent marginal updates that can be caused by
|
// Prevent marginal updates that can be caused by
|
||||||
// floating point error when nodes are very far apart.
|
// floating point error when nodes are very far apart.
|
||||||
if math.Hypot(f.X, f.Y) > 1e-12 {
|
if math.Hypot(f.X, f.Y) > 1e-12 {
|
||||||
@@ -137,16 +137,16 @@ func (u *EadesR2) Update(g graph.Graph, layout LayoutR2) bool {
|
|||||||
yidx := u.indexOf[yid]
|
yidx := u.indexOf[yid]
|
||||||
|
|
||||||
// Apply adjacent node attraction.
|
// Apply adjacent node attraction.
|
||||||
v := u.particles[yidx].Coord2().Sub(u.particles[xidx].Coord2())
|
v := r2.Sub(u.particles[yidx].Coord2(), u.particles[xidx].Coord2())
|
||||||
f := v.Scale(weight(xid, yid) * math.Log(math.Hypot(v.X, v.Y)))
|
f := r2.Scale(weight(xid, yid)*math.Log(math.Hypot(v.X, v.Y)), v)
|
||||||
if math.IsInf(f.X, 0) || math.IsInf(f.Y, 0) {
|
if math.IsInf(f.X, 0) || math.IsInf(f.Y, 0) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if math.Hypot(f.X, f.Y) > 1e-12 {
|
if math.Hypot(f.X, f.Y) > 1e-12 {
|
||||||
updated = true
|
updated = true
|
||||||
}
|
}
|
||||||
u.forces[xidx] = u.forces[xidx].Add(f)
|
u.forces[xidx] = r2.Add(u.forces[xidx], f)
|
||||||
u.forces[yidx] = u.forces[yidx].Sub(f)
|
u.forces[yidx] = r2.Sub(u.forces[yidx], f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ func (u *EadesR2) Update(g graph.Graph, layout LayoutR2) bool {
|
|||||||
}
|
}
|
||||||
for i, f := range u.forces {
|
for i, f := range u.forces {
|
||||||
n := u.particles[i].(eadesR2Node)
|
n := u.particles[i].(eadesR2Node)
|
||||||
n.pos = n.pos.Add(f.Scale(rate))
|
n.pos = r2.Add(n.pos, r2.Scale(rate, f))
|
||||||
u.particles[i] = n
|
u.particles[i] = n
|
||||||
layout.SetCoord2(n.id, n.pos)
|
layout.SetCoord2(n.id, n.pos)
|
||||||
}
|
}
|
||||||
|
@@ -37,7 +37,7 @@ func Gravity2(_, _ Particle2, m1, m2 float64, v r2.Vec) r2.Vec {
|
|||||||
if d2 == 0 {
|
if d2 == 0 {
|
||||||
return r2.Vec{}
|
return r2.Vec{}
|
||||||
}
|
}
|
||||||
return v.Scale((m1 * m2) / (d2 * math.Sqrt(d2)))
|
return r2.Scale((m1*m2)/(d2*math.Sqrt(d2)), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plane implements Barnes-Hut force approximation calculations.
|
// Plane implements Barnes-Hut force approximation calculations.
|
||||||
@@ -135,7 +135,7 @@ func (q *Plane) ForceOn(p Particle2, theta float64, f Force2) (force r2.Vec) {
|
|||||||
m := p.Mass()
|
m := p.Mass()
|
||||||
pv := p.Coord2()
|
pv := p.Coord2()
|
||||||
for _, e := range q.Particles {
|
for _, e := range q.Particles {
|
||||||
v = v.Add(f(p, e, m, e.Mass(), e.Coord2().Sub(pv)))
|
v = r2.Add(v, f(p, e, m, e.Mass(), r2.Sub(e.Coord2(), pv)))
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@@ -260,7 +260,7 @@ func (t *tile) forceOn(p Particle2, pt r2.Vec, m, theta float64, f Force2) (vect
|
|||||||
s := ((t.bounds.Max.X - t.bounds.Min.X) + (t.bounds.Max.Y - t.bounds.Min.Y)) / 2
|
s := ((t.bounds.Max.X - t.bounds.Min.X) + (t.bounds.Max.Y - t.bounds.Min.Y)) / 2
|
||||||
d := math.Hypot(pt.X-t.center.X, pt.Y-t.center.Y)
|
d := math.Hypot(pt.X-t.center.X, pt.Y-t.center.Y)
|
||||||
if s/d < theta || t.particle != nil {
|
if s/d < theta || t.particle != nil {
|
||||||
return f(p, t.particle, m, t.mass, t.center.Sub(pt))
|
return f(p, t.particle, m, t.mass, r2.Sub(t.center, pt))
|
||||||
}
|
}
|
||||||
|
|
||||||
var v r2.Vec
|
var v r2.Vec
|
||||||
@@ -268,7 +268,7 @@ func (t *tile) forceOn(p Particle2, pt r2.Vec, m, theta float64, f Force2) (vect
|
|||||||
if d == nil {
|
if d == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v = v.Add(d.forceOn(p, pt, m, theta, f))
|
v = r2.Add(v, d.forceOn(p, pt, m, theta, f))
|
||||||
}
|
}
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
@@ -427,9 +427,9 @@ func TestPlaneForceOn(t *testing.T) {
|
|||||||
m := p.Mass()
|
m := p.Mass()
|
||||||
pv := p.Coord2()
|
pv := p.Coord2()
|
||||||
for _, e := range particles {
|
for _, e := range particles {
|
||||||
v = v.Add(Gravity2(p, e, m, e.Mass(), e.Coord2().Sub(pv)))
|
v = r2.Add(v, Gravity2(p, e, m, e.Mass(), r2.Sub(e.Coord2(), pv)))
|
||||||
}
|
}
|
||||||
moved[i] = p.Coord2().Add(v)
|
moved[i] = r2.Add(p.Coord2(), v)
|
||||||
}
|
}
|
||||||
|
|
||||||
plane, err := NewPlane(particles)
|
plane, err := NewPlane(particles)
|
||||||
@@ -448,8 +448,8 @@ func TestPlaneForceOn(t *testing.T) {
|
|||||||
calls++
|
calls++
|
||||||
return Gravity2(p1, p2, m1, m2, v)
|
return Gravity2(p1, p2, m1, m2, v)
|
||||||
})
|
})
|
||||||
pos := p.Coord2().Add(v)
|
pos := r2.Add(p.Coord2(), v)
|
||||||
d := moved[i].Sub(pos)
|
d := r2.Sub(moved[i], pos)
|
||||||
ssd += d.X*d.X + d.Y*d.Y
|
ssd += d.X*d.X + d.Y*d.Y
|
||||||
sd += math.Hypot(d.X, d.Y)
|
sd += math.Hypot(d.X, d.Y)
|
||||||
}
|
}
|
||||||
|
49
spatial/r2/deprecated.go
Normal file
49
spatial/r2/deprecated.go
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright ©2021 The Gonum Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package r2
|
||||||
|
|
||||||
|
// TODO(sbinet): remove this file for Gonum-v0.10.0.
|
||||||
|
|
||||||
|
// Add returns the vector sum of p and q.
|
||||||
|
//
|
||||||
|
// DEPRECATED: use r2.Add.
|
||||||
|
func (p Vec) Add(q Vec) Vec {
|
||||||
|
return Add(p, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sub returns the vector sum of p and -q.
|
||||||
|
//
|
||||||
|
// DEPRECATED: use r2.Sub.
|
||||||
|
func (p Vec) Sub(q Vec) Vec {
|
||||||
|
return Sub(p, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale returns the vector p scaled by f.
|
||||||
|
//
|
||||||
|
// DEPRECATED: use r2.Scale.
|
||||||
|
func (p Vec) Scale(f float64) Vec {
|
||||||
|
return Scale(f, p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dot returns the dot product p·q.
|
||||||
|
//
|
||||||
|
// DEPRECATED: use r2.Dot.
|
||||||
|
func (p Vec) Dot(q Vec) float64 {
|
||||||
|
return Dot(p, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cross returns the cross product p×q.
|
||||||
|
//
|
||||||
|
// DEPRECATED: use r2.Cross.
|
||||||
|
func (p Vec) Cross(q Vec) float64 {
|
||||||
|
return Cross(p, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate returns a new vector, rotated by alpha around the provided point, q.
|
||||||
|
//
|
||||||
|
// DEPRECATED: use r2.Rotate.
|
||||||
|
func (p Vec) Rotate(alpha float64, q Vec) Vec {
|
||||||
|
return Rotate(p, alpha, q)
|
||||||
|
}
|
@@ -12,38 +12,41 @@ type Vec struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add returns the vector sum of p and q.
|
// Add returns the vector sum of p and q.
|
||||||
func (p Vec) Add(q Vec) Vec {
|
func Add(p, q Vec) Vec {
|
||||||
p.X += q.X
|
return Vec{
|
||||||
p.Y += q.Y
|
X: p.X + q.X,
|
||||||
return p
|
Y: p.Y + q.Y,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub returns the vector sum of p and -q.
|
// Sub returns the vector sum of p and -q.
|
||||||
func (p Vec) Sub(q Vec) Vec {
|
func Sub(p, q Vec) Vec {
|
||||||
p.X -= q.X
|
return Vec{
|
||||||
p.Y -= q.Y
|
X: p.X - q.X,
|
||||||
return p
|
Y: p.Y - q.Y,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale returns the vector p scaled by f.
|
// Scale returns the vector p scaled by f.
|
||||||
func (p Vec) Scale(f float64) Vec {
|
func Scale(f float64, p Vec) Vec {
|
||||||
p.X *= f
|
return Vec{
|
||||||
p.Y *= f
|
X: f * p.X,
|
||||||
return p
|
Y: f * p.Y,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dot returns the dot product p·q.
|
// Dot returns the dot product p·q.
|
||||||
func (p Vec) Dot(q Vec) float64 {
|
func Dot(p, q Vec) float64 {
|
||||||
return p.X*q.X + p.Y*q.Y
|
return p.X*q.X + p.Y*q.Y
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross returns the cross product p×q.
|
// Cross returns the cross product p×q.
|
||||||
func (p Vec) Cross(q Vec) float64 {
|
func Cross(p, q Vec) float64 {
|
||||||
return p.X*q.Y - p.Y*q.X
|
return p.X*q.Y - p.Y*q.X
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rotate returns a new vector, rotated by alpha around the provided point, q.
|
// Rotate returns a new vector, rotated by alpha around the provided point, q.
|
||||||
func (p Vec) Rotate(alpha float64, q Vec) Vec {
|
func Rotate(p Vec, alpha float64, q Vec) Vec {
|
||||||
return NewRotation(alpha, q).Rotate(p)
|
return NewRotation(alpha, q).Rotate(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,12 +68,12 @@ func Unit(p Vec) Vec {
|
|||||||
if p.X == 0 && p.Y == 0 {
|
if p.X == 0 && p.Y == 0 {
|
||||||
return Vec{X: math.NaN(), Y: math.NaN()}
|
return Vec{X: math.NaN(), Y: math.NaN()}
|
||||||
}
|
}
|
||||||
return p.Scale(1 / Norm(p))
|
return Scale(1/Norm(p), p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cos returns the cosine of the opening angle between p and q.
|
// Cos returns the cosine of the opening angle between p and q.
|
||||||
func Cos(p, q Vec) float64 {
|
func Cos(p, q Vec) float64 {
|
||||||
return p.Dot(q) / (Norm(p) * Norm(q))
|
return Dot(p, q) / (Norm(p) * Norm(q))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Box is a 2D bounding box.
|
// Box is a 2D bounding box.
|
||||||
@@ -98,11 +101,11 @@ func (r Rotation) Rotate(p Vec) Vec {
|
|||||||
if r.isIdentity() {
|
if r.isIdentity() {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
o := p.Sub(r.p)
|
o := Sub(p, r.p)
|
||||||
return Vec{
|
return Add(Vec{
|
||||||
X: (o.X*r.cos - o.Y*r.sin),
|
X: (o.X*r.cos - o.Y*r.sin),
|
||||||
Y: (o.X*r.sin + o.Y*r.cos),
|
Y: (o.X*r.sin + o.Y*r.cos),
|
||||||
}.Add(r.p)
|
}, r.p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Rotation) isIdentity() bool {
|
func (r Rotation) isIdentity() bool {
|
||||||
|
@@ -22,7 +22,7 @@ func TestAdd(t *testing.T) {
|
|||||||
{Vec{1, -3}, Vec{1, -6}, Vec{2, -9}},
|
{Vec{1, -3}, Vec{1, -6}, Vec{2, -9}},
|
||||||
{Vec{1, 2}, Vec{-1, -2}, Vec{}},
|
{Vec{1, 2}, Vec{-1, -2}, Vec{}},
|
||||||
} {
|
} {
|
||||||
got := test.v1.Add(test.v2)
|
got := Add(test.v1, test.v2)
|
||||||
if got != test.want {
|
if got != test.want {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"error: %v + %v: got=%v, want=%v",
|
"error: %v + %v: got=%v, want=%v",
|
||||||
@@ -43,7 +43,7 @@ func TestSub(t *testing.T) {
|
|||||||
{Vec{1, -3}, Vec{1, -6}, Vec{0, 3}},
|
{Vec{1, -3}, Vec{1, -6}, Vec{0, 3}},
|
||||||
{Vec{1, 2}, Vec{1, 2}, Vec{}},
|
{Vec{1, 2}, Vec{1, 2}, Vec{}},
|
||||||
} {
|
} {
|
||||||
got := test.v1.Sub(test.v2)
|
got := Sub(test.v1, test.v2)
|
||||||
if got != test.want {
|
if got != test.want {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"error: %v - %v: got=%v, want=%v",
|
"error: %v - %v: got=%v, want=%v",
|
||||||
@@ -67,7 +67,7 @@ func TestScale(t *testing.T) {
|
|||||||
{2, Vec{1, -3}, Vec{2, -6}},
|
{2, Vec{1, -3}, Vec{2, -6}},
|
||||||
{10, Vec{1, 2}, Vec{10, 20}},
|
{10, Vec{1, 2}, Vec{10, 20}},
|
||||||
} {
|
} {
|
||||||
got := test.v.Scale(test.a)
|
got := Scale(test.a, test.v)
|
||||||
if got != test.want {
|
if got != test.want {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"error: %v * %v: got=%v, want=%v",
|
"error: %v * %v: got=%v, want=%v",
|
||||||
@@ -89,7 +89,7 @@ func TestDot(t *testing.T) {
|
|||||||
{Vec{1, 2}, Vec{-0.3, 0.4}, 0.5},
|
{Vec{1, 2}, Vec{-0.3, 0.4}, 0.5},
|
||||||
} {
|
} {
|
||||||
{
|
{
|
||||||
got := test.u.Dot(test.v)
|
got := Dot(test.u, test.v)
|
||||||
if got != test.want {
|
if got != test.want {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"error: %v · %v: got=%v, want=%v",
|
"error: %v · %v: got=%v, want=%v",
|
||||||
@@ -98,7 +98,7 @@ func TestDot(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
got := test.v.Dot(test.u)
|
got := Dot(test.v, test.u)
|
||||||
if got != test.want {
|
if got != test.want {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"error: %v · %v: got=%v, want=%v",
|
"error: %v · %v: got=%v, want=%v",
|
||||||
@@ -120,7 +120,7 @@ func TestCross(t *testing.T) {
|
|||||||
{Vec{1, 2}, Vec{-4, 5}, 13},
|
{Vec{1, 2}, Vec{-4, 5}, 13},
|
||||||
{Vec{1, 2}, Vec{2, 3}, -1},
|
{Vec{1, 2}, Vec{2, 3}, -1},
|
||||||
} {
|
} {
|
||||||
got := test.v1.Cross(test.v2)
|
got := Cross(test.v1, test.v2)
|
||||||
if got != test.want {
|
if got != test.want {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"error: %v × %v = %v, want %v",
|
"error: %v × %v = %v, want %v",
|
||||||
@@ -236,7 +236,7 @@ func TestRotate(t *testing.T) {
|
|||||||
{Vec{2, 2}, Vec{1, 1}, math.Pi, Vec{0, 0}},
|
{Vec{2, 2}, Vec{1, 1}, math.Pi, Vec{0, 0}},
|
||||||
{Vec{2, 2}, Vec{2, 0}, math.Pi, Vec{2, -2}},
|
{Vec{2, 2}, Vec{2, 0}, math.Pi, Vec{2, -2}},
|
||||||
} {
|
} {
|
||||||
got := test.v.Rotate(test.alpha, test.q)
|
got := Rotate(test.v, test.alpha, test.q)
|
||||||
if !vecApproxEqual(got, test.want) {
|
if !vecApproxEqual(got, test.want) {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"rotate(%v, %v, %v)= %v, want=%v",
|
"rotate(%v, %v, %v)= %v, want=%v",
|
||||||
|
Reference in New Issue
Block a user