-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathvalue.go
More file actions
137 lines (117 loc) · 2.75 KB
/
value.go
File metadata and controls
137 lines (117 loc) · 2.75 KB
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
package texture
import (
"image/color"
"math"
)
type ColorToGray struct {
Name string
Src ColorField
}
func NewColorToGray(src ColorField) *ColorToGray {
return &ColorToGray{"ColorToGray", src}
}
func (c *ColorToGray) Eval2(x, y float64) float64 {
col := c.Src.Eval2(x, y)
g := color.Gray16Model.Convert(col).(color.Gray16)
v := float64(g.Y)
v /= 0xffff
return v*2 - 1
}
type ColorSelect struct {
Name string
Src ColorField
Chan int
}
func NewColorSelect(src ColorField, ch int) *ColorSelect {
return &ColorSelect{"ColorSelect", src, ch}
}
func (c *ColorSelect) Eval2(x, y float64) float64 {
r, g, b, a := c.Src.Eval2(x, y).RGBA()
var col uint32
switch c.Chan {
default:
fallthrough
case 0: // Red
col = r
case 1: // Green
col = g
case 2: // Blue
col = b
case 3: // Alpha
col = a
}
v := float64(col)
v /= 0xffff
return v*2 - 1
}
const oneOverPi = 1 / math.Pi
// Direction converts a VectorField to a Field based on the vector's direction in the XY plane.
type Direction struct {
Name string
Src VectorField
}
func NewDirection(src VectorField) *Direction {
return &Direction{"Direction", src}
}
// Eval2 implements the Field interface.
func (d *Direction) Eval2(x, y float64) float64 {
vec := d.Src.Eval2(x, y)
theta := math.Atan2(vec[1], vec[0])
return theta * oneOverPi
}
// Magnitude converts a VectorField to a Field based on the vector's magnitude.
type Magnitude struct {
Name string
Src VectorField
Scale float64
}
func NewMagnitude(src VectorField, scale float64) *Magnitude {
return &Magnitude{"Magnitude", src, scale}
}
// Eval2 implements the Field interface. Always >= 0
func (m *Magnitude) Eval2(x, y float64) float64 {
v := m.Src.Eval2(x, y)
var s float64
for _, f := range v {
s += f * f
}
r := math.Sqrt(s) * m.Scale
return clamp(r)
}
// Select converts a VectorField to a field by selecting one of its components.
type Select struct {
Name string
Src VectorField
Chan int
Scale float64
}
func NewSelect(src VectorField, ch int, scale float64) *Select {
return &Select{"Select", src, ch, scale}
}
// Eval2 implements the Field interface.
func (s *Select) Eval2(x, y float64) float64 {
v := s.Src.Eval2(x, y)[s.Chan] * s.Scale
return clamp(v)
}
// Weighted converts a VectorField to a field by selecting one of its components.
type Weighted struct {
Name string
Src VectorField
Weights []float64
}
func NewWeighted(src VectorField, w []float64) *Weighted {
return &Weighted{"Weighted", src, w}
}
// Eval2 implements the Field interface.
func (w *Weighted) Eval2(x, y float64) float64 {
v := w.Src.Eval2(x, y)
var s float64
n, j := len(v), len(w.Weights)
if j < n {
n = j // Implicitly set additional weights to 0
}
for i := 0; i < n; i++ {
s += v[i] * w.Weights[i]
}
return clamp(s)
}