cs110_ex3

   1### IGNORE EVERYTHING THAT STARTS WITH A _
   2from random import randint
   3from math import sqrt, pi, radians, sin, cos, floor
   4
   5__docformat__ = "google"
   6
   7_a_canvas = None
   8
   9
  10def _safe_color(color ):
  11
  12    if not isinstance(color, ):
  13        raise TypeError(f"Colors must be a string! You entered: {color}")
  14
  15    color = color.strip()
  16
  17    # Could also do some other verifications here...
  18    return color
  19
  20
  21def rectangle(
  22    top_left=(0, 0), width=25, height=50, color="hotpink", outline="", tag="", 
  23):
  24    """
  25    A reporter function that draws a rectangle.
  26    Args:
  27        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
  28        width (`int`): How wide to draw the shape.
  29        height (`int`): How tall to draw the shape.
  30        color (`str`): What color to draw the shape.
  31        outline (`str`): What color should the border of the shape be.
  32        tag (`str`): The tag to assign to the shape.
  33
  34    Returns:
  35         `Shape`: The rectangle that was created.
  36    """
  37    point_0 = top_left
  38    point_1 = (top_left[0] + width, top_left[1])
  39    point_2 = (top_left[0] + width, top_left[1] + height)
  40    point_3 = (top_left[0], top_left[1] + height)
  41    return _a_canvas.create_polygon(
  42        point_0, point_1, point_2, point_3, fill=_safe_color(color), tags=tag, 
  43    )
  44
  45
  46def square(top_left=(0, 0), size=25, color="hotpink", outline="", tag="", ):
  47    """
  48    A reporter function that draws a square.
  49    Args:
  50        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
  51        size (`int`): How big to draw the shape.
  52        color (`str`): What color to draw the shape.
  53        outline (`str`): What color should the border of the shape be.
  54        tag (`str`): The tag to assign to the shape.
  55
  56    Returns:
  57         `Shape`: The square that was created.
  58    """
  59    return rectangle(
  60        top_left=top_left, width=size, height=size, color=color, tag=tag, 
  61    )
  62
  63
  64def oval(
  65    center=(0, 0),
  66    radius_x=25,
  67    radius_y=50,
  68    color="hotpink",
  69    outline="",
  70    tag="",
  71    ,
  72):
  73    """
  74    A reporter function that draws an oval.
  75    Args:
  76        center (`tuple`): A coordinate representing the center of the shape.
  77        radius_x (`int`): Specifies the oval"s radius on the x-axis.
  78        radius_y (`int`): Specifies the oval"s radius on the y-axis.
  79        color (`str`): What color to draw the shape.
  80        outline (`str`): What color should the border of the shape be.
  81        tag (`str`): The tag to assign to the shape.
  82
  83    Returns:
  84         `Shape`: The oval that was created.
  85    """
  86    x = center[0]
  87    y = center[1]
  88    x0, y0, x1, y1 = (x - radius_x, y - radius_y, x + radius_x, y + radius_y)
  89    steps = 100
  90    # major and minor axes
  91    a = (x1 - x0) / 2.0
  92    b = (y1 - y0) / 2.0
  93    # center
  94    xc = x0 + a
  95    yc = y0 + b
  96    point_list = []
  97    # create the oval as a list of points
  98    for i in range(steps):
  99        # Calculate the angle for this step
 100        theta = (pi * 2) * (float(i) / steps)
 101        x = a * cos(theta)
 102        y = b * sin(theta)
 103        point_list.append(round(x + xc))
 104        point_list.append(round(y + yc))
 105
 106    return _a_canvas.create_polygon(
 107        point_list, fill=_safe_color(color), tags=tag, 
 108    )
 109
 110
 111def circle(center=(0, 0), radius=25, color="hotpink", outline="", tag="", ):
 112    """
 113    A reporter function that draws a circle.
 114    Args:
 115        center (`tuple`): A coordinate representing the center of the shape.
 116        radius (`int`): Specifies the circle"s radius.
 117        color (`str`): What color to draw the shape.
 118        outline (`str`): What color should the border of the shape be.
 119        tag (`str`): The tag to assign to the shape.
 120
 121    Returns:
 122         `Shape`: The circle that was created.
 123    """
 124    return oval(
 125        center=center, radius_x=radius, radius_y=radius, color=color, tag=tag, 
 126    )
 127
 128
 129def wedge(
 130    center=(0, 0), radius=25, angle=180, color="hotpink", outline="", tag="", 
 131):
 132    """
 133    A reporter function that draws a circle.
 134    Args:
 135        center (`tuple`): A coordinate representing the center of the shape.
 136        radius (`int`): Specifies the circle"s radius.
 137        angle (`int`): A number between 0 and 360 that specifies how much of the circle to draw.
 138        color (`str`): What color to draw the shape.
 139        outline (`str`): What color should the border of the shape be.
 140        tag (`str`): The tag to assign to the shape.
 141
 142    Returns:
 143         `Shape`: The wedge that was created.
 144    """
 145    point_list = [center[0], center[1]]
 146    for i in range(0, 0 + angle):
 147        x1 = center[0] + radius * cos(radians(i))
 148        point_list.append(x1)
 149        y1 = center[1] + radius * sin(radians(i))
 150        point_list.append(y1)
 151
 152    point_list.append(center[0])
 153    point_list.append(center[1])
 154
 155    return _a_canvas.create_polygon(
 156        point_list, fill=_safe_color(color), outline=outline, tags=tag, 
 157    )
 158
 159
 160def triangle(
 161    bottom_center=(0, 0),
 162    width=25,
 163    top_shift=0,
 164    height=0,
 165    color="hotpink",
 166    outline="",
 167    tag="",
 168    ,
 169):
 170    """
 171    A reporter function that draws a triangle.
 172    Args:
 173        bottom_center (`tuple`): A coordinate representing the bottom center of the shape.
 174        width (`int`): Specifies the width of the base of the triangle.
 175        top_shift (`int`): Specifies the how far to the left or right to shift the top of
 176            the triangle from the bottom center.
 177        height (`int`): Specifies the triangle"s height.
 178        color (`str`): What color to draw the shape.
 179        outline (`str`): What color should the border of the shape be.
 180        tag (`str`): The tag to assign to the shape.
 181
 182    Returns:
 183         `Shape`: The triangle that was created.
 184    """
 185    if height == 0
 186        height = width * sqrt(3) / 2
 187    point_0 = (bottom_center[0] - width / 2, bottom_center[1])
 188    point_1 = (bottom_center[0] + width / 2, bottom_center[1])
 189    point_2 = (bottom_center[0] + top_shift, bottom_center[1] - height)
 190
 191    return _a_canvas.create_polygon(
 192        point_0, point_1, point_2, fill=_safe_color(color), tags=tag, 
 193    )
 194
 195
 196def line(points=[], curvy=False, color="hotpink", tag="", ):
 197    """
 198    A reporter function that draws a line given a list of points.
 199    Args:
 200        points (`list`): The points that define the line; this should be a list of tuples (coordinates).
 201        curvy (`bool`): Makes a curvy line instead.
 202        color (`str`): What color to make the shape.
 203        tag (`str`): The tag to assign to the shape.
 204
 205    Returns:
 206        `Shape`: The line that was created.
 207    """
 208    return _a_canvas.create_line(points, fill=color, smooth=curvy, tags=tag, )
 209
 210
 211def arc(points=[], width=5, color="hotpink", line_steps=15, tag="", ):
 212    """
 213    A reporter function that draws an arc ("curve") given a list of points.
 214    Args:
 215        points (`list`): The points outlining the curve; this should be a list of tuples (coordinates).
 216            Make sure to give it at least 3 (x,y) coordinates that aren"t a straight line!
 217        color (`str`): What color to make the shape.
 218        tag (`str`): The tag to assign to the shape.
 219
 220    Returns:
 221        `Shape`: The arc that was created.
 222    """
 223    return _a_canvas.create_line(
 224        points,
 225        width=width,
 226        fill=color,
 227        splinesteps=line_steps,
 228        smooth=True,
 229        tags=tag,
 230        ,
 231    )
 232
 233
 234def diamond(
 235    center=(0, 0), width=25, height=50, color="hotpink", outline="", tag="", 
 236):
 237    """
 238    A reporter function that draws a rectangle.
 239    Args:
 240        center (`tuple`): A coordinate representing the center of the shape.
 241        width (`int`): How wide to draw the shape.
 242        height (`int`): How tall to draw the shape.
 243        color (`str`): What color to draw the shape.
 244        outline (`str`): What color should the border of the shape be.
 245        tag (`str`): The tag to assign to the shape.
 246
 247    Returns:
 248         `Shape`: The shape that was created.
 249    """
 250    point_0 = (center[0] - width / 2, center[1])
 251    point_1 = (center[0], center[1] - height / 2)
 252    point_2 = (center[0] + width / 2, center[1])
 253    point_3 = (center[0], center[1] + height / 2)
 254    return _a_canvas.create_polygon(
 255        point_0,
 256        point_1,
 257        point_2,
 258        point_3,
 259        fill=_safe_color(color),
 260        tags=tag,
 261        outline=outline,
 262        ,
 263    )
 264
 265
 266def star(
 267    center=(0, 0),
 268    radius=50,
 269    color="hotpink",
 270    outer_radius=75,
 271    points=5,
 272    outline="",
 273    tag="",
 274    ,
 275):
 276    """
 277    A reporter function that draws a star.
 278    Args:
 279        center (`tuple`): A coordinate representing the center of the shape.
 280        radius (`int`): Specifies the radius of the inside part of the star.
 281        color (`str`): Specifies the color of the star.
 282        outer_radius (`int`): Specifies the radius of the outside part of the star.
 283        points (`int`): Specifies the number of points for the star.
 284        outline (`str`): What color should the border of the shape be.
 285        tag (`str`): The tag to assign to the shape.
 286
 287    Returns:
 288         `Shape`: The star that was created.
 289    """
 290    arc_segment = 360 / points
 291    vertices = []
 292    for i in range(points):
 293        inner_point = (
 294            radius * cos(radians(arc_segment * i)) + center[0],
 295            -1 * radius * sin(radians(arc_segment * i)) + center[1],
 296        )
 297        vertices.append(inner_point)
 298        outer_point = (
 299            outer_radius * cos(radians(arc_segment * i + arc_segment / 2)) + center[0],
 300            -1 * outer_radius * sin(radians(arc_segment * i + arc_segment / 2))
 301            + center[1],
 302        )
 303        vertices.append(outer_point)
 304    return polygon(vertices, color=color, tag=tag, )
 305
 306
 307def polygon(points=[], color="hotpink", outline="", tag="", ):
 308    """
 309    A reporter function that draws a polygon given a list of points.
 310    Args:
 311        points (`list`): The points outlining the polygon; this should be a list of tuples (coordinates).
 312            defaults to an empty list.
 313        outline (`str`): What color should the border of the shape be.
 314        color (`str`): What color to make the shape.
 315
 316    Returns:
 317        `Shape`: The polygon that was created.
 318    """
 319    return _a_canvas.create_polygon(points, fill=_safe_color(color), tags=tag, )
 320
 321
 322def _polar_to_cartesian(r, theta):
 323    return (r * cos(theta)), (r * sin(theta))
 324
 325
 326def spiral(
 327    center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1, 
 328):
 329    """
 330    A reporter function that draws a spiral.
 331    Args:
 332        center (`tuple`): A coordinate representing the center of the shape.
 333        width (`int`): Specifies the total width of the spiral.
 334        roughness (`float`): Controls how spiral-y the shape is (lower is less spiral-y)
 335        start (`int`): Where on the spiral to start drawing.
 336        spirals (`int`): How many loops to draw.
 337        line_width (`int`): How wide for the line to be drawn.
 338        tag (`str`): The tag to assign to the shape.
 339
 340    Returns:
 341         `Shape`: The spiral that was created.
 342    """
 343    theta = 0.0
 344    r = start
 345    all_points = []
 346    prev_pos = _polar_to_cartesian(r, theta)
 347    distance = width / 4 / pi / spirals
 348    all_points.append((prev_pos[0] + center[0], prev_pos[1] + center[1]))
 349    while theta < 2 * spirals * pi
 350        theta += roughness
 351        r = start + distance * theta
 352        pos = _polar_to_cartesian(r, theta)
 353        all_points.append((pos[0] + center[0], pos[1] + center[1]))
 354
 355    return arc(points=all_points, width=line_width, )
 356
 357
 358def move(shape, x_shift=0, y_shift=0):
 359    """
 360    Purpose: Move the x and y position of all shapes that have been tagged
 361    with the tag argument
 362
 363    Args:
 364        shape (`Shape` or Tag): The shape in question.
 365        x_shift (`int`; optional): amount to move in the x direction
 366        y_shift (`int`; optional): amount to move in the y direction
 367    """
 368    shape_ids = _a_canvas.find_withtag(shape)
 369    for id in shape_ids
 370        _a_canvas.move(id, x_shift, y_shift)
 371
 372
 373def portion(shape, start=0, end=0.5):
 374    """
 375    Purpose: Take a slice or portion of some already created shape.
 376
 377    Args:
 378        shape (`Shape` or Tag): The shape to take a portion of
 379        start (`float`): A number between 0 and 1 representing where to start the slice.
 380        end (`float`): A number between 0 and 1 representing where to end the slice.
 381
 382    For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle.
 383
 384    Note: this function is experimental. It might produce unexpected results!
 385    """
 386    all_shapes = _a_canvas.find_withtag(shape)
 387
 388    for a_shape in all_shapes
 389        coords = _a_canvas.coords(a_shape)
 390
 391        start_coord = floor(start * len(coords))
 392        if start_coord % 2 == 1
 393            start_coord = start_coord - 1  # need to start with an x,y pair
 394        end_coord = floor(end * len(coords))
 395        if end_coord % 2 == 1
 396            end_coord = end_coord - 1  # need to end with an x,y pair
 397
 398        # slice is up to not including so get the last x,y pair
 399        new_coords = coords[start_coord  end_coord + 2]
 400
 401        # loop shape back in on itself
 402        new_coords.append(new_coords[0])
 403        new_coords.append(new_coords[1])
 404
 405        # set the coordinates:
 406        _a_canvas.coords(a_shape, new_coords)
 407
 408
 409def put_in_front(shape):
 410    """
 411    A function that "raises" a shape to the "top" of the screen."
 412
 413    Args:
 414        shape (`Shape` or Tag): The shape in question.
 415    """
 416    _a_canvas.tag_raise(shape)
 417
 418
 419def put_in_back(shape):
 420    """
 421    A function that "lowers" a shape to the "bottom" of the screen."
 422
 423    Args:
 424        shape (`Shape` or Tag): The shape in question.
 425    """
 426    _a_canvas.tag_lower(shape)
 427
 428
 429def _get_outline(shape):
 430    """
 431    A reporter function that takes in a shape and calls the various helper functions to generate
 432    a sort of "summary" of that particular shape and returns it in the form of a dictionary.
 433
 434    Args:
 435        shape (`Shape` or Tag): The shape in question.
 436
 437    Returns:
 438        a `Dictionary` with the various properties of the shape
 439    """
 440
 441    return {
 442        "center" get_center(shape),
 443        "left" get_left(shape),
 444        "right" get_right(shape),
 445        "top" get_top(shape),
 446        "bottom" get_bottom(shape),
 447    }
 448
 449
 450def align(shape1, shape2, via="middle", offset_x=0, offset_y=0):
 451    """
 452    A reporter function that aligns `shape1` with `shape2`. It does this by moving `shape1` to align with
 453    whatever property of `shape2` is selected with the `via` input.
 454
 455    Args:
 456        shape1 (`Shape` or Tag): The first shape to use.
 457        shape2 (`Shape` or Tag): The second shape to use.
 458        via (`str`): Has to be one of, the following options: `"center"` (horizontal center),
 459            `"middle"` (vertical center), `"top"`, `"bottom"`, `"left"`, or `"right"`
 460        offset_x (`int`): How much to shift in the x-axis after alignment
 461        offset_y (`int`): How much to shift in the y-axis after alignment
 462
 463    Returns:
 464        `Shape`: The modified shape1.
 465    """
 466    via_options = ["center", "middle", "top", "bottom", "left", "right"]
 467    if via not in via_options
 468        raise ValueError(
 469            "The via input must be one of "
 470            + (via_options)
 471            + " but instead we found "
 472            + (via)
 473        )
 474
 475    outline1 = _get_outline(shape1)
 476    outline2 = _get_outline(shape2)
 477
 478    if via == "center"
 479        _a_canvas.move(
 480            shape1, (outline2["center"][0] - outline1["center"][0]) + offset_x, offset_y
 481        )
 482
 483    elif via == "middle"
 484        _a_canvas.move(
 485            shape1, offset_x, (outline2["center"][1] - outline1["center"][1]) + offset_y
 486        )
 487
 488    elif via == "top"
 489        _a_canvas.move(shape1, offset_x, (outline2["top"] - outline1["top"]) + offset_y)
 490
 491    elif via == "bottom"
 492        _a_canvas.move(
 493            shape1, offset_x, (outline2["bottom"] - outline1["bottom"]) + offset_y
 494        )
 495
 496    elif via == "left"
 497        _a_canvas.move(
 498            shape1, (outline2["left"] - outline1["left"]) + offset_x, offset_y
 499        )
 500
 501    elif via == "right"
 502        _a_canvas.move(
 503            shape1, (outline2["right"] - outline1["right"]) + offset_x, offset_y
 504        )
 505
 506    return shape1
 507
 508
 509def scale(shape, x_scale=1.0, y_scale=1.0):
 510    """
 511    A function that takes a given `Shape` or tag and scales it on either/both the x and y-axis.
 512
 513    The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause
 514    the shape to grow along that access. Values less than 1.0 will cause the shape to shrink.
 515
 516    Args:
 517        shape (`Shape` or Tag): The shape or tag to re-fill.
 518        x_scale (`float`): How much to scale in the x-axis.
 519        y_scale (`float`): How much to scale in the y-axis.
 520    """
 521    ids = _a_canvas.find_withtag(shape)
 522
 523    coord = get_center(shape)
 524
 525    for i in ids
 526        _a_canvas.scale(i, coord[0], coord[1], x_scale, y_scale)
 527
 528def overlay(shape1, shape2, offset_x=0, offset_y=0):
 529    """
 530    A reporter function that overlays shape1 onto shape2. It does this by moving shape 1"s center
 531    to shape 2"s center, and then applying any specified offset.
 532    Args:
 533        shape1 (`Shape` or Tag): The first shape to use.
 534        shape2 (`Shape` or Tag): The second shape to use.
 535        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
 536        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
 537
 538    Returns:
 539        `Shape`: The modified shape1.
 540    """
 541    center1 = get_center(shape1)
 542    center2 = get_center(shape2)
 543    _a_canvas.move(
 544        shape1,
 545        (center2[0] - center1[0]) + offset_x,
 546        (center2[1] - center1[1]) + offset_y,
 547    )
 548    _a_canvas.tag_raise(shape1, shape2)
 549    return shape1
 550
 551
 552def underlay(shape1, shape2, offset_x=0, offset_y=0):
 553    """
 554    A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1"s center
 555    to shape 2"s center, and then applying any specified offset.
 556    Args:
 557        shape1 (`Shape` or Tag): The first shape to use.
 558        shape2 (`Shape` or Tag): The second shape to use.
 559        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
 560        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
 561
 562    Returns:
 563        `Shape`: The modified shape1.
 564    """
 565    center1 = get_center(shape1)
 566    center2 = get_center(shape2)
 567    _a_canvas.move(
 568        shape1,
 569        (center2[0] - center1[0]) + offset_x,
 570        (center2[1] - center1[1]) + offset_y,
 571    )
 572    _a_canvas.tag_lower(shape1, shape2)
 573    return shape1
 574
 575
 576def above(shape1, shape2, offset_x=0, offset_y=0):
 577    """
 578    A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1"s center
 579    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
 580    specified offset.
 581
 582    Args:
 583        shape1 (`Shape` or Tag): The first shape to use.
 584        shape2 (`Shape` or Tag): The second shape to use.
 585        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
 586        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
 587
 588    Returns:
 589        `Shape`: The modified shape1.
 590    """
 591    overlay(shape1, shape2)
 592    _a_canvas.move(
 593        shape1,
 594        0 + offset_x,
 595        -1 * (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
 596    )
 597    return shape1
 598
 599
 600def beside(shape1, shape2, offset_x=0, offset_y=0):
 601    """
 602    A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1"s center
 603    to shape 2"s center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any
 604    specified offset.
 605
 606    Args:
 607        shape1 (`Shape` or Tag): The first shape to use.
 608        shape2 (`Shape` or Tag): The second shape to use.
 609        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
 610        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
 611
 612    Returns:
 613        `Shape`: The modified shape1.
 614    """
 615    overlay(shape1, shape2)
 616    _a_canvas.move(
 617        shape1,
 618        (get_width(shape2) + get_width(shape1)) / 2 + offset_x,
 619        0 + offset_y,
 620    )
 621    return shape1
 622
 623
 624def below(shape1, shape2, offset_x=0, offset_y=0):
 625    """
 626    A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1"s center
 627    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
 628    specified offset.
 629
 630    Args:
 631        shape1 (`Shape` or Tag): The first shape to use.
 632        shape2 (`Shape` or Tag): The second shape to use.
 633        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
 634        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
 635
 636    Returns:
 637        `Shape`: The modified shape1.
 638    """
 639    overlay(shape1, shape2)
 640    _a_canvas.move(
 641        shape1,
 642        0 + offset_x,
 643        (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
 644    )
 645    return shape1
 646
 647
 648def delete(shape):
 649    """
 650    A function that deletes a shape from our screen.
 651
 652    Args:
 653        shape (`Shape` or Tag): The shape to delete.
 654    """
 655    _a_canvas.delete(shape)
 656
 657
 658def duplicate(shape, color=None):
 659    """
 660    A reporter function that perfectly copies a shape and returns that copy.
 661
 662    Args:
 663        shape (`Shape` or Tag): The shape to duplicate.
 664        color (`str`): A new color to use with the duplicated shape.
 665
 666    Returns:
 667        `Shape`: The new duplicated shape.
 668    """
 669    shape_type = _a_canvas.type(shape)
 670    shape_config = _a_canvas.itemconfig(shape)
 671    shape_coords = _a_canvas.coords(shape)
 672    the_copy = None
 673    if shape_type == "polygon"
 674        new_config = {key shape_config[key][-1] for key in shape_config.keys()}
 675        if color != None
 676            new_config["fill"] = color
 677        the_copy = _a_canvas.create_polygon(shape_coords, new_config)
 678        return the_copy
 679
 680
 681def mirror(shape):
 682    """
 683    A function that takes a shape and flips it across its vertical
 684    axis, returning the modified shape.
 685
 686    Args:
 687        shape (`Shape` or Tag): The shape in question.
 688
 689    """
 690    center = get_center(shape)[0]
 691    shape_ids = _a_canvas.find_withtag(shape)
 692    for shape_id in shape_ids
 693        flipped_coordinates = []
 694        shape_coords = _a_canvas.coords(shape_id)
 695        counter = 0
 696        for num in shape_coords
 697            if counter % 2 == 0
 698                if num < center
 699                    flipped_coordinates.append(num + 2 * (center - num))
 700                elif num > center
 701                    flipped_coordinates.append(num - 2 * (num - center))
 702                else
 703                    flipped_coordinates.append(num)
 704            else
 705                flipped_coordinates.append(num)
 706            counter += 1
 707        _a_canvas.coords(shape_id, flipped_coordinates)
 708
 709
 710def rotate(shape, degrees=5, origin=None):
 711    """
 712    A reporter function that takes a shape and rotates it by a specified amount around a specified point.
 713    It does this by interpolating a polygon around the shape and calculating the shifts of individual
 714    points on the edge of the polygon.
 715
 716    Args:
 717        shape (`Shape` or Tag): The shape to rotate.
 718        degrees (`int`): The number of degrees to rotate the shape.
 719        origin (`tuple`): An `(x,y)` coordinate about which to perform the rotation. Defaults to the center
 720            of the given shape.
 721
 722    Returns:
 723        `Shape`: The modified shape.
 724    """
 725    if origin is None
 726        origin = get_center(shape)
 727
 728    theta = radians(degrees)
 729    ox, oy = origin
 730
 731    all_shapes = _a_canvas.find_withtag(shape)
 732
 733    for a_shape in all_shapes
 734        coords = _a_canvas.coords(a_shape)
 735        # update coordinates:
 736        for i in range(0, len(coords), 2):
 737            px, py = coords[i], coords[i + 1]
 738            qx = cos(theta) * (px - ox) - sin(theta) * (py - oy) + ox
 739            qy = sin(theta) * (px - ox) + cos(theta) * (py - oy) + oy
 740            coords[i] = qx
 741            coords[i + 1] = qy
 742        # set the coordinates:
 743        _a_canvas.coords(a_shape, coords)
 744
 745    return shape
 746
 747
 748def distance(point1, point2):
 749    """
 750    A reporter function calculates the distance between two `(x, y)` coordinates.
 751
 752    Args:
 753        point1 (`tuple`): The first `(x, y)` coordinate.
 754        point2 (`tuple`): The second `(x, y)` coordinate.
 755
 756    Returns:
 757         A `float` representing the distance between the two points.
 758    """
 759    return sqrt(((point1[0] - point2[0])  2) + ((point1[1] - point2[1])  2))
 760
 761
 762def update_color(shape, color):
 763    """
 764    Change the fill color of a tagged object.
 765
 766    Args:
 767        shape (`Shape` or Tag): The shape or tag to re-fill.
 768        color (`str`): A color name or hex code to re-fill with.
 769    """
 770    ids = _a_canvas.find_withtag(shape)
 771    for id in ids
 772        _a_canvas.itemconfig(id, fill=color)
 773
 774
 775def interpolate_colors(color1, color2, frac):
 776    """
 777    A reporter function that generates a new color between two given colors.
 778    Args:
 779        color1 (`str`): The path of the file to wrap
 780        color2 (`str`): The path of the file to wrap
 781        frac (`float`): What fraction of each color to take. An input of 0 returns
 782            color1, an input of 1 returns color2, an input of 0.5 returns a color
 783            perfectly between the two.
 784
 785    Returns:
 786         A color (as a hex `str`) to be used elsewhere
 787    """
 788    if "#" not in color1
 789        color1 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color1)))
 790    else
 791        color1 = _tupelize_color(color1)
 792    if "#" not in color2
 793        color2 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color2)))
 794    else
 795        color2 = _tupelize_color(color2)
 796    return _interpolate_tuple(color1, color2, frac)
 797
 798
 799def get_colors(shape_or_shapes):
 800    """
 801    A reporter function that returns all the colors associated with a tag or list of tags.
 802
 803    Args:
 804        shape_or_shapes (`str`/`Shape` or `List`): the shape/tag or list of shapes/tags you"d like to find the colors of
 805
 806    Returns:
 807        A `List` containing all unique colors associated with that tag(s)
 808    """
 809    all_shapes = []
 810    if not isinstance(shape_or_shapes, ):
 811        shape_or_shapes = [shape_or_shapes]
 812    for shape in shape_or_shapes
 813        all_shapes += _a_canvas.find_withtag(shape)
 814
 815    all_colors = []
 816    for shape in all_shapes
 817        color = _a_canvas.itemcget(shape, "fill")
 818        if color not in all_colors
 819            all_colors.append(color)
 820
 821    return all_colors
 822
 823
 824def get_center(shape):
 825    """
 826    A reporter function calculates the a coordinate at the center of some shape.
 827
 828    Args:
 829        shape (`Shape` or Tag): The shape in question.
 830
 831    Returns:
 832         A `tuple` representing center of the given shape.
 833    """
 834    bbox = _safe_bbox(shape)
 835
 836    if bbox is None
 837        raise Exception(
 838            f"We couldn"t find the shape with id/tag {shape}. Make sure it exists!"
 839        )
 840
 841    return (((bbox[2] + bbox[0]) / 2), ((bbox[1] + bbox[3]) / 2))
 842
 843
 844def get_top(shape):
 845    """
 846    A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped).
 847
 848    Args:
 849        shape (`Shape` or Tag): The shape in question.
 850
 851    Returns:
 852         A `int` representing the minimum y-coordinate of the shape.
 853    """
 854    bbox = _safe_bbox(shape)
 855    return bbox[1]
 856
 857
 858def get_bottom(shape):
 859    """
 860    A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped).
 861
 862    Args:
 863        shape (`Shape` or Tag): The shape in question.
 864
 865    Returns:
 866         A `int` representing the maximum y-coordinate of the shape.
 867    """
 868    bbox = _safe_bbox(shape)
 869    return bbox[3]
 870
 871
 872def get_left(shape):
 873    """
 874    A reporter function calculates the minimum x-value of a given shape.
 875
 876    Args:
 877        shape (`Shape` or Tag): The shape in question.
 878
 879    Returns:
 880         A `int` representing the minimum x-coordinate of the shape.
 881    """
 882    bbox = _safe_bbox(shape)
 883    return bbox[0]
 884
 885
 886def get_right(shape):
 887    """
 888    A reporter function calculates the maximum x-value of a given shape.
 889
 890    Args:
 891        shape (`Shape` or Tag): The shape in question.
 892
 893    Returns:
 894         A `int` representing the maximum x-coordinate of the shape.
 895    """
 896    bbox = _safe_bbox(shape)
 897    return bbox[2]
 898
 899
 900def get_height(shape):
 901    """
 902    A reporter function calculates the height of some given shape.
 903
 904    Args:
 905        shape (`Shape` or Tag): The shape in question.
 906
 907    Returns:
 908         A `int` representing the height of the shape.
 909    """
 910    bbox = _safe_bbox(shape)
 911    return bbox[3] - bbox[1] - 1
 912
 913
 914def get_width(shape):
 915    """
 916    A reporter function calculates the width of some given shape.
 917
 918    Args:
 919        shape (`Shape` or Tag): The shape in question.
 920
 921    Returns:
 922         An `int` representing width of the shape.
 923    """
 924    bbox = _safe_bbox(shape)
 925    return bbox[2] - bbox[0] - 1
 926
 927
 928def make_grid(c, w, h):
 929    """
 930    Draws a grid on a screen with intervals of 100.
 931
 932    Args:
 933        w (`int`): The width of the grid to draw
 934        h (`int`): The height of the grid to draw
 935    """
 936    interval = 100
 937    # Creates all vertical lines at intervals of 100
 938    for i in range(0, w, interval):
 939        _a_canvas.create_line(i, 0, i, h, tag="grid_line")
 940    # Creates all horizontal lines at intervals of 100
 941    for i in range(0, h, interval):
 942        _a_canvas.create_line(0, i, w, i, tag="grid_line")
 943    # Creates axis labels
 944    offset = 2
 945    for y in range(0, h, interval):
 946        for x in range(0, w, interval):
 947            _a_canvas.create_oval(
 948                x - offset, y - offset, x + offset, y + offset, fill="black"
 949            )
 950            _a_canvas.create_text(
 951                x + offset,
 952                y + offset,
 953                text="({0}, {1})".format(x, y),
 954                anchor="nw",
 955                font=("Purisa", 8),
 956            )
 957
 958
 959def _safe_bbox(shape):
 960    try
 961        bbox = _a_canvas.bbox(shape)
 962        if bbox is None
 963            Exception(
 964                f"We couldn"t find the shape with tag/id: {shape}. Make sure this shape exists!"
 965            )
 966        return bbox
 967    except
 968        raise Exception(
 969            f"We couldn"t find the shape with tag/id: {shape}. Make sure this shape exists!"
 970        )
 971
 972
 973def _tupelize_color(color):
 974    R = (color[13], 16)
 975    G = (color[35], 16)
 976    B = (color[57], 16)
 977    return R, G, B
 978
 979
 980def _interpolate_tuple(startcolor, goalcolor, frac):
 981    R = startcolor[0]
 982    G = startcolor[1]
 983    B = startcolor[2]
 984
 985    targetR = goalcolor[0]
 986    targetG = goalcolor[1]
 987    targetB = goalcolor[2]
 988
 989    DiffR = targetR - R
 990    DiffG = targetG - G
 991    DiffB = targetB - B
 992
 993    iR = (R + (DiffR * frac))
 994    iG = (G + (DiffG * frac))
 995    iB = (B + (DiffB * frac))
 996
 997    hR = hex(iR).replace("0x", "")
 998    hG = hex(iG).replace("0x", "")
 999    hB = hex(iB).replace("0x", "")
