To rephrase a spirograph code into a function

I am writing a spirograph program in python, and I need help converting part of it into a function. The code is trying to reproduce the result illustrated in the video I found here . One line rotates around the origin, and then another rotates from the end, etc.

With a bit of research in trigonometry, I think I put together the rotate(point, angle, center=(0, 0)) function rotate(point, angle, center=(0, 0)) . The user enters a rotating point, an angle (clockwise) to be rotated, and a center point to rotate it around.

Then I performed an initial test whereby one line rotates around another. The end of the second line is drawn as if he is holding a pen. The code is a little dirty, but it looks like this.

 x, y = 0, 0 lines = [] while 1: point1 = rotate((0,50), x) point2 = map(sum,zip(rotate((0, 50), y), point1)) if x == 0: oldpoint2 = point2 else: canvas.create_line(oldpoint2[0], oldpoint2[1], point2[0], point2[1]) lines.append( canvas.create_line(0, 0, point1[0], point1[1]) ) lines.append( canvas.create_line(point1[0], point1[1], point2[0], point2[1]) ) oldpoint2 = point2 tk.update() x += 5 if x > 360 and y > 360: x -= 360 canvas.delete("all") time.sleep(1) y += 8.8 if y > 360: y -= 360 for line in lines: canvas.delete(line) lines = [] 

Great, works great. My ultimate goal is what is in the video. In the video, the user can enter any arbitrary number of hands, and then determine the length and angular speed for each hand. Mine works with only two hands. In the end, my question is how to put the code I entered into a function that looks like drawSpiral(arms, lenlist, velocitylist) . It requires the number of weapons, a list of speeds for each arm, and a list of the lengths of each arm as arguments.

What i tried

I have already tried several times to do this. At first, I had something that didn't work at all. I got some cool shapes, but definitely not the desired result. I worked for several hours, and the closest I could get was:

 def drawSpiral(arms, lenlist, velocitylist): if not arms == len(lenlist) == len(velocitylist): raise ValueError("The lists don't match the provided number of arms") iteration = 0 while 1: tk.update() iteration += 1 #Empty the list of points pointlist = [] pointlist.append((0, 0)) #Create a list of the final rotation degrees for each point rotations = [] for vel in velocitylist: rotations.append(vel*iteration) for n in range(arms): point = tuple(map(sum,zip(rotate((0, lenlist[n]), rotations[n], pointlist[n])))) pointlist.append(point) for point in pointlist: create_point(point) for n in range(arms): print pointlist[n], pointlist[n+1] 

This is pretty close to my decision, I feel, but not quite there. The drawSpiral(2, [50, 75], [1, 5]) call drawSpiral(2, [50, 75], [1, 5]) looks like it can create some correct points, but not bind the correct sets. Looking at him for about an hour and trying several things, I have not made any progress. I am also quite confused looking at my own code. I am stuck! A point rotating around the center is attached to a point that simply flies diagonally across the screen and back. A line attached to the center stretches back and forth. Can someone point me in the right direction?

Further Test Results

I set both functions to plot points at the ends of each arm and found some interesting results. The first lever in both cases rotates at a speed of 5, and the second at a speed of -3. The loop, outside the function, creates a pattern: Loop's result

The function called with drawSpiral(2, [50, 50], [5, -3]) produces the result Function's result

He seems to be stretching the upper half. With both arrows having a speed of 5, it is expected that the function will create two circles, one larger than the other. However, it creates an inverted cardioid shape with a point connected to the center. enter image description here

Now there is more evidence, can anyone who understands math more than me help me?

+6
source share
1 answer

Your mistake is in

  for n in range(arms): point = tuple(map(sum,zip(rotate((0, lenlist[n]), rotations[n], pointlist[n])))) pointlist.append(point) 

In particular,

 rotate((0, lenlist[n]) 

replace it with

  for n in range(arms): point = tuple(map(sum,zip(rotate((pointlist[n][0], lenlist[n]), rotations[n], pointlist[n])))) pointlist.append(point) 

You go against the usual mathematical notation for polar explorers (circular graphs), which caused your confusion and possible problems. As far as I can tell, your function is to build the point (X, Y) (0, length), and then find the difference between this point and the center point (which is correctly identified as the last point you found) and rotating around it is the center. The problem is that (0, length) is not "length" from the center. Replacing (0, lenlist [n]) with (pointlist [n] [0], lenlist [n]), the next point is based on the last point.

I would also recommend editing a rotating function that will rotate (length, angle, center point), which will simplify input to a more traditional representation.

+1
source

Source: https://habr.com/ru/post/986872/


All Articles