cs110_p1

   1## DON"T OPEN THIS FILE! USE THE PURPLE BUTTON ON THE ASSIGNMENT
   2##   to see what functions are available and what their inputs are!
   3
   4###################################################################
   5
   6## PROCEED AT YOUR OWN RISK! THERE BE DRAGONS!
   7
   8_VERSION = "2025.1.1"
   9
  10## 2025.1.1
  11# Feature: adds ability to fill the screen with the window
  12# Feature: grid - add show_label param
  13
  14###################################################################
  15### IGNORE EVERYTHING THAT STARTS WITH A _
  16from random import randint
  17from math import sqrt, pi, radians, sin, cos, floor
  18from time import sleep
  19from tkinter import Tk, Canvas
  20
  21
  22__docformat__ = "google"
  23
  24_a_canvas = None
  25_resize_enabled = False
  26
  27
  28Shape_Drawing_Functions = ""
  29
  30
  31def arc(points=[], width=5, color="hot pink", line_steps=15, tag="", ):
  32    """
  33    A reporter function that draws an arc ("curve") given a list of points.
  34    Args:
  35        points (`list`): The points outlining the curve; this should be a list of tuples (coordinates).
  36            Make sure to give it at least 3 (x,y) coordinates that aren"t a straight line!
  37        color (`str`): What color to make the shape.
  38        tag (`str`): The tag to assign to the shape.
  39
  40    Returns:
  41        `Shape`: The arc that was created.
  42    """
  43    return _a_canvas.create_line(
  44        points,
  45        width=width,
  46        fill=color,
  47        splinesteps=line_steps,
  48        smooth=True,
  49        tags=tag,
  50        ,
  51    )
  52
  53
  54def car(top_left=(0, 0), size=100, body_color="#3D9970", wheel_color="black", tag=""):
  55    """
  56    Draws a cool car.
  57
  58    Args:
  59        top_left (`tuple`): A coordinate at which to draw the car.
  60        body_color (`str`): Color to make the body of the car.
  61        wheel_color (`str`): Color to make the wheel of the car.
  62        tag (`str`): The tag to assign to the shape.
  63    """
  64    x, y = top_left
  65    rectangle((x + 5 * size / 10, y), size, size / 10 * 4, color=body_color, tag=tag)
  66    rectangle(
  67        (x, y + size - 7 * size / 10),
  68        size * 2,
  69        size / 10 * 4.5,
  70        color=body_color,
  71        tag=tag,
  72    )
  73    circle(
  74        (x + 5 * size / 10, y + size - size / 5), size / 5, color=wheel_color, tag=tag
  75    )
  76    circle(
  77        (x + 15 * size / 10, y + size - size / 5), size / 5, color=wheel_color, tag=tag
  78    )
  79
  80
  81def circle(center=(0, 0), radius=25, color="hot pink", outline="", tag="", ):
  82    """
  83    A reporter function that draws a circle.
  84    Args:
  85        center (`tuple`): A coordinate representing the center of the shape.
  86        radius (`int`): Specifies the circle"s radius.
  87        color (`str`): What color to draw the shape.
  88        outline (`str`): What color should the border of the shape be.
  89        tag (`str`): The tag to assign to the shape.
  90
  91    Returns:
  92        `Shape`: The circle that was created.
  93    """
  94    return oval(
  95        center=center, radius_x=radius, radius_y=radius, color=color, tag=tag, 
  96    )
  97
  98
  99def cloud(center=(0, 0), size=30, color="white", tag=""):
 100    """
 101    Reporter function that draws a cloud to the screen.
 102    Args:
 103        center (`tuple`): the point on which to center the cloud
 104        size (`int`): how big (roughly) the cloud is drawn
 105        color (`str`): which determines the color of the cloud
 106        tag (`str`): to give the cloud a name
 107
 108    Returns:
 109        `Shape`: The cloud that was created.
 110    """
 111    for i in range(10):
 112        x_offset = randint((-1 * size * 1.333), (size * 1.333))
 113        y_offset = randint(0, (size * 0.667))
 114        circle(
 115            center=(center[0] + x_offset, center[1] + y_offset),
 116            radius=randint((size * 0.667), (size * 1.667)),
 117            color=color,
 118            tag=tag,
 119        )
 120    return tag
 121
 122
 123def diamond(
 124    center=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 
 125):
 126    """
 127    A reporter function that draws a rectangle.
 128    Args:
 129        center (`tuple`): A coordinate representing the center of the shape.
 130        width (`int`): How wide to draw the shape.
 131        height (`int`): How tall to draw the shape.
 132        color (`str`): What color to draw the shape.
 133        outline (`str`): What color should the border of the shape be.
 134        tag (`str`): The tag to assign to the shape.
 135
 136    Returns:
 137        `Shape`: The shape that was created.
 138    """
 139    point_0 = (center[0] - width / 2, center[1])
 140    point_1 = (center[0], center[1] - height / 2)
 141    point_2 = (center[0] + width / 2, center[1])
 142    point_3 = (center[0], center[1] + height / 2)
 143    return _a_canvas.create_polygon(
 144        point_0,
 145        point_1,
 146        point_2,
 147        point_3,
 148        fill=_safe_color(color),
 149        tags=tag,
 150        outline=outline,
 151        ,
 152    )
 153
 154
 155def grid(width=None, height=None, interval=100, show_labels=True):
 156    """
 157    Draws a grid on a screen with intervals of 100.
 158
 159    Args:
 160        width (`int`): The width of the grid to draw (defaults to the whole window)
 161        height (`int`): The height of the grid to draw (defaults to the whole window)
 162        interval (`int`): The interval to draw the grid on.
 163        show_labels (`bool`): Whether or not to show coordinate labels.
 164
 165    """
 166
 167    if width is None
 168        width = get_window_width()
 169
 170    if height is None
 171        height = get_window_height()
 172
 173    # Creates all vertical lines at intervals of 100
 174    for i in range(0, width, interval):
 175        _a_canvas.create_line(i, 0, i, height, tag="grid", fill="black")
 176    # Creates all horizontal lines at intervals of 100
 177    for i in range(0, height, interval):
 178        _a_canvas.create_line(0, i, width, i, tag="grid", fill="black")
 179
 180    if show_labels
 181        # Creates axis labels
 182        offset = 2
 183        for y in range(0, height, interval):
 184            for x in range(0, width, interval):
 185                _a_canvas.create_oval(
 186                    x - offset,
 187                    y - offset,
 188                    x + offset,
 189                    y + offset,
 190                    fill="black",
 191                    tag="grid",
 192                )
 193                _a_canvas.create_text(
 194                    x + offset,
 195                    y + offset,
 196                    text="({0}, {1})".format(x, y),
 197                    anchor="nw",
 198                    font=("Purisa", 8),
 199                    fill="black",
 200                    tag="grid",
 201                )
 202
 203
 204_cache = []
 205
 206
 207def image(image_path, position=(200, 200), rotation=None, scale=None, tag="", ):
 208    """
 209    Draws a given image on the screen. NOTE: Requires the `pillow` package to be installed - contact
 210    Prof. Bain or post on edSTEM if you"d like more details!
 211
 212    Args:
 213        image_path (`str`): Location of the image file on your computer.
 214        position (`tuple`): A coordinate at which to render the image.
 215        rotation (`int`): A number of degrees to rotate the given image.
 216        scale (`int`): A scaling factor to multiply the image size by.
 217        tag (`str`): A string representing the "name" fo this shape.
 218    """
 219    # import PIL libraries
 220    from PIL import Image, ImageTk
 221
 222    anchor = "nw"
 223
 224    import os
 225
 226    # 1. create PIL image and apply any image transformations:
 227    dir_path = os.path.dirname(os.path.realpath(__file__))
 228    image_path = os.path.join(dir_path, image_path)
 229    pil_image = Image.open(image_path)
 230    if scale
 231        size = (round(pil_image.size[0] * scale), round(pil_image.size[1] * scale))
 232        pil_image = pil_image.resize(size)
 233    if rotation
 234        pil_image = pil_image.rotate(rotation)  # note: returns a copy
 235
 236    # 2. convert to tkinter-compatible image format:
 237    tkinter_image = ImageTk.PhotoImage(pil_image)
 238    _cache.append(
 239        tkinter_image
 240    )  # workaround for known tkinter bug: http://effbot.org/pyfaq/why-do-my-tkinter-images-not-appear.htm
 241
 242    # 3. draw image on canvas:
 243    _a_canvas.create_image(
 244        *position, image=tkinter_image, anchor=anchor, tags=tag, 
 245    )
 246
 247
 248def line(points=[], curvy=False, color="hot pink", tag="", ):
 249    """
 250    A reporter function that draws a line given a list of points.
 251    Args:
 252        points (`list`): The points that define the line; this should be a list of tuples (coordinates).
 253        curvy (`bool`): Makes a curvy line instead.
 254        color (`str`): What color to make the shape.
 255        tag (`str`): The tag to assign to the shape.
 256
 257    Returns:
 258        `Shape`: The line that was created.
 259    """
 260    return _a_canvas.create_line(points, fill=color, smooth=curvy, tags=tag, )
 261
 262
 263def oval(
 264    center=(0, 0),
 265    radius_x=25,
 266    radius_y=50,
 267    color="hot pink",
 268    outline="",
 269    tag="",
 270    ,
 271):
 272    """
 273    A reporter function that draws an oval.
 274    Args:
 275        center (`tuple`): A coordinate representing the center of the shape.
 276        radius_x (`int`): Specifies the oval"s radius on the x-axis.
 277        radius_y (`int`): Specifies the oval"s radius on the y-axis.
 278        color (`str`): What color to draw the shape.
 279        outline (`str`): What color should the border of the shape be.
 280        tag (`str`): The tag to assign to the shape.
 281
 282    Returns:
 283        `Shape`: The oval that was created.
 284    """
 285    x = center[0]
 286    y = center[1]
 287    x0, y0, x1, y1 = (x - radius_x, y - radius_y, x + radius_x, y + radius_y)
 288    steps = 100
 289    # major and minor axes
 290    a = (x1 - x0) / 2.0
 291    b = (y1 - y0) / 2.0
 292    # center
 293    xc = x0 + a
 294    yc = y0 + b
 295    point_list = []
 296    # create the oval as a list of points
 297    for i in range(steps):
 298        # Calculate the angle for this step
 299        theta = (pi * 2) * (float(i) / steps)
 300        x = a * cos(theta)
 301        y = b * sin(theta)
 302        point_list.append(round(x + xc))
 303        point_list.append(round(y + yc))
 304
 305    return _a_canvas.create_polygon(
 306        point_list, fill=_safe_color(color), tags=tag, 
 307    )
 308
 309
 310def pixel_art(top_left, artwork, palette, pixel=10, tag=""):
 311    """
 312    Draws a pixel art design!
 313
 314    Args:
 315        top_left (`tuple`): the top left coordinate of the pixel art
 316        artwork (sequence of sequences): the art to draw
 317        palette (sequence): the palette of colors to use for each different square
 318        pixel (`int`, optional): how big each individual pixel should be
 319        tag (`str`, optional): the tag to assign to every square in the row
 320
 321    Note: this doesn"t return anything so make sure to use a tag if you want to animate / modify.
 322    """
 323    x = top_left[0]
 324    y = top_left[1]
 325    for row in artwork
 326        # draw each row at the specified (x, y) position:
 327        _draw_row(row, (x, y), colors=palette, pixel=pixel, tag=tag)
 328        # ...and don"t forget to shift the y-value down by the proper
 329        #  amount so that the next row won"t draw on top of the first one:
 330        y += pixel
 331
 332
 333def polygon(points=[], color="hot pink", outline="", tag="", ):
 334    """
 335    A reporter function that draws a polygon given a list of points.
 336    Args:
 337        points (`list`): The points outlining the polygon; this should be a list of tuples (coordinates).
 338            defaults to an empty list.
 339        outline (`str`): What color should the border of the shape be.
 340        color (`str`): What color to make the shape.
 341
 342    Returns:
 343        `Shape`: The polygon that was created.
 344    """
 345    return _a_canvas.create_polygon(points, fill=_safe_color(color), tags=tag, )
 346
 347
 348def rectangle(
 349    top_left=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 
 350):
 351    """
 352    A reporter function that draws a rectangle.
 353    Args:
 354        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
 355        width (`int`): How wide to draw the shape.
 356        height (`int`): How tall to draw the shape.
 357        color (`str`): What color to draw the shape.
 358        outline (`str`): What color should the border of the shape be.
 359        tag (`str`): The tag to assign to the shape.
 360
 361    Returns:
 362        `Shape`: The rectangle that was created.
 363    """
 364    point_0 = top_left
 365    point_1 = (top_left[0] + width, top_left[1])
 366    point_2 = (top_left[0] + width, top_left[1] + height)
 367    point_3 = (top_left[0], top_left[1] + height)
 368    return _a_canvas.create_polygon(
 369        point_0, point_1, point_2, point_3, fill=_safe_color(color), tags=tag, 
 370    )
 371
 372
 373def spiral(
 374    center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1, 
 375):
 376    """
 377    A reporter function that draws a spiral.
 378    Args:
 379        center (`tuple`): A coordinate representing the center of the shape.
 380        width (`int`): Specifies the total width of the spiral.
 381        roughness (`float`): Controls how spiral-y the shape is (lower is less spiral-y)
 382        start (`int`): Where on the spiral to start drawing.
 383        spirals (`int`): How many loops to draw.
 384        line_width (`int`): How wide for the line to be drawn.
 385        tag (`str`): The tag to assign to the shape.
 386
 387    Returns:
 388        `Shape`: The spiral that was created.
 389    """
 390    theta = 0.0
 391    r = start
 392    all_points = []
 393    prev_pos = _polar_to_cartesian(r, theta)
 394    distance = width / 4 / pi / spirals
 395    all_points.append((prev_pos[0] + center[0], prev_pos[1] + center[1]))
 396    while theta < 2 * spirals * pi
 397        theta += roughness
 398        r = start + distance * theta
 399        pos = _polar_to_cartesian(r, theta)
 400        all_points.append((pos[0] + center[0], pos[1] + center[1]))
 401
 402    return arc(points=all_points, width=line_width, )
 403
 404
 405def square(top_left=(0, 0), size=25, color="hot pink", outline="", tag="", ):
 406    """
 407    A reporter function that draws a square.
 408    Args:
 409        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
 410        size (`int`): How big to draw the shape.
 411        color (`str`): What color to draw the shape.
 412        outline (`str`): What color should the border of the shape be.
 413        tag (`str`): The tag to assign to the shape.
 414
 415    Returns:
 416        `Shape`: The square that was created.
 417    """
 418    return rectangle(
 419        top_left=top_left, width=size, height=size, color=color, tag=tag, 
 420    )
 421
 422
 423def star(
 424    center=(0, 0),
 425    radius=50,
 426    color="hot pink",
 427    outer_radius=75,
 428    points=5,
 429    outline="",
 430    tag="",
 431    ,
 432):
 433    """
 434    A reporter function that draws a star.
 435    Args:
 436        center (`tuple`): A coordinate representing the center of the shape.
 437        radius (`int`): Specifies the radius of the inside part of the star.
 438        color (`str`): Specifies the color of the star.
 439        outer_radius (`int`): Specifies the radius of the outside part of the star.
 440        points (`int`): Specifies the number of points for the star.
 441        outline (`str`): What color should the border of the shape be.
 442        tag (`str`): The tag to assign to the shape.
 443
 444    Returns:
 445        `Shape`: The star that was created.
 446    """
 447    arc_segment = 360 / points
 448    vertices = []
 449    for i in range(points):
 450        inner_point = (
 451            radius * cos(radians(arc_segment * i)) + center[0],
 452            -1 * radius * sin(radians(arc_segment * i)) + center[1],
 453        )
 454        vertices.append(inner_point)
 455        outer_point = (
 456            outer_radius * cos(radians(arc_segment * i + arc_segment / 2)) + center[0],
 457            -1 * outer_radius * sin(radians(arc_segment * i + arc_segment / 2))
 458            + center[1],
 459        )
 460        vertices.append(outer_point)
 461    return polygon(vertices, color=color, tag=tag, )
 462
 463
 464def text(
 465    top_left=(0, 0), text="", font=("Purisa", 32), color="black", tag="", 
 466):
 467    """
 468    A reporter function that draws text to the screen
 469    Args:
 470        top_left (`tuple`): coordinate pair to specify the location.
 471        text (`str`): What text to draw.
 472        font (`tuple`): A tuple where the first element is a string for the font name and the second is an
 473           int with the font size.
 474        color (`str`): What color should the text be.
 475        tag (`str`): The name to tag this thing with.
 476
 477    Returns:
 478        `Shape`: The text that was created.
 479    """
 480    return _a_canvas.create_text(
 481        top_left, text=text, font=font, fill=color, tags=tag, 
 482    )
 483
 484
 485def triangle(
 486    bottom_center=(0, 0),
 487    width=25,
 488    top_shift=0,
 489    height=0,
 490    color="hot pink",
 491    outline="",
 492    tag="",
 493    ,
 494):
 495    """
 496    A reporter function that draws a triangle.
 497    Args:
 498        bottom_center (`tuple`): A coordinate representing the bottom center of the shape.
 499        width (`int`): Specifies the width of the base of the triangle.
 500        top_shift (`int`): Specifies the how far to the left or right to shift the top of
 501            the triangle from the bottom center.
 502        height (`int`): Specifies the triangle"s height.
 503        color (`str`): What color to draw the shape.
 504        outline (`str`): What color should the border of the shape be.
 505        tag (`str`): The tag to assign to the shape.
 506
 507    Returns:
 508        `Shape`: The triangle that was created.
 509    """
 510    if height == 0
 511        height = width * sqrt(3) / 2
 512    point_0 = (bottom_center[0] - width / 2, bottom_center[1])
 513    point_1 = (bottom_center[0] + width / 2, bottom_center[1])
 514    point_2 = (bottom_center[0] + top_shift, bottom_center[1] - height)
 515
 516    return _a_canvas.create_polygon(
 517        point_0, point_1, point_2, fill=_safe_color(color), tags=tag, 
 518    )
 519
 520
 521def wedge(
 522    center=(0, 0), radius=25, angle=180, color="hot pink", outline="", tag="", 
 523):
 524    """
 525    A reporter function that draws a circle.
 526    Args:
 527        center (`tuple`): A coordinate representing the center of the shape.
 528        radius (`int`): Specifies the circle"s radius.
 529        angle (`int`): A number between 0 and 360 that specifies how much of the circle to draw.
 530        color (`str`): What color to draw the shape.
 531        outline (`str`): What color should the border of the shape be.
 532        tag (`str`): The tag to assign to the shape.
 533
 534    Returns:
 535        `Shape`: The wedge that was created.
 536    """
 537    point_list = [center[0], center[1]]
 538    for i in range(0, 0 + angle):
 539        x1 = center[0] + radius * cos(radians(i))
 540        point_list.append(x1)
 541        y1 = center[1] + radius * sin(radians(i))
 542        point_list.append(y1)
 543
 544    point_list.append(center[0])
 545    point_list.append(center[1])
 546
 547    return _a_canvas.create_polygon(
 548        point_list, fill=_safe_color(color), outline=outline, tags=tag, 
 549    )
 550
 551
 552Shape_Modifier_Functions = ""
 553
 554
 555def above(shape1, shape2, offset_x=0, offset_y=0):
 556    """
 557    A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1"s center
 558    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
 559    specified offset.
 560
 561    Args:
 562        shape1 (`Shape` or Tag): The first shape to use.
 563        shape2 (`Shape` or Tag): The second shape to use.
 564        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
 565        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
 566
 567    Returns:
 568        `Shape`: The modified shape1.
 569    """
 570    overlay(shape1, shape2)
 571    _a_canvas.move(
 572        shape1,
 573        0 + offset_x,
 574        -1 * (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
 575    )
 576    return shape1
 577
 578
 579def align(shape1, shape2, via="middle", offset_x=0, offset_y=0):
 580    """
 581    A reporter function that aligns `shape1` with `shape2`. It does this by moving `shape1` to align with
 582    whatever property of `shape2` is selected with the `via` input.
 583
 584    Args:
 585        shape1 (`Shape` or Tag): The first shape to use.
 586        shape2 (`Shape` or Tag): The second shape to use.
 587        via (`str`): Has to be one of, the following options: `"center"` (horizontal center),
 588            `"middle"` (vertical center), `"top"`, `"bottom"`, `"left"`, or `"right"`
 589        offset_x (`int`): How much to shift in the x-axis after alignment
 590        offset_y (`int`): How much to shift in the y-axis after alignment
 591
 592    Returns:
 593        `Shape`: The modified shape1.
 594    """
 595    via_options = ["center", "middle", "top", "bottom", "left", "right"]
 596    if via not in via_options
 597        raise ValueError(
 598            "The via input must be one of "
 599            + (via_options)
 600            + " but instead we found "
 601            + (via)
 602        )
 603
 604    outline1 = _get_outline(shape1)
 605    outline2 = _get_outline(shape2)
 606
 607    if via == "center"
 608        _a_canvas.move(
 609            shape1, (outline2["center"][0] - outline1["center"][0]) + offset_x, offset_y
 610        )
 611
 612    elif via == "middle"
 613        _a_canvas.move(
 614            shape1, offset_x, (outline2["center"][1] - outline1["center"][1]) + offset_y
 615        )
 616
 617    elif via == "top"
 618        _a_canvas.move(shape1, offset_x, (outline2["top"] - outline1["top"]) + offset_y)
 619
 620    elif via == "bottom"
 621        _a_canvas.move(
 622            shape1, offset_x, (outline2["bottom"] - outline1["bottom"]) + offset_y
 623        )
 624
 625    elif via == "left"
 626        _a_canvas.move(
 627            shape1, (outline2["left"] - outline1["left"]) + offset_x, offset_y
 628        )
 629
 630    elif via == "right"
 631        _a_canvas.move(
 632            shape1, (outline2["right"] - outline1["right"]) + offset_x, offset_y
 633        )
 634
 635    return shape1
 636
 637
 638def beside(shape1, shape2, offset_x=0, offset_y=0):
 639    """
 640    A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1"s center
 641    to shape 2"s center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any
 642    specified offset.
 643
 644    Args:
 645        shape1 (`Shape` or Tag): The first shape to use.
 646        shape2 (`Shape` or Tag): The second shape to use.
 647        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
 648        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
 649
 650    Returns:
 651        `Shape`: The modified shape1.
 652    """
 653    overlay(shape1, shape2)
 654    _a_canvas.move(
 655        shape1,
 656        (get_width(shape2) + get_width(shape1)) / 2 + offset_x,
 657        0 + offset_y,
 658    )
 659    return shape1
 660
 661
 662def below(shape1, shape2, offset_x=0, offset_y=0):
 663    """
 664    A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1"s center
 665    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
 666    specified offset.
 667
 668    Args:
 669        shape1 (`Shape` or Tag): The first shape to use.
 670        shape2 (`Shape` or Tag): The second shape to use.
 671        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
 672        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
 673
 674    Returns:
 675        `Shape`: The modified shape1.
 676    """
 677    overlay(shape1, shape2)
 678    _a_canvas.move(
 679        shape1,
 680        0 + offset_x,
 681        (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
 682    )
 683    return shape1
 684
 685
 686def change_color(shape, color):
 687    """
 688    Change the fill color of a tagged object.
 689
 690    Args:
 691        shape (`Shape` or Tag): The shape or tag to re-fill.
 692        color (`str`): A color name or hex code to re-fill with.
 693    """
 694    ids = _a_canvas.find_withtag(shape)
 695    for id in ids
 696        _a_canvas.itemconfig(id, fill=color)
 697
 698
 699def delete(shape):
 700    """
 701    A function that deletes a shape from our screen.
 702
 703    Args:
 704        shape (`Shape` or Tag): The shape to delete.
 705    """
 706    _a_canvas.delete(shape)
 707
 708
 709def duplicate(shape, color=None):
 710    """
 711    A reporter function that perfectly copies a shape and returns that copy.
 712
 713    Args:
 714        shape (`Shape` or Tag): The shape to duplicate.
 715        color (`str`): A new color to use with the duplicated shape.
 716
 717    Returns:
 718        `Shape`: The new duplicated shape.
 719    """
 720    shape_type = _a_canvas.type(shape)
 721    shape_config = _a_canvas.itemconfig(shape)
 722    shape_coords = _a_canvas.coords(shape)
 723    the_copy = None
 724    if shape_type == "polygon"
 725        new_config = {key shape_config[key][-1] for key in shape_config.keys()}
 726        if color != None
 727            new_config["fill"] = color
 728        the_copy = _a_canvas.create_polygon(shape_coords, new_config)
 729        return the_copy
 730
 731
 732def mirror(shape):
 733    """
 734    A function that takes a shape and flips it across its vertical
 735    axis, returning the modified shape.
 736
 737    Args:
 738        shape (`Shape` or Tag): The shape in question.
 739
 740    """
 741    center = get_center(shape)[0]
 742    shape_ids = _a_canvas.find_withtag(shape)
 743    for shape_id in shape_ids
 744        flipped_coordinates = []
 745        shape_coords = _a_canvas.coords(shape_id)
 746        counter = 0
 747        for num in shape_coords
 748            if counter % 2 == 0
 749                if num < center
 750                    flipped_coordinates.append(num + 2 * (center - num))
 751                elif num > center
 752                    flipped_coordinates.append(num - 2 * (num - center))
 753                else
 754                    flipped_coordinates.append(num)
 755            else
 756                flipped_coordinates.append(num)
 757            counter += 1
 758        _a_canvas.coords(shape_id, flipped_coordinates)
 759
 760
 761def move(shape, x_shift=0, y_shift=0):
 762    """
 763    Purpose: Move the x and y position of all shapes that have been tagged
 764    with the tag argument
 765
 766    Args:
 767        shape (`Shape` or Tag): The shape in question.
 768        x_shift (`int`; optional): amount to move in the x direction
 769        y_shift (`int`; optional): amount to move in the y direction
 770    """
 771    shape_ids = _a_canvas.find_withtag(shape)
 772    for id in shape_ids
 773        _a_canvas.move(id, x_shift, y_shift)
 774
 775
 776def move_to(tag, to, anchor="center"):
 777    """
 778    Move the given tagged item to a particular `point` maintaining some `anchor`.
 779    Note: this is NOT the same as the `move` function which moves an object by a specific amount.
 780
 781    Args:
 782        tag (Shape or `str`): the shape (or shapes) to move
 783        to (`tuple`): the `(x, y)` coordinate to which you wish to move the tagged object
 784        anchor (`str`): which point on the shape do you want to move toward the given tuple. You can
 785            use either `"center"` (default), `"top_left"`, `"top_right"`, `"bottom_left"`, or `"bottom_right"`.
 786    """
 787    anchor_options = ["center", "top_left", "top_right", "bottom_left", "bottom_right"]
 788    if anchor not in anchor_options
 789        raise ValueError(
 790            "The anchor input must be one of "
 791            + (anchor_options)
 792            + " but instead we found "
 793            + (anchor)
 794        )
 795
 796    outline = _get_outline(tag)
 797    delta_x = 0
 798    delta_y = 0
 799
 800    if anchor == "top_left"
 801        delta_x = to[0] - outline["left"]
 802        delta_y = to[1] - outline["top"]
 803    elif anchor == "top_right"
 804        delta_x = to[0] - outline["right"]
 805        delta_y = to[1] - outline["top"]
 806    elif anchor == "bottom_right"
 807        delta_x = to[0] - outline["right"]
 808        delta_y = to[1] - outline["bottom"]
 809    elif anchor == "bottom_left"
 810        delta_x = to[0] - outline["left"]
 811        delta_y = to[1] - outline["bottom"]
 812    elif anchor == "center"
 813        delta_x = to[0] - outline["center"][0]
 814        delta_y = to[1] - outline["center"][1]
 815
 816    _a_canvas.move(tag, delta_x, delta_y)
 817
 818
 819def overlay(shape1, shape2, offset_x=0, offset_y=0):
 820    """
 821    A reporter function that overlays shape1 onto shape2. It does this by moving shape 1"s center
 822    to shape 2"s center, and then applying any specified offset.
 823    Args:
 824        shape1 (`Shape` or Tag): The first shape to use.
 825        shape2 (`Shape` or Tag): The second shape to use.
 826        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
 827        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
 828
 829    Returns:
 830        `Shape`: The modified shape1.
 831    """
 832    center1 = get_center(shape1)
 833    center2 = get_center(shape2)
 834    _a_canvas.move(
 835        shape1,
 836        (center2[0] - center1[0]) + offset_x,
 837        (center2[1] - center1[1]) + offset_y,
 838    )
 839    _a_canvas.tag_raise(shape1, shape2)
 840    return shape1
 841
 842
 843def portion(shape, start=0, end=0.5):
 844    """
 845    Purpose: Take a slice or portion of some already created shape.
 846
 847    Args:
 848        shape (`Shape` or Tag): The shape to take a portion of
 849        start (`float`): A number between 0 and 1 representing where to start the slice.
 850        end (`float`): A number between 0 and 1 representing where to end the slice.
 851
 852    For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle.
 853
 854    Note: this function is experimental. It might produce unexpected results!
 855    """
 856    all_shapes = _a_canvas.find_withtag(shape)
 857
 858    for a_shape in all_shapes
 859        coords = _a_canvas.coords(a_shape)
 860
 861        start_coord = floor(start * len(coords))
 862        if start_coord % 2 == 1
 863            start_coord = start_coord - 1  # need to start with an x,y pair
 864        end_coord = floor(end * len(coords))
 865        if end_coord % 2 == 1
 866            end_coord = end_coord - 1  # need to end with an x,y pair
 867
 868        # slice is up to not including so get the last x,y pair
 869        new_coords = coords[start_coord  end_coord + 2]
 870
 871        # loop shape back in on itself
 872        new_coords.append(new_coords[0])
 873        new_coords.append(new_coords[1])
 874
 875        # set the coordinates:
 876        _a_canvas.coords(a_shape, new_coords)
 877
 878
 879def put_in_back(shape):
 880    """
 881    A function that "lowers" a shape to the "bottom" of the screen."
 882
 883    Args:
 884        shape (`Shape` or Tag): The shape in question.
 885    """
 886    _a_canvas.tag_lower(shape)
 887
 888
 889def put_in_front(shape):
 890    """
 891    A function that "raises" a shape to the "top" of the screen."
 892
 893    Args:
 894        shape (`Shape` or Tag): The shape in question.
 895    """
 896    _a_canvas.tag_raise(shape)
 897
 898
 899def rotate(shape, degrees=5, origin=None):
 900    """
 901    A reporter function that takes a shape and rotates it by a specified amount around a specified point.
 902    It does this by interpolating a polygon around the shape and calculating the shifts of individual
 903    points on the edge of the polygon.
 904
 905    Args:
 906        shape (`Shape` or Tag): The shape to rotate.
 907        degrees (`int`): The number of degrees to rotate the shape.
 908        origin (`tuple`): An `(x,y)` coordinate about which to perform the rotation. Defaults to the center
 909            of the given shape.
 910
 911    Returns:
 912        `Shape`: The modified shape.
 913    """
 914    if origin is None
 915        origin = get_center(shape)
 916
 917    theta = radians(degrees)
 918    ox, oy = origin
 919
 920    all_shapes = _a_canvas.find_withtag(shape)
 921
 922    for a_shape in all_shapes
 923        coords = _a_canvas.coords(a_shape)
 924        # update coordinates:
 925        for i in range(0, len(coords), 2):
 926            px, py = coords[i], coords[i + 1]
 927            qx = cos(theta) * (px - ox) - sin(theta) * (py - oy) + ox
 928            qy = sin(theta) * (px - ox) + cos(theta) * (py - oy) + oy
 929            coords[i] = qx
 930            coords[i + 1] = qy
 931        # set the coordinates:
 932        _a_canvas.coords(a_shape, coords)
 933
 934    return shape
 935
 936
 937def scale(shape, x_scale=1.0, y_scale=1.0):
 938    """
 939    A function that takes a given `Shape` or tag and scales it on either/both the x and y-axis.
 940
 941    The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause
 942    the shape to grow along that access. Values less than 1.0 will cause the shape to shrink.
 943
 944    Args:
 945        shape (`Shape` or Tag): The shape or tag to re-fill.
 946        x_scale (`float`): How much to scale in the x-axis.
 947        y_scale (`float`): How much to scale in the y-axis.
 948    """
 949    ids = _a_canvas.find_withtag(shape)
 950
 951    coord = get_center(shape)
 952
 953    for i in ids
 954        _a_canvas.scale(i, coord[0], coord[1], x_scale, y_scale)
 955
 956
 957def underlay(shape1, shape2, offset_x=0, offset_y=0):
 958    """
 959    A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1"s center
 960    to shape 2"s center, and then applying any specified offset.
 961    Args:
 962        shape1 (`Shape` or Tag): The first shape to use.
 963        shape2 (`Shape` or Tag): The second shape to use.
 964        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
 965        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
 966
 967    Returns:
 968        `Shape`: The modified shape1.
 969    """
 970    center1 = get_center(shape1)
 971    center2 = get_center(shape2)
 972    _a_canvas.move(
 973        shape1,
 974        (center2[0] - center1[0]) + offset_x,
 975        (center2[1] - center1[1]) + offset_y,
 976    )
 977    _a_canvas.tag_lower(shape1, shape2)
 978    return shape1
 979
 980
 981Utility_Functions = ""
 982
 983
 984def clear_window(keep_grid=True):
 985    """
 986    A function that deletes everything from the window.
 987
 988    Args:
 989        keep_grid (`bool`): Whether or not to keep the grid.
 990    """
 991    all_shapes = _a_canvas.find_all()
 992
 993    for shape in all_shapes
 994        tags = _a_canvas.gettags(shape)
 995        if "grid" in tags and keep_grid
 996            continue
 997        _a_canvas.delete(shape)
 998
 999    global _resize_enabled
1000    _resize_enabled = True
1001
1002
1003def distance(point1, point2):
1004    """
1005    A reporter function calculates the distance between two `(x, y)` coordinates.
1006
1007    Args:
1008        point1 (`tuple`): The first `(x, y)` coordinate.
1009        point2 (`tuple`): The second `(x, y)` coordinate.
1010
1011    Returns:
1012         A `float` representing the distance between the two points.
1013    """
1014    return sqrt(((point1[0] - point2[0])  2) + ((point1[1] - point2[1])  2))
1015
1016
1017def does_tag_exist(tag):
1018    """
1019    Returns `True` if a given tag exists otherwise returns `False`.
1020
1021    Args:
1022        `tag` (`str`): [Required] The tag of the object to lookup.
1023
1024    """
1025    result = _a_canvas.find_withtag(tag)
1026
1027    if result
1028        return True
1029    else
1030        return False
1031
1032
1033def get_bottom(shape):
1034    """
1035    A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped).
1036
1037    Args:
1038        shape (`Shape` or Tag): The shape in question.
1039
1040    Returns:
1041         A `int` representing the maximum y-coordinate of the shape.
1042    """
1043    bbox = _safe_bbox(shape)
1044    return bbox[3]
1045
1046
1047def get_center(shape):
1048    """
1049    A reporter function calculates the a coordinate at the center of some shape.
1050
1051    Args:
1052        shape (`Shape` or Tag): The shape in question.
1053
1054    Returns:
1055         A `tuple` representing center of the given shape.
1056    """
1057    bbox = _safe_bbox(shape)
1058
1059    if bbox is None
1060        raise Exception(
1061            f"We couldn"t find the shape with id/tag {shape}. Make sure it exists!"
1062        )
1063
1064    return (((bbox[2] + bbox[0]) / 2), ((bbox[1] + bbox[3]) / 2))
1065
1066
1067def get_colors(shape_or_shapes):
1068    """
1069    A reporter function that returns all the colors associated with a tag or list of tags.
1070
1071    Args:
1072        shape_or_shapes (`str`/`Shape` or `List`): the shape/tag or list of shapes/tags you"d like to find the colors of
1073
1074    Returns:
1075        A `List` containing all unique colors associated with that tag(s)
1076    """
1077    all_shapes = []
1078    if not isinstance(shape_or_shapes, ):
1079        shape_or_shapes = [shape_or_shapes]
1080    for shape in shape_or_shapes
1081        all_shapes += _a_canvas.find_withtag(shape)
1082
1083    all_colors = []
1084    for shape in all_shapes
1085        color = _a_canvas.itemcget(shape, "fill")
1086        if color not in all_colors
1087            all_colors.append(color)
1088
1089    return all_colors
1090
1091
1092def get_height(shape):
1093    """
1094    A reporter function calculates the height of some given shape.
1095
1096    Args:
1097        shape (`Shape` or Tag): The shape in question.
1098
1099    Returns:
1100         A `int` representing the height of the shape.
1101    """
1102    bbox = _safe_bbox(shape)
1103    return bbox[3] - bbox[1] - 1
1104
1105
1106def get_left(shape):
1107    """
1108    A reporter function calculates the minimum x-value of a given shape.
1109
1110    Args:
1111        shape (`Shape` or Tag): The shape in question.
1112
1113    Returns:
1114         A `int` representing the minimum x-coordinate of the shape.
1115    """
1116    bbox = _safe_bbox(shape)
1117    return bbox[0]
1118
1119
1120def get_right(shape):
1121    """
1122    A reporter function calculates the maximum x-value of a given shape.
1123
1124    Args:
1125        shape (`Shape` or Tag): The shape in question.
1126
1127    Returns:
1128         A `int` representing the maximum x-coordinate of the shape.
1129    """
1130    bbox = _safe_bbox(shape)
1131    return bbox[2]
1132
1133
1134def get_tag_from_event(event, precision=25):
1135    """
1136    Tries to return a tag of an object at a given mouse-event.
1137
1138    Args:
1139        event (`Event`): Must be a mouse event otherwise we"ll give back an error.
1140        precision (`int`): How precise in number of pixels does a user have be in order to "select" an object
1141
1142    Returns a blank string `""` if no shapes are found closer than `precision`.
1143    """
1144
1145    if (event.type) not in [4, 6]:
1146        raise Exception(f"Received an event that isn"t a mouse event: {event}")
1147
1148    try
1149        x = event.x
1150        y = event.y
1151        shape_id = _a_canvas.find_closest(x, y)  # get the top shape
1152        if shape_id and distance(get_center(shape_id), (x, y)) < precision
1153            tags = _a_canvas.gettags(shape_id)
1154            if len(tags) > 0
1155                return tags[0]
1156        return ""
1157
1158    except
1159        raise Exception(
1160            "No tag found! Maybe you passed us an event that isn"t a mouse event?"
1161        )
1162
1163
1164def get_top(shape):
1165    """
1166    A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped).
1167
1168    Args:
1169        shape (`Shape` or Tag): The shape in question.
1170
1171    Returns:
1172         A `int` representing the minimum y-coordinate of the shape.
1173    """
1174    bbox = _safe_bbox(shape)
1175    return bbox[1]
1176
1177
1178def get_width(shape):
1179    """
1180    A reporter function calculates the width of some given shape.
1181
1182    Args:
1183        shape (`Shape` or Tag): The shape in question.
1184
1185    Returns:
1186         An `int` representing width of the shape.
1187    """
1188    bbox = _safe_bbox(shape)
1189    return bbox[2] - bbox[0] - 1
1190
1191
1192def get_window_height():
1193    """
1194    A reporter function that returns the current height of the window.
1195
1196    Returns:
1197         An `int` representing height of the window.
1198    """
1199    return _a_canvas.winfo_height()
1200
1201
1202def get_window_width():
1203    """
1204    A reporter function that returns the current width of the window.
1205
1206    Returns:
1207         An `int` representing width of the window.
1208    """
1209    return _a_canvas.winfo_width()
1210
1211
1212def interpolate_colors(color1, color2, frac):
1213    """
1214    A reporter function that generates a new color between two given colors.
1215    Args:
1216        color1 (`str`): The path of the file to wrap
1217        color2 (`str`): The path of the file to wrap
1218        frac (`float`): What fraction of each color to take. An input of 0 returns
1219            color1, an input of 1 returns color2, an input of 0.5 returns a color
1220            perfectly between the two.
1221
1222    Returns:
1223         A color (as a hex `str`) to be used elsewhere
1224    """
1225    if "#" not in color1
1226        color1 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color1)))
1227    else
1228        color1 = _tupelize_color(color1)
1229    if "#" not in color2
1230        color2 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color2)))
1231    else
1232        color2 = _tupelize_color(color2)
1233    return _interpolate_tuple(color1, color2, frac)
1234
1235
1236def random_color():
1237    """
1238    Returns a random color as a `string` to be used.
1239    It does not accept any inputs.
1240    """
1241    r = lambda randint(0, 255)
1242    return "#%02X%02X%02X" % (r(), r(), r())
1243
1244
1245def setup_listener(event_str, handler_function, override=False):
1246    """
1247    Sets up a listener for a given event on our window.
1248
1249    Args:
1250        event_str (`str`): The magic string that represents this event in the window
1251        handler_function (`func`): The name (not a string though) of the function you want called when the event his heard
1252        override (`bool`): Only use this if you speak to Prof. Bain and he recommends it.
1253
1254    The supported events are:
1255      * `"LEFT-CLICK"`: Left mouse click
1256      * `"RIGHT-CLICK"`: Right mouse click
1257      * `"ALT-CLICK"`: If you"re using a PC, this event might instead work for Right Click
1258      * `"LEFT-DRAG"`: Left mouse clicked and dragged on the screen
1259      * `"RIGHT-DRAG"`: Right mouse clicked and dragged on the screen
1260      * `"ALT-DRAG"`: For PCs, this event might instead work for RIGHT-DRAG
1261      * `"DOUBLE-LEFT"`: Left mouse double click
1262      * `"DOUBLE-RIGHT"`: Right mouse double click
1263      * `"DOUBLE-ALT"`: For PCs, this event might instead work for DOUBLE-RIGHT
1264      * `"KEY"`: The catch-all event for Keyboard presses
1265    """
1266
1267    event_translator = {
1268        "LEFT-CLICK" "<Button-1>",
1269        "RIGHT-CLICK" "<Button-2>",
1270        "ALT-CLICK" "<Button-3>",
1271        "LEFT-DRAG" "<B1-Motion>",
1272        "RIGHT-DRAG" "<B2-Motion>",
1273        "ALT-DRAG" "<B3-Motion>",
1274        "DOUBLE-LEFT" "<Double-Button-1>",
1275        "DOUBLE-RIGHT" "<Double-Button-2>",
1276        "DOUBLE-ALT" "<Double-Button-3>",
1277        "KEY" "<Key>",
1278    }
1279
1280    if event_str not in event_translator and not override
1281        raise (
1282            TypeError(
1283                f"The event you entered, {event_str}, isn"t supported. Here are the supported events: {[i for i in event_translator]}"
1284            )
1285        )
1286
1287    event = event_translator[event_str]
1288    
1289    setup_listener.tracker.add(event_str)
1290
1291    _a_canvas.bind(event, handler_function)
1292
1293setup_listener.tracker = set()
1294
1295def setup_shapes(title, background="white", include_grid=True, width=600, height=600):
1296    """
1297    A static function that sets up the pop-up window. You can specify the size of the window here.
1298
1299    However, you should NOT add any calls to this function unless Prof. Bain specifically tells you to!
1300
1301    Args:
1302        title (`str`): The title of the pop-up window.
1303        background (`str`): A valid color as a string to be used as the background color.
1304        include_grid (`bool`): Whether or not to draw the grid.
1305        width (`int` or `str`): How wide the window should appear (advanced: use the string "FULLWIDTH" to maximize the width)
1306        height (`int` or `str`): How wide the window should appear (advanced: use the string "FULLHEIGHT" to maximize the width)
1307    """
1308
1309    global _a_canvas
1310    gui = Tk()
1311    gui.title(title)
1312
1313    if width == "FULLWIDTH"
1314        width = gui.winfo_screenwidth()
1315
1316    if height == "FULLHEIGHT"
1317        height = gui.winfo_screenheight()
1318
1319    _a_canvas = Canvas(gui, background=background, width=width, height=height)
1320    _a_canvas.pack()
1321    if include_grid
1322        grid(width, height)
1323
1324    _a_canvas.focus_set()
1325    return _a_canvas
1326
1327
1328def update():
1329    """
1330    A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION unless Prof. Bain explictly says to use it.
1331    """
1332    _a_canvas.update()
1333
1334
1335def _safe_color(color ):
1336    color = color.strip()
1337    # Could also do some other verifications here...
1338    return color
1339
1340
1341def _tupelize_color(color):
1342    R = (color[13], 16)
1343    G = (color[35], 16)
1344    B = (color[57], 16)
1345    return R, G, B
1346
1347
1348def _interpolate_tuple(startcolor, goalcolor, frac):
1349    R = startcolor[0]
1350    G = startcolor[1]
1351    B = startcolor[2]
1352
1353    targetR = goalcolor[0]
1354    targetG = goalcolor[1]
1355    targetB = goalcolor[2]
1356
1357    DiffR = targetR - R
1358    DiffG = targetG - G
1359    DiffB = targetB - B
1360
1361    iR = (R + (DiffR * frac))
1362    iG = (G + (DiffG * frac))
1363    iB = (B + (DiffB * frac))
1364
1365    hR = hex(iR).replace("0x", "")
1366    hG = hex(iG).replace("0x", "")
1367    hB = hex(iB).replace("0x", "")
1368
1369    if len(hR) == 1
1370        hR = "0" + hR
1371    if len(hB) == 1
1372        hB = "0" + hB
1373    if len(hG) == 1
1374        hG = "0" + hG
1375
1376    color = ("#" + hR + hG + hB).upper()
1377
1378    return color
1379
1380
1381def _polar_to_cartesian(r, theta):
1382    return (r * cos(theta)), (r * sin(theta))
1383
1384
1385def _get_outline(shape):
1386    """
1387    A reporter function that takes in a shape and calls the various helper functions to generate
1388    a sort of "summary" of that particular shape and returns it in the form of a dictionary.
1389
1390    Args:
1391        shape (`Shape` or Tag): The shape in question.
1392
1393    Returns:
1394        a `Dictionary` with the various properties of the shape
1395    """
1396
1397    return {
1398        "center" get_center(shape),
1399        "left" get_left(shape),
1400        "right" get_right(shape),
1401        "top" get_top(shape),
1402        "bottom" get_bottom(shape),
1403    }
1404
1405
1406def _draw_row(row, top_left, colors, pixel=25, tag=""):
1407    """
1408    Draws a single row of some pixel art.
1409
1410    Args:
1411        row (sequence): the row of artwork to draw
1412        top_left (`tuple`): the top left coordinate of the pixel art
1413        color (sequence): the colors to use for each square
1414        pixel (`int`, optional): how big each individual pixel should be
1415        tag (`str`, optional): the tag to assign to every square in the row
1416    """
1417    x = top_left[0]
1418    y = top_left[1]
1419    for cell in row
1420        if cell != 0
1421            square((x, y), pixel, color=colors[cell], tag=tag)
1422        x += pixel
1423
1424
1425def _safe_bbox(shape):
1426    try
1427        bbox = _a_canvas.bbox(shape)
1428        if bbox is None
1429            Exception(
1430                f"We couldn"t find the shape with tag/id: {shape}. Make sure this shape exists!"
1431            )
1432        return bbox
1433    except
1434        raise Exception(
1435            f"We couldn"t find the shape with tag/id: {shape}. Make sure this shape exists!"
1436        )
Shape_Drawing_Functions = ""
def arc( points=[], width=5, color="hot pink", line_steps=15, tag="",):
32def arc(points=[], width=5, color="hot pink", line_steps=15, tag="", ):
33    """
34    A reporter function that draws an arc ("curve") given a list of points.
35    Args:
36        points (`list`): The points outlining the curve; this should be a list of tuples (coordinates).
37            Make sure to give it at least 3 (x,y) coordinates that aren"t a straight line!
38        color (`str`): What color to make the shape.
39        tag (`str`): The tag to assign to the shape.
40
41    Returns:
42        `Shape`: The arc that was created.
43    """
44    return _a_canvas.create_line(
45        points,
46        width=width,
47        fill=color,
48        splinesteps=line_steps,
49        smooth=True,
50        tags=tag,
51        ,
52    )

