All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.data2viz.scale.Power.kt Maven / Gradle / Ivy

package io.data2viz.scale

import io.data2viz.interpolate.interpolateNumber
import io.data2viz.interpolate.interpolateRound
import io.data2viz.interpolate.uninterpolateNumber
import kotlin.math.pow

/**
 * Power scales are similar to linear scales, except an exponential transform is applied to the input domain
 * value before the output range value is computed.
 * Each range value y can be expressed as a function of the domain value x: y = mx^k + b, where k is the exponent value.
 * Power scales also support negative domain values, in which case the input value and the resulting output
 * value are multiplied by -1.
 */
class PowerScale(exponent: Double = 1.0, interpolateRange: (R, R) -> (Double) -> R,
                    uninterpolateRange: ((R, R) -> (R) -> Double)? = null,
                    rangeComparator: Comparator? = null)
    : LinearScale(interpolateRange, uninterpolateRange, rangeComparator) {

    var exponent: Double = exponent
        set(value) {
            field = value
            rescale()
        }

    override fun uninterpolateDomain(from: Double, to: Double): (Double) -> Double {
        val dFrom = raise(from, exponent)
        val dTo = raise(to, exponent) - dFrom

        return if (dTo == .0 || dTo == Double.NaN) { _ -> dTo }
        else { t -> (raise(t, exponent) - dFrom) / dTo }
    }

    override fun interpolateDomain(from: Double, to: Double): (Double) -> Double {
        val ra = raise(from, exponent)
        val rb = raise(to, exponent) - ra
        return { t -> raise(ra + rb * t, 1.0 / exponent) }
    }

    private fun raise(x: Double, exponent: Double): Double {
        val pow = x.pow(exponent)
        return if (x < 0.0) -pow else pow
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy