File size: 3,847 Bytes
1e2f65e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import math
from color import Color

class ColorWheel:
	@property
	def base_color(self):
		return self._base_color

	@property
	def hue(self):
		return [
			self.base_color, self.add_h(1.0 / 12), self.add_h(2.0 / 12), self.add_h(3.0 / 12), self.add_h(4.0 / 12), self.add_h(5.0 / 12),
			self.add_h(-6.0 / 12), self.add_h(-5.0 / 12), self.add_h(-4.0 / 12), self.add_h(-3.0 / 12), self.add_h(-2.0 / 12), self.add_h(-1.0 / 12)
		]

	@property
	def tone(self):
		return [self.add_white(-2.0 / 16), self.add_white(-1.0 / 16), self.base_color, self.add_white(1.0 / 16), self.add_white(2.0 / 16)]

	@property
	def tone15(self):
		return [self.add_white(-7.0 / 16), self.add_white(-6.0 / 16), self.add_white(-5.0 / 16), self.add_white(-4.0 / 16), self.add_white(-3.0 / 16), 
				self.add_white(-2.0 / 16), self.add_white(-1.0 / 16), self.base_color, self.add_white(1.0 / 16), self.add_white(2.0 / 16),
				self.add_white(3.0 / 16), self.add_white(4.0 / 16), self.add_white(5.0 / 16), self.add_white(6.0 / 16), self.add_white(7.0 / 16)]

	@property
	def complementary_colors(self):
		return [self.base_color, self.add_h(0.5)]

	@property
	def triadic_colors(self):
		return [self.add_h(-4.0 / 12), self.base_color, self.add_h(4.0 / 12)]

	@property
	def split_complementary_colors(self):
		return [self.add_h(-5.0 / 12), self.base_color, self.add_h(5.0 / 12)]

	@property
	def analogous_colors(self):
		return [self.add_h(-2.0 / 12), self.add_h(-1.0 / 12), self.base_color, self.add_h(1.0 / 12), self.add_h(2.0 / 12)]

	def __init__(self, c):
		self._base_color = c
		self._r = c.r / 255.0
		self._g = c.g / 255.0
		self._b = c.b / 255.0

	@staticmethod
	def from_hsv(h, s, v):
		r, g, b = ColorWheel.hsv_to_rgb(h, s, v)
		c = Color.from_rgb(round(r * 255), round(g * 255), round(b * 255))
		return ColorWheel(c)

	def add_white(self, value):
		r, g, b = (self._r + value, self._g + value, self._b + value)
		r = min(max(r, 0.0), 1.0)
		g = min(max(g, 0.0), 1.0)
		b = min(max(b, 0.0), 1.0)
		return self._from_rgb(r, g, b)

	def add_h(self, value):
		h, s, v = ColorWheel.rgb_to_hsv(self._r, self._g, self._b)
		h = (h + value) % 1.0
		if h < 0.0:
			h += 1.0
		r, g, b = ColorWheel.hsv_to_rgb(h, s, v)
		return self._from_rgb(r, g, b)

	def add_s(self, value):
		h, s, v = ColorWheel.rgb_to_hsv(self._r, self._g, self._b)
		s += value
		s = min(max(s, 0.0), 1.0)
		r, g, b = ColorWheel.hsv_to_rgb(h, s, v)
		return self._from_rgb(r, g, b)

	def add_v(self, value):
		h, s, v = ColorWheel.rgb_to_hsv(self._r, self._g, self._b)
		v += value
		v = min(max(v, 0.0), 1.0)
		r, g, b = ColorWheel.hsv_to_rgb(h, s, v)
		return self._from_rgb(r, g, b)

	@staticmethod
	def rgb_to_hsv(r, g, b):
		if r < 0.0 or r > 1.0:
			raise ValueError()
		if g < 0.0 or g > 1.0:
			raise ValueError()
		if b < 0.0 or b > 1.0:
			raise ValueError()
		cmax = max(r, g, b)
		cmin = min(r, g, b)
		h = cmax - cmin
		if h > 0.0:
			if cmax == r:
				h = (g - b) / h
				if h < 0.0:
					h += 6.0
			elif cmax == g:
				h = 2.0 + (b - r) / h
			else:
				h = 4.0 + (r - g) / h
		h /= 6.0
		s = cmax - cmin
		if cmax != 0.0:
			s /= cmax
		v = cmax
		return h, s, v

	@staticmethod
	def hsv_to_rgb(h, s, v):
		if h < 0.0 or h > 1.0:
			raise ValueError()
		if s < 0.0 or s > 1.0:
			raise ValueError()
		if v < 0.0 or v > 1.0:
			raise ValueError()
		r = v
		g = v
		b = v
		if s > 0.0:
			h *= 6.0
			i = math.floor(h)
			f = h - i
			if i == 1:
				r *= 1 - s * f
				b *= 1 - s
			elif i == 2:
				r *= 1 - s
				b *= 1 - s * (1 - f)
			elif i == 3:
				r *= 1 - s
				g *= 1 - s * f
			elif i == 4:
				r *= 1 - s * (1 - f)
				g *= 1 - s
			elif i == 5:
				g *= 1 - s
				b *= 1 - s * f
			else:
				g *= 1 - s * (1 - f)
				b *= 1 - s
		return r, g, b

	def _from_rgb(self, r, g, b):
		return Color.from_argb(self.base_color.a, round(r * 255), round(g * 255), round(b * 255))