...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package r3
16
17 import (
18 "fmt"
19 "math"
20
21 "github.com/golang/geo/s1"
22 )
23
24
25 type Vector struct {
26 X, Y, Z float64
27 }
28
29
30 func (v Vector) ApproxEqual(ov Vector) bool {
31 const epsilon = 1e-16
32 return math.Abs(v.X-ov.X) < epsilon && math.Abs(v.Y-ov.Y) < epsilon && math.Abs(v.Z-ov.Z) < epsilon
33 }
34
35 func (v Vector) String() string { return fmt.Sprintf("(%0.24f, %0.24f, %0.24f)", v.X, v.Y, v.Z) }
36
37
38 func (v Vector) Norm() float64 { return math.Sqrt(v.Dot(v)) }
39
40
41 func (v Vector) Norm2() float64 { return v.Dot(v) }
42
43
44 func (v Vector) Normalize() Vector {
45 n2 := v.Norm2()
46 if n2 == 0 {
47 return Vector{0, 0, 0}
48 }
49 return v.Mul(1 / math.Sqrt(n2))
50 }
51
52
53 func (v Vector) IsUnit() bool {
54 const epsilon = 5e-14
55 return math.Abs(v.Norm2()-1) <= epsilon
56 }
57
58
59 func (v Vector) Abs() Vector { return Vector{math.Abs(v.X), math.Abs(v.Y), math.Abs(v.Z)} }
60
61
62 func (v Vector) Add(ov Vector) Vector { return Vector{v.X + ov.X, v.Y + ov.Y, v.Z + ov.Z} }
63
64
65 func (v Vector) Sub(ov Vector) Vector { return Vector{v.X - ov.X, v.Y - ov.Y, v.Z - ov.Z} }
66
67
68 func (v Vector) Mul(m float64) Vector { return Vector{m * v.X, m * v.Y, m * v.Z} }
69
70
71 func (v Vector) Dot(ov Vector) float64 {
72 return float64(v.X*ov.X) + float64(v.Y*ov.Y) + float64(v.Z*ov.Z)
73 }
74
75
76 func (v Vector) Cross(ov Vector) Vector {
77 return Vector{
78 float64(v.Y*ov.Z) - float64(v.Z*ov.Y),
79 float64(v.Z*ov.X) - float64(v.X*ov.Z),
80 float64(v.X*ov.Y) - float64(v.Y*ov.X),
81 }
82 }
83
84
85 func (v Vector) Distance(ov Vector) float64 { return v.Sub(ov).Norm() }
86
87
88 func (v Vector) Angle(ov Vector) s1.Angle {
89 return s1.Angle(math.Atan2(v.Cross(ov).Norm(), v.Dot(ov))) * s1.Radian
90 }
91
92
93 type Axis int
94
95
96 const (
97 XAxis Axis = iota
98 YAxis
99 ZAxis
100 )
101
102
103
104 func (v Vector) Ortho() Vector {
105 ov := Vector{}
106 switch v.LargestComponent() {
107 case XAxis:
108 ov.Z = 1
109 case YAxis:
110 ov.X = 1
111 default:
112 ov.Y = 1
113 }
114 return v.Cross(ov).Normalize()
115 }
116
117
118 func (v Vector) LargestComponent() Axis {
119 t := v.Abs()
120
121 if t.X > t.Y {
122 if t.X > t.Z {
123 return XAxis
124 }
125 return ZAxis
126 }
127 if t.Y > t.Z {
128 return YAxis
129 }
130 return ZAxis
131 }
132
133
134 func (v Vector) SmallestComponent() Axis {
135 t := v.Abs()
136
137 if t.X < t.Y {
138 if t.X < t.Z {
139 return XAxis
140 }
141 return ZAxis
142 }
143 if t.Y < t.Z {
144 return YAxis
145 }
146 return ZAxis
147 }
148
149
150
151
152
153
154
155
156
157
158
159 func (v Vector) Cmp(ov Vector) int {
160 if v.X < ov.X {
161 return -1
162 }
163 if v.X > ov.X {
164 return 1
165 }
166
167
168 if v.Y < ov.Y {
169 return -1
170 }
171 if v.Y > ov.Y {
172 return 1
173 }
174
175
176 if v.Z < ov.Z {
177 return -1
178 }
179 if v.Z > ov.Z {
180 return 1
181 }
182
183
184 return 0
185 }
186
View as plain text