File: palette.go

package info (click to toggle)
golang-gonum-v1-plot 0.7.0-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 13,980 kB
  • sloc: sh: 81; makefile: 13
file content (188 lines) | stat: -rw-r--r-- 5,439 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// Copyright ©2015 The Gonum Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Copyright ©2013 The bíogo Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package palette provides basic color palette handling.
package palette // import "gonum.org/v1/plot/palette"

import (
	"errors"
	"image/color"
	"math"
)

// Palette is a collection of colors ordered into a palette.
type Palette interface {
	Colors() []color.Color
}

// DivergingPalette is a collection of colors ordered into a palette with
// a critical class or break in the middle of the color range.
type DivergingPalette interface {
	Palette

	// CriticalIndex returns the indices of the lightest
	// (median) color or colors in the DivergingPalette.
	// The low and high index values will be equal when
	// there is a single median color.
	CriticalIndex() (low, high int)
}

// A ColorMap maps scalar values to colors.
type ColorMap interface {
	// At returns the color associated with the given value.
	// If the value is not between Max() and Min(), an error is returned.
	At(float64) (color.Color, error)

	// Max returns the current maximum value of the ColorMap.
	Max() float64

	// SetMax sets the maximum value of the ColorMap.
	SetMax(float64)

	// Min returns the current minimum value of the ColorMap.
	Min() float64

	// SetMin sets the minimum value of the ColorMap.
	SetMin(float64)

	// Alpha returns the opacity value of the ColorMap.
	Alpha() float64

	// SetAlpha sets the opacity value of the ColorMap. Zero is transparent
	// and one is completely opaque. The default value of alpha should be
	// expected to be one. The function should be expected to panic
	// if alpha is not between zero and one.
	SetAlpha(float64)

	// Palette creates a Palette with the specified number of colors
	// from the ColorMap.
	Palette(colors int) Palette
}

// DivergingColorMap maps scalar values to colors that diverge
// from a central value.
type DivergingColorMap interface {
	ColorMap

	// SetConvergePoint sets the value where the diverging colors
	// should meet. The default value should be expected to be
	// (Min() + Max()) / 2. It should be expected that calling either
	// SetMax() or SetMin() will set a new default value, so for a
	// custom convergence point this function should be called after
	// SetMax() and SetMin(). The function should be expected to panic
	// if the value is not between Min() and Max().
	SetConvergePoint(float64)

	// ConvergePoint returns the value where the diverging colors meet.
	ConvergePoint() float64
}

// Hue represents a hue in HSV color space. Valid Hues are within [0, 1].
type Hue float64

const (
	Red Hue = Hue(iota) / 6
	Yellow
	Green
	Cyan
	Blue
	Magenta
)

var (
	// ErrOverflow is the error returned by ColorMaps when the specified
	// value is greater than the maximum value.
	ErrOverflow = errors.New("palette: specified value > maximum")

	// ErrUnderflow is the error returned by ColorMaps when the specified
	// value is less than the minimum value.
	ErrUnderflow = errors.New("palette: specified value < minimum")

	// ErrNaN is the error returned by ColorMaps when the specified
	// value is NaN.
	ErrNaN = errors.New("palette: specified value == NaN")
)

// Complement returns the complementary hue of a Hue.
func (h Hue) Complement() Hue { return Hue(math.Mod(float64(h+0.5), 1)) }

type palette []color.Color

func (p palette) Colors() []color.Color { return p }

type divergingPalette []color.Color

func (p divergingPalette) Colors() []color.Color { return p }

func (d divergingPalette) CriticalIndex() (low, high int) {
	l := len(d)
	return (l - 1) / 2, l / 2
}

// Rainbow returns a rainbow palette with the specified number of colors, saturation
// value and alpha, and hues in the specified range.
func Rainbow(colors int, start, end Hue, sat, val, alpha float64) Palette {
	p := make(palette, colors)
	hd := float64(end-start) / float64(colors-1)
	c := HSVA{V: val, S: sat, A: alpha}
	for i := range p {
		c.H = float64(start) + float64(i)*hd
		p[i] = color.NRGBAModel.Convert(c)
	}

	return p
}

// Heat returns a red to yellow palette with the specified number of colors and alpha.
func Heat(colors int, alpha float64) Palette {
	p := make(palette, colors)
	j := colors / 4
	i := colors - j

	hd := float64(Yellow-Red) / float64(i-1)
	c := HSVA{V: 1, S: 1, A: alpha}
	for k := range p[:i] {
		c.H = float64(Red) + float64(k)*hd
		p[k] = color.NRGBAModel.Convert(c)
	}
	if j == 0 {
		return p
	}

	c.H = float64(Yellow)
	start, end := 1-1/(2*float64(j)), 1/(2*float64(j))
	c.S = start
	sd := (end - start) / float64(j-1)
	for k := range p[i:] {
		c.S = start + float64(k)*sd
		p[k+i] = color.NRGBAModel.Convert(c)
	}

	return p
}

// Radial return a diverging palette across the specified range, through white and with
// the specified alpha.
func Radial(colors int, start, end Hue, alpha float64) DivergingPalette {
	p := make(divergingPalette, colors)
	h := colors / 2
	c := HSVA{V: 1, A: alpha}
	ds := 0.5 / float64(h)
	for i := range p[:h] {
		c.H = float64(start)
		c.S = 0.5 - float64(i)*ds
		p[i] = color.NRGBAModel.Convert(c)
		c.H = float64(end)
		p[len(p)-1-i] = color.NRGBAModel.Convert(c)
	}
	if colors%2 != 0 {
		p[colors/2] = color.NRGBA{0xff, 0xff, 0xff, byte(math.MaxUint8 * alpha)}
	}

	return p
}