A reporter function that draws an arc ("curve") given a list of points.

Arguments:
  • points (list): The points outlining the curve; this should be a list of tuples (coordinates). Make sure to give it at least 3 (x,y) coordinates that aren't a straight line!
  • color (str): What color to make the shape.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The arc that was created.

def car( top_left=(0, 0), size=100, body_color="#3D9970", wheel_color="black", tag=""):
55def car(top_left=(0, 0), size=100, body_color="#3D9970", wheel_color="black", tag=""):
56    """
57    Draws a cool car.
58
59    Args:
60        top_left (`tuple`): A coordinate at which to draw the car.
61        body_color (`str`): Color to make the body of the car.
62        wheel_color (`str`): Color to make the wheel of the car.
63        tag (`str`): The tag to assign to the shape.
64    """
65    x, y = top_left
66    rectangle((x + 5 * size / 10, y), size, size / 10 * 4, color=body_color, tag=tag)
67    rectangle(
68        (x, y + size - 7 * size / 10),
69        size * 2,
70        size / 10 * 4.5,
71        color=body_color,
72        tag=tag,
73    )
74    circle(
75        (x + 5 * size / 10, y + size - size / 5), size / 5, color=wheel_color, tag=tag
76    )
77    circle(
78        (x + 15 * size / 10, y + size - size / 5), size / 5, color=wheel_color, tag=tag
79    )

