github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/spatial/r2/vector.go (about)

     1  // Copyright ©2019 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package r2
     6  
     7  import "math"
     8  
     9  // Vec is a 2D vector.
    10  type Vec struct {
    11  	X, Y float64
    12  }
    13  
    14  // Add returns the vector sum of p and q.
    15  func Add(p, q Vec) Vec {
    16  	return Vec{
    17  		X: p.X + q.X,
    18  		Y: p.Y + q.Y,
    19  	}
    20  }
    21  
    22  // Sub returns the vector sum of p and -q.
    23  func Sub(p, q Vec) Vec {
    24  	return Vec{
    25  		X: p.X - q.X,
    26  		Y: p.Y - q.Y,
    27  	}
    28  }
    29  
    30  // Scale returns the vector p scaled by f.
    31  func Scale(f float64, p Vec) Vec {
    32  	return Vec{
    33  		X: f * p.X,
    34  		Y: f * p.Y,
    35  	}
    36  }
    37  
    38  // Dot returns the dot product p·q.
    39  func Dot(p, q Vec) float64 {
    40  	return p.X*q.X + p.Y*q.Y
    41  }
    42  
    43  // Cross returns the cross product p×q.
    44  func Cross(p, q Vec) float64 {
    45  	return p.X*q.Y - p.Y*q.X
    46  }
    47  
    48  // Rotate returns a new vector, rotated by alpha around the provided point, q.
    49  func Rotate(p Vec, alpha float64, q Vec) Vec {
    50  	return NewRotation(alpha, q).Rotate(p)
    51  }
    52  
    53  // Norm returns the Euclidean norm of p
    54  //  |p| = sqrt(p_x^2 + p_y^2).
    55  func Norm(p Vec) float64 {
    56  	return math.Hypot(p.X, p.Y)
    57  }
    58  
    59  // Norm returns the Euclidean squared norm of p
    60  //  |p|^2 = p_x^2 + p_y^2.
    61  func Norm2(p Vec) float64 {
    62  	return p.X*p.X + p.Y*p.Y
    63  }
    64  
    65  // Unit returns the unit vector colinear to p.
    66  // Unit returns {NaN,NaN} for the zero vector.
    67  func Unit(p Vec) Vec {
    68  	if p.X == 0 && p.Y == 0 {
    69  		return Vec{X: math.NaN(), Y: math.NaN()}
    70  	}
    71  	return Scale(1/Norm(p), p)
    72  }
    73  
    74  // Cos returns the cosine of the opening angle between p and q.
    75  func Cos(p, q Vec) float64 {
    76  	return Dot(p, q) / (Norm(p) * Norm(q))
    77  }
    78  
    79  // Box is a 2D bounding box.
    80  type Box struct {
    81  	Min, Max Vec
    82  }
    83  
    84  // Rotation describes a rotation in 2D.
    85  type Rotation struct {
    86  	sin, cos float64
    87  	p        Vec
    88  }
    89  
    90  // NewRotation creates a rotation by alpha, around p.
    91  func NewRotation(alpha float64, p Vec) Rotation {
    92  	if alpha == 0 {
    93  		return Rotation{sin: 0, cos: 1, p: p}
    94  	}
    95  	sin, cos := math.Sincos(alpha)
    96  	return Rotation{sin: sin, cos: cos, p: p}
    97  }
    98  
    99  // Rotate returns the rotated vector according to the definition of rot.
   100  func (r Rotation) Rotate(p Vec) Vec {
   101  	if r.isIdentity() {
   102  		return p
   103  	}
   104  	o := Sub(p, r.p)
   105  	return Add(Vec{
   106  		X: (o.X*r.cos - o.Y*r.sin),
   107  		Y: (o.X*r.sin + o.Y*r.cos),
   108  	}, r.p)
   109  }
   110  
   111  func (r Rotation) isIdentity() bool {
   112  	return r.sin == 0 && r.cos == 1
   113  }