Skip to content

Commit 5f43377

Browse files
committed
Finished gradient
1 parent d9257e6 commit 5f43377

File tree

1 file changed

+141
-5
lines changed

1 file changed

+141
-5
lines changed
Lines changed: 141 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,177 @@
11
package io.github.scalamath.colorlib
22

3-
import io.github.scalamath
4-
53
import scala.collection.immutable.TreeMap
64

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+
*/
728
class Gradient private(private val points: TreeMap[Float, Color]) {
829

30+
/**
31+
* Creates an empty gradient.
32+
*/
933
def this() = this(new TreeMap())
1034

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+
*/
1142
def addPoint(color: Color, offset: Float): Gradient = new Gradient(this.points.updated(offset, color))
1243

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+
*/
1351
def addPoint(offset: Float, color: Color): Gradient = this.addPoint(color, offset)
1452

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+
*/
1562
def +(color: Color, offset: Float): Gradient = this.addPoint(color, offset)
1663

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+
*/
1773
def +(offset: Float, color: Color): Gradient = this + (color, offset)
1874

75+
/**
76+
* Returns the number of colors in the gradient.
77+
*
78+
* @return The number of colors in the gradient.
79+
*/
1980
def pointCount: Int = this.points.size
2081

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+
*/
2189
def sample(offset: Float): Color = {
2290
if(this.points.isEmpty) {
2391
Col3f(0.0f, 0.0f, 0.0f)
2492
} else if(this.points.contains(offset)) {
2593
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)
2698
} 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))
30102
}
31103
}
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+
}
32136
}
33137

138+
/**
139+
* Factory methods for gradients.
140+
*/
34141
object Gradient {
35142

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+
*/
36150
def apply(): Gradient = new Gradient()
37151

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+
*/
38166
def apply(points: (Float, Color)*): Gradient = new Gradient(TreeMap.from(points))
39167

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+
*/
40176
def between(col1: Color, col2: Color): Gradient = this.apply(0.0f -> col1, 1.0f -> col2)
41177
}

0 commit comments

Comments
 (0)