Draws a cool car.

Arguments:
  • top_left (tuple): A coordinate at which to draw the car.
  • body_color (str): Color to make the body of the car.
  • wheel_color (str): Color to make the wheel of the car.
  • tag (str): The tag to assign to the shape.
def circle( center=(0, 0), radius=25, color="hot pink", outline="", tag="",):
82def circle(center=(0, 0), radius=25, color="hot pink", outline="", tag="", ):
83    """
84    A reporter function that draws a circle.
85    Args:
86        center (`tuple`): A coordinate representing the center of the shape.
87        radius (`int`): Specifies the circle"s radius.
88        color (`str`): What color to draw the shape.
89        outline (`str`): What color should the border of the shape be.
90        tag (`str`): The tag to assign to the shape.
91
92    Returns:
93        `Shape`: The circle that was created.
94    """
95    return oval(
96        center=center, radius_x=radius, radius_y=radius, color=color, tag=tag, 
97    )

A reporter function that draws a circle.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • radius (int): Specifies the circle's radius.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The circle that was created.

def cloud(center=(0, 0), size=30, color="white", tag=""):
100def cloud(center=(0, 0), size=30, color="white", tag=""):
101    """
102    Reporter function that draws a cloud to the screen.
103    Args:
104        center (`tuple`): the point on which to center the cloud
105        size (`int`): how big (roughly) the cloud is drawn
106        color (`str`): which determines the color of the cloud
107        tag (`str`): to give the cloud a name
108
109    Returns:
110        `Shape`: The cloud that was created.
111    """
112    for i in range(10):
113        x_offset = randint((-1 * size * 1.333), (size * 1.333))
114        y_offset = randint(0, (size * 0.667))
115        circle(
116            center=(center[0] + x_offset, center[1] + y_offset),
117            radius=randint((size * 0.667), (size * 1.667)),
118            color=color,
119            tag=tag,
120        )
121    return tag

