commonMain.jetbrains.datalore.plot.base.Aes.kt Maven / Gradle / Ivy
/*
* 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.gcommon.collect.Iterables.filter
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 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>): Iterable> {
// safe to cast all 'numeric' aesthetics are 'Double'
@Suppress("UNCHECKED_CAST")
return filter(unfiltered) { aes -> aes.isNumeric } as Iterable>
}
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>): Iterable> {
val numeric = numeric(unfiltered)
return filter(numeric) { isAffectingScaleX(it) }
}
fun affectingScaleY(unfiltered: Iterable>): Iterable> {
val numeric = numeric(unfiltered)
return filter(numeric) { isAffectingScaleY(it) }
}
fun noGuideNeeded(aes: Aes<*>): Boolean {
return 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