1000
1001    if len(hR) == 1
1002        hR = "0" + hR
1003    if len(hB) == 1
1004        hB = "0" + hB
1005    if len(hG) == 1
1006        hG = "0" + hG
1007
1008    color = ("#" + hR + hG + hB).upper()
1009
1010    return color
1011
1012
1013def does_tag_exist(tag):
1014    """
1015    Returns `True` if a given tag exists otherwise returns `False`.
1016
1017    Args:
1018        `tag` (`str`): [Required] The tag of the object to lookup.
1019
1020    """
1021    result = _a_canvas.find_withtag(tag)
1022
1023    if result
1024        return True
1025    else
1026        return False
1027
1028
1029def random_color():
1030    """
1031    Returns a random color as a `string` to be used with `tkinter`.
1032    It does not accept any inputs.
1033    """
1034    r = lambda randint(0, 255)
1035    return "#%02X%02X%02X" % (r(), r(), r())
1036
1037
1038from tkinter import Tk, Canvas
1039
1040
1041def setup_shapes(title, background="white", width=600, height=600):
1042    """
1043    A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION.
1044    """
1045    global _a_canvas
1046    gui = Tk()
1047    gui.title(title)
1048    _a_canvas = Canvas(gui, background=background, width=width, height=width)
1049    _a_canvas.pack()
1050    make_grid(_a_canvas, width, height)
1051    return _a_canvas
def rectangle( top_left=(0, 0), width=25, height=50, color="hotpink", outline="", tag="",):
22def rectangle(
23    top_left=(0, 0), width=25, height=50, color="hotpink", outline="", tag="", 
24):
25    """
26    A reporter function that draws a rectangle.
27    Args:
28        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
29        width (`int`): How wide to draw the shape.
30        height (`int`): How tall to draw the shape.
31        color (`str`): What color to draw the shape.
32        outline (`str`): What color should the border of the shape be.
33        tag (`str`): The tag to assign to the shape.
34
35    Returns:
36         `Shape`: The rectangle that was created.
37    """
38    point_0 = top_left
39    point_1 = (top_left[0] + width, top_left[1])
40    point_2 = (top_left[0] + width, top_left[1] + height)
41    point_3 = (top_left[0], top_left[1] + height)
42    return _a_canvas.create_polygon(
43        point_0, point_1, point_2, point_3, fill=_safe_color(color), tags=tag, 
44    )

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 square( top_left=(0, 0), size=25, color="hotpink", outline="", tag="",):
47def square(top_left=(0, 0), size=25, color="hotpink", outline="", tag="", ):
48    """
49    A reporter function that draws a square.
50    Args:
51        top_left (`tuple`): A coordinate representing the top left-hand corner of the shape.
52        size (`int`): How big to draw the shape.
53        color (`str`): What color to draw the shape.
54        outline (`str`): What color should the border of the shape be.
55        tag (`str`): The tag to assign to the shape.
56
57    Returns:
58         `Shape`: The square that was created.
59    """
60    return rectangle(
61        top_left=top_left, width=size, height=size, color=color, tag=tag, 
62    )

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 oval( center=(0, 0), radius_x=25, radius_y=50, color="hotpink", outline="", tag="",):
 65def oval(
 66    center=(0, 0),
 67    radius_x=25,
 68    radius_y=50,
 69    color="hotpink",
 70    outline="",
 71    tag="",
 72    ,
 73):
 74    """
 75    A reporter function that draws an oval.
 76    Args:
 77        center (`tuple`): A coordinate representing the center of the shape.
 78        radius_x (`int`): Specifies the oval"s radius on the x-axis.
 79        radius_y (`int`): Specifies the oval"s radius on the y-axis.
 80        color (`str`): What color to draw the shape.
 81        outline (`str`): What color should the border of the shape be.
 82        tag (`str`): The tag to assign to the shape.
 83
 84    Returns:
 85         `Shape`: The oval that was created.
 86    """
 87    x = center[0]
 88    y = center[1]
 89    x0, y0, x1, y1 = (x - radius_x, y - radius_y, x + radius_x, y + radius_y)
 90    steps = 100
 91    # major and minor axes
 92    a = (x1 - x0) / 2.0
 93    b = (y1 - y0) / 2.0
 94    # center
 95    xc = x0 + a
 96    yc = y0 + b
 97    point_list = []
 98    # create the oval as a list of points
 99    for i in range(steps):
100        # Calculate the angle for this step
101        theta = (pi * 2) * (float(i) / steps)
102        x = a * cos(theta)
103        y = b * sin(theta)
104        point_list.append(round(x + xc))
105        point_list.append(round(y + yc))
106
107    return _a_canvas.create_polygon(
108        point_list, fill=_safe_color(color), tags=tag, 
109    )

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 circle( center=(0, 0), radius=25, color="hotpink", outline="", tag="",):
112def circle(center=(0, 0), radius=25, color="hotpink", outline="", tag="", ):
113    """
114    A reporter function that draws a circle.
115    Args:
116        center (`tuple`): A coordinate representing the center of the shape.
117        radius (`int`): Specifies the circle"s radius.
118        color (`str`): What color to draw the shape.
119        outline (`str`): What color should the border of the shape be.
120        tag (`str`): The tag to assign to the shape.
121
122    Returns:
123         `Shape`: The circle that was created.
124    """
125    return oval(
126        center=center, radius_x=radius, radius_y=radius, color=color, tag=tag, 
127    )

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 wedge( center=(0, 0), radius=25, angle=180, color="hotpink", outline="", tag="",):
130def wedge(
131    center=(0, 0), radius=25, angle=180, color="hotpink", outline="", tag="", 
132):
133    """
134    A reporter function that draws a circle.
135    Args:
136        center (`tuple`): A coordinate representing the center of the shape.
137        radius (`int`): Specifies the circle"s radius.
138        angle (`int`): A number between 0 and 360 that specifies how much of the circle to draw.
139        color (`str`): What color to draw the shape.
140        outline (`str`): What color should the border of the shape be.
141        tag (`str`): The tag to assign to the shape.
142
143    Returns:
144         `Shape`: The wedge that was created.
145    """
146    point_list = [center[0], center[1]]
147    for i in range(0, 0 + angle):
148        x1 = center[0] + radius * cos(radians(i))
149        point_list.append(x1)
150        y1 = center[1] + radius * sin(radians(i))
151        point_list.append(y1)
152
153    point_list.append(center[0])
154    point_list.append(center[1])
155
156    return _a_canvas.create_polygon(
157        point_list, fill=_safe_color(color), outline=outline, tags=tag, 
158    )

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.

