Move a circle along the circumference of another circle

circlesgeometrylinear algebra

I am trying to make a simple program to just move a circle around another circle.

The circle starts from the right side of the bigger circle and moves upwards.

See: https://i.sstatic.net/1HFpm.jpg

I tried doing that by just moving it 1 pixel at a time, so circle.move(-x, -y) where $x = y = 1$. That didn't work because the circle was doing a linear movement, while I wanted it to follow the curvature of the main circle.

I am using Python and the graphics.py library to do the animation.
This is the linear movement I was talking about. This is 90 loops because the secondary circle is moving 90 degrees.

See animation: https://gfycat.com/anothergrippingheifer

Here is my code:

import numpy as np
from graphics import *


def main():
    width = 500
    height = 500
    win = GraphWin("Main", width, height, autoflush=False)
    win.setBackground(color_rgb(255, 255, 255))

    main_rad = 100
    main_circle = Circle(Point(width//2, height//2), main_rad)
    main_circle.setFill(color_rgb(255, 0, 0))
    main_circle.setWidth(3)
    main_circle.draw(win)

    sec_rad = main_rad // 2
    sec_circleX = main_circle.getCenter().getX() + main_rad + sec_rad
    sec_circleY = main_circle.getCenter().getY()
    sec_circle = Circle(Point(sec_circleX, sec_circleY), sec_rad)
    sec_circle.setFill(color_rgb(80, 135, 230))
    sec_circle.setWidth(3)
    sec_circle.draw(win)

    x = 1
    y = 1
    for i in range(90):
        sec_circle.move(-x, -y)  # Moves the center of the circle by the given amount
        update(30)

    win.getMouse()  # Just to view the window

if __name__ == "__main__":
    main()

I don't know how to approach this problem and some answers that I saw where a bit complicated, or not well explained.
I don't know what to tag this because I don't have a lot of math knowledge.

Best Answer

I suggest you alter the last half of the program to look something like this (I have not tested this code; it's written off the top of my head):

    sec_rad = main_rad // 2
    big_rad = main_rad + sec_rad
   
    sec_circle = Circle(Point(0,0), 0)
    for i in range(90):
        sec_circle.undraw(win)
        c = cos(i * 3.14159/180)
        s = sin(i * 3.14159/180)

        sec_circleX = main_circle.getCenter().getX() + big_rad * c
        sec_circleY = main_circle.getCenter().getY() + big_rad * s
        sec_circle.setFill(color_rgb(80, 135, 230))
        sec_circle.setWidth(3) 
        sec_circle.draw(win)
        update(30)

NB: the line sec_circle.setWidth(3) seems wrong to me; I'd think it would be sec_circle.setWidth(sec_rad * 2), since the width of a circle is twice its radius, but I may be misunderstanding your intent here.

There are three main ideas here.

  1. Repeatedly "moving" objects amounts to computing sums, and in most programming languages, $\frac{1}{3} + \frac{1}{3} + \frac{1}{3} \ne 1$, so it's better to just approximately compute the value you want once and then throw it away, rather than reusing both it, and the error it entails

  2. If you want the object to move at a constant speed, the angle from the center of the big circle to the center of the small circle needs to grow at a constant rate. (A lot of people would use the name theta or t where you've used i for this very reason --- the angle you're using is represented by i.

  3. To avoid the problem of accumulating errors, you need to destroy and recreate your circle-object's existence in the window, because this library's design is perhaps not so great(*). So we're using "undraw" and then "draw" within the loop. That's ugly, but it's what needs to be done. To make it work, sec_circle has to be defined before we enter the loop, so we make a bogus circle just before the loop simply so that when we call "undraw", we don't get an error. Sigh.

(*) When I say that the design is "not so great," I mean "as a graphics library" not "as a teaching tool." It may actually serve the author well as a teaching tool, which seems to be where it arose. You may think I'm talking through my hat about whether it's a good library or not, and I'm sure smart people would be happy to debate me. But I am an author of one of the standard computer graphics texts, and have been doing computer graphics of one kind or another since about 1975. Nearly a half-century of experience has taught me a lot of lessons. Take my opinion for what it's worth.

Related Question