solution_156.py

#!/usr/bin/python3
# ====================================================================
# create an animated GIF file
# ====================================================================

import math
from PIL import Image, ImageDraw

# --------------------------------------------------------------------
# ---- convert x,y Cartesian coordinates to image coordinates
# ---- Cartesian coordinate's origin is in the center of the image
# --------------------------------------------------------------------

def coord_convert(cx,cy,image_size):

    wx = image_size[0]/2 + cx
    wy = image_size[1]/2 - cy

    return (wx,wy)

# --------------------------------------------------------------------
# create a new image for the GIF
# --------------------------------------------------------------------

def new_image(angle,radius,image_size):

    # ---- new image
    
    image = Image.new('RGB', image_size, 'white')
    
    # ---- create a draw object
    
    draw = ImageDraw.Draw(image)

    # ---- draw x axis

    xy = (0,image_size[1]/2,image_size[0],image_size[1]/2)

    draw.line(xy,fill='black',width=2)

    # ---- draw y axis

    xy = (image_size[0]/2,0,image_size[0]/2,image_size[1])

    draw.line(xy,fill='black',width=2)
        
    # ---- draw a circle (x1 <= x2 and y1 <= y2)

    x1,y1 = coord_convert(-radius,radius,image_size)
    x2,y2 = coord_convert(radius,-radius,image_size)
    xy = (x1,y1,x2,y2)
    ##print(xy)
 
    draw.ellipse(xy,
                 outline='black',
                 fill=None,
                 width=3)

    # ---- draw the point on the circle and
    # ---- perpendicular lines to the axes
    
    rad = math.radians(angle)    
    x = raidus * math.cos(rad)
    y = raidus * math.sin(rad)

    # ---- draw horizontal line

    wx1,wy1 = coord_convert(0,y,image_size)
    wx2,wy2 = coord_convert(x,y,image_size)
    xy = (wx1,wy1,wx2,wy2)

    color = 'black'   
    if x < 0: color = 'red'
    
    draw.line(xy,fill=color,width=2)

    # ---- draw vertical line

    wx1,wy1 = coord_convert(x,0,image_size)
    wx2,wy2 = coord_convert(x,y,image_size)
    xy = (wx1,wy1,wx2,wy2)

    color = 'black'   
    if y < 0: color = 'red'

    draw.line(xy,fill=color,width=2)

    # ---- draw dot on the circle
    
    wx,wy = coord_convert(x,y,image_size)
    xy = (wx-6,wy-6,wx+6,wy+6)    
    draw.ellipse(xy,
                 outline='black',
                 fill='black',
                 width=0)

    return image

# --------------------------------------------------------------------
# ---- make animated GIF with multiple images
# --------------------------------------------------------------------

def make_gif(raidus,image_size,file_name):

    c      = 0
    frames = []

    # ---- create and image for each angle in the loop
    
    for angle in range(0,360,5):
        c += 1
        frames.append(new_image(angle,raidus,image_size))

    # ---- collect the images into a GIF

    frame_one = frames[0]
    frame_one.save(file_name,format='GIF',
                   append_images=frames[1:len(frames)],
                   save_all=True, duration=200, loop=0)

    # ---- return the image count in the GIF
    
    return c

# --------------------------------------------------------------------
# ---- main
# --------------------------------------------------------------------

if __name__ == "__main__":

    raidus     = 300.0
    image_size = (800,800)
    file_name  = './gif-images/circle.gif'

    c = make_gif(raidus,image_size,file_name)

    print()
    print(f'{c} images in GIF file {file_name}')