Title: Draw colorful butterfly curves in Python
My post Draw butterfly curves with different periods in Python explains how to draw a butterfly curve. It lets you enter the number of multiples of t the program should use to draw part or all of the curve.
This example draws the curve in colored pieces.
Drawing the Curve
The draw_curve method generates the curve's points the same way it did in the previous post. The interesting part is how it beaks the points into sub-curves that it then draws in different colors.
The following code shows the draw_curve method with the modified code highlighted in blue.
import itertools
...
def draw_curve(self):
'''Draw the butterfly curve.'''
# Generate the points.
period = float(self.period_var.get())
num_points = 5000
dt = period * math.pi / num_points
points = [get_point(i * dt) for i in range(num_points)]
# Transform to fit the canvas.
self.canvas.update()
wid = self.canvas.winfo_width()
hgt = self.canvas.winfo_height()
margin = 5
target_rect = (margin, margin, wid - margin, hgt - margin)
points = transform_points(points, target_rect)
# Divide the points into num_colors batches.
colors = [
'purple', 'mediumpurple', 'blue', 'royalblue', 'deepskyblue',
'cyan', 'lightseagreen', 'green', 'lime', 'springgreen',
'yellowgreen', 'olivedrab', 'yellow', 'gold', 'goldenrod',
'orange', 'darkorange', 'tomato', 'red', 'crimson', 'deeppink',
'magenta', 'orchid', 'violet'
]
num_colors = len(colors)
batch_size = num_points // num_colors + 1
polylines = list(itertools.batched(points, batch_size))
# Draw.
self.canvas.delete(tk.ALL)
for i, points in enumerate(polylines):
self.canvas.create_line(points, fill=colors[i])
The code generates the points and then transforms them to fit on the drawing canvas as before. It then defines a list of colors.
Next, the code calculates batch_size, the number of points that should receive each color. It sets that value to one more than the total number of points divided by the number of colors. The + 1 is there to ensure the points are divided into at most num_colors batches. If the number of colors doesn't divide evenly into the number of points, the calculation num_points // num_colors truncates the result so we would end up with num_colors + 1 batches and that would cause problems when we try to access colors[num_colors].
Having calculated the batch size, the code calls itertools.batched to break the list of points into batches. It then enumerates the batches and draws each in a different color.
Conclusion
There are other ways you could color the butterfly. For example, you could switch colors every time t passes a multiple of π. That wouldn't change the result if you draw the whole curve because the example uses 24 colors and the curve's period is 24 π. It would make a difference for other t ranges. For example, the picture on the right shows the curve when t ranges from 0 to 2 π. That curve uses all 24 colors despite the fact that t covers a smaller range of values.
It might be interesting to fill the curve with translucent colors, but tkinter doesn't work well with translucency so it would require some extra work. Perhaps I'll get to it someday.
Meanwhile, download the example to experiment with it and to see additional details.
|