-
Notifications
You must be signed in to change notification settings - Fork 4
/
tensor.go
132 lines (108 loc) · 2.44 KB
/
tensor.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
package gencitymap
import (
"math"
"github.com/Flokey82/go_gens/vectors"
)
// Tensor represents a tensor used for generating a city map.
// Represent the matrix as a 2 element list
// [ 0, 1 , 1, -0 ]
type Tensor struct {
matrix [2]float64
r float64
theta float64
oldTheta bool
}
func newTensor(r float64, matrix [2]float64) *Tensor {
return &Tensor{
matrix: matrix,
r: r,
}
}
func newZeroTensor() *Tensor {
return newTensor(0, [2]float64{0, 0})
}
func fromVector(vector vectors.Vec2) *Tensor {
t1 := vector.X*vector.X - vector.Y*vector.Y
t2 := 2 * vector.X * vector.Y
t3 := t1*t1 - t2*t2
t4 := 2 * t1 * t2
return newTensor(1, [2]float64{t3, t4})
}
func (t *Tensor) calculateTheta() float64 {
if t.r == 0 {
return 0
}
return math.Atan2(t.matrix[1]/t.r, t.matrix[0]/t.r) / 2
}
func (t *Tensor) add(tensor *Tensor, smooth bool) *Tensor {
t.matrix = mapMatrix(t.matrix, func(v float64, i int) float64 {
return v*t.r + tensor.matrix[i]*tensor.r
})
if smooth {
t.r = hypot(t.matrix[:]...)
t.matrix = mapMatrix(t.matrix, func(v float64, i int) float64 {
return v / t.r
})
} else {
t.r = 2
}
t.oldTheta = true
return t
}
func (t *Tensor) Scale(s float64) *Tensor {
return t.scale(s)
}
// hypot returns the square root of the sum of squares of its arguments.
func hypot(vals ...float64) float64 {
var sum float64
for _, v := range vals {
sum += v * v
}
return math.Sqrt(sum)
}
func mapMatrix(matrix [2]float64, f func(float64, int) float64) [2]float64 {
return [2]float64{
f(matrix[0], 0),
f(matrix[1], 1),
}
}
func (t *Tensor) getTheta() float64 {
if t.oldTheta {
t.theta = t.calculateTheta()
t.oldTheta = false
}
return t.theta
}
func (t *Tensor) scale(s float64) *Tensor {
t.r *= s
t.oldTheta = true
return t
}
func (t *Tensor) rotate(theta float64) *Tensor {
if theta == 0 {
return t
}
newTheta := t.getTheta() + theta
if newTheta < math.Pi {
newTheta += math.Pi
}
if newTheta >= math.Pi {
newTheta -= math.Pi
}
t.matrix[0] = math.Cos(2*newTheta) * t.r
t.matrix[1] = math.Sin(2*newTheta) * t.r
t.theta = newTheta
return t
}
func (t *Tensor) getMajor() vectors.Vec2 {
if t.r == 0 {
return vectors.NewVec2(0, 0)
}
return vectors.NewVec2(math.Cos(t.getTheta()), math.Sin(t.getTheta()))
}
func (t *Tensor) getMinor() vectors.Vec2 {
if t.r == 0 {
return vectors.NewVec2(0, 0)
}
return vectors.NewVec2(math.Cos(t.getTheta()+math.Pi/2), math.Sin(t.getTheta()+math.Pi/2))
}