commonMain.jetbrains.datalore.plot.base.scale.DiscreteScale.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of lets-plot-common Show documentation
Show all versions of lets-plot-common Show documentation
Lets-Plot JVM package without rendering part
/*
* Copyright (c) 2019. JetBrains s.r.o.
* Use of this source code is governed by the MIT license that can be found in the LICENSE file.
*/
package jetbrains.datalore.plot.base.scale
import jetbrains.datalore.plot.base.ContinuousTransform
import jetbrains.datalore.plot.base.DiscreteTransform
import jetbrains.datalore.plot.base.Scale
import jetbrains.datalore.plot.base.Transform
internal class DiscreteScale : AbstractScale {
private val discreteTransform: DiscreteTransform
override val transform: Transform
get() = discreteTransform
constructor(
name: String,
domainValues: Collection,
mapper: ((Double?) -> T?)
) : super(name, mapper, breaks = domainValues.toList()) {
discreteTransform = DiscreteTransform(domainValues, emptyList())
// see: https://ggplot2.tidyverse.org/reference/scale_continuous.html
// defaults for discrete scale.
multiplicativeExpand = 0.0
additiveExpand = 0.6
}
private constructor(b: MyBuilder) : super(b) {
discreteTransform = DiscreteTransform(b.myDomainValues, b.myDomainLimits)
}
override fun getBreaksGenerator(): BreaksGenerator {
throw IllegalStateException("No breaks generator for discrete scale '$name'")
}
override fun hasDomainLimits(): Boolean {
return discreteTransform.hasDomainLimits()
}
override fun isInDomainLimits(v: Any): Boolean {
return discreteTransform.isInDomain(v)
}
protected override fun getBreaksIntern(): List {
return if (!hasDomainLimits()) {
super.getBreaksIntern()
} else {
// Filter and preserve the order defined by limits.
val breaksSet = super.getBreaksIntern().toSet()
discreteTransform.domainLimits.filter { it in breaksSet }
}
}
override fun getLabelsIntern(): List {
val labels = super.getLabelsIntern()
return if (!hasDomainLimits() || labels.isEmpty()) {
labels
} else {
val breaks = super.getBreaksIntern()
val breakLabels = breaks.mapIndexed { i, _ -> labels[i % labels.size] }
// Filter and preserve the order defined by limits.
val labelByBreak = breaks.zip(breakLabels).toMap()
discreteTransform.domainLimits
.filter { labelByBreak.containsKey(it) }
.map { labelByBreak.getValue(it) }
}
}
override fun with(): Scale.Builder {
return MyBuilder(this)
}
private class MyBuilder(scale: DiscreteScale) : AbstractBuilder(scale) {
internal val myDomainValues: Collection = scale.discreteTransform.domainValues
internal var myDomainLimits: List = scale.discreteTransform.domainLimits
override fun breaksGenerator(v: BreaksGenerator): Scale.Builder {
throw IllegalStateException("Not applicable to scale with discrete domain")
}
override fun lowerLimit(v: Double): Scale.Builder {
throw IllegalStateException("Not applicable to scale with discrete domain")
}
override fun upperLimit(v: Double): Scale.Builder {
throw IllegalStateException("Not applicable to scale with discrete domain")
}
override fun limits(domainValues: List): Scale.Builder {
myDomainLimits = domainValues
return this
}
override fun continuousTransform(v: ContinuousTransform): Scale.Builder {
// ignore
return this
}
override fun build(): Scale {
return DiscreteScale(this)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy