-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathvec2.go
167 lines (138 loc) · 4.3 KB
/
vec2.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// Copyright 2013 Frederik Zipp. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package geom
import "math"
// A Vec2 represents a vector with coordinates X and Y in 2-dimensional
// euclidean space.
type Vec2 struct {
X, Y float32
}
// A Size represents the dimensions of a rectangle.
type Size struct {
// Width and height
W, H float32
}
var (
// V2Zero is the zero vector (0,0).
V2Zero = Vec2{0, 0}
// V2Unit is the unit vector (1,1).
V2Unit = Vec2{1, 1}
// V2UnitX is the x-axis unit vector (1,0).
V2UnitX = Vec2{1, 0}
// V2UnitY is the y-axis unit vector (0,1).
V2UnitY = Vec2{0, 1}
)
// V2 is shorthand for Vec2{X: x, Y: y}.
func V2(x, y float32) Vec2 {
return Vec2{x, y}
}
// Add returns the vector v+w.
func (v Vec2) Add(w Vec2) Vec2 {
return Vec2{v.X + w.X, v.Y + w.Y}
}
// Sub returns the vector v-w.
func (v Vec2) Sub(w Vec2) Vec2 {
return Vec2{v.X - w.X, v.Y - w.Y}
}
// Mul returns the vector v*s.
func (v Vec2) Mul(s float32) Vec2 {
return Vec2{v.X * s, v.Y * s}
}
// Div returns the vector v/s.
func (v Vec2) Div(s float32) Vec2 {
return Vec2{v.X / s, v.Y / s}
}
// Neg returns the negated vector of v.
func (v Vec2) Neg() Vec2 {
return v.Mul(-1)
}
// Dot returns the dot (a.k.a. scalar) product of v and w.
func (v Vec2) Dot(w Vec2) float32 {
return v.X*w.X + v.Y*w.Y
}
// CrossLen returns the length that the cross product of v and w would have
// in 3-dimensional euclidean space. This is effectively the Z component
// of the 3D cross product vector.
func (v Vec2) CrossLen(w Vec2) float32 {
return v.X*w.Y - v.Y*w.X
}
// CompMul returns the component-wise multiplication of two vectors.
func (v Vec2) CompMul(w Vec2) Vec2 {
return Vec2{v.X * w.X, v.Y * w.Y}
}
// CompDiv returns the component-wise division of two vectors.
func (v Vec2) CompDiv(w Vec2) Vec2 {
return Vec2{v.X / w.X, v.Y / w.Y}
}
// SqDist returns the square of the euclidean distance between two vectors.
func (v Vec2) SqDist(w Vec2) float32 {
return v.Sub(w).SqLen()
}
// Dist returns the euclidean distance between two vectors.
func (v Vec2) Dist(w Vec2) float32 {
return v.Sub(w).Len()
}
// SqLen returns the square of the length (euclidean norm) of a vector.
func (v Vec2) SqLen() float32 {
return v.Dot(v)
}
// Len returns the length (euclidean norm) of a vector.
func (v Vec2) Len() float32 {
return float32(math.Sqrt(float64(v.SqLen())))
}
// Norm returns the normalized vector of a vector.
func (v Vec2) Norm() Vec2 {
return v.Div(v.Len())
}
// Reflect returns the reflection vector of v given a normal n.
func (v Vec2) Reflect(n Vec2) Vec2 {
return v.Sub(n.Mul(2 * v.Dot(n)))
}
// Lerp returns the linear interpolation between v and w by amount t.
// The amount t is usually a value between 0 and 1. If t=0 v will be
// returned; if t=1 w will be returned.
func (v Vec2) Lerp(w Vec2, t float32) Vec2 {
// return v.Add(w.Sub(v).Mul(t))
return Vec2{lerp(v.X, w.X, t), lerp(v.Y, w.Y, t)}
}
// angle returns the angle (counterclockwise) of vector v with the x axis in
// radians. The result is in the interval [0,2π).
func (v Vec2) angle() float32 {
a := math.Atan2(float64(v.Y), float64(v.X))
if a < 0 {
a += 2 * math.Pi
}
return float32(a)
}
// Min returns a vector with each component set to the lesser value
// of the corresponding component pair of v and w.
func (v Vec2) Min(w Vec2) Vec2 {
return Vec2{min(v.X, w.X), min(v.Y, w.Y)}
}
// Max returns a vector with each component set to the greater value
// of the corresponding component pair of v and w.
func (v Vec2) Max(w Vec2) Vec2 {
return Vec2{max(v.X, w.X), max(v.Y, w.Y)}
}
// Transform transforms vector v with 4x4 matrix m.
func (v Vec2) Transform(m *Mat4) Vec2 {
return Vec2{
m[0][0]*v.X + m[1][0]*v.Y + m[3][0],
m[0][1]*v.X + m[1][1]*v.Y + m[3][1],
}
}
// Z returns a Vec3 based on v with the additional coordinate z.
func (v Vec2) Z(z float32) Vec3 {
return Vec3{v.X, v.Y, z}
}
// NearEq returns whether v and w are approximately equal. This relation is not
// transitive in general. The tolerance for the floating-point components is
// ±1e-5.
func (v Vec2) NearEq(w Vec2) bool {
return nearEq(v.X, w.X, epsilon) && nearEq(v.Y, w.Y, epsilon)
}
// String returns a string representation of v like "(3.25, -1.5)".
func (v Vec2) String() string {
return "(" + str(v.X) + ", " + str(v.Y) + ")"
}