%useLatestDescriptors
%use lets-plot
LetsPlot.getInfo()
Lets-Plot Kotlin API v.4.9.3. Frontend: Notebook with dynamically loaded JS. Lets-Plot JS v.4.5.2.
import org.jetbrains.letsPlot.intern.Feature
val colorMargin = "#b3cde3"
val colorKey = "#decbe4"
val colorLabel = "#fddaec"
val colorPlot = "#ccebc5"
data class Bounds(val xmin: Double, val ymin: Double, val xmax: Double, val ymax: Double)
fun legendElement(b: Bounds): Feature {
return geomRect(xmin = b.xmin, xmax = b.xmax, ymin = b.ymin, ymax = b.ymax,
fill = colorLabel, color = colorLabel, size = 0) +
geomRect(xmin = b.xmin, xmax = b.xmin + 1.5, ymin = b.ymin, ymax = b.ymax,
fill = colorKey, color = colorKey, size = 0) +
geomText(x = b.xmin + 0.1, y = (b.ymin + b.ymax) / 2.0,
label = "key", vjust = 0.5, hjust = 0.0, size = 10) +
geomText(x = b.xmin + 1.6, y = (b.ymin + b.ymax) / 2.0,
label = "label", vjust = 0.5, hjust = 0.0, size = 10)
}
fun legend(x: Double, y: Double, w: Double, h: Double): Feature {
val xmin = x
val xmax = x + w
val ymin = y
val ymax = ymin + h
val margin = 1.0
val space = 1.0
val titleH = 1.5
val elemW = ((w - margin * 2.0) - space) / 2.0
val elemH = ((h - margin * 2.0)) / 2.0 - space - 0.2
// elements bounds
val innerBounds = Bounds(xmin + margin, ymin + margin,
xmax - margin, ymax - margin)
val elem11 = Bounds(innerBounds.xmin, innerBounds.ymax - titleH - elemH,
innerBounds.xmin + elemW, innerBounds.ymax - titleH)
val elem12 = Bounds(innerBounds.xmin + elemW + space, innerBounds.ymax - titleH - elemH,
innerBounds.xmax, innerBounds.ymax - titleH)
val elem21 = Bounds(elem11.xmin, innerBounds.ymin, elem11.xmax, innerBounds.ymin + elemH)
val elem22 = Bounds(elem12.xmin, innerBounds.ymin, innerBounds.xmax, elem21.ymax)
// plot elements
val legendBackground = geomRect(xmin = xmin, xmax = xmax,
ymin = ymin, ymax = ymax,
fill = colorMargin, size = 1.5)
val legendElementsBox = geomRect(xmin = innerBounds.xmin, xmax = innerBounds.xmax,
ymin = innerBounds.ymin, ymax = innerBounds.ymax,
fill = "white", size = 0)
val title = geomText(label = "Title",
x = innerBounds.xmin + 0.1, y = innerBounds.ymax - titleH / 2.0,
vjust = 0.5, hjust = 0, size = 10)
val row1 = legendElement(elem11) + legendElement(elem12)
val row2 = legendElement(elem21) + legendElement(elem22)
return legendBackground + legendElementsBox + title + row1 + row2
}
fun annotationLine(x: Double, y: Double, xend: Double? = null, yend: Double? = null,
typeArrow: String? = "both", linetype: String = "solid"): Feature {
val xend: Double = xend ?: x
val yend: Double = yend ?: y
val withArrow: Map<String, Any>? = typeArrow?.let { ends ->
arrow(length = 5, ends = ends, type = "closed")
}
return geomSegment(x = x, y = y, xend = xend, yend = yend, linetype = linetype, arrow = withArrow)
}
val plottingArea = geomRect(xmin = 0, xmax = 3, ymin = -1, ymax = 19,
fill = colorPlot, color = colorMargin,
size = 14, alpha = 0.5) +
geomText(label = "plotting area", x = 2, y = 10,
hjust = 0.5, vjust = 0, angle = 90, size = 11, color = "grey") +
geomText(label = "plotInset", x = 2.8, y = 10,
hjust = 0.5, vjust = 1, angle = 90, family = "Courier")
val legendBoxSpacing = geomText(label = "legendBoxSpacing", x = 4.2, y = 10.5,
hjust = 0, vjust = 0, angle = 90, family = "Courier") +
annotationLine(x = 3.3, y = 10.2, xend = 5.0)
val legendBoxes = legend(x = 5.0, y = 10.0, w = 15.0, h = 8.5) +
legend(x = 5.0, y = 0.0, w = 12.0, h = 8.5) +
geomText(label = "legendJustification(0, 1)", x = 23, y = 19,
hjust = 1, vjust = 0, family = "Courier") +
annotationLine(x = -1.0, y = 18.5, xend = 22.0, typeArrow = null, linetype = "dashed")
val legendAnnotations = geomText(label = "legendMargin", x = 15, y = 18, hjust = 0, family = "Courier") +
geomText(label = "legendSpacingY", x = 6, y = 9.2, hjust = 0, family = "Courier") +
annotationLine(x = 5.4, y = 8.5, yend = 10.0) +
geomText(label = "legendKeySpacingX", x = 12.8, y = 9.2, hjust = 0, family = "Courier") +
annotationLine(x = 12.0, y = 11.5, xend = 13.0) +
annotationLine(x = 12.5, y = 9.2, yend = 11.5, typeArrow = null) +
geomText(label = "legendKeySpacingY", x = 14, y = 13.5, hjust = 0, family = "Courier") +
annotationLine(x = 13.8, y = 13.1, yend = 13.9) +
geomText(label = "legendBoxJustificationLeft() (legendBoxVertical())",
x = 5.3, y = -1, hjust = 0, family = "Courier") +
annotationLine(x = 5.0, y = -2.0, yend = 20.0, typeArrow = null, linetype = "dashed") +
geomText(label = "legendKeyWidth", x = 12, y = 7, hjust = 0, family = "Courier") +
annotationLine(x = 11.5, y = 6.5, xend = 13.0) +
geomText(label = "legendKeyHeight", x = 10.5, y = 3.5, hjust = 0, family = "Courier") +
annotationLine(x = 11.2, y = 4.0, yend = 5.9)
letsPlot() +
plottingArea +
legendBoxSpacing +
legendBoxes +
legendAnnotations +
coordCartesian(xlim = Pair(1.2, 23)) +
themeVoid() +
ggsize(1000, 800)