We make a version of the artist's color wheel which shows how any known color and shade of color can be obtained by judicious mixing of the three primary colors of red, green and blue.
We have made a set of twelve color lists. Each list represents the color that results when you mix colors on either side of it, except for the primary colors of red, green, and blue. The other critical addition to the code is the function rotate(xya, xyb, theta_deg_incr)
that is used to rotate the color wedge pattern to a new chosen position around a central point. As some trigonometry is used to do the rotation, the math module needs to be imported at the top of the code. Each segment forms part of the complete circle of color variations. The following screenshot shows a version of Isaac Newton's Color Wheel.
# primary_color_wheel_1.py #>>>>>>>>>>>>>>>>>>>>> from Tkinter import * import math root = Tk() root.title("Color wheel segments") cw = 400 # canvas width ch = 400 # canvas height chart_1 = Canvas(root, width=cw, height=ch, background="black") chart_1.grid(row=0, column=0) theta_deg = 0.0 color mixingx_orig = 200 y_orig = 200 x_width = 40 y_hite = 160 xy0 = [x_orig, y_orig] xy1 = [x_orig - x_width, y_orig - y_hite] xy2 = [x_orig + x_width, y_orig - y_hite ] wedge =[ xy0, xy1 , xy2 ] width= 40 #standard disk diameter hite = 80 # median wedge height. hFac = [0.25, 0.45, 0.75, 1.2, 1.63, 1.87, 2.05] # Radial # factors wFac = [ 0.2, 0.36, 0.6, 1.0, 0.5, 0.3, 0.25] # disk # diameter factors x_DiskRot = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] # rotational coordinates y_DiskRot = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0] #RED kulaRed = ["#000000", "#6e0000", "#a00000", "#ff0000", "#ff5050", "#ff8c8c", "#ffc8c8", "#440000" ] # Khaki kulaRRedGreen = ["#000000", "#606000", "#8f9f00", "#b3b300", "#d6d600", "#dbdb30", "#dbdb77", "#3e2700" ] # Yellow kulaRedGreen = ["#000000", "#6e6e00", "#a0a000", "#ffff00", "#ffff50", "#ffff8c", "#ffffc8", "#444400" ] # Orange kulaRedGGreen = ["#000000", "#493100", "#692f00", "#a25d00", "#ff8300", "#ffa55a", "#ffb681", "#303030" ] # Green kulaGreen = ["#000000", "#006e00", "#00a000", "#00ff00", "#50ff50", "#8cff8c", "#c8ffc8", "#004400" ] # Dark green kulaGGreenBlue = ["#000000", "#003227", "#009358", "#00a141", "#00ff76", "#72ff99", "#acffbf", "#003a1d" ] # Cyan kulaGreenBlue = ["#000000", "#006e6e", "#00a0a0", "#00ffff", "#50ffff", "#8cffff", "#c8ffff", "#004444" ] # Steel Blue kulaGreenBBlue = ["#000000", "#002c46", "#00639c", "#008cc8", "#00b6ff", "#7bb6ff", "#addfff", "#001a27" ] # Blue kulaBlue = ["#000000", "#00006e", "#0000a0", "#0000ff", "#5050ff", "#8c8cff", "#c8c8ff", "#000044" ] # Purple kulaBBlueRed = ["#000000", "#470047", "#6c00a2", "#8f00ff", "#b380ff", "#d8b3ff", "#f1deff", "#200031" ] # Crimson kulaBlueRed = ["#000000", "#6e006e", "#a000a0", "#ff00ff", "#ff50ff", "#ff8cff", "#ffc8ff", "#440044" ] # Magenta kulaBlueRRed = ["#000000", "#380023", "#80005a", "#b8007b", "#ff00a1", "#ff64c5", "#ff89ea", "#2e0018" ] # ROTATE def rotate(xya, xyb, theta_deg_incr): #xya, xyb are 2 component # points # General purpose point rotation function theta_rad = math.radians(theta_deg_incr) a_radian = math.atan2( (xyb[1] - xya[1]) , (xyb[0] - xya[0]) ) a_length = math.sqrt( (xyb[1] - xya[1])**2 + (xyb[0] - xya[0])**2) theta_rad += a_radian theta_deg = math.degrees(theta_rad) new_x = a_length * math.cos(theta_rad) new_y = a_length * math.sin(theta_rad) return new_x, new_y, theta_deg # theta_deg = post # rotation angle # GENL. SEGMENT BACKGROUND FUNCTION defsegmentBackground(kula, angle, xy1, xy2): xy_new1 = rotate(xy0, xy1, angle) # rotate xy1 xy1 =[ xy_new1[0] + xy0[0], xy_new1[1] + xy0[1] ] xy_new2 = rotate(xy0, xy2, angle) # rotate xy2 xy2 =[ xy_new2[0] + xy0[0], xy_new2[1] + xy0[1] ] wedge =[ xy0, xy1 , xy2 ] chart_1.create_polygon(wedge,fill=kula[7]) # GENL. COLOR DISKS FUNCTION defcolorDisks( kula, angle): global hite, width, hFac, wFac for i in range(0, 7): # green segment disks xya = [xy0[0], xy0[1] - hite * hFac[i] ] # position of point for # rotation xy_new1 = rotate(xy0, xya, angle) # rotate xya # NEW CIRCLE CENTERS AFTER ROTATION OF CENTERLINE x0_disk = xy_new1[0] + xy0[0] - width*wFac[i]/2 y0_disk = xy_new1[1] + xy0[1] + width * wFac[i]/2 xya = [x0_disk, y0_disk] # BOTTOM LEFT x1_disk = xy_new1[0] + xy0[0] + width*wFac[i]/2 y1_disk = xy_new1[1] + xy0[1] - width * wFac[i]/2 xyb = [x1_disk, y1_disk] #TOP RIGHT chart_1.create_oval(xya ,xyb , fill=kula[i], outline=kula[i]) for i in range(0,12): if i==0: angle = 0.0 kula = kulaRed if i==1: angle = 30.0 kula = kulaRRedGreen if i==2: angle = 60.0 kula = kulaRedGreen if i==3: angle = 90.0 kula = kulaRedGGreen if i==4: angle = 120.0 kula = kulaGreen if i==5: angle = 150.0 kula = kulaGGreenBlue if i==6: angle = 180.0 kula = kulaGreenBlue if i==7: angle = 210.0 kula = kulaGreenBBlue if i==8: angle = 240.0 kula = kulaBlue if i==9: angle = 270.0 kula = kulaBBlueRed if i==10: angle = 300.0 kula = kulaBlueRed if i==11: angle = 330.0 kula = kulaBlueRRed if i==12: angle = 360.0 kula = kulaBlueRRed segmentBackground( kula, angle, xy1, xy2) colorDisks( kula, angle) root.mainloop()
For each color segment of the wheel a list of shaded hex color values was included in the list. The exact amounts of red, green, and blue to add together for colors that require portions of all three primary colors is not a simple matter. In general, to lighten a color we need to add extra amounts of the color that doesn't even belong to the target color. For example, if we want a pale yellow we need equal amounts of red and green together. But to make the yellow paler we need to add some blue. To darken the yellow we make sure there is no blue at all and we combine smaller but equal proportions of red and blue.
Mixing colors is an art as much as a science. Astute color mixing demands practice and experimentation. Mixing colors numerically does not come naturally to the human brain. We need some visual-numerical-computational tools to help us mix colors. But the math must be invisible. It must not hamper the artist. We want the equivalent of tubes of primary colors and a palette to mix them on. Our palette must automatically display the numerical values that represent the colors we have mixed so that we can record and incorporate them into Python code. It would be cool if our palette could be placed on top of or next to portions of existing pictures so that we could match existing colors in the picture. Would that be a nice thing to have? Well, the next recipe tries to grant that wish.
3.136.18.141