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

commonMain.jetbrains.datalore.plot.base.Aes.kt Maven / Gradle / Ivy

There is a newer version: 4.5.3-alpha1
Show newest version
/*
 * 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

import jetbrains.datalore.base.typedKey.TypedKey
import jetbrains.datalore.base.values.Color
import jetbrains.datalore.plot.base.render.linetype.LineType
import jetbrains.datalore.plot.base.render.point.PointShape

class Aes private constructor(val name: String, val isNumeric: Boolean = true) : TypedKey {

    val isColor: Boolean
        get() = isColor(this)

    init {
        values.add(this)
    }

    override fun toString(): String {
        return "aes '$name'"
    }

    companion object {
        private val values = ArrayList>()

        val X: Aes = Aes("x")
        val Y: Aes = Aes("y")
        val Z: Aes = Aes("z")

        val COLOR: Aes = Aes("color", false)
        val FILL: Aes = Aes("fill", false)
        val ALPHA: Aes = Aes("alpha")
        val SHAPE: Aes = Aes("shape", false)
        val LINETYPE: Aes = Aes("linetype", false)

        val SIZE: Aes = Aes("size")
        val WIDTH: Aes = Aes("width")
        val HEIGHT: Aes = Aes("height")
        val WEIGHT: Aes = Aes("weight")
        val INTERCEPT: Aes = Aes("intercept")
        val SLOPE: Aes = Aes("slope")
        val XINTERCEPT: Aes = Aes("xintercept")
        val YINTERCEPT: Aes = Aes("yintercept")
        val LOWER: Aes = Aes("lower")
        val MIDDLE: Aes = Aes("middle")
        val UPPER: Aes = Aes("upper")

        val XMIN: Aes = Aes("xmin")
        val XMAX: Aes = Aes("xmax")
        val YMIN: Aes = Aes("ymin")
        val YMAX: Aes = Aes("ymax")
        val XEND: Aes = Aes("xend")
        val YEND: Aes = Aes("yend")

        val MAP_ID: Aes = Aes("map_id", false)
        val FRAME: Aes = Aes("frame", false)

        val SPEED: Aes = Aes("speed")
        val FLOW: Aes = Aes("flow")

        val LABEL: Aes = Aes("label", false)
        val FAMILY: Aes = Aes("family", false)
        val FONTFACE: Aes = Aes("fontface", false)

        // text horizontal justification (numbers [0..1] or predefined strings = new Aes<>(); not positional)
        val HJUST = Aes("hjust", false)

        // text vertical justification (numbers [0..1] or predefined strings, not positional)
        val VJUST = Aes("vjust", false)

        val ANGLE: Aes = Aes("angle")

        val SYM_X: Aes = Aes("sym_x")
        val SYM_Y: Aes = Aes("sym_y")


        fun numeric(unfiltered: Iterable>): List> {
            // safe to cast all 'numeric' aesthetics are 'Double'
            @Suppress("UNCHECKED_CAST")
            return unfiltered.filter { aes -> aes.isNumeric } as List>
        }

        fun isPositional(aes: Aes<*>): Boolean {
            return isPositionalXY(aes) ||
                    // SLOPE must be positional or
                    // `geom_abline(slope=number)` will not work.
                    // it should draw the same line as:
                    // `geom_abline(slope=number, intersept=0)`
                    // See: PlotUtil.createLayerAesthetics()
                    aes == SLOPE
        }

        fun isPositionalXY(aes: Aes<*>): Boolean {
            return isPositionalX(aes) ||
                    isPositionalY(aes)
        }

        fun isPositionalX(aes: Aes<*>): Boolean {
            return aes == X ||
                    aes == XINTERCEPT ||
                    aes == XMIN ||
                    aes == XMAX ||
                    aes == XEND
        }

        fun isPositionalY(aes: Aes<*>): Boolean {
            return aes == Y ||
                    aes == YMIN ||
                    aes == YMAX ||
                    aes == INTERCEPT ||
                    aes == YINTERCEPT ||
                    aes == LOWER ||
                    aes == MIDDLE ||
                    aes == UPPER ||
                    aes == YEND
        }

        fun isColor(aes: Aes<*>): Boolean {
            return aes == COLOR || aes == FILL
        }

        fun isAffectingScaleX(aes: Aes<*>): Boolean {
            return isPositionalX(aes) // && aes != XINTERCEPT
        }

        fun isAffectingScaleY(aes: Aes<*>): Boolean {
            return isPositionalY(aes) &&
                    // "INTERCEPT" is "positional Y" because it must use the same 'mapper' as other "positional Y"-s,
                    // but its range of values is not taken in account when computing the Y-mapper.
                    aes != INTERCEPT // &&
//                    aes != YINTERCEPT
        }

        fun affectingScaleX(unfiltered: Iterable>): List> {
            val numeric = numeric(unfiltered)
            return numeric.filter { isAffectingScaleX(it) }
        }

        fun affectingScaleY(unfiltered: Iterable>): List> {
            val numeric = numeric(unfiltered)
            return numeric.filter { isAffectingScaleY(it) }
        }

        fun noGuideNeeded(aes: Aes<*>): Boolean {
            return aes == MAP_ID ||
                    aes == FRAME ||
                    aes == SPEED ||
                    aes == FLOW ||
                    aes == LABEL ||
                    aes == SLOPE ||
                    aes == WIDTH ||
                    aes == HEIGHT ||
                    aes == HJUST ||
                    aes == VJUST ||
                    aes == ANGLE ||
                    aes == FAMILY ||
                    aes == FONTFACE ||
                    aes == SYM_X ||
                    aes == SYM_Y ||
                    isPositional(aes)
        }

        fun values(): List> {
            return values
        }

        fun allPositional(): List> {
            @Suppress("UNCHECKED_CAST")
            return values.filter { isPositional(it) } as List>
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy