From a60aef02d5e6d3f97d15b517cb4899b2de8b0745 Mon Sep 17 00:00:00 2001 From: Steve Donnelly Date: Thu, 5 Oct 2023 14:08:32 -0700 Subject: [PATCH] Add 'nice' function from d3 (#283) --- scale/api/scale.api | 5 +++++ scale/src/commonMain/kotlin/Nice.kt | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 scale/src/commonMain/kotlin/Nice.kt diff --git a/scale/api/scale.api b/scale/api/scale.api index 30fdc628..2c70b095 100644 --- a/scale/api/scale.api +++ b/scale/api/scale.api @@ -69,6 +69,11 @@ public final class com/juul/krayon/scale/MinKt { public static final fun min (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/lang/Comparable; } +public final class com/juul/krayon/scale/NiceKt { + public static final fun nice (DDI)Ljava/util/List; + public static final fun nice (FFI)Ljava/util/List; +} + public abstract interface class com/juul/krayon/scale/Scale { public abstract fun scale (Ljava/lang/Object;)Ljava/lang/Object; } diff --git a/scale/src/commonMain/kotlin/Nice.kt b/scale/src/commonMain/kotlin/Nice.kt new file mode 100644 index 00000000..f8cecd55 --- /dev/null +++ b/scale/src/commonMain/kotlin/Nice.kt @@ -0,0 +1,28 @@ +package com.juul.krayon.scale + +import kotlin.math.ceil +import kotlin.math.floor + +/** See equivalent [d3 function](https://github.com/d3/d3-array#nice). */ +public fun nice(start: Float, stop: Float, count: Int): List = + nice(start.toDouble(), stop.toDouble(), count).map { it.toFloat() } + +/** See equivalent [d3 function](https://github.com/d3/d3-array#nice). */ +public fun nice(start: Double, stop: Double, count: Int): List { + var nextStart = start + var nextStop = stop + var previousIncrement: Int? = null + while (true) { + val increment = tickIncrement(nextStart, nextStop, count) + if (increment == previousIncrement || increment == 0) { + return listOf(nextStart, nextStop) + } else if (increment > 0) { + nextStart = floor(nextStart / increment) * increment + nextStop = ceil(nextStop / increment) * increment + } else { + nextStart = ceil(nextStart * increment) / increment + nextStop = floor(nextStop * increment) / increment + } + previousIncrement = increment + } +}