Beauty of Mathematical Curiousity

Once there was a girl who thought math was pretty, and wanted to program her own games. This is her story.

Unfortunatly for her, one of her setbacks was impatience.

In this story, I lay the groundwork for a brighter tomorrow. I have prepared a basic home for my thoughts, and filled it with bright, cheery colors which hopefully don't look too awful. I have neglected spell checking, but everything looks okay. If I've misspelled something please correct me. I don't approve of careless spelling errors any more than lazy capitalization and punctuation.

I've been working through a few different tutorials found from pygame.org. A link somewhere led me to this blog tutorial. One of the pluses of this particular tutorial is that it has exercises - suggestions to improve your code that require figuring it out yourself.

The exercise that caught my attention was to draw this pattern to the screen:

the original challenge - to simply recreate this pattern using a single line in a for loop

After staring at it for a few minutes, I still couldn't recognize the pattern. That's frustrating by itself, but I also knew I'd seen it before. I think a larger picture would have helped, but what can you do? Shane looked over and saw the relationship much more quickly, so he had to explain it to me. After that, I could play and tweak the pattern to suit my whims. So here I'll describe how I made the pattern, and variations of it.

Here is a larger image with fewer lines, which I generated to help show the mathematical relationship. a display to make the challenge more clear, larger with fewer lines

It is relatively simple once you spot it:

Now for some code. First, the framework. I'll be changing the code up from my original code a bit, but I'll test it as I go.

import pygame, sys

w=800 # width of the screen
h=800 # height
screen = pygame.display.set_mode((w,h))

# I like to have basic colors predefined
white = (255,255,255)
black = (0,0,0)

# since we are producing a static image, just draw to the screen once.
screen.fill(black)
pygame.display.flip()

# main loop - close the window properly
while True:
  for event in pygame.event.get():
    if event.type == pygame.QUIT: sys.exit(0)
This creates a very exciting 800x800 window filled with black. The only user interaction is to close the window. This Framework (or something very similar) is what all my pygame programs look like so far, since I'm still learning the basics myself.

Next I'm going to draw some lines. Since there's a simple relationship between the start and end points of a line, and each line start is evenly spaced, the situation screams for a function and a for loop. I mean function in the mathematical sense, although it could be implemented in code just as well. I'm only going to present the code that changed. I've added some additional variables to keep track of handy values, and a loop which draws the lines. Place it all between the python.fill(black) and pygame.display.flip() and you're home free. For slightly better organization, place the variables above any of the drawing code.

N = 10 # this is the number of lines to draw (actually, it draws N-1)
dx = w/N # this is the horizontal pixel offset (the number of pixels between each line, give or take one pixel)
dy = h/N # the same for vertical offset
for i in range(1,N): # loop over the line number
  pygame.draw.aaline(screen,white, (0,i*dy), (w-i*dx,0)) # express the simple relationship between the line number and its position
Now this code will create the image above (the second shown), which uses only a few lines and a large screen to show the pattern in the line positions. From here on out, I'll probably be using N = 20 and a screen size of 400x400.

Notice that you'll get the same effect if you just set dx and dy to the same value. There's a good reason not to do this though - because then I can't have the pattern scale if I choose a window that is not square (like 600x400). Here is the difference between scaling it for just the y value, and scaling it for both values. You'll see something different if you scale it for the larger value instead - it will look like it is scaled for a 600x600 square, and simply cropped.
A skewed rectangle using the same value for dx and dy

If you run this, and play around with the values N,w, and h, you will find you can create very delicate looking images, or something more course looking.
the basic pattern using 10 lines the basic pattern using 20 lines the basic pattern using 50 lines

On with the challenge: the goal is to repeat this pattern at all four corners (overlapping). We'll use four calls to python.draw.aaline in the for loop, one for each corner. We only need to add the three lines:

    pygame.draw.aaline(screen, white, (0,i*dy), (w-i*dx,0)) # top left
    pygame.draw.aaline(screen, white, (w,h-i*dy), (i*dx,h)) # bottom right
    pygame.draw.aaline(screen, white, (0,i*dy), (i*dx,h)) # bottom left
    pygame.draw.aaline(screen, white, (w,h-i*dy), (w-i*dx,0)) # top right
My original code was slightly different. The last two lines used the points (0,h-i*dy), (w-i*dx,h) and (w,h-i*dy), (i*dx,0) respectively. The only change this makes is if the lines were drawn one at a time, the order they are placed would be opposite (in fact, I may do this a bit later - if I feel like it. If not, feel free to do so yourself. There is a lesson here: there is more than one way to get the exact same effect. There is a reason I changed it, which I'll point out later. Another inconsequential varient: it does not matter which point is first or last in the line. For the top left pattern, (w-i*dx,0), (0,i*dy) is the same. a white pattern repeated in each corner

There are some cool varients on this as well. I like drawing just two of the four corners. Opposite corners and adjacent corners look very differnt patterns. Another interesting one is if you accidently (or purposely) mix up some of the positions. For example, the bottom left corner can be switched from (0,i*dy) (i*dx,h)to use (0,i*dy) (w-i*dx,h), a pattern which appears much more linear than the original. Just for fun, I also overlapped the original "curvy" image and the linear image, using all four corners. Quite complicated looking, but build from a single, simple idea.
the pattern repeated on two opposing corners the pattern repeated on two adjacent corners
a linear pattern (shown in one corner only), the result of a small change a layered pattern which appears very complex but is built on the same simple idea as all the other patterns

There are more variations of this. What about color?

the pattern in the top left corner fades from yellow to white
Color can be varied just as easily as position. Let's try it. Add a delta for color (which can range from 0 to 255): dc = 255/N. Add color = (255,255,255-i*dc) to the for loop, and change the line from using "white" to "color". To reverse the light and dark side of the pattern, use i*dc instead of 255-i*dc. Now for the reason I changed the order the lines were drawn in for two of the colors: when you draw all four colors, you now get this pretty display:
fading oclor applied to all four corners, with white overlapping yellow
If I had not reordered the lines, I would have gotten this one instead:
fading color applied to all four corners, with yellow overlapping yellow and white overlapping white
This second image can be achieved by either changing the line order as mentioned above, or adding an additional color alt = (255,255,i*c), and using this new color with the top right and bottom left. Once again, many ways for the same result. As a last touch for now, here's the same colors used with the linear pattern:
a linear pattern on all four corners add a touch of color to the linear pattern

Labels: , , , ,

1 comments.
Leave one.
Comments
# Blogger Chrissy Delk (Sunday, February 8, 2009 at 10:34:00 PM MST)
Unfortunatly = Unfortunately
Top of the blog, but what can I say. This is why firefox rocks my socks. It underlines the words I misspell.

Other than that, I like your shiny pictures. I am an art student. That is the extent of my ability to say anything about anything.

Oh yes, and the green of your blog? Hard to read the text on my screen. Darker/more neutral would help.

THE END  

Post a Comment