solution_117_7b.py

#!/usr/bin/python3
# ====================================================================
# Plot sine function with an offset origin
#
# An offset origin means the origin for the working X,Y coordinates
# is not in the center of the graphics window. The origin offset is
# specified as pixels from the left side of the graphics window
# (Xoffset) and from the bottom of the graphics window (Yoffset).
# Working (cartesian) coordinates must be converted to window
# coordinate for drawing.
#
#      window coordinates       working (cartesian) coordinates
#
#       0,0                            +Y
#        +--------- +X                  |
#        |                              |
#        |                              |
#        |                              +------- +X
#       +Y                              0,0
#
# ====================================================================

import numpy as np
import graphics as gr

# --------------------------------------------------------------------
# ---- sine func
# --------------------------------------------------------------------

def sine_func(deg):
    rad = np.deg2rad(deg)
    y = np.sin(rad)
    return y

# --------------------------------------------------------------------
# ---- range function for floats
# --------------------------------------------------------------------

def frange(start,end,inc):
    while start < end:
        yield start
        start += inc

# --------------------------------------------------------------------
# ---- given working (cartesian) coordinates, calculate the offset
# ---- origin window coordinates. returned coordinates are integers.
# --------------------------------------------------------------------

def offset_xy(win,xoffset,yoffset,x,y):

    ##print(f'offset_xy({xoffset},{yoffset},{x},{y})')

    wx = round(x + xoffset)
    wy = round(win.height - y - yoffset)

    ##print(f'offset_xy returned x={wx}, y={wy}')
    
    return (wx,wy)    


# --------------------------------------------------------------------
# ---- draw X,Y offset axes
# --------------------------------------------------------------------

def draw_xy_offset_axes(win,xoffset,yoffset,linewidth=1,linecolor="black"):

    # ---- window coordinates for offset origin

    wx,wy = offset_xy(win,xoffset,yoffset,0,0)

    # ---- X axis

    xl = gr.Line(gr.Point(0,wy),gr.Point(win.width-1,wy))
    xl.setWidth(linewidth)
    xl.setFill(linecolor)
    xl.draw(win)

    # ---- Y axis

    yl = gr.Line(gr.Point(wx,0),gr.Point(wx,win.height-1))
    yl.setWidth(linewidth)
    yl.setFill(linecolor)
    yl.draw(win)        

# --------------------------------------------------------------------
# ---- draw a point (small circle) using window coordinates
# --------------------------------------------------------------------

def draw_point(wx,wy,color='red',size=4):
    p = gr.Circle(gr.Point(wx,wy),size)
    p.setFill(color)
    p.setOutline('black')
    p.draw(win)
    return p


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

if __name__ == '__main__':

    # ---- graphics window size

    window_height = 801
    window_width  = 801

    # ---- offset origin in window coordinates

    ##xoffset = 400     # origin in center of graphics window
    ##yoffset = 400     # origin in center of graphics window
    ##xoffset = 600     # origin in upper right of graphics window
    ##yoffset = 600     # origin in upper right of graphics window
    xoffset = 100       # origin in lower left of graphics window
    yoffset = 300       # origin in lower left of graphics window

    # ---- setup graphics window

    win = gr.GraphWin('Sine Function w/ Offset Origin',
                      window_width,window_height)
    win.setBackground("white")

    # ---- draw X,Y axes offset

    draw_xy_offset_axes(win,xoffset,yoffset)

    # ---- plot sine function
    # ---- X scale factor 0.5
    # ---- Y scale factor 100

    xmin = win.width
    xmax = 0
    ymin = win.height
    ymax = 0

    for deg in range(-720,721,18):
        y = sine_func(deg)
        x = deg * .5
        y = y * 100
        wx,wy = offset_xy(win,xoffset,yoffset,x,y)
        draw_point(wx,wy)

        if wx < xmin:
            xmin = wx
        if wx > xmax:
            xmax = wx

        if wy < ymin:
            ymin = wy
        if wy > ymax:
            ymax = wy
        
    print(f'Xmin = {xmin}  Xmax = {xmax}')
    print(f'Ymin = {ymin}  Ymax = {ymax}')

    # ---- pause program (click in window to continue)

    click = win.getMouse()
    win.close()