1
1
package io.monstarlab.mosaic.slider
2
2
3
- public class SensitivityDistribution private constructor(
3
+ public class FragmentedLinearDistribution private constructor(
4
4
equationMap : Map <Float , LinearEquation >,
5
- ) {
6
- private var _equationList : MutableList <RangedLinearEquation > =
7
- mutableListOf<RangedLinearEquation >()
5
+ ) : SliderValueDistribution {
6
+ private var _equationList : MutableList <RangedLinearEquation > = mutableListOf ()
8
7
public val equationList: List <RangedLinearEquation > get() = _equationList .toList()
9
8
9
+ private lateinit var valueRange: ClosedFloatingPointRange <Float >
10
+
10
11
init {
11
12
var previous: Pair <Float , LinearEquation >? = null
12
13
// get the max range start value to help us identify the last equation
@@ -21,8 +22,17 @@ public class SensitivityDistribution private constructor(
21
22
}
22
23
previous = pair.toPair()
23
24
}
25
+ valueRange = valueFromOffset(0f ).. valueFromOffset(1f )
24
26
}
25
27
28
+
29
+ override fun interpolate (value : Float ): Float =
30
+ valueFromOffset(value).valueToFraction(valueRange)
31
+
32
+ override fun inverse (value : Float ): Float = offsetFromValue(
33
+ value.fractionToValue(valueRange)
34
+ )
35
+
26
36
private fun addEquation (equation : LinearEquation , rangeStart : Float , rangeEnd : Float ) {
27
37
val offsetRange = rangeStart.. rangeEnd
28
38
val valueRange =
@@ -36,45 +46,75 @@ public class SensitivityDistribution private constructor(
36
46
)
37
47
}
38
48
39
- public fun valueFromOffset (offset : Float ): Float? =
49
+ private fun valueFromOffset (offset : Float ): Float =
40
50
_equationList .firstOrNull { offset in it.offsetRange }?.equation?.valueFromOffset(offset)
51
+ ? : 0f
52
+
53
+ private fun offsetFromValue (value : Float ): Float =
54
+ _equationList .firstOrNull { value in it.valueRange }?.equation?.offsetFromValue(value) ? : 0f
41
55
42
- public fun offsetFromValue (value : Float ): Float? =
43
- _equationList .firstOrNull { value in it.valueRange }?.equation?.offsetFromValue(value)
44
56
45
57
public class Builder {
46
58
private var equationRangeStartMap = mutableMapOf<Float , LinearEquation >()
47
59
private var maxRangeValue: Float = - 1f
48
60
private var lastEquation: LinearEquation ? = null
61
+ private var rangeStart: Float = 0f
62
+ private var rangeEnd: Float = 1f
63
+
64
+
65
+ /* *
66
+ * Create a distribution on a range with an initial sensitivity provided by [initialSensitivity]
67
+ * please note that the range is for the offset and not the value we get from the offset
68
+ *
69
+ * @param offsetRangeStart the start of the range that the offset values can start from
70
+ * @param offsetRangeEnd the end of the range that the offset values can go up to
71
+ */
72
+ public fun createDistribution (
73
+ offsetRangeStart : Float ,
74
+ offsetRangeEnd : Float ,
75
+ initialSensitivity : Float
76
+ ) {
77
+ rangeStart = offsetRangeStart
78
+ rangeEnd = offsetRangeEnd
79
+ sliceAt(initialSensitivity, fractionalValue(rangeStart))
80
+ }
81
+
49
82
50
- public fun add (sensitivity : Float , rangeStart : Float ): Builder = apply {
51
- if (equationRangeStartMap.isEmpty() && rangeStart != 0f ) {
83
+ private fun fractionalValue (value : Float ) = value.valueToFraction(rangeStart, rangeEnd)
84
+
85
+ public fun sliceAt (
86
+ sensitivity : Float ,
87
+ position : Float ,
88
+ ): Builder = apply {
89
+ val relativePosition = fractionalValue(position)
90
+ if (equationRangeStartMap.isEmpty() && relativePosition != 0f ) {
52
91
throw FirstValueNotZeroException ()
53
92
}
54
- if (rangeStart !in 0.0f .. 1f ) throw OutOfRangeException ()
55
- if (rangeStart < maxRangeValue) throw OverlappingRangeException ()
93
+ if (position !in rangeStart .. rangeEnd ) throw OutOfRangeException ()
94
+ if (position < maxRangeValue) throw OverlappingRangeException ()
56
95
57
- val equationRangeStartPair = calcNextEquation(sensitivity, rangeStart, lastEquation)
96
+ val equationRangeStartPair =
97
+ calcNextEquation(sensitivity, relativePosition, lastEquation)
58
98
equationRangeStartMap[equationRangeStartPair.first] = equationRangeStartPair.second
59
99
lastEquation = equationRangeStartPair.second
60
- maxRangeValue = rangeStart
100
+ maxRangeValue = position
101
+ }
102
+
103
+ public fun build (): FragmentedLinearDistribution {
104
+ if (equationRangeStartMap.isEmpty()) {
105
+ sliceAt(1f , 0f )
106
+ }
107
+ return FragmentedLinearDistribution (equationRangeStartMap)
61
108
}
62
109
63
110
private fun calcNextEquation (
64
111
slope : Float ,
65
- rangeStart : Float ,
112
+ startPos : Float ,
66
113
previousEquation : LinearEquation ? ,
67
114
): Pair <Float , LinearEquation > {
68
- val y0 = previousEquation?.valueFromOffset(rangeStart) ? : 0f
69
- val c = y0 - slope * rangeStart
70
- return Pair (rangeStart, LinearEquation (slope, c))
71
- }
72
-
73
- public fun build (): SensitivityDistribution {
74
- if (equationRangeStartMap.isEmpty()) {
75
- add(1f , 0f )
76
- }
77
- return SensitivityDistribution (equationRangeStartMap)
115
+ val y0 = previousEquation?.valueFromOffset(startPos) ? : 0f
116
+ val c = y0 - slope * startPos
117
+ return Pair (startPos, LinearEquation (slope, c))
78
118
}
79
119
}
80
120
0 commit comments