1
1
package io .github .scalamath .colorlib
2
2
3
- import io .github .scalamath
4
-
5
3
import scala .collection .immutable .TreeMap
6
4
5
+ /**
6
+ * Represents a color transition.
7
+ *
8
+ * Created from a set of points made of a color and an offset.
9
+ * A color can be sampled from the gradient and the result will be an interpolation between the colors of the gradient.
10
+ *
11
+ * @example {{{
12
+ * // Scala
13
+ * val gradient = Gradient(
14
+ * 0.0f -> Col4f(1.0f, 0.0f, 0.0f), // Red
15
+ * 0.5f -> Col4f(1.0f, 1.0f, 0.0f), // Yellow
16
+ * 1.0f -> Col4f(0.0f, 1.0f, 0.0f) // Green
17
+ * )
18
+ * // Java
19
+ * var gradient = new Gradient()
20
+ * .addPoint(0.0f, new Col4f(1.0f, 0.0f, 0.0f))
21
+ * .addPoint(0.5f, new Col4f(1.0f, 1.0f, 0.0f))
22
+ * .addPoint(1.0f, new Col4f(0.0f, 1.0f, 0.0f));
23
+ * }}}
24
+ *
25
+ * @param points Points in the gradient.
26
+ * @see [[sample ]]
27
+ */
7
28
class Gradient private (private val points : TreeMap [Float , Color ]) {
8
29
30
+ /**
31
+ * Creates an empty gradient.
32
+ */
9
33
def this () = this (new TreeMap ())
10
34
35
+ /**
36
+ * Creates a new gradient obtained by updating this gradient with the given color and offset.
37
+ *
38
+ * @param color The color to add to the gradient.
39
+ * @param offset The offset of the color.
40
+ * @return The new gradient.
41
+ */
11
42
def addPoint (color : Color , offset : Float ): Gradient = new Gradient (this .points.updated(offset, color))
12
43
44
+ /**
45
+ * Creates a new gradient obtained by updating this gradient with the given color and offset.
46
+ *
47
+ * @param offset The offset of the color.
48
+ * @param color The color to add to the gradient.
49
+ * @return The new gradient.
50
+ */
13
51
def addPoint (offset : Float , color : Color ): Gradient = this .addPoint(color, offset)
14
52
53
+ /**
54
+ * Creates a new gradient obtained by updating this gradient with the given color and offset.
55
+ *
56
+ * This method is an alias for `addPoint`.
57
+ *
58
+ * @param color The color to add to the gradient.
59
+ * @param offset The offset of the color.
60
+ * @return The new gradient.
61
+ */
15
62
def + (color : Color , offset : Float ): Gradient = this .addPoint(color, offset)
16
63
64
+ /**
65
+ * Creates a new gradient obtained by updating this gradient with the given color and offset.
66
+ *
67
+ * This method is an alias for `addPoint`.
68
+ *
69
+ * @param offset The offset of the color.
70
+ * @param color The color to add to the gradient.
71
+ * @return The new gradient.
72
+ */
17
73
def + (offset : Float , color : Color ): Gradient = this + (color, offset)
18
74
75
+ /**
76
+ * Returns the number of colors in the gradient.
77
+ *
78
+ * @return The number of colors in the gradient.
79
+ */
19
80
def pointCount : Int = this .points.size
20
81
82
+ /**
83
+ * Returns the interpolated color specified by the given offset.
84
+ * Colors are interpolated linearly.
85
+ *
86
+ * @param offset The offset of the color.
87
+ * @return The result of linearly interpolating the color of this gradient at the given offset.
88
+ */
21
89
def sample (offset : Float ): Color = {
22
90
if (this .points.isEmpty) {
23
91
Col3f (0.0f , 0.0f , 0.0f )
24
92
} else if (this .points.contains(offset)) {
25
93
this .points(offset)
94
+ } else if (offset < this .points.firstKey) {
95
+ this .points(this .points.firstKey)
96
+ } else if (offset > this .points.lastKey) {
97
+ this .points(this .points.lastKey)
26
98
} else {
27
- val (offset1, col1) = this .points.maxBefore(offset).getOrElse(( 0.0f , this .points( this .points.firstKey)))
28
- val (offset2, col2) = this .points.minAfter(offset).getOrElse(( 1.0f , this .points( this .points.lastKey)))
29
- col1.lerp(col2, scalamath.map (offset, offset1, offset2, 0.0f , 1.0f ))
99
+ val (offset1, col1) = this .points.maxBefore(offset).get
100
+ val (offset2, col2) = this .points.minAfter(offset).get
101
+ col1.lerp(col2, (offset - offset1) / ( offset2 - offset1 ))
30
102
}
31
103
}
104
+
105
+ /**
106
+ * Returns the color of the gradient at the given offset.
107
+ * Can also be used to interpolate colors using a constant interpolation.
108
+ *
109
+ * @param offset The offset of the color.
110
+ * @return The color at the given offset.
111
+ */
112
+ def getColor (offset : Float ): Color = this .points.maxBefore(offset).map(entry => entry._2).getOrElse(this .points(this .points.firstKey))
113
+
114
+ /**
115
+ * Creates a new gradient obtained by removing the color at the given offset from this gradient.
116
+ *
117
+ * @param offset The offset of the color.
118
+ * @return The new gradient.
119
+ */
120
+ def removePoint (offset : Float ): Gradient = new Gradient (this .points.removed(offset))
121
+
122
+ /**
123
+ * Creates a new gradient obtained by removing the color at the given offset from this gradient.
124
+ *
125
+ * This method is an alias for `removePoint`.
126
+ *
127
+ * @param offset The offset of the color.
128
+ * @return The new gradient.
129
+ */
130
+ def - (offset : Float ): Gradient = this .removePoint(offset)
131
+
132
+ override def equals (obj : Any ): Boolean = obj match {
133
+ case gradient : Gradient => this .points.equals(gradient.points)
134
+ case _ => super .equals(obj)
135
+ }
32
136
}
33
137
138
+ /**
139
+ * Factory methods for gradients.
140
+ */
34
141
object Gradient {
35
142
143
+ /**
144
+ * Creates an empty gradient.
145
+ *
146
+ * Allows to construct a gradient without using the `new` keyword in Scala.
147
+ *
148
+ * @return The newly instantiated gradient.
149
+ */
36
150
def apply (): Gradient = new Gradient ()
37
151
152
+ /**
153
+ * Creates a gradient from the given points.
154
+ *
155
+ * @example {{{
156
+ * val gradient = Gradient(
157
+ * 0.0f -> Col4f(1.0f, 0.0f, 0.0f),
158
+ * 0.5f -> Col4f(1.0f, 1.0f, 0.0f),
159
+ * 1.0f -> Col4f(0.0f, 1.0f, 0.0f)
160
+ * )
161
+ * }}}
162
+ *
163
+ * @param points The points that make up the gradient.
164
+ * @return The newly instantiated gradient.
165
+ */
38
166
def apply (points : (Float , Color )* ): Gradient = new Gradient (TreeMap .from(points))
39
167
168
+ /**
169
+ * Creates a gradient with only two points, with the two given colors.
170
+ * The two given colors will have offsets of `0.0` and `1.0`.
171
+ *
172
+ * @param col1 The color with offset `0.0`.
173
+ * @param col2 The color with offset `1.0`.
174
+ * @return The newly instantiated gradient.
175
+ */
40
176
def between (col1 : Color , col2 : Color ): Gradient = this .apply(0.0f -> col1, 1.0f -> col2)
41
177
}
0 commit comments