Skip to content

Commit 60701e0

Browse files
committed
refactor: move math things to the separate package
1 parent 629417e commit 60701e0

File tree

9 files changed

+84
-60
lines changed

9 files changed

+84
-60
lines changed

slider/src/main/java/io/monstarlab/mosaic/slider/SliderState.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import androidx.compose.runtime.remember
1212
import androidx.compose.runtime.setValue
1313
import androidx.compose.ui.geometry.Offset
1414
import io.monstarlab.mosaic.slider.distribution.SliderValueDistribution
15+
import io.monstarlab.mosaic.slider.math.fractionToValue
16+
import io.monstarlab.mosaic.slider.math.valueToFraction
1517
import kotlinx.coroutines.coroutineScope
1618

1719
/**
Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package io.monstarlab.mosaic.slider.distribution
22

3-
import io.monstarlab.mosaic.slider.valueToFraction
3+
import io.monstarlab.mosaic.slider.math.LinearEquation
4+
import io.monstarlab.mosaic.slider.math.Point
5+
import io.monstarlab.mosaic.slider.math.RangedLinearEquation
6+
import io.monstarlab.mosaic.slider.math.valueToFraction
47

58
public class CheckPointsValueDistribution(
69
valuesMap: List<Pair<Float, Float>>,
@@ -16,32 +19,30 @@ public class CheckPointsValueDistribution(
1619

1720
val offsetRange = valuesMap.minOf { it.first }..valuesMap.maxOf { it.first }
1821
val valueRange = valuesMap.minOf { it.second }..valuesMap.maxOf { it.second }
19-
val zipped = valuesMap.sortedBy { it.first }
22+
23+
equations = valuesMap.sortedBy { it.first }
2024
.zipWithNext()
21-
// make sure all values are increasing, otherwise throw an exception
22-
zipped.firstOrNull { it.first.second >= it.second.second }
23-
?.let {
24-
throw DecreasingValueException(it.first)
25+
.checkIncreasingValues() // check if values are always increasing
26+
.map {
27+
val x1Fraction = it.first.first.valueToFraction(offsetRange)
28+
val x2Fraction = it.second.first.valueToFraction(offsetRange)
29+
val y1Fraction = it.first.second.valueToFraction(valueRange)
30+
val y2Fraction = it.second.second.valueToFraction(valueRange)
31+
val equation = LinearEquation.fromTwoPoints(
32+
x1 = x1Fraction,
33+
x2 = x2Fraction,
34+
y1 = y1Fraction,
35+
y2 = y2Fraction,
36+
)
37+
RangedLinearEquation(
38+
equation = equation,
39+
offsetRange = x1Fraction..x2Fraction,
40+
valueRange = y1Fraction..y2Fraction,
41+
)
2542
}
26-
equations = zipped.map {
27-
val x1Fraction = it.first.first.valueToFraction(offsetRange)
28-
val x2Fraction = it.second.first.valueToFraction(offsetRange)
29-
val y1Fraction = it.first.second.valueToFraction(valueRange)
30-
val y2Fraction = it.second.second.valueToFraction(valueRange)
31-
val equation = LinearEquation.fromTwoPoints(
32-
x1 = x1Fraction,
33-
x2 = x2Fraction,
34-
y1 = y1Fraction,
35-
y2 = y2Fraction,
36-
)
37-
RangedLinearEquation(
38-
equation = equation,
39-
offsetRange = x1Fraction..x2Fraction,
40-
valueRange = y1Fraction..y2Fraction,
41-
)
42-
}
4343
}
4444

45+
4546
override fun interpolate(value: Float): Float {
4647
val equation = equations.firstOrNull { it.offsetRange.contains(value) }?.equation
4748
checkNotNull(equation) { "No equation found for value $value during interpolate" }
@@ -54,10 +55,17 @@ public class CheckPointsValueDistribution(
5455
return equation.offsetFromValue(value)
5556
}
5657

57-
public class DecreasingValueException(progressValuePair: Pair<Float, Float>) :
58+
private fun List<Pair<Point, Point>>.checkIncreasingValues(): List<Pair<Point, Point>> {
59+
find { it.first.second >= it.second.second }?.let {
60+
throw DecreasingValueException(it.first)
61+
}
62+
return this
63+
}
64+
65+
public class DecreasingValueException(progressValuePair: Point) :
5866
IllegalStateException(
5967
"Values must be always increasing with increasing progress," +
60-
" item at progress ${progressValuePair.first} with value " +
61-
"${progressValuePair.second} is breaking this rule ",
68+
" item at progress ${progressValuePair.first} with value " +
69+
"${progressValuePair.second} is breaking this rule ",
6270
)
6371
}

slider/src/main/java/io/monstarlab/mosaic/slider/distribution/LinearEquation.kt

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.monstarlab.mosaic.slider.distribution
2+
3+
/**
4+
* Represents a linear distribution strategy for slider values.
5+
*/
6+
public object LinearValueDistribution: SliderValueDistribution {
7+
override fun interpolate(value: Float): Float {
8+
return value
9+
}
10+
11+
override fun inverse(value: Float): Float {
12+
return value
13+
}
14+
}

slider/src/main/java/io/monstarlab/mosaic/slider/distribution/SliderValueDistribution.kt

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,18 @@ public interface SliderValueDistribution {
3535
* @param c constant term in the parabolic equation
3636
* @return a [SliderValueDistribution] instance with a parabolic distribution strategy
3737
*/
38-
public fun parabolic(a: Float, b: Float = 0f, c: Float = 0f): SliderValueDistribution {
38+
public fun parabolic(
39+
a: Float,
40+
b: Float = 0f,
41+
c: Float = 0f
42+
): SliderValueDistribution {
3943
return ParabolicValueDistribution(a, b, c)
4044
}
4145

4246
/**
4347
* A linear distribution strategy where the input value is directly mapped to the output value.
4448
* Used in [Slider] by default
4549
*/
46-
public val Linear: SliderValueDistribution = object : SliderValueDistribution {
47-
override fun interpolate(value: Float): Float {
48-
return value
49-
}
50-
51-
override fun inverse(value: Float): Float {
52-
return value
53-
}
54-
}
50+
public val Linear: SliderValueDistribution = LinearValueDistribution
5551
}
5652
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.monstarlab.mosaic.slider.math
2+
3+
internal data class LinearEquation(
4+
private val m: Float,
5+
private val c: Float,
6+
) {
7+
internal fun valueFromOffset(offset: Float): Float = m * offset + c
8+
9+
internal fun offsetFromValue(value: Float): Float = (value - c) / m
10+
11+
internal companion object {
12+
internal fun fromTwoPoints(x1: Float, y1: Float, x2: Float, y2: Float): LinearEquation {
13+
require(x2 != x1) { "can't calc equation from points with similar x value" }
14+
val slope = (y2 - y1) / (x2 - x1)
15+
val c = y2 - slope * x2
16+
return LinearEquation(slope, c)
17+
}
18+
}
19+
}

slider/src/main/java/io/monstarlab/mosaic/slider/MathUtils.kt renamed to slider/src/main/java/io/monstarlab/mosaic/slider/math/MathUtils.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package io.monstarlab.mosaic.slider
1+
package io.monstarlab.mosaic.slider.math
22

33
import androidx.compose.ui.util.lerp
44

@@ -15,7 +15,7 @@ internal fun Float.valueToFraction(range: ClosedFloatingPointRange<Float>) =
1515
valueToFraction(range.start, range.endInclusive)
1616

1717
internal fun Float.fractionToValue(rangeStart: Float, rangeEnd: Float): Float =
18-
scale(0f, 1f, this.coerceIn(0f, 1f), rangeStart, rangeEnd)
18+
scale(0f, 1f, coerceIn(0f, 1f), rangeStart, rangeEnd)
1919

2020
internal fun Float.fractionToValue(range: ClosedFloatingPointRange<Float>): Float =
21-
scale(0f, 1f, this, range.start, range.endInclusive)
21+
fractionToValue(range.start, range.endInclusive)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package io.monstarlab.mosaic.slider.math
2+
3+
internal typealias Point = Pair<Float, Float>

slider/src/main/java/io/monstarlab/mosaic/slider/distribution/RangedLinearEquation.kt renamed to slider/src/main/java/io/monstarlab/mosaic/slider/math/RangedLinearEquation.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
package io.monstarlab.mosaic.slider.distribution
1+
package io.monstarlab.mosaic.slider.math
22

3-
public data class RangedLinearEquation(
3+
4+
internal data class RangedLinearEquation(
45
val equation: LinearEquation,
56
val offsetRange: ClosedFloatingPointRange<Float>,
67
val valueRange: ClosedFloatingPointRange<Float>,

0 commit comments

Comments
 (0)