def triangle( bottom_center=(0, 0), width=25, top_shift=0, height=0, color="hotpink", outline="", tag="",):
161def triangle(
162    bottom_center=(0, 0),
163    width=25,
164    top_shift=0,
165    height=0,
166    color="hotpink",
167    outline="",
168    tag="",
169    ,
170):
171    """
172    A reporter function that draws a triangle.
173    Args:
174        bottom_center (`tuple`): A coordinate representing the bottom center of the shape.
175        width (`int`): Specifies the width of the base of the triangle.
176        top_shift (`int`): Specifies the how far to the left or right to shift the top of
177            the triangle from the bottom center.
178        height (`int`): Specifies the triangle"s height.
179        color (`str`): What color to draw the shape.
180        outline (`str`): What color should the border of the shape be.
181        tag (`str`): The tag to assign to the shape.
182
183    Returns:
184         `Shape`: The triangle that was created.
185    """
186    if height == 0
187        height = width * sqrt(3) / 2
188    point_0 = (bottom_center[0] - width / 2, bottom_center[1])
189    point_1 = (bottom_center[0] + width / 2, bottom_center[1])
190    point_2 = (bottom_center[0] + top_shift, bottom_center[1] - height)
191
192    return _a_canvas.create_polygon(
193        point_0, point_1, point_2, fill=_safe_color(color), tags=tag, 
194    )

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 line(points=[], curvy=False, color="hotpink", tag="", ):
197def line(points=[], curvy=False, color="hotpink", tag="", ):
198    """
199    A reporter function that draws a line given a list of points.
200    Args:
201        points (`list`): The points that define the line; this should be a list of tuples (coordinates).
202        curvy (`bool`): Makes a curvy line instead.
203        color (`str`): What color to make the shape.
204        tag (`str`): The tag to assign to the shape.
205
206    Returns:
207        `Shape`: The line that was created.
208    """
209    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 arc(points=[], width=5, color="hotpink", line_steps=15, tag="", ):
212def arc(points=[], width=5, color="hotpink", line_steps=15, tag="", ):
213    """
214    A reporter function that draws an arc ("curve") given a list of points.
215    Args:
216        points (`list`): The points outlining the curve; this should be a list of tuples (coordinates).
217            Make sure to give it at least 3 (x,y) coordinates that aren"t a straight line!
218        color (`str`): What color to make the shape.
219        tag (`str`): The tag to assign to the shape.
220
221    Returns:
222        `Shape`: The arc that was created.
223    """
224    return _a_canvas.create_line(
225        points,
226        width=width,
227        fill=color,
228        splinesteps=line_steps,
229        smooth=True,
230        tags=tag,
231        ,
232    )

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 diamond( center=(0, 0), width=25, height=50, color="hotpink", outline="", tag="",):
235def diamond(
236    center=(0, 0), width=25, height=50, color="hotpink", outline="", tag="", 
237):
238    """
239    A reporter function that draws a rectangle.
240    Args:
241        center (`tuple`): A coordinate representing the center of the shape.
242        width (`int`): How wide to draw the shape.
243        height (`int`): How tall to draw the shape.
244        color (`str`): What color to draw the shape.
245        outline (`str`): What color should the border of the shape be.
246        tag (`str`): The tag to assign to the shape.
247
248    Returns:
249         `Shape`: The shape that was created.
250    """
251    point_0 = (center[0] - width / 2, center[1])
252    point_1 = (center[0], center[1] - height / 2)
253    point_2 = (center[0] + width / 2, center[1])
254    point_3 = (center[0], center[1] + height / 2)
255    return _a_canvas.create_polygon(
256        point_0,
257        point_1,
258        point_2,
259        point_3,
260        fill=_safe_color(color),
261        tags=tag,
262        outline=outline,
263        ,
264    )

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 star( center=(0, 0), radius=50, color="hotpink", outer_radius=75, points=5, outline="", tag="",):
267def star(
268    center=(0, 0),
269    radius=50,
270    color="hotpink",
271    outer_radius=75,
272    points=5,
273    outline="",
274    tag="",
275    ,
276):
277    """
278    A reporter function that draws a star.
279    Args:
280        center (`tuple`): A coordinate representing the center of the shape.
281        radius (`int`): Specifies the radius of the inside part of the star.
282        color (`str`): Specifies the color of the star.
283        outer_radius (`int`): Specifies the radius of the outside part of the star.
284        points (`int`): Specifies the number of points for the star.
285        outline (`str`): What color should the border of the shape be.
286        tag (`str`): The tag to assign to the shape.
287
288    Returns:
289         `Shape`: The star that was created.
290    """
291    arc_segment = 360 / points
292    vertices = []
293    for i in range(points):
294        inner_point = (
295            radius * cos(radians(arc_segment * i)) + center[0],
296            -1 * radius * sin(radians(arc_segment * i)) + center[1],
297        )
298        vertices.append(inner_point)
299        outer_point = (
300            outer_radius * cos(radians(arc_segment * i + arc_segment / 2)) + center[0],
301            -1 * outer_radius * sin(radians(arc_segment * i + arc_segment / 2))
302            + center[1],
303        )
304        vertices.append(outer_point)
305    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 polygon(points=[], color="hotpink", outline="", tag="", ):
308def polygon(points=[], color="hotpink", outline="", tag="", ):
309    """
310    A reporter function that draws a polygon given a list of points.
311    Args:
312        points (`list`): The points outlining the polygon; this should be a list of tuples (coordinates).
313            defaults to an empty list.
314        outline (`str`): What color should the border of the shape be.
315        color (`str`): What color to make the shape.
316
317    Returns:
318        `Shape`: The polygon that was created.
319    """
320    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 spiral( center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1,):
327def spiral(
328    center=(0, 0), width=100, roughness=0.01, start=0, spirals=5, line_width=1, 
329):
330    """
331    A reporter function that draws a spiral.
332    Args:
333        center (`tuple`): A coordinate representing the center of the shape.
334        width (`int`): Specifies the total width of the spiral.
335        roughness (`float`): Controls how spiral-y the shape is (lower is less spiral-y)
336        start (`int`): Where on the spiral to start drawing.
337        spirals (`int`): How many loops to draw.
338        line_width (`int`): How wide for the line to be drawn.
339        tag (`str`): The tag to assign to the shape.
340
341    Returns:
342         `Shape`: The spiral that was created.
343    """
344    theta = 0.0
345    r = start
346    all_points = []
347    prev_pos = _polar_to_cartesian(r, theta)
348    distance = width / 4 / pi / spirals
349    all_points.append((prev_pos[0] + center[0], prev_pos[1] + center[1]))
350    while theta < 2 * spirals * pi
351        theta += roughness
352        r = start + distance * theta
353        pos = _polar_to_cartesian(r, theta)
354        all_points.append((pos[0] + center[0], pos[1] + center[1]))
355
356    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 move(shape, x_shift=0, y_shift=0):
359def move(shape, x_shift=0, y_shift=0):
360    """
361    Purpose: Move the x and y position of all shapes that have been tagged
362    with the tag argument
363
364    Args:
365        shape (`Shape` or Tag): The shape in question.
366        x_shift (`int`; optional): amount to move in the x direction
367        y_shift (`int`; optional): amount to move in the y direction
368    """
369    shape_ids = _a_canvas.find_withtag(shape)
370    for id in shape_ids
371        _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 portion(shape, start=0, end=0.5):
374def portion(shape, start=0, end=0.5):
375    """
376    Purpose: Take a slice or portion of some already created shape.
377
378    Args:
379        shape (`Shape` or Tag): The shape to take a portion of
380        start (`float`): A number between 0 and 1 representing where to start the slice.
381        end (`float`): A number between 0 and 1 representing where to end the slice.
382
383    For example, taking a portion from 0 to 0.5 of a circle would result in a semi-circle.
384
385    Note: this function is experimental. It might produce unexpected results!
386    """
387    all_shapes = _a_canvas.find_withtag(shape)
388
389    for a_shape in all_shapes
390        coords = _a_canvas.coords(a_shape)
391
392        start_coord = floor(start * len(coords))
393        if start_coord % 2 == 1
394            start_coord = start_coord - 1  # need to start with an x,y pair
395        end_coord = floor(end * len(coords))
396        if end_coord % 2 == 1
397            end_coord = end_coord - 1  # need to end with an x,y pair
398
399        # slice is up to not including so get the last x,y pair
400        new_coords = coords[start_coord  end_coord + 2]
401
402        # loop shape back in on itself
403        new_coords.append(new_coords[0])
404        new_coords.append(new_coords[1])
405
406        # set the coordinates:
407        _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_front(shape):
410def put_in_front(shape):
411    """
412    A function that "raises" a shape to the "top" of the screen."
413
414    Args:
415        shape (`Shape` or Tag): The shape in question.
416    """
417    _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 put_in_back(shape):
420def put_in_back(shape):
421    """
422    A function that "lowers" a shape to the "bottom" of the screen."
423
424    Args:
425        shape (`Shape` or Tag): The shape in question.
426    """
427    _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 align(shape1, shape2, via="middle", offset_x=0, offset_y=0):
451def align(shape1, shape2, via="middle", offset_x=0, offset_y=0):
452    """
453    A reporter function that aligns `shape1` with `shape2`. It does this by moving `shape1` to align with
454    whatever property of `shape2` is selected with the `via` input.
455
456    Args:
457        shape1 (`Shape` or Tag): The first shape to use.
458        shape2 (`Shape` or Tag): The second shape to use.
459        via (`str`): Has to be one of, the following options: `"center"` (horizontal center),
460            `"middle"` (vertical center), `"top"`, `"bottom"`, `"left"`, or `"right"`
461        offset_x (`int`): How much to shift in the x-axis after alignment
462        offset_y (`int`): How much to shift in the y-axis after alignment
463
464    Returns:
465        `Shape`: The modified shape1.
466    """
467    via_options = ["center", "middle", "top", "bottom", "left", "right"]
468    if via not in via_options
469        raise ValueError(
470            "The via input must be one of "
471            + (via_options)
472            + " but instead we found "
473            + (via)
474        )
475
476    outline1 = _get_outline(shape1)
477    outline2 = _get_outline(shape2)
478
479    if via == "center"
480        _a_canvas.move(
481            shape1, (outline2["center"][0] - outline1["center"][0]) + offset_x, offset_y
482        )
483
484    elif via == "middle"
485        _a_canvas.move(
486            shape1, offset_x, (outline2["center"][1] - outline1["center"][1]) + offset_y
487        )
488
489    elif via == "top"
490        _a_canvas.move(shape1, offset_x, (outline2["top"] - outline1["top"]) + offset_y)
491
492    elif via == "bottom"
493        _a_canvas.move(
494            shape1, offset_x, (outline2["bottom"] - outline1["bottom"]) + offset_y
495        )
496
497    elif via == "left"
498        _a_canvas.move(
499            shape1, (outline2["left"] - outline1["left"]) + offset_x, offset_y
500        )
501
502    elif via == "right"
503        _a_canvas.move(
504            shape1, (outline2["right"] - outline1["right"]) + offset_x, offset_y
505        )
506
507    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 scale(shape, x_scale=1.0, y_scale=1.0):
510def scale(shape, x_scale=1.0, y_scale=1.0):
511    """
512    A function that takes a given `Shape` or tag and scales it on either/both the x and y-axis.
513
514    The two optional inputs accept floats between 0.0 and 1.0. Values greater than 1 will cause
515    the shape to grow along that access. Values less than 1.0 will cause the shape to shrink.
516
517    Args:
518        shape (`Shape` or Tag): The shape or tag to re-fill.
519        x_scale (`float`): How much to scale in the x-axis.
520        y_scale (`float`): How much to scale in the y-axis.
521    """
522    ids = _a_canvas.find_withtag(shape)
523
524    coord = get_center(shape)
525
526    for i in ids
527        _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 overlay(shape1, shape2, offset_x=0, offset_y=0):
529def overlay(shape1, shape2, offset_x=0, offset_y=0):
530    """
531    A reporter function that overlays shape1 onto shape2. It does this by moving shape 1"s center
532    to shape 2"s center, and then applying any specified offset.
533    Args:
534        shape1 (`Shape` or Tag): The first shape to use.
535        shape2 (`Shape` or Tag): The second shape to use.
536        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
537        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
538
539    Returns:
540        `Shape`: The modified shape1.
541    """
542    center1 = get_center(shape1)
543    center2 = get_center(shape2)
544    _a_canvas.move(
545        shape1,
546        (center2[0] - center1[0]) + offset_x,
547        (center2[1] - center1[1]) + offset_y,
548    )
549    _a_canvas.tag_raise(shape1, shape2)
550    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 underlay(shape1, shape2, offset_x=0, offset_y=0):
553def underlay(shape1, shape2, offset_x=0, offset_y=0):
554    """
555    A reporter function that underlays shape1 beneath shape2. It does this by moving shape 1"s center
556    to shape 2"s center, and then applying any specified offset.
557    Args:
558        shape1 (`Shape` or Tag): The first shape to use.
559        shape2 (`Shape` or Tag): The second shape to use.
560        offset_x (`int`): How much to shift shape 2 in the x-direction after centering it.
561        offset_y (`int`): How much to shift shape 2 in the x-direction after centering it.
562
563    Returns:
564        `Shape`: The modified shape1.
565    """
566    center1 = get_center(shape1)
567    center2 = get_center(shape2)
568    _a_canvas.move(
569        shape1,
570        (center2[0] - center1[0]) + offset_x,
571        (center2[1] - center1[1]) + offset_y,
572    )
573    _a_canvas.tag_lower(shape1, shape2)
574    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.