Reporter function that draws a cloud to the screen.

Arguments:
  • center (tuple): the point on which to center the cloud
  • size (int): how big (roughly) the cloud is drawn
  • color (str): which determines the color of the cloud
  • tag (str): to give the cloud a name
Returns:

Shape: The cloud that was created.

def diamond( center=(0, 0), width=25, height=50, color="hot pink", outline="", tag="",):
124def diamond(
125    center=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 
126):
127    """
128    A reporter function that draws a rectangle.
129    Args:
130        center (`tuple`): A coordinate representing the center of the shape.
131        width (`int`): How wide to draw the shape.
132        height (`int`): How tall to draw the shape.
133        color (`str`): What color to draw the shape.
134        outline (`str`): What color should the border of the shape be.
135        tag (`str`): The tag to assign to the shape.
136
137    Returns:
138        `Shape`: The shape that was created.
139    """
140    point_0 = (center[0] - width / 2, center[1])
141    point_1 = (center[0], center[1] - height / 2)
142    point_2 = (center[0] + width / 2, center[1])
143    point_3 = (center[0], center[1] + height / 2)
144    return _a_canvas.create_polygon(
145        point_0,
146        point_1,
147        point_2,
148        point_3,
149        fill=_safe_color(color),
150        tags=tag,
151        outline=outline,
152        ,
153    )

A reporter function that draws a rectangle.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • width (int): How wide to draw the shape.
  • height (int): How tall to draw the shape.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The shape that was created.

def grid(width=None, height=None, interval=100, show_labels=True):
156def grid(width=None, height=None, interval=100, show_labels=True):
157    """
158    Draws a grid on a screen with intervals of 100.
159
160    Args:
161        width (`int`): The width of the grid to draw (defaults to the whole window)
162        height (`int`): The height of the grid to draw (defaults to the whole window)
163        interval (`int`): The interval to draw the grid on.
164        show_labels (`bool`): Whether or not to show coordinate labels.
165
166    """
167
168    if width is None
169        width = get_window_width()
170
171    if height is None
172        height = get_window_height()
173
174    # Creates all vertical lines at intervals of 100
175    for i in range(0, width, interval):
176        _a_canvas.create_line(i, 0, i, height, tag="grid", fill="black")
177    # Creates all horizontal lines at intervals of 100
178    for i in range(0, height, interval):
179        _a_canvas.create_line(0, i, width, i, tag="grid", fill="black")
180
181    if show_labels
182        # Creates axis labels
183        offset = 2
184        for y in range(0, height, interval):
185            for x in range(0, width, interval):
186                _a_canvas.create_oval(
187                    x - offset,
188                    y - offset,
189                    x + offset,
190                    y + offset,
191                    fill="black",
192                    tag="grid",
193                )
194                _a_canvas.create_text(
195                    x + offset,
196                    y + offset,
197                    text="({0}, {1})".format(x, y),
198                    anchor="nw",
199                    font=("Purisa", 8),
200                    fill="black",
201                    tag="grid",
202                )

Draws a grid on a screen with intervals of 100.

Arguments:
  • width (int): The width of the grid to draw (defaults to the whole window)
  • height (int): The height of the grid to draw (defaults to the whole window)
  • interval (int): The interval to draw the grid on.
  • show_labels (bool): Whether or not to show coordinate labels.
def image( image_path, position=(200, 200), rotation=None, scale=None, tag="",):
208def image(image_path, position=(200, 200), rotation=None, scale=None, tag="", ):
209    """
210    Draws a given image on the screen. NOTE: Requires the `pillow` package to be installed - contact
211    Prof. Bain or post on edSTEM if you"d like more details!
212
213    Args:
214        image_path (`str`): Location of the image file on your computer.
215        position (`tuple`): A coordinate at which to render the image.
216        rotation (`int`): A number of degrees to rotate the given image.
217        scale (`int`): A scaling factor to multiply the image size by.
218        tag (`str`): A string representing the "name" fo this shape.
219    """
220    # import PIL libraries
221    from PIL import Image, ImageTk
222
223    anchor = "nw"
224
225    import os
226
227    # 1. create PIL image and apply any image transformations:
228    dir_path = os.path.dirname(os.path.realpath(__file__))
229    image_path = os.path.join(dir_path, image_path)
230    pil_image = Image.open(image_path)
231    if scale
232        size = (round(pil_image.size[0] * scale), round(pil_image.size[1] * scale))
233        pil_image = pil_image.resize(size)
234    if rotation
235        pil_image = pil_image.rotate(rotation)  # note: returns a copy
236
237    # 2. convert to tkinter-compatible image format:
238    tkinter_image = ImageTk.PhotoImage(pil_image)
239    _cache.append(
240        tkinter_image
241    )  # workaround for known tkinter bug: http://effbot.org/pyfaq/why-do-my-tkinter-images-not-appear.htm
242
243    # 3. draw image on canvas:
244    _a_canvas.create_image(
245        *position, image=tkinter_image, anchor=anchor, tags=tag, 
246    )

Draws a given image on the screen. NOTE: Requires the pillow package to be installed - contact Prof. Bain or post on edSTEM if you'd like more details!

Arguments:
  • image_path (str): Location of the image file on your computer.
  • position (tuple): A coordinate at which to render the image.
  • rotation (int): A number of degrees to rotate the given image.
  • scale (int): A scaling factor to multiply the image size by.
  • tag (str): A string representing the "name" fo this shape.
def line(points=[], curvy=False, color="hot pink", tag="", ):
249def line(points=[], curvy=False, color="hot pink", tag="", ):
250    """
251    A reporter function that draws a line given a list of points.
252    Args:
253        points (`list`): The points that define the line; this should be a list of tuples (coordinates).
254        curvy (`bool`): Makes a curvy line instead.
255        color (`str`): What color to make the shape.
256        tag (`str`): The tag to assign to the shape.
257
258    Returns:
259        `Shape`: The line that was created.
260    """
261    return _a_canvas.create_line(points, fill=color, smooth=curvy, tags=tag, )

A reporter function that draws a line given a list of points.

Arguments:
  • points (list): The points that define the line; this should be a list of tuples (coordinates).
  • curvy (bool): Makes a curvy line instead.
  • color (str): What color to make the shape.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The line that was created.

def oval( center=(0, 0), radius_x=25, radius_y=50, color="hot pink", outline="", tag="",):
264def oval(
265    center=(0, 0),
266    radius_x=25,
267    radius_y=50,
268    color="hot pink",
269    outline="",
270    tag="",
271    ,
272):
273    """
274    A reporter function that draws an oval.
275    Args:
276        center (`tuple`): A coordinate representing the center of the shape.
277        radius_x (`int`): Specifies the oval"s radius on the x-axis.
278        radius_y (`int`): Specifies the oval"s radius on the y-axis.
279        color (`str`): What color to draw the shape.
280        outline (`str`): What color should the border of the shape be.
281        tag (`str`): The tag to assign to the shape.
282
283    Returns:
284        `Shape`: The oval that was created.
285    """
286    x = center[0]
287    y = center[1]
288    x0, y0, x1, y1 = (x - radius_x, y - radius_y, x + radius_x, y + radius_y)
289    steps = 100
290    # major and minor axes
291    a = (x1 - x0) / 2.0
292    b = (y1 - y0) / 2.0
293    # center
294    xc = x0 + a
295    yc = y0 + b
296    point_list = []
297    # create the oval as a list of points
298    for i in range(steps):
299        # Calculate the angle for this step
300        theta = (pi * 2) * (float(i) / steps)
301        x = a * cos(theta)
302        y = b * sin(theta)
303        point_list.append(round(x + xc))
304        point_list.append(round(y + yc))
305
306    return _a_canvas.create_polygon(
307        point_list, fill=_safe_color(color), tags=tag, 
308    )

A reporter function that draws an oval.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • radius_x (int): Specifies the oval's radius on the x-axis.
  • radius_y (int): Specifies the oval's radius on the y-axis.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The oval that was created.

def pixel_art(top_left, artwork, palette, pixel=10, tag=""):
311def pixel_art(top_left, artwork, palette, pixel=10, tag=""):
312    """
313    Draws a pixel art design!
314
315    Args:
316        top_left (`tuple`): the top left coordinate of the pixel art
317        artwork (sequence of sequences): the art to draw
318        palette (sequence): the palette of colors to use for each different square
319        pixel (`int`, optional): how big each individual pixel should be
320        tag (`str`, optional): the tag to assign to every square in the row
321
322    Note: this doesn"t return anything so make sure to use a tag if you want to animate / modify.
323    """
324    x = top_left[0]
325    y = top_left[1]
326    for row in artwork
327        # draw each row at the specified (x, y) position:
328        _draw_row(row, (x, y), colors=palette, pixel=pixel, tag=tag)
329        # ...and don"t forget to shift the y-value down by the proper
330        #  amount so that the next row won"t draw on top of the first one:
331        y += pixel

Draws a pixel art design!

Arguments:
  • top_left (tuple): the top left coordinate of the pixel art
  • artwork (sequence of sequences): the art to draw
  • palette (sequence): the palette of colors to use for each different square
  • pixel (int, optional): how big each individual pixel should be
  • tag (str, optional): the tag to assign to every square in the row

Note: this doesn't return anything so make sure to use a tag if you want to animate / modify.

def polygon(points=[], color="hot pink", outline="", tag="", ):
334def polygon(points=[], color="hot pink", outline="", tag="", ):
335    """
336    A reporter function that draws a polygon given a list of points.
337    Args:
338        points (`list`): The points outlining the polygon; this should be a list of tuples (coordinates).
339            defaults to an empty list.
340        outline (`str`): What color should the border of the shape be.
341        color (`str`): What color to make the shape.
342
343    Returns:
344        `Shape`: The polygon that was created.
345    """
346    return _a_canvas.create_polygon(points, fill=_safe_color(color), tags=tag, )

A reporter function that draws a polygon given a list of points.

Arguments:
  • points (list): The points outlining the polygon; this should be a list of tuples (coordinates). defaults to an empty list.
  • outline (str): What color should the border of the shape be.
  • color (str): What color to make the shape.
Returns:

Shape: The polygon that was created.

def rectangle( top_left=(0, 0), width=25, height=50, color="hot pink", outline="", tag="",):
349def rectangle(
350    top_left=(0, 0), width=25, height=50, color="hot pink", outline="", tag="", 
351):
352    """
353    A reporter function that draws a rectangle.
354    Args:
355        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
356        width (`int`): How wide to draw the shape.
357        height (`int`): How tall to draw the shape.
358        color (`str`): What color to draw the shape.
359        outline (`str`): What color should the border of the shape be.
360        tag (`str`): The tag to assign to the shape.
361
362    Returns:
363        `Shape`: The rectangle that was created.
364    """
365    point_0 = top_left
366    point_1 = (top_left[0] + width, top_left[1])
367    point_2 = (top_left[0] + width, top_left[1] + height)
368    point_3 = (top_left[0], top_left[1] + height)
369    return _a_canvas.create_polygon(
370        point_0, point_1, point_2, point_3, fill=_safe_color(color), tags=tag, 
371    )

A reporter function that draws a rectangle.

Arguments:
  • top_left (tuple): A coordinate representing the top left-hand corner of the shape.
  • width (int): How wide to draw the shape.
  • height (int): How tall to draw the shape.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The rectangle that was created.

def spiral( center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1,):
374def spiral(
375    center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1, 
376):
377    """
378    A reporter function that draws a spiral.
379    Args:
380        center (`tuple`): A coordinate representing the center of the shape.
381        width (`int`): Specifies the total width of the spiral.
382        roughness (`float`): Controls how spiral-y the shape is (lower is less spiral-y)
383        start (`int`): Where on the spiral to start drawing.
384        spirals (`int`): How many loops to draw.
385        line_width (`int`): How wide for the line to be drawn.
386        tag (`str`): The tag to assign to the shape.
387
388    Returns:
389        `Shape`: The spiral that was created.
390    """
391    theta = 0.0
392    r = start
393    all_points = []
394    prev_pos = _polar_to_cartesian(r, theta)
395    distance = width / 4 / pi / spirals
396    all_points.append((prev_pos[0] + center[0], prev_pos[1] + center[1]))
397    while theta < 2 * spirals * pi
398        theta += roughness
399        r = start + distance * theta
400        pos = _polar_to_cartesian(r, theta)
401        all_points.append((pos[0] + center[0], pos[1] + center[1]))
402
403    return arc(points=all_points, width=line_width, )

A reporter function that draws a spiral.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • width (int): Specifies the total width of the spiral.
  • roughness (float): Controls how spiral-y the shape is (lower is less spiral-y)
  • start (int): Where on the spiral to start drawing.
  • spirals (int): How many loops to draw.
  • line_width (int): How wide for the line to be drawn.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The spiral that was created.

def square( top_left=(0, 0), size=25, color="hot pink", outline="", tag="",):
406def square(top_left=(0, 0), size=25, color="hot pink", outline="", tag="", ):
407    """
408    A reporter function that draws a square.
409    Args:
410        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
411        size (`int`): How big to draw the shape.
412        color (`str`): What color to draw the shape.
413        outline (`str`): What color should the border of the shape be.
414        tag (`str`): The tag to assign to the shape.
415
416    Returns:
417        `Shape`: The square that was created.
418    """
419    return rectangle(
420        top_left=top_left, width=size, height=size, color=color, tag=tag, 
421    )

A reporter function that draws a square.

Arguments:
  • top_left (tuple): A coordinate representing the top left-hand corner of the shape.
  • size (int): How big to draw the shape.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The square that was created.

