Skip to content

Commit 4ee33b3

Browse files
committed
make FragmentedLinearDistribution implement the SliderValueDistribution interface
1 parent baec41f commit 4ee33b3

File tree

1 file changed

+64
-24
lines changed

1 file changed

+64
-24
lines changed

slider/src/main/java/io/monstarlab/mosaic/slider/SensitivityDistribution.kt renamed to slider/src/main/java/io/monstarlab/mosaic/slider/FragmentedLinearDistribution.kt

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package io.monstarlab.mosaic.slider
22

3-
public class SensitivityDistribution private constructor(
3+
public class FragmentedLinearDistribution private constructor(
44
equationMap: Map<Float, LinearEquation>,
5-
) {
6-
private var _equationList: MutableList<RangedLinearEquation> =
7-
mutableListOf<RangedLinearEquation>()
5+
) : SliderValueDistribution {
6+
private var _equationList: MutableList<RangedLinearEquation> = mutableListOf()
87
public val equationList: List<RangedLinearEquation> get() = _equationList.toList()
98

9+
private lateinit var valueRange: ClosedFloatingPointRange<Float>
10+
1011
init {
1112
var previous: Pair<Float, LinearEquation>? = null
1213
// get the max range start value to help us identify the last equation
@@ -21,8 +22,17 @@ public class SensitivityDistribution private constructor(
2122
}
2223
previous = pair.toPair()
2324
}
25+
valueRange = valueFromOffset(0f)..valueFromOffset(1f)
2426
}
2527

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+
2636
private fun addEquation(equation: LinearEquation, rangeStart: Float, rangeEnd: Float) {
2737
val offsetRange = rangeStart..rangeEnd
2838
val valueRange =
@@ -36,45 +46,75 @@ public class SensitivityDistribution private constructor(
3646
)
3747
}
3848

39-
public fun valueFromOffset(offset: Float): Float? =
49+
private fun valueFromOffset(offset: Float): Float =
4050
_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
4155

42-
public fun offsetFromValue(value: Float): Float? =
43-
_equationList.firstOrNull { value in it.valueRange }?.equation?.offsetFromValue(value)
4456

4557
public class Builder {
4658
private var equationRangeStartMap = mutableMapOf<Float, LinearEquation>()
4759
private var maxRangeValue: Float = -1f
4860
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+
4982

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) {
5291
throw FirstValueNotZeroException()
5392
}
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()
5695

57-
val equationRangeStartPair = calcNextEquation(sensitivity, rangeStart, lastEquation)
96+
val equationRangeStartPair =
97+
calcNextEquation(sensitivity, relativePosition, lastEquation)
5898
equationRangeStartMap[equationRangeStartPair.first] = equationRangeStartPair.second
5999
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)
61108
}
62109

63110
private fun calcNextEquation(
64111
slope: Float,
65-
rangeStart: Float,
112+
startPos: Float,
66113
previousEquation: LinearEquation?,
67114
): 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))
78118
}
79119
}
80120

0 commit comments

Comments
 (0)