gg/plotargs.go

186 lines
4.3 KiB
Go
Raw Normal View History

package gg
import (
"image"
"strings"
)
// PlotArgs holds the arguments for drawing line graphs (charts)
type PlotArgs struct {
// curve name
L string // label
// lines
C string // line: color
A float64 // line: alpha (0, 1]. A<1e-14 => A=1.0
Ls string // line: style
Lw float64 // line: width
// markers
M string // marker: type, e.g. "o", "s", "+", "x", "img:filename.png"
Ms int // marker: size
Me int // marker: mark-every
Mec string // marker: edge color
Mew float64 // marker: edge width
Void bool // marker: void marker (draw edge only)
// internal
markerImg image.Image // marker image
markerName string // filename corresponding to loaded image
}
// DrawMarker draws marker
func (o *PlotArgs) DrawMarker(dc *Context, x, y int) {
// skip if marker type is empty
if o.M == "" {
return
}
// markersize and half-markersize
s := o.markerSize()
h := s / 2
// draw marker
switch o.M {
// circle
case "o":
if !o.Void {
o.Circle(dc, true, false, x, y, h)
}
o.Circle(dc, true, true, x, y, h)
// square
case "s":
if !o.Void {
o.Rect(dc, true, false, x-h, y-h, s, s)
}
o.Rect(dc, true, true, x-h, y-h, s, s)
// cross
case "+":
o.Line(dc, true, true, x-h, y, x+h, y)
o.Line(dc, true, true, x, y-h, x, y+h)
// x
case "x":
o.Line(dc, true, true, x-h, y-h, x+h, y+h)
o.Line(dc, true, true, x-h, y+h, x+h, y-h)
// use image as marker
default:
if o.checkMarkerImage() {
dc.DrawImageAnchored(o.markerImg, x, y, 0.5, 0.5)
}
}
}
// Activate activates properties of lines/shapes
func (o *PlotArgs) Activate(dc *Context, marker, edge bool) {
// color
clr := o.C
if marker && edge && o.Mec != "" {
clr = o.Mec
}
r, g, b, _ := parseHexColor(clr)
// alpha
alpha := o.A
if alpha < 1e-14 || marker {
alpha = 1.0
}
// set color
dc.SetRGBA255(r, g, b, int(alpha*255))
}
// Circle draws Circle
func (o *PlotArgs) Circle(dc *Context, marker, edge bool, x, y, r int) {
o.Activate(dc, marker, edge)
dc.DrawCircle(float64(x), float64(y), float64(r))
if edge {
dc.Stroke()
} else {
dc.Fill()
}
}
// Rect draws rectangle
func (o *PlotArgs) Rect(dc *Context, marker, edge bool, x, y, w, h int) {
o.Activate(dc, marker, edge)
dc.DrawRectangle(float64(x), float64(y), float64(w), float64(h))
if edge {
dc.Stroke()
} else {
dc.Fill()
}
}
// Line draws Line
func (o *PlotArgs) Line(dc *Context, marker, edge bool, x1, y1, x2, y2 int) {
o.Activate(dc, marker, edge)
dc.DrawLine(float64(x1), float64(y1), float64(x2), float64(y2))
if edge {
dc.Stroke()
} else {
dc.Fill()
}
}
// checkMarkerImage loads marker image if not loaded already
func (o *PlotArgs) checkMarkerImage() (useImage bool) {
useImage = strings.HasPrefix(o.M, "img:")
if useImage {
fn := strings.TrimPrefix(o.M, "img:")
if o.markerImg == nil || o.markerName != fn { // load only if not loaded already
var err error
o.markerImg, err = LoadPNG(fn)
if err != nil {
panic(err)
}
o.markerName = fn
}
}
return
}
// markerSize returns the size of marker
func (o *PlotArgs) markerSize() int {
if o.checkMarkerImage() {
return o.markerImg.Bounds().Dy()
}
if o.Ms == 0 {
return 8 // default value
}
return o.Ms
}
// colors /////////////////////////////////////////////////////////////////////////////////////////
// GetColor returns a color from a default palette
// use palette < 0 for automatic color
func GetColor(i, palette int) string {
if palette < 0 || palette >= len(palettes) {
return ""
}
p := palettes[palette]
return p[i%len(p)]
}
// palettes holds color palettes
var palettes = [][]string{
{"#003fff", "#35b052", "#e8000b", "#8a2be2", "#ffc400", "#00d7ff"},
{"blue", "green", "magenta", "orange", "red", "cyan", "black", "#de9700", "#89009d", "#7ad473", "#737ad4", "#d473ce", "#7e6322", "#462222", "#98ac9d", "#37a3e8", "yellow"},
{"#4c72b0", "#55a868", "#c44e52", "#8172b2", "#ccb974", "#64b5cd"},
{"#9b59b6", "#3498db", "#95a5a6", "#e74c3c", "#34495e", "#2ecc71"},
{"#e41a1c", "#377eb8", "#4daf4a", "#984ea3", "#ff7f00", "#ffff33"},
{"#7fc97f", "#beaed4", "#fdc086", "#ffff99", "#386cb0", "#f0027f", "#bf5b17"},
{"#001c7f", "#017517", "#8c0900", "#7600a1", "#b8860b", "#006374"},
{"#0072b2", "#009e73", "#d55e00", "#cc79a7", "#f0e442", "#56b4e9"},
{"#4878cf", "#6acc65", "#d65f5f", "#b47cc7", "#c4ad66", "#77bedb"},
{"#92c6ff", "#97f0aa", "#ff9f9a", "#d0bbff", "#fffea3", "#b0e0e6"},
}