def star( center=(0, 0), radius=50, color="hot pink", outer_radius=75, points=5, outline="", tag="",):
424def star(
425    center=(0, 0),
426    radius=50,
427    color="hot pink",
428    outer_radius=75,
429    points=5,
430    outline="",
431    tag="",
432    ,
433):
434    """
435    A reporter function that draws a star.
436    Args:
437        center (`tuple`): A coordinate representing the center of the shape.
438        radius (`int`): Specifies the radius of the inside part of the star.
439        color (`str`): Specifies the color of the star.
440        outer_radius (`int`): Specifies the radius of the outside part of the star.
441        points (`int`): Specifies the number of points for the star.
442        outline (`str`): What color should the border of the shape be.
443        tag (`str`): The tag to assign to the shape.
444
445    Returns:
446        `Shape`: The star that was created.
447    """
448    arc_segment = 360 / points
449    vertices = []
450    for i in range(points):
451        inner_point = (
452            radius * cos(radians(arc_segment * i)) + center[0],
453            -1 * radius * sin(radians(arc_segment * i)) + center[1],
454        )
455        vertices.append(inner_point)
456        outer_point = (
457            outer_radius * cos(radians(arc_segment * i + arc_segment / 2)) + center[0],
458            -1 * outer_radius * sin(radians(arc_segment * i + arc_segment / 2))
459            + center[1],
460        )
461        vertices.append(outer_point)
462    return polygon(vertices, color=color, tag=tag, )

A reporter function that draws a star.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • radius (int): Specifies the radius of the inside part of the star.
  • color (str): Specifies the color of the star.
  • outer_radius (int): Specifies the radius of the outside part of the star.
  • points (int): Specifies the number of points for the star.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The star that was created.

def text( top_left=(0, 0), text="", font=("Purisa", 32), color="black", tag="",):
465def text(
466    top_left=(0, 0), text="", font=("Purisa", 32), color="black", tag="", 
467):
468    """
469    A reporter function that draws text to the screen
470    Args:
471        top_left (`tuple`): coordinate pair to specify the location.
472        text (`str`): What text to draw.
473        font (`tuple`): A tuple where the first element is a string for the font name and the second is an
474           int with the font size.
475        color (`str`): What color should the text be.
476        tag (`str`): The name to tag this thing with.
477
478    Returns:
479        `Shape`: The text that was created.
480    """
481    return _a_canvas.create_text(
482        top_left, text=text, font=font, fill=color, tags=tag, 
483    )

A reporter function that draws text to the screen

Arguments:
  • top_left (tuple): coordinate pair to specify the location.
  • text (str): What text to draw.
  • font (tuple): A tuple where the first element is a string for the font name and the second is an int with the font size.
  • color (str): What color should the text be.
  • tag (str): The name to tag this thing with.
Returns:

Shape: The text that was created.

def triangle( bottom_center=(0, 0), width=25, top_shift=0, height=0, color="hot pink", outline="", tag="",):
486def triangle(
487    bottom_center=(0, 0),
488    width=25,
489    top_shift=0,
490    height=0,
491    color="hot pink",
492    outline="",
493    tag="",
494    ,
495):
496    """
497    A reporter function that draws a triangle.
498    Args:
499        bottom_center (`tuple`): A coordinate representing the bottom center of the shape.
500        width (`int`): Specifies the width of the base of the triangle.
501        top_shift (`int`): Specifies the how far to the left or right to shift the top of
502            the triangle from the bottom center.
503        height (`int`): Specifies the triangle"s height.
504        color (`str`): What color to draw the shape.
505        outline (`str`): What color should the border of the shape be.
506        tag (`str`): The tag to assign to the shape.
507
508    Returns:
509        `Shape`: The triangle that was created.
510    """
511    if height == 0
512        height = width * sqrt(3) / 2
513    point_0 = (bottom_center[0] - width / 2, bottom_center[1])
514    point_1 = (bottom_center[0] + width / 2, bottom_center[1])
515    point_2 = (bottom_center[0] + top_shift, bottom_center[1] - height)
516
517    return _a_canvas.create_polygon(
518        point_0, point_1, point_2, fill=_safe_color(color), tags=tag, 
519    )

A reporter function that draws a triangle.

Arguments:
  • bottom_center (tuple): A coordinate representing the bottom center of the shape.
  • width (int): Specifies the width of the base of the triangle.
  • top_shift (int): Specifies the how far to the left or right to shift the top of the triangle from the bottom center.
  • height (int): Specifies the triangle's height.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The triangle that was created.

def wedge( center=(0, 0), radius=25, angle=180, color="hot pink", outline="", tag="",):
522def wedge(
523    center=(0, 0), radius=25, angle=180, color="hot pink", outline="", tag="", 
524):
525    """
526    A reporter function that draws a circle.
527    Args:
528        center (`tuple`): A coordinate representing the center of the shape.
529        radius (`int`): Specifies the circle"s radius.
530        angle (`int`): A number between 0 and 360 that specifies how much of the circle to draw.
531        color (`str`): What color to draw the shape.
532        outline (`str`): What color should the border of the shape be.
533        tag (`str`): The tag to assign to the shape.
534
535    Returns:
536        `Shape`: The wedge that was created.
537    """
538    point_list = [center[0], center[1]]
539    for i in range(0, 0 + angle):
540        x1 = center[0] + radius * cos(radians(i))
541        point_list.append(x1)
542        y1 = center[1] + radius * sin(radians(i))
543        point_list.append(y1)
544
545    point_list.append(center[0])
546    point_list.append(center[1])
547
548    return _a_canvas.create_polygon(
549        point_list, fill=_safe_color(color), outline=outline, tags=tag, 
550    )

A reporter function that draws a circle.

Arguments:
  • center (tuple): A coordinate representing the center of the shape.
  • radius (int): Specifies the circle's radius.
  • angle (int): A number between 0 and 360 that specifies how much of the circle to draw.
  • color (str): What color to draw the shape.
  • outline (str): What color should the border of the shape be.
  • tag (str): The tag to assign to the shape.
Returns:

Shape: The wedge that was created.