def above(shape1, shape2, offset_x=0, offset_y=0):
577def above(shape1, shape2, offset_x=0, offset_y=0):
578    """
579    A reporter function that places shape1 above shape2 (vertically). It does this by moving shape 1"s center
580    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
581    specified offset.
582
583    Args:
584        shape1 (`Shape` or Tag): The first shape to use.
585        shape2 (`Shape` or Tag): The second shape to use.
586        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
587        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
588
589    Returns:
590        `Shape`: The modified shape1.
591    """
592    overlay(shape1, shape2)
593    _a_canvas.move(
594        shape1,
595        0 + offset_x,
596        -1 * (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
597    )
598    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 beside(shape1, shape2, offset_x=0, offset_y=0):
601def beside(shape1, shape2, offset_x=0, offset_y=0):
602    """
603    A reporter function that places shape1 beside shape2 (horizontally). It does this by moving shape 1"s center
604    to shape 2"s center, moving shape 1 in the x-direction the exact width of shape 2, and then applying any
605    specified offset.
606
607    Args:
608        shape1 (`Shape` or Tag): The first shape to use.
609        shape2 (`Shape` or Tag): The second shape to use.
610        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
611        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
612
613    Returns:
614        `Shape`: The modified shape1.
615    """
616    overlay(shape1, shape2)
617    _a_canvas.move(
618        shape1,
619        (get_width(shape2) + get_width(shape1)) / 2 + offset_x,
620        0 + offset_y,
621    )
622    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):
625def below(shape1, shape2, offset_x=0, offset_y=0):
626    """
627    A reporter function that places shape1 below shape2 (vertically). It does this by moving shape 1"s center
628    to shape 2"s center, moving shape 1 in the y-direction the exact height of shape 2, and then applying any
629    specified offset.
630
631    Args:
632        shape1 (`Shape` or Tag): The first shape to use.
633        shape2 (`Shape` or Tag): The second shape to use.
634        offset_x (`int`): How much to shift shape 2 in the x-direction after moving it.
635        offset_y (`int`): How much to shift shape 2 in the x-direction after moving it.
636
637    Returns:
638        `Shape`: The modified shape1.
639    """
640    overlay(shape1, shape2)
641    _a_canvas.move(
642        shape1,
643        0 + offset_x,
644        (get_height(shape2) + get_height(shape1)) / 2 + offset_y,
645    )
646    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 delete(shape):
649def delete(shape):
650    """
651    A function that deletes a shape from our screen.
652
653    Args:
654        shape (`Shape` or Tag): The shape to delete.
655    """
656    _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):
659def duplicate(shape, color=None):
660    """
661    A reporter function that perfectly copies a shape and returns that copy.
662
663    Args:
664        shape (`Shape` or Tag): The shape to duplicate.
665        color (`str`): A new color to use with the duplicated shape.
666
667    Returns:
668        `Shape`: The new duplicated shape.
669    """
670    shape_type = _a_canvas.type(shape)
671    shape_config = _a_canvas.itemconfig(shape)
672    shape_coords = _a_canvas.coords(shape)
673    the_copy = None
674    if shape_type == "polygon"
675        new_config = {key shape_config[key][-1] for key in shape_config.keys()}
676        if color != None
677            new_config["fill"] = color
678        the_copy = _a_canvas.create_polygon(shape_coords, new_config)
679        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):
682def mirror(shape):
683    """
684    A function that takes a shape and flips it across its vertical
685    axis, returning the modified shape.
686
687    Args:
688        shape (`Shape` or Tag): The shape in question.
689
690    """
691    center = get_center(shape)[0]
692    shape_ids = _a_canvas.find_withtag(shape)
693    for shape_id in shape_ids
694        flipped_coordinates = []
695        shape_coords = _a_canvas.coords(shape_id)
696        counter = 0
697        for num in shape_coords
698            if counter % 2 == 0
699                if num < center
700                    flipped_coordinates.append(num + 2 * (center - num))
701                elif num > center
702                    flipped_coordinates.append(num - 2 * (num - center))
703                else
704                    flipped_coordinates.append(num)
705            else
706                flipped_coordinates.append(num)
707            counter += 1
708        _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 rotate(shape, degrees=5, origin=None):
711def rotate(shape, degrees=5, origin=None):
712    """
713    A reporter function that takes a shape and rotates it by a specified amount around a specified point.
714    It does this by interpolating a polygon around the shape and calculating the shifts of individual
715    points on the edge of the polygon.
716
717    Args:
718        shape (`Shape` or Tag): The shape to rotate.
719        degrees (`int`): The number of degrees to rotate the shape.
720        origin (`tuple`): An `(x,y)` coordinate about which to perform the rotation. Defaults to the center
721            of the given shape.
722
723    Returns:
724        `Shape`: The modified shape.
725    """
726    if origin is None
727        origin = get_center(shape)
728
729    theta = radians(degrees)
730    ox, oy = origin
731
732    all_shapes = _a_canvas.find_withtag(shape)
733
734    for a_shape in all_shapes
735        coords = _a_canvas.coords(a_shape)
736        # update coordinates:
737        for i in range(0, len(coords), 2):
738            px, py = coords[i], coords[i + 1]
739            qx = cos(theta) * (px - ox) - sin(theta) * (py - oy) + ox
740            qy = sin(theta) * (px - ox) + cos(theta) * (py - oy) + oy
741            coords[i] = qx
742            coords[i + 1] = qy
743        # set the coordinates:
744        _a_canvas.coords(a_shape, coords)
745
746    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 distance(point1, point2):
749def distance(point1, point2):
750    """
751    A reporter function calculates the distance between two `(x, y)` coordinates.
752
753    Args:
754        point1 (`tuple`): The first `(x, y)` coordinate.
755        point2 (`tuple`): The second `(x, y)` coordinate.
756
757    Returns:
758         A `float` representing the distance between the two points.
759    """
760    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 update_color(shape, color):
763def update_color(shape, color):
764    """
765    Change the fill color of a tagged object.
766
767    Args:
768        shape (`Shape` or Tag): The shape or tag to re-fill.
769        color (`str`): A color name or hex code to re-fill with.
770    """
771    ids = _a_canvas.find_withtag(shape)
772    for id in ids
773        _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 interpolate_colors(color1, color2, frac):
776def interpolate_colors(color1, color2, frac):
777    """
778    A reporter function that generates a new color between two given colors.
779    Args:
780        color1 (`str`): The path of the file to wrap
781        color2 (`str`): The path of the file to wrap
782        frac (`float`): What fraction of each color to take. An input of 0 returns
783            color1, an input of 1 returns color2, an input of 0.5 returns a color
784            perfectly between the two.
785
786    Returns:
787         A color (as a hex `str`) to be used elsewhere
788    """
789    if "#" not in color1
790        color1 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color1)))
791    else
792        color1 = _tupelize_color(color1)
793    if "#" not in color2
794        color2 = tuple((c // 256 for c in _a_canvas.winfo_rgb(color2)))
795    else
796        color2 = _tupelize_color(color2)
797    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 get_colors(shape_or_shapes):
800def get_colors(shape_or_shapes):
801    """
802    A reporter function that returns all the colors associated with a tag or list of tags.
803
804    Args:
805        shape_or_shapes (`str`/`Shape` or `List`): the shape/tag or list of shapes/tags you"d like to find the colors of
806
807    Returns:
808        A `List` containing all unique colors associated with that tag(s)
809    """
810    all_shapes = []
811    if not isinstance(shape_or_shapes, ):
812        shape_or_shapes = [shape_or_shapes]
813    for shape in shape_or_shapes
814        all_shapes += _a_canvas.find_withtag(shape)
815
816    all_colors = []
817    for shape in all_shapes
818        color = _a_canvas.itemcget(shape, "fill")
819        if color not in all_colors
820            all_colors.append(color)
821
822    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_center(shape):
825def get_center(shape):
826    """
827    A reporter function calculates the a coordinate at the center of some shape.
828
829    Args:
830        shape (`Shape` or Tag): The shape in question.
831
832    Returns:
833         A `tuple` representing center of the given shape.
834    """
835    bbox = _safe_bbox(shape)
836
837    if bbox is None
838        raise Exception(
839            f"We couldn"t find the shape with id/tag {shape}. Make sure it exists!"
840        )
841
842    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_top(shape):
845def get_top(shape):
846    """
847    A reporter function calculates the minimum y-value of a given shape (since the y-axis is flipped).
848
849    Args:
850        shape (`Shape` or Tag): The shape in question.
851
852    Returns:
853         A `int` representing the minimum y-coordinate of the shape.
854    """
855    bbox = _safe_bbox(shape)
856    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_bottom(shape):
859def get_bottom(shape):
860    """
861    A reporter function calculates the maximum y-value of a given shape (since the y-axis is flipped).
862
863    Args:
864        shape (`Shape` or Tag): The shape in question.
865
866    Returns:
867         A `int` representing the maximum y-coordinate of the shape.
868    """
869    bbox = _safe_bbox(shape)
870    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_left(shape):
873def get_left(shape):
874    """
875    A reporter function calculates the minimum x-value of a given shape.
876
877    Args:
878        shape (`Shape` or Tag): The shape in question.
879
880    Returns:
881         A `int` representing the minimum x-coordinate of the shape.
882    """
883    bbox = _safe_bbox(shape)
884    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):
887def get_right(shape):
888    """
889    A reporter function calculates the maximum x-value of a given shape.
890
891    Args:
892        shape (`Shape` or Tag): The shape in question.
893
894    Returns:
895         A `int` representing the maximum x-coordinate of the shape.
896    """
897    bbox = _safe_bbox(shape)
898    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_height(shape):
901def get_height(shape):
902    """
903    A reporter function calculates the height of some given shape.
904
905    Args:
906        shape (`Shape` or Tag): The shape in question.
907
908    Returns:
909         A `int` representing the height of the shape.
910    """
911    bbox = _safe_bbox(shape)
912    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_width(shape):
915def get_width(shape):
916    """
917    A reporter function calculates the width of some given shape.
918
919    Args:
920        shape (`Shape` or Tag): The shape in question.
921
922    Returns:
923         An `int` representing width of the shape.
924    """
925    bbox = _safe_bbox(shape)
926    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 make_grid(c, w, h):
929def make_grid(c, w, h):
930    """
931    Draws a grid on a screen with intervals of 100.
932
933    Args:
934        w (`int`): The width of the grid to draw
935        h (`int`): The height of the grid to draw
936    """
937    interval = 100
938    # Creates all vertical lines at intervals of 100
939    for i in range(0, w, interval):
940        _a_canvas.create_line(i, 0, i, h, tag="grid_line")
941    # Creates all horizontal lines at intervals of 100
942    for i in range(0, h, interval):
943        _a_canvas.create_line(0, i, w, i, tag="grid_line")
944    # Creates axis labels
945    offset = 2
946    for y in range(0, h, interval):
947        for x in range(0, w, interval):
948            _a_canvas.create_oval(
949                x - offset, y - offset, x + offset, y + offset, fill="black"
950            )
951            _a_canvas.create_text(
952                x + offset,
953                y + offset,
954                text="({0}, {1})".format(x, y),
955                anchor="nw",
956                font=("Purisa", 8),
957            )

Draws a grid on a screen with intervals of 100.

Arguments:
  • w (int): The width of the grid to draw
  • h (int): The height of the grid to draw
def does_tag_exist(tag):
1014def does_tag_exist(tag):
1015    """
1016    Returns `True` if a given tag exists otherwise returns `False`.
1017
1018    Args:
1019        `tag` (`str`): [Required] The tag of the object to lookup.
1020
1021    """
1022    result = _a_canvas.find_withtag(tag)
1023
1024    if result
1025        return True
1026    else
1027        return False

Returns True if a given tag exists otherwise returns False.

Arguments:
  • tag (str): [Required] The tag of the object to lookup.
def random_color():
1030def random_color():
1031    """
1032    Returns a random color as a `string` to be used with `tkinter`.
1033    It does not accept any inputs.
1034    """
1035    r = lambda randint(0, 255)
1036    return "#%02X%02X%02X" % (r(), r(), r())

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

def setup_shapes(title, background="white", width=600, height=600):
1042def setup_shapes(title, background="white", width=600, height=600):
1043    """
1044    A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION.
1045    """
1046    global _a_canvas
1047    gui = Tk()
1048    gui.title(title)
1049    _a_canvas = Canvas(gui, background=background, width=width, height=width)
1050    _a_canvas.pack()
1051    make_grid(_a_canvas, width, height)
1052    return _a_canvas

A static function that sets up the pop-up window. DO NOT USE THIS FUNCTION.