Tuesday, April 3, 2018

Cardioid on Hula Hoop

My husband, Link, and I just moved into a new house. It is significantly bigger than our previous place and there were lots of blank walls to fill. I wanted to create a piece for this one section of blank wall in our living room. We mostly have photos and paintings in the room, so I wanted to make something more 3-dimensional and tactile. I had this idea of doing something mathematical with string art. I toyed with the idea of building a set of triangular frames and doing envelopes of parabolas, but found this picture of a computer generated envelope of a cardioid on Pinterest. It seemed really interesting so I dug a little deeper.

Planning

So, according to wikipedia, if you have n points around a circle and you connect every point p to 2*p (mod n), you will create an envelope of a cardioid. (somewhat off topic, but if you switch it to 3*p or m*p, you get m-1 cusps in your curve. More info below). I figured this would make some good string art, but I didn't want to use a different piece of string for every chord. I wanted to use a couple pieces and get as many chords in sequence as I could. I ended up writing a python script (included at bottom of post) using turtle draw to create pictures on n points generating cycles rather than just knowing which two points to connect.
For example, if you have 10 points, you would want the first cycle to be (1, 2, 4, 8, 6, 2) since 8*2 = 16 = 6 mod 10. it ends at 2 since you would continue in a cycle from there. As you see though, we have a problem. Some points are not covered. What about 3? What about 10 (though we will call this 0). We should go back and start again at 3. The next grouping would be (3, 6) We end here since 6 was already covered and we would just loop back into the original cycle. Next we start at 5 since it is the smallest point not yet hit. We get the next grouping to be (5, 0) since 5*2 = 10 = 0 mod 10. If you continue in this manner you get the following groupings and picture:

(1, 2, 4, 8, 6, 2), (3, 6), (5, 0), (7, 4), (9, 8)
Cardioid on 10 points
On 10 points, you don't get enough detail to see the envelope. The pictures get more detailed the more points you add. With 50 points you get the following groupings and resulting picture:

[[1, 2, 4, 8, 16, 32, 14, 28, 6, 12, 24, 48, 46, 42, 34, 18, 36, 22, 44, 38, 26, 2], [3, 6], [5, 10, 20, 40, 30, 10], [7, 14], [9, 18], [11, 22], [13, 26], [15, 30], [17, 34], [19, 38], [21, 42], [23, 46], [25, 0, 0], [27, 4], [29, 8], [31, 12], [33, 16], [35, 20], [37, 24], [39, 28], [41, 32], [43, 36], [45, 40], [47, 44], [49, 48], [50, 0]]
Much better! However, if you see the groupings you will notice that there are a lot of groupings of just two points, meaning they define only one chord. I wanted to lengthen the groupings. Either have just one large cycle or lots of medium sized ones. After testing out a few numbers I arrived at 75 points. You get the following groupings and resulting picture:


[[1, 2, 4, 8, 16, 32, 64, 55, 37, 1], [3, 6, 12, 24, 48, 23, 46, 19, 38, 3], [5, 10, 20, 40, 7, 14, 28, 56, 39, 5], [9, 18, 36, 72, 71, 69, 65, 57, 41, 9], [11, 22, 44, 15, 30, 60, 47, 21, 42, 11], [13, 26, 52, 31, 62, 51, 29, 58, 43, 13], [17, 34, 68, 63, 53, 33, 66, 59, 45, 17], [25, 50, 27, 54, 35, 70, 67, 61, 49, 25], [73, 0, 0]]

I decided on this one since the groupings are all equally sized. There are 8 groupings, enough for each color of the rainbow (ROYGBIV) and one silver. Now that I had the plan, it was on to making this thing!

Making

I wanted something large and I did NOT want to spend a lot of time cutting down and finishing wood, either as a board with a circle of nails or a wooden hoop. So I decided to buy a hula hoop and put nails in around the outside. I wasn't 100% sure this would work since I have never hammered nails into a hula hoop before, but it was worth a shot!

It did end up working out. I measured the circumference of the hoop and divided it by 73. I think I should have been more careful about how I measured the circumference or how I marked out the nails because I ended up with 74 nails in there somehow. It didn't really matter in the end, but if I were to do it again, I would be more careful. Anyway, I marked out my points and began hammering.
As you can see, the hoop I got was not a perfect torus. It was whatever Target had. I liked the metallic color and thought it would go well with the rainbow theme. I also ended up angling the nails so they would disappear a bit when the hoop was hanging up. It also made it easier to loop the string.

Here are some pics of the process:

All ready for the string!
First grouping in red, am I doing this wrong?
Four groupings and you can start to see it
One more to go!
All done!

What happens if you multiply by something other than 2?

When I was writing my program, I was wondering why multiplying by 2 would give you this cardioid and what happens if you multiply by something else? Well here are images on 100 points of different multipliers.
p -> 2p mod n

p -> 3p mod n

p -> 4p mod n

p -> 5p mod n

But why does this work?

Ah, that is the question...
The proof for the Cardioid requires a bit of unit circle trig, but its definitely worth working through on your own. Can you generalize to the other multipliers?

How does this relate to Group Theory?

Also a good question. You are probably thinking, are these subgroups? Why do some numbers generate long strings of groupings and others short ones? Are these orbits under a group action?
Probably orbits, definitely not always subgroups. Might have some quotients in relatively prime situations. I would have to go back to Dummit & Foote to answer for sure. It has been too long...
If you know enough math to even be asking this question, you know enough to answer it for yourself.

Python Code


import turtle 
import math 

RADIUS = 300 

num_points = int(input("How many points?")) 
factor = int(input("What factor?")) 

#generate points list 
points = [] theta = 2 * math.pi / (num_points) 
for i in range(num_points): 
    points.append((RADIUS * math.cos(i * theta), RADIUS * math.sin(i * theta))) 
    #generate drawing sequences 
    sequences = [[1]] 
    finished = False 
    while not finished: 
        # do the appending
        sequences[-1].append((sequences[-1][-1] * factor) % (num_points)) 
        # check if current value is redundant 
        redundant = False 
        for sequence in sequences[:(len(sequences) - 1)]:
            if sequences[-1][-1] in sequence: 
                redundant = True 
                break 
        if sequences[-1][-1] in sequences[-1][:(len(sequences[-1]) - 1)]:
            redundant = True 
        if redundant: 
            finished = True 
            for i in range(1, num_points + 1): 
                new_num = True 
                for sequence in sequences: 
                    if i in sequence: 
                        new_num = False 
                if new_num: sequences.append([i]) 
                    finished = False 
                    break 
print(sequences)  
sheldon = turtle.Turtle() 
sheldon.speed(0) 
win = turtle.Screen() 
for sequence in sequences: 
    sheldon.pu() 
    sheldon.goto(points[sequence[0] - 1]) 
    sheldon.pd() 
    for index in sequence: 
        sheldon.goto(points[index - 1]) 
    sheldon.pu() 

win.exitonclick()