Shape_Modifier_Functions = ""
def above(shape1, shape2, offset_x=0, offset_y=0):
556def above(shape1, shape2, offset_x=0, offset_y=0):
557    """
558    A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1"s center
559    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
560    specified offset.
561
562    Args:
563        shape1 (`Shape` or Tag): The first shape to use.
564        shape2 (`Shape` or Tag): The second shape to use.
565        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
566        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
567
568    Returns:
569        `Shape`: The modified shape1.
570    """
571    overlay(shape1, shape2)
572    _a_canvas.move(
573        shape1,
574        0 + offset_x,
575        -1 * (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
576    )
577    return shape1

A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1's center to shape 2's center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any specified offset.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • offset_x (int): How much to shift shape 2 in the x-direction after moving it.
  • offset_y (int): How much to shift shape 2 in the x-direction after moving it.
Returns:

Shape: The modified shape1.

def align(shape1, shape2, via="middle", offset_x=0, offset_y=0):
580def align(shape1, shape2, via="middle", offset_x=0, offset_y=0):
581    """
582    A reporter function that aligns `shape1` with `shape2`. It does this by moving `shape1` to align with
583    whatever property of `shape2` is selected with the `via` input.
584
585    Args:
586        shape1 (`Shape` or Tag): The first shape to use.
587        shape2 (`Shape` or Tag): The second shape to use.
588        via (`str`): Has to be one of, the following options: `"center"` (horizontal center),
589            `"middle"` (vertical center), `"top"`, `"bottom"`, `"left"`, or `"right"`
590        offset_x (`int`): How much to shift in the x-axis after alignment
591        offset_y (`int`): How much to shift in the y-axis after alignment
592
593    Returns:
594        `Shape`: The modified shape1.
595    """
596    via_options = ["center", "middle", "top", "bottom", "left", "right"]
597    if via not in via_options
598        raise ValueError(
599            "The via input must be one of "
600            + (via_options)
601            + " but instead we found "
602            + (via)
603        )
604
605    outline1 = _get_outline(shape1)
606    outline2 = _get_outline(shape2)
607
608    if via == "center"
609        _a_canvas.move(
610            shape1, (outline2["center"][0] - outline1["center"][0]) + offset_x, offset_y
611        )
612
613    elif via == "middle"
614        _a_canvas.move(
615            shape1, offset_x, (outline2["center"][1] - outline1["center"][1]) + offset_y
616        )
617
618    elif via == "top"
619        _a_canvas.move(shape1, offset_x, (outline2["top"] - outline1["top"]) + offset_y)
620
621    elif via == "bottom"
622        _a_canvas.move(
623            shape1, offset_x, (outline2["bottom"] - outline1["bottom"]) + offset_y
624        )
625
626    elif via == "left"
627        _a_canvas.move(
628            shape1, (outline2["left"] - outline1["left"]) + offset_x, offset_y
629        )
630
631    elif via == "right"
632        _a_canvas.move(
633            shape1, (outline2["right"] - outline1["right"]) + offset_x, offset_y
634        )
635
636    return shape1

A reporter function that aligns shape1 with shape2. It does this by moving shape1 to align with whatever property of shape2 is selected with the via input.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • via (str): Has to be one of, the following options: "center" (horizontal center), "middle" (vertical center), "top", "bottom", "left", or "right"
  • offset_x (int): How much to shift in the x-axis after alignment
  • offset_y (int): How much to shift in the y-axis after alignment
Returns:

Shape: The modified shape1.

def beside(shape1, shape2, offset_x=0, offset_y=0):
639def beside(shape1, shape2, offset_x=0, offset_y=0):
640    """
641    A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1"s center
642    to shape 2"s center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any
643    specified offset.
644
645    Args:
646        shape1 (`Shape` or Tag): The first shape to use.
647        shape2 (`Shape` or Tag): The second shape to use.
648        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
649        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
650
651    Returns:
652        `Shape`: The modified shape1.
653    """
654    overlay(shape1, shape2)
655    _a_canvas.move(
656        shape1,
657        (get_width(shape2) + get_width(shape1)) / 2 + offset_x,
658        0 + offset_y,
659    )
660    return shape1

A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1's center to shape 2's center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any specified offset.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • offset_x (int): How much to shift shape 2 in the x-direction after moving it.
  • offset_y (int): How much to shift shape 2 in the x-direction after moving it.
Returns:

Shape: The modified shape1.

def below(shape1, shape2, offset_x=0, offset_y=0):
663def below(shape1, shape2, offset_x=0, offset_y=0):
664    """
665    A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1"s center
666    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
667    specified offset.
668
669    Args:
670        shape1 (`Shape` or Tag): The first shape to use.
671        shape2 (`Shape` or Tag): The second shape to use.
672        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
673        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
674
675    Returns:
676        `Shape`: The modified shape1.
677    """
678    overlay(shape1, shape2)
679    _a_canvas.move(
680        shape1,
681        0 + offset_x,
682        (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
683    )
684    return shape1

A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1's center to shape 2's center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any specified offset.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • offset_x (int): How much to shift shape 2 in the x-direction after moving it.
  • offset_y (int): How much to shift shape 2 in the x-direction after moving it.
Returns:

Shape: The modified shape1.

def change_color(shape, color):
687def change_color(shape, color):
688    """
689    Change the fill color of a tagged object.
690
691    Args:
692        shape (`Shape` or Tag): The shape or tag to re-fill.
693        color (`str`): A color name or hex code to re-fill with.
694    """
695    ids = _a_canvas.find_withtag(shape)
696    for id in ids
697        _a_canvas.itemconfig(id, fill=color)

Change the fill color of a tagged object.

Arguments:
  • shape (Shape or Tag): The shape or tag to re-fill.
  • color (str): A color name or hex code to re-fill with.
def delete(shape):
700def delete(shape):
701    """
702    A function that deletes a shape from our screen.
703
704    Args:
705        shape (`Shape` or Tag): The shape to delete.
706    """
707    _a_canvas.delete(shape)

A function that deletes a shape from our screen.

Arguments:
  • shape (Shape or Tag): The shape to delete.
def duplicate(shape, color=None):
710def duplicate(shape, color=None):
711    """
712    A reporter function that perfectly copies a shape and returns that copy.
713
714    Args:
715        shape (`Shape` or Tag): The shape to duplicate.
716        color (`str`): A new color to use with the duplicated shape.
717
718    Returns:
719        `Shape`: The new duplicated shape.
720    """
721    shape_type = _a_canvas.type(shape)
722    shape_config = _a_canvas.itemconfig(shape)
723    shape_coords = _a_canvas.coords(shape)
724    the_copy = None
725    if shape_type == "polygon"
726        new_config = {key shape_config[key][-1] for key in shape_config.keys()}
727        if color != None
728            new_config["fill"] = color
729        the_copy = _a_canvas.create_polygon(shape_coords, new_config)
730        return the_copy

A reporter function that perfectly copies a shape and returns that copy.

Arguments:
  • shape (Shape or Tag): The shape to duplicate.
  • color (str): A new color to use with the duplicated shape.
Returns:

Shape: The new duplicated shape.

def mirror(shape):
733def mirror(shape):
734    """
735    A function that takes a shape and flips it across its vertical
736    axis, returning the modified shape.
737
738    Args:
739        shape (`Shape` or Tag): The shape in question.
740
741    """
742    center = get_center(shape)[0]
743    shape_ids = _a_canvas.find_withtag(shape)
744    for shape_id in shape_ids
745        flipped_coordinates = []
746        shape_coords = _a_canvas.coords(shape_id)
747        counter = 0
748        for num in shape_coords
749            if counter % 2 == 0
750                if num < center
751                    flipped_coordinates.append(num + 2 * (center - num))
752                elif num > center
753                    flipped_coordinates.append(num - 2 * (num - center))
754                else
755                    flipped_coordinates.append(num)
756            else
757                flipped_coordinates.append(num)
758            counter += 1
759        _a_canvas.coords(shape_id, flipped_coordinates)

A function that takes a shape and flips it across its vertical axis, returning the modified shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
def move(shape, x_shift=0, y_shift=0):
762def move(shape, x_shift=0, y_shift=0):
763    """
764    Purpose: Move the x and y position of all shapes that have been tagged
765    with the tag argument
766
767    Args:
768        shape (`Shape` or Tag): The shape in question.
769        x_shift (`int`; optional): amount to move in the x direction
770        y_shift (`int`; optional): amount to move in the y direction
771    """
772    shape_ids = _a_canvas.find_withtag(shape)
773    for id in shape_ids
774        _a_canvas.move(id, x_shift, y_shift)

Purpose: Move the x and y position of all shapes that have been tagged with the tag argument

Arguments:
  • shape (Shape or Tag): The shape in question.
  • x_shift (int; optional): amount to move in the x direction
  • y_shift (int; optional): amount to move in the y direction
def move_to(tag, to, anchor="center"):
777def move_to(tag, to, anchor="center"):
778    """
779    Move the given tagged item to a particular `point` maintaining some `anchor`.
780    Note: this is NOT the same as the `move` function which moves an object by a specific amount.
781
782    Args:
783        tag (Shape or `str`): the shape (or shapes) to move
784        to (`tuple`): the `(x, y)` coordinate to which you wish to move the tagged object
785        anchor (`str`): which point on the shape do you want to move toward the given tuple. You can
786            use either `"center"` (default), `"top_left"`, `"top_right"`, `"bottom_left"`, or `"bottom_right"`.
787    """
788    anchor_options = ["center", "top_left", "top_right", "bottom_left", "bottom_right"]
789    if anchor not in anchor_options
790        raise ValueError(
791            "The anchor input must be one of "
792            + (anchor_options)
793            + " but instead we found "
794            + (anchor)
795        )
796
797    outline = _get_outline(tag)
798    delta_x = 0
799    delta_y = 0
800
801    if anchor == "top_left"
802        delta_x = to[0] - outline["left"]
803        delta_y = to[1] - outline["top"]
804    elif anchor == "top_right"
805        delta_x = to[0] - outline["right"]
806        delta_y = to[1] - outline["top"]
807    elif anchor == "bottom_right"
808        delta_x = to[0] - outline["right"]
809        delta_y = to[1] - outline["bottom"]
810    elif anchor == "bottom_left"
811        delta_x = to[0] - outline["left"]
812        delta_y = to[1] - outline["bottom"]
813    elif anchor == "center"
814        delta_x = to[0] - outline["center"][0]
815        delta_y = to[1] - outline["center"][1]
816
817    _a_canvas.move(tag, delta_x, delta_y)

Move the given tagged item to a particular point maintaining some anchor. Note: this is NOT the same as the move function which moves an object by a specific amount.

Arguments:
  • tag (Shape or str): the shape (or shapes) to move
  • to (tuple): the (x, y) coordinate to which you wish to move the tagged object
  • anchor (str): which point on the shape do you want to move toward the given tuple. You can use either "center" (default), "top_left", "top_right", "bottom_left", or "bottom_right".
def overlay(shape1, shape2, offset_x=0, offset_y=0):
820def overlay(shape1, shape2, offset_x=0, offset_y=0):
821    """
822    A reporter function that overlays shape1 onto shape2. It does this by moving shape 1"s center
823    to shape 2"s center, and then applying any specified offset.
824    Args:
825        shape1 (`Shape` or Tag): The first shape to use.
826        shape2 (`Shape` or Tag): The second shape to use.
827        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
828        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
829
830    Returns:
831        `Shape`: The modified shape1.
832    """
833    center1 = get_center(shape1)
834    center2 = get_center(shape2)
835    _a_canvas.move(
836        shape1,
837        (center2[0] - center1[0]) + offset_x,
838        (center2[1] - center1[1]) + offset_y,
839    )
840    _a_canvas.tag_raise(shape1, shape2)
841    return shape1

A reporter function that overlays shape1 onto shape2. It does this by moving shape 1's center to shape 2's center, and then applying any specified offset.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • offset_x (int): How much to shift shape 2 in the x-direction after centering it.
  • offset_y (int): How much to shift shape 2 in the x-direction after centering it.
Returns:

Shape: The modified shape1.

def portion(shape, start=0, end=0.5):
844def portion(shape, start=0, end=0.5):
845    """
846    Purpose: Take a slice or portion of some already created shape.
847
848    Args:
849        shape (`Shape` or Tag): The shape to take a portion of
850        start (`float`): A number between 0 and 1 representing where to start the slice.
851        end (`float`): A number between 0 and 1 representing where to end the slice.
852
853    For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle.
854
855    Note: this function is experimental. It might produce unexpected results!
856    """
857    all_shapes = _a_canvas.find_withtag(shape)
858
859    for a_shape in all_shapes
860        coords = _a_canvas.coords(a_shape)
861
862        start_coord = floor(start * len(coords))
863        if start_coord % 2 == 1
864            start_coord = start_coord - 1  # need to start with an x,y pair
865        end_coord = floor(end * len(coords))
866        if end_coord % 2 == 1
867            end_coord = end_coord - 1  # need to end with an x,y pair
868
869        # slice is up to not including so get the last x,y pair
870        new_coords = coords[start_coord  end_coord + 2]
871
872        # loop shape back in on itself
873        new_coords.append(new_coords[0])
874        new_coords.append(new_coords[1])
875
876        # set the coordinates:
877        _a_canvas.coords(a_shape, new_coords)

Purpose: Take a slice or portion of some already created shape.

Arguments:
  • shape (Shape or Tag): The shape to take a portion of
  • start (float): A number between 0 and 1 representing where to start the slice.
  • end (float): A number between 0 and 1 representing where to end the slice.

For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle.

Note: this function is experimental. It might produce unexpected results!

def put_in_back(shape):
880def put_in_back(shape):
881    """
882    A function that "lowers" a shape to the "bottom" of the screen."
883
884    Args:
885        shape (`Shape` or Tag): The shape in question.
886    """
887    _a_canvas.tag_lower(shape)

A function that "lowers" a shape to the "bottom" of the screen."

Arguments:
  • shape (Shape or Tag): The shape in question.
def put_in_front(shape):
890def put_in_front(shape):
891    """
892    A function that "raises" a shape to the "top" of the screen."
893
894    Args:
895        shape (`Shape` or Tag): The shape in question.
896    """
897    _a_canvas.tag_raise(shape)

A function that "raises" a shape to the "top" of the screen."

Arguments:
  • shape (Shape or Tag): The shape in question.
def rotate(shape, degrees=5, origin=None):
900def rotate(shape, degrees=5, origin=None):
901    """
902    A reporter function that takes a shape and rotates it by a specified amount around a specified point.
903    It does this by interpolating a polygon around the shape and calculating the shifts of individual
904    points on the edge of the polygon.
905
906    Args:
907        shape (`Shape` or Tag): The shape to rotate.
908        degrees (`int`): The number of degrees to rotate the shape.
909        origin (`tuple`): An `(x,y)` coordinate about which to perform the rotation. Defaults to the center
910            of the given shape.
911
912    Returns:
913        `Shape`: The modified shape.
914    """
915    if origin is None
916        origin = get_center(shape)
917
918    theta = radians(degrees)
919    ox, oy = origin
920
921    all_shapes = _a_canvas.find_withtag(shape)
922
923    for a_shape in all_shapes
924        coords = _a_canvas.coords(a_shape)
925        # update coordinates:
926        for i in range(0, len(coords), 2):
927            px, py = coords[i], coords[i + 1]
928            qx = cos(theta) * (px - ox) - sin(theta) * (py - oy) + ox
929            qy = sin(theta) * (px - ox) + cos(theta) * (py - oy) + oy
930            coords[i] = qx
931            coords[i + 1] = qy
932        # set the coordinates:
933        _a_canvas.coords(a_shape, coords)
934
935    return shape

A reporter function that takes a shape and rotates it by a specified amount around a specified point. It does this by interpolating a polygon around the shape and calculating the shifts of individual points on the edge of the polygon.

Arguments:
  • shape (Shape or Tag): The shape to rotate.
  • degrees (int): The number of degrees to rotate the shape.
  • origin (tuple): An (x,y) coordinate about which to perform the rotation. Defaults to the center of the given shape.
Returns:

Shape: The modified shape.

def scale(shape, x_scale=1.0, y_scale=1.0):
938def scale(shape, x_scale=1.0, y_scale=1.0):
939    """
940    A function that takes a given `Shape` or tag and scales it on either/both the x and y-axis.
941
942    The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause
943    the shape to grow along that access. Values less than 1.0 will cause the shape to shrink.
944
945    Args:
946        shape (`Shape` or Tag): The shape or tag to re-fill.
947        x_scale (`float`): How much to scale in the x-axis.
948        y_scale (`float`): How much to scale in the y-axis.
949    """
950    ids = _a_canvas.find_withtag(shape)
951
952    coord = get_center(shape)
953
954    for i in ids
955        _a_canvas.scale(i, coord[0], coord[1], x_scale, y_scale)

A function that takes a given Shape or tag and scales it on either/both the x and y-axis.

The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause the shape to grow along that access. Values less than 1.0 will cause the shape to shrink.

Arguments:
  • shape (Shape or Tag): The shape or tag to re-fill.
  • x_scale (float): How much to scale in the x-axis.
  • y_scale (float): How much to scale in the y-axis.
def underlay(shape1, shape2, offset_x=0, offset_y=0):
958def underlay(shape1, shape2, offset_x=0, offset_y=0):
959    """
960    A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1"s center
961    to shape 2"s center, and then applying any specified offset.
962    Args:
963        shape1 (`Shape` or Tag): The first shape to use.
964        shape2 (`Shape` or Tag): The second shape to use.
965        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
966        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
967
968    Returns:
969        `Shape`: The modified shape1.
970    """
971    center1 = get_center(shape1)
972    center2 = get_center(shape2)
973    _a_canvas.move(
974        shape1,
975        (center2[0] - center1[0]) + offset_x,
976        (center2[1] - center1[1]) + offset_y,
977    )
978    _a_canvas.tag_lower(shape1, shape2)
979    return shape1

A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1's center to shape 2's center, and then applying any specified offset.

Arguments:
  • shape1 (Shape or Tag): The first shape to use.
  • shape2 (Shape or Tag): The second shape to use.
  • offset_x (int): How much to shift shape 2 in the x-direction after centering it.
  • offset_y (int): How much to shift shape 2 in the x-direction after centering it.
Returns:

Shape: The modified shape1.

Utility_Functions = ""
def clear_window(keep_grid=True):
 985def clear_window(keep_grid=True):
 986    """
 987    A function that deletes everything from the window.
 988
 989    Args:
 990        keep_grid (`bool`): Whether or not to keep the grid.
 991    """
 992    all_shapes = _a_canvas.find_all()
 993
 994    for shape in all_shapes
 995        tags = _a_canvas.gettags(shape)
 996        if "grid" in tags and keep_grid
 997            continue
 998        _a_canvas.delete(shape)
 999
1000    global _resize_enabled
1001    _resize_enabled = True

A function that deletes everything from the window.

Arguments:
  • keep_grid (bool): Whether or not to keep the grid.
def distance(point1, point2):
1004def distance(point1, point2):
1005    """
1006    A reporter function calculates the distance between two `(x, y)` coordinates.
1007
1008    Args:
1009        point1 (`tuple`): The first `(x, y)` coordinate.
1010        point2 (`tuple`): The second `(x, y)` coordinate.
1011
1012    Returns:
1013         A `float` representing the distance between the two points.
1014    """
1015    return sqrt(((point1[0] - point2[0])  2) + ((point1[1] - point2[1])  2))

A reporter function calculates the distance between two (x, y) coordinates.

Arguments:
  • point1 (tuple): The first (x, y) coordinate.
  • point2 (tuple): The second (x, y) coordinate.
Returns:

A float representing the distance between the two points.

def does_tag_exist(tag):
1018def does_tag_exist(tag):
1019    """
1020    Returns `True` if a given tag exists otherwise returns `False`.
1021
1022    Args:
1023        `tag` (`str`): [Required] The tag of the object to lookup.
1024
1025    """
1026    result = _a_canvas.find_withtag(tag)
1027
1028    if result
1029        return True
1030    else
1031        return False

Returns True if a given tag exists otherwise returns False.

Arguments:
  • tag (str): [Required] The tag of the object to lookup.
def get_bottom(shape):
1034def get_bottom(shape):
1035    """
1036    A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped).
1037
1038    Args:
1039        shape (`Shape` or Tag): The shape in question.
1040
1041    Returns:
1042         A `int` representing the maximum y-coordinate of the shape.
1043    """
1044    bbox = _safe_bbox(shape)
1045    return bbox[3]

A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped).

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A int representing the maximum y-coordinate of the shape.

def get_center(shape):
1048def get_center(shape):
1049    """
1050    A reporter function calculates the a coordinate at the center of some shape.
1051
1052    Args:
1053        shape (`Shape` or Tag): The shape in question.
1054
1055    Returns:
1056         A `tuple` representing center of the given shape.
1057    """
1058    bbox = _safe_bbox(shape)
1059
1060    if bbox is None
1061        raise Exception(
1062            f"We couldn"t find the shape with id/tag {shape}. Make sure it exists!"
1063        )
1064
1065    return (((bbox[2] + bbox[0]) / 2), ((bbox[1] + bbox[3]) / 2))

A reporter function calculates the a coordinate at the center of some shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A tuple representing center of the given shape.

def get_colors(shape_or_shapes):
1068def get_colors(shape_or_shapes):
1069    """
1070    A reporter function that returns all the colors associated with a tag or list of tags.
1071
1072    Args:
1073        shape_or_shapes (`str`/`Shape` or `List`): the shape/tag or list of shapes/tags you"d like to find the colors of
1074
1075    Returns:
1076        A `List` containing all unique colors associated with that tag(s)
1077    """
1078    all_shapes = []
1079    if not isinstance(shape_or_shapes, ):
1080        shape_or_shapes = [shape_or_shapes]
1081    for shape in shape_or_shapes
1082        all_shapes += _a_canvas.find_withtag(shape)
1083
1084    all_colors = []
1085    for shape in all_shapes
1086        color = _a_canvas.itemcget(shape, "fill")
1087        if color not in all_colors
1088            all_colors.append(color)
1089
1090    return all_colors

A reporter function that returns all the colors associated with a tag or list of tags.

Arguments:
  • shape_or_shapes (str/Shape or List): the shape/tag or list of shapes/tags you'd like to find the colors of
Returns:

A List containing all unique colors associated with that tag(s)

def get_height(shape):
1093def get_height(shape):
1094    """
1095    A reporter function calculates the height of some given shape.
1096
1097    Args:
1098        shape (`Shape` or Tag): The shape in question.
1099
1100    Returns:
1101         A `int` representing the height of the shape.
1102    """
1103    bbox = _safe_bbox(shape)
1104    return bbox[3] - bbox[1] - 1

A reporter function calculates the height of some given shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A int representing the height of the shape.

def get_left(shape):
1107def get_left(shape):
1108    """
1109    A reporter function calculates the minimum x-value of a given shape.
1110
1111    Args:
1112        shape (`Shape` or Tag): The shape in question.
1113
1114    Returns:
1115         A `int` representing the minimum x-coordinate of the shape.
1116    """
1117    bbox = _safe_bbox(shape)
1118    return bbox[0]

A reporter function calculates the minimum x-value of a given shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A int representing the minimum x-coordinate of the shape.

def get_right(shape):
1121def get_right(shape):
1122    """
1123    A reporter function calculates the maximum x-value of a given shape.
1124
1125    Args:
1126        shape (`Shape` or Tag): The shape in question.
1127
1128    Returns:
1129         A `int` representing the maximum x-coordinate of the shape.
1130    """
1131    bbox = _safe_bbox(shape)
1132    return bbox[2]

A reporter function calculates the maximum x-value of a given shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A int representing the maximum x-coordinate of the shape.

def get_tag_from_event(event, precision=25):
1135def get_tag_from_event(event, precision=25):
1136    """
1137    Tries to return a tag of an object at a given mouse-event.
1138
1139    Args:
1140        event (`Event`): Must be a mouse event otherwise we"ll give back an error.
1141        precision (`int`): How precise in number of pixels does a user have be in order to "select" an object
1142
1143    Returns a blank string `""` if no shapes are found closer than `precision`.
1144    """
1145
1146    if (event.type) not in [4, 6]:
1147        raise Exception(f"Received an event that isn"t a mouse event: {event}")
1148
1149    try
1150        x = event.x
1151        y = event.y
1152        shape_id = _a_canvas.find_closest(x, y)  # get the top shape
1153        if shape_id and distance(get_center(shape_id), (x, y)) < precision
1154            tags = _a_canvas.gettags(shape_id)
1155            if len(tags) > 0
1156                return tags[0]
1157        return ""
1158
1159    except
1160        raise Exception(
1161            "No tag found! Maybe you passed us an event that isn"t a mouse event?"
1162        )

Tries to return a tag of an object at a given mouse-event.

Arguments:
  • event (Event): Must be a mouse event otherwise we'll give back an error.
  • precision (int): How precise in number of pixels does a user have be in order to "select" an object

Returns a blank string "" if no shapes are found closer than precision.

def get_top(shape):
1165def get_top(shape):
1166    """
1167    A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped).
1168
1169    Args:
1170        shape (`Shape` or Tag): The shape in question.
1171
1172    Returns:
1173         A `int` representing the minimum y-coordinate of the shape.
1174    """
1175    bbox = _safe_bbox(shape)
1176    return bbox[1]

A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped).

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

A int representing the minimum y-coordinate of the shape.

def get_width(shape):
1179def get_width(shape):
1180    """
1181    A reporter function calculates the width of some given shape.
1182
1183    Args:
1184        shape (`Shape` or Tag): The shape in question.
1185
1186    Returns:
1187         An `int` representing width of the shape.
1188    """
1189    bbox = _safe_bbox(shape)
1190    return bbox[2] - bbox[0] - 1

A reporter function calculates the width of some given shape.

Arguments:
  • shape (Shape or Tag): The shape in question.
Returns:

An int representing width of the shape.

def get_window_height():
1193def get_window_height():
1194    """
1195    A reporter function that returns the current height of the window.
1196
1197    Returns:
1198         An `int` representing height of the window.
1199    """
1200    return _a_canvas.winfo_height()

A reporter function that returns the current height of the window.

Returns:

An int representing height of the window.

def get_window_width():
1203def get_window_width():
1204    """
1205    A reporter function that returns the current width of the window.
1206
1207    Returns:
1208         An `int` representing width of the window.
1209    """
1210    return _a_canvas.winfo_width()

A reporter function that returns the current width of the window.

Returns:

An int representing width of the window.

def interpolate_colors(color1, color2, frac):
1213def interpolate_colors(color1, color2, frac):
1214    """
1215    A reporter function that generates a new color between two given colors.
1216    Args:
1217        color1 (`str`): The path of the file to wrap
1218        color2 (`str`): The path of the file to wrap
1219        frac (`float`): What fraction of each color to take. An input of 0 returns
1220            color1, an input of 1 returns color2, an input of 0.5 returns a color
1221            perfectly between the two.
1222
1223    Returns:
1224         A color (as a hex `str`) to be used elsewhere
1225    """
1226    if "#" not in color1
1227        color1 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color1)))
1228    else
1229        color1 = _tupelize_color(color1)
1230    if "#" not in color2
1231        color2 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color2)))
1232    else
1233        color2 = _tupelize_color(color2)
1234    return _interpolate_tuple(color1, color2, frac)

A reporter function that generates a new color between two given colors.

Arguments:
  • color1 (str): The path of the file to wrap
  • color2 (str): The path of the file to wrap
  • frac (float): What fraction of each color to take. An input of 0 returns color1, an input of 1 returns color2, an input of 0.5 returns a color perfectly between the two.
Returns:

A color (as a hex str) to be used elsewhere

def random_color():
1237def random_color():
1238    """
1239    Returns a random color as a `string` to be used.
1240    It does not accept any inputs.
1241    """
1242    r = lambda randint(0, 255)
1243    return "#%02X%02X%02X" % (r(), r(), r())

Returns a random color as a string to be used. It does not accept any inputs.

def setup_listener(event_str, handler_function, override=False):
1246def setup_listener(event_str, handler_function, override=False):
1247    """
1248    Sets up a listener for a given event on our window.
1249
1250    Args:
1251        event_str (`str`): The magic string that represents this event in the window
1252        handler_function (`func`): The name (not a string though) of the function you want called when the event his heard
1253        override (`bool`): Only use this if you speak to Prof. Bain and he recommends it.
1254
1255    The supported events are:
1256      * `"LEFT-CLICK"`: Left mouse click
1257      * `"RIGHT-CLICK"`: Right mouse click
1258      * `"ALT-CLICK"`: If you"re using a PC, this event might instead work for Right Click
1259      * `"LEFT-DRAG"`: Left mouse clicked and dragged on the screen
1260      * `"RIGHT-DRAG"`: Right mouse clicked and dragged on the screen
1261      * `"ALT-DRAG"`: For PCs, this event might instead work for RIGHT-DRAG
1262      * `"DOUBLE-LEFT"`: Left mouse double click
1263      * `"DOUBLE-RIGHT"`: Right mouse double click
1264      * `"DOUBLE-ALT"`: For PCs, this event might instead work for DOUBLE-RIGHT
1265      * `"KEY"`: The catch-all event for Keyboard presses
1266    """
1267
1268    event_translator = {
1269        "LEFT-CLICK" "<Button-1>",
1270        "RIGHT-CLICK" "<Button-2>",
1271        "ALT-CLICK" "<Button-3>",
1272        "LEFT-DRAG" "<B1-Motion>",
1273        "RIGHT-DRAG" "<B2-Motion>",
1274        "ALT-DRAG" "<B3-Motion>",
1275        "DOUBLE-LEFT" "<Double-Button-1>",
1276        "DOUBLE-RIGHT" "<Double-Button-2>",
1277        "DOUBLE-ALT" "<Double-Button-3>",
1278        "KEY" "<Key>",
1279    }
1280
1281    if event_str not in event_translator and not override
1282        raise (
1283            TypeError(
1284                f"The event you entered, {event_str}, isn"t supported. Here are the supported events: {[i for i in event_translator]}"
1285            )
1286        )
1287
1288    event = event_translator[event_str]
1289    
1290    setup_listener.tracker.add(event_str)
1291
1292    _a_canvas.bind(event, handler_function)

Sets up a listener for a given event on our window.

Arguments:
  • event_str (str): The magic string that represents this event in the window
  • handler_function (func): The name (not a string though) of the function you want called when the event his heard
  • override (bool): Only use this if you speak to Prof. Bain and he recommends it.
The supported events are:
  • "LEFT-CLICK": Left mouse click
  • "RIGHT-CLICK": Right mouse click
  • "ALT-CLICK": If you're using a PC, this event might instead work for Right Click
  • "LEFT-DRAG": Left mouse clicked and dragged on the screen
  • "RIGHT-DRAG": Right mouse clicked and dragged on the screen
  • "ALT-DRAG": For PCs, this event might instead work for RIGHT-DRAG
  • "DOUBLE-LEFT": Left mouse double click
  • "DOUBLE-RIGHT": Right mouse double click
  • "DOUBLE-ALT": For PCs, this event might instead work for DOUBLE-RIGHT
  • "KEY": The catch-all event for Keyboard presses
def setup_shapes(title, background="white", include_grid=True, width=600, height=600):
1296def setup_shapes(title, background="white", include_grid=True, width=600, height=600):
1297    """
1298    A static function that sets up the pop-up window. You can specify the size of the window here.
1299
1300    However, you should NOT add any calls to this function unless Prof. Bain specifically tells you to!
1301
1302    Args:
1303        title (`str`): The title of the pop-up window.
1304        background (`str`): A valid color as a string to be used as the background color.
1305        include_grid (`bool`): Whether or not to draw the grid.
1306        width (`int` or `str`): How wide the window should appear (advanced: use the string "FULLWIDTH" to maximize the width)
1307        height (`int` or `str`): How wide the window should appear (advanced: use the string "FULLHEIGHT" to maximize the width)
1308    """
1309
1310    global _a_canvas
1311    gui = Tk()
1312    gui.title(title)
1313
1314    if width == "FULLWIDTH"
1315        width = gui.winfo_screenwidth()
1316
1317    if height == "FULLHEIGHT"
1318        height = gui.winfo_screenheight()
1319
1320    _a_canvas = Canvas(gui, background=background, width=width, height=height)
1321    _a_canvas.pack()
1322    if include_grid
1323        grid(width, height)
1324
1325    _a_canvas.focus_set()
1326    return _a_canvas

A static function that sets up the pop-up window. You can specify the size of the window here.

However, you should NOT add any calls to this function unless Prof. Bain specifically tells you to!

Arguments:
  • title (str): The title of the pop-up window.
  • background (str): A valid color as a string to be used as the background color.
  • include_grid (bool): Whether or not to draw the grid.
  • width (int or str): How wide the window should appear (advanced: use the string "FULLWIDTH" to maximize the width)
  • height (int or str): How wide the window should appear (advanced: use the string "FULLHEIGHT" to maximize the width)
def update():
1329def update():
1330    """
1331    A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION unless Prof. Bain explictly says to use it.
1332    """
1333    _a_canvas.update()

A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION unless Prof. Bain explictly says to use it.