Пример #1
0
def get_endlines_sidelines(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the bounding box of the
    end lines and sidelines as specified in Rule 1, Section 3, Article 2 of
    the NCAA rule book

    Returns
    -------
    endline_sideline: a pandas dataframe of the end lines and side lines
    """
    endline_sideline = pd.DataFrame({
        'x': [0, -47, -47, 0, 0, -47 - (2 / 12), -47 - (2 / 12), 0, 0],
        'y': [
            -25, -25, 25, 25, 25 + (2 / 12), 25 + (2 / 12), -25 - (2 / 12),
            -25 - (2 / 12), -25
        ]
    })

    if full_court:
        # Reflect the x coordinates over the y axis
        endline_sideline = endline_sideline.append(
            transform.reflect(endline_sideline, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        endline_sideline = transform.rotate(endline_sideline, rotation_dir)

    return endline_sideline
Пример #2
0
def get_division_line(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the bounding box of
    the division line as specified in Rule 1, Section 5, Article 1 of the NCAA
    rule book

    Returns
    -------
    division_line: a pandas dataframe of the interior boundaries of the court
    """
    # The line's center should be 47' from the interior side of the baselines,
    # and must be 2" thick
    division_line = pd.DataFrame({
        'x': [-1 / 12, 0, 0, -1 / 12, -1 / 12],
        'y': [25, 25, -25, -25, 25]
    })
    if full_court:
        # Reflect the x coordinates over the y axis
        division_line = division_line.append(
            transform.reflect(division_line, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        division_line = transform.rotate(division_line, rotation_dir)

    return division_line
Пример #3
0
def get_backboards(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the backboard as
    specified in Rule 1, Section 10, Article 2 of the NCAA rule book

    Returns
    -------
    backboard: a pandas dataframe of the backboard
    """
    # Per the rule book, the backboard must by 6' wide. The height of the
    # backboard is irrelevant in this graphic, as this is a bird's eye view
    # over the court
    backboard = pd.DataFrame({
        'x': [-43 - (4 / 12), -43, -43, -43 - (4 / 12), -43 - (4 / 12)],
        'y': [-3, -3, 3, 3, -3]
    })

    if full_court:
        # Reflect x coordinates over y axis
        backboard = backboard.append(transform.reflect(backboard, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        backboard = transform.rotate(backboard, rotation_dir)

    return backboard
Пример #4
0
def get_painted_areas(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the bounding box of the
    free throw lane as specified in Rule 1, Section 6, Articles 1, 2, 3, and 4
    of the NCAA rule book
    
    Returns
    -------
    painted_areas: a pandas dataframe of the painted areas
    """
    # The interior of the free throw lane is known as the painted area, and
    # can be a different color than the markings and court. These coordinates
    # can be used to color them on the plot
    painted_area = pd.DataFrame({
        'x': [-47, -47, -28 - (2 / 12), -28 - (2 / 12), -47],
        'y': [
            -6 + (2 / 12), 6 - (2 / 12), 6 - (2 / 12), -6 + (2 / 12),
            -6 + (2 / 12)
        ]
    })

    if full_court:
        # Reflect the x coordinates over the y axis
        painted_area = painted_area.append(
            transform.reflect(painted_area, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        painted_area = transform.rotate(painted_area, rotation_dir)

    return painted_area
Пример #5
0
def get_center_circle(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the center circle as
    specified in Rule 1, Section 4, Article 1 of the NCAA rule book

    Returns
    -------
    center_circle: a pandas dataframe containing the points that comprise the
        center circle of the court
    """
    # Draw the right outer semicircle, then move in 2" per the NCAA's required
    # line thickness, and draw inner semicircle. Doing it this way alleviates
    # future fill issues.
    center_circle = helper.create_circle(d=12, start=1 / 2, end=3 / 2).append(
        pd.DataFrame({
            'x': [0],
            'y': [6 - (2 / 12)]
        })).append(
            helper.create_circle(d=12 - (4 / 12), start=3 / 2,
                                 end=1 / 2)).append(
                                     pd.DataFrame({
                                         'x': [0],
                                         'y': [-6]
                                     }))

    if full_court:
        # Reflect the x coordinates over the y axis
        center_circle = center_circle.append(
            transform.reflect(center_circle, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        center_circle = transform.rotate(center_circle, rotation_dir)

    return center_circle
Пример #6
0
def get_bench_areas(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the team bench areas
    as specified on the court diagram in the NCAA rule book

    Returns
    -------
    bench_areas: a pandas dataframe of the team bench areas
    """
    # The bench area is 28 feet from the interior of the endline, is 2" wide,
    # and extends 3' on each side of the sideline
    bench_area = pd.DataFrame({
        'x': [
            -19 - (2 / 12),
            -19 - (2 / 12),
            -19,
            -19,
            -19 - (2 / 12),
        ],
        'y': [22, 28, 28, 22, 22]
    })

    if full_court:
        # Reflect the x coordinates over the y axis
        bench_area = bench_area.append(
            transform.reflect(bench_area, over_y=True))
    # Rotate the coordinates if necessary
    if rotate:
        bench_area = transform.rotate(bench_area, rotation_dir)

    return bench_area
Пример #7
0
def get_coaching_boxes(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the bounding box of the
    coaching boxes as specified in Rule 1, Section 9, Articles 1 and 2 of the
    NCAA rule book

    Returns
    -------
    coaching_boxes: a pandas dataframe of the sidelines
    """
    # The coaching boxes are 38' from the interior of the baseline on each
    # side of the court, and extend 2' out of bounds from the exterior of the
    # sideline
    coaching_box = pd.DataFrame({
        'x': [-9 - (2 / 12), -9 - (2 / 12), -9, -9, -9 - (2 / 12)],
        'y': [25, 27, 27, 25, 25]
    })

    if full_court:
        # Reflect the x coordinates over the y axis
        coaching_box = coaching_box.append(
            transform.reflect(coaching_box, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        coaching_box = transform.rotate(coaching_box, rotation_dir)

    return coaching_box
Пример #8
0
def get_restricted_area_arcs(full_court=True,
                             rotate=False,
                             rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the restricted-area
    arcs as specified in Rule 1, Section 8 of the NCAA rule book

    Returns
    -------
    restricted_area_arcs: a pandas dataframe of the restricted-area arcs
    """
    # The restricted area arc is an arc of radius 4' from the center of the
    # basket, and extending in a straight line to the front face of the
    # backboard, and having thickness of 2"
    restricted_area_arc = pd.DataFrame({
        'x': [-43],
        'y': [-4 - (2 / 12)]
    }).append(
        helper.create_circle(center=(-41.75, 0),
                             d=8 + (4 / 12),
                             start=-1 / 2,
                             end=1 / 2)).append(
                                 pd.DataFrame({
                                     'x': [-43, -43],
                                     'y': [4 + (2 / 12), 4]
                                 })).append(
                                     helper.create_circle(
                                         center=(-41.75, 0),
                                         d=8,
                                         start=1 / 2,
                                         end=-1 / 2)).append(
                                             pd.DataFrame({
                                                 'x': [-43, -43],
                                                 'y': [-4, -4 - (2 / 12)]
                                             }))

    if full_court:
        # Reflect the x coordinates over the y axis
        restricted_area_arc = restricted_area_arc.append(
            transform.reflect(restricted_area_arc, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        restricted_area_arc = transform.rotate(rotation_dir=rotation_dir,
                                               df=restricted_area_arc)

    return restricted_area_arc
Пример #9
0
def get_w_three_pt_lines(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the three-point line
    as specified in Rule 1, Section 7 of the NCAA rule book. These points are
    the women's three-point line, and also where the men's three-point line was
    prior to the 2019-2020 season

    Returns
    -------
    w_three_pt_lines: a pandas dataframe of the three-point line
    """
    # This can be computed similarly to how the men's line was computed
    w_three_pt_line = pd.DataFrame({
        'x': [-47],
        'y': [-20.75]
    }).append(
        helper.create_circle(center=(-41.75, 0),
                             d=41.5,
                             start=-1 / 2,
                             end=1 / 2)).append(
                                 pd.DataFrame({
                                     'x': [-47, -47],
                                     'y': [20.75, 20.75 - (2 / 12)]
                                 })).append(
                                     helper.create_circle(
                                         center=(-41.75, 0),
                                         d=41.5 - (4 / 12),
                                         start=1 / 2,
                                         end=-1 / 2)).append(
                                             pd.DataFrame({
                                                 'x': [-47, -47],
                                                 'y':
                                                 [-20.75 + (2 / 12), -20.75]
                                             }))

    if full_court:
        # Reflect the x coordinates over the y axis
        w_three_pt_line = w_three_pt_line.append(
            transform.reflect(w_three_pt_line, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        w_three_pt_line = transform.rotate(w_three_pt_line, rotation_dir)

    return w_three_pt_line
Пример #10
0
def get_goals(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the goals as specified
    in Rule 1, Sections 14 and 15 of the NCAA rule book

    Returns
    -------
    goals: a pandas dataframe of the goals
    """
    # Get the starting angle of the ring. The connector has a width of 5", so
    # 2.5" are on either side. The ring has a radius of 9", so the arcsine of
    # these measurements should give the angle at which point they connect
    start_angle = np.pi - math.asin(2.5 / 9)

    # The ending angle of the ring would be the negative of the starting angle
    end_angle = -start_angle

    # Define the coordinates for the goal
    goal = pd.DataFrame({
        'x': [-43, -41.75 - ((9 / 12) * math.cos(start_angle))],
        'y': [2.5 / 12, 2.5 / 12]
    }).append(
        helper.create_circle(
            center=(-41.75, 0),
            start=start_angle,
            end=end_angle,
            d=1.5 + (4 / 12))).append(
                pd.DataFrame({
                    'x':
                    [-41.75 - ((9 / 12) * math.cos(start_angle)), -43, -43],
                    'y': [-2.5 / 12, -2.5 / 12, 2.5 / 12]
                }))

    if full_court:
        # Reflect x coordinates over y axis
        goal = goal.append(transform.reflect(goal, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        goal = transform.rotate(goal, rotation_dir)

    return goal
Пример #11
0
def get_nets(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the rings as specified
    in Rule 1, Section 14, Article 2 of the NCAA rule book

    Returns
    -------
    nets: a pandas dataframe of the nets
    """
    # The ring's center is 15" from the backboard, and 63" from the baseline,
    # which means it is centered at (+/-41.75, 0). The ring has an interior
    # diameter of 18", which is where the net is visible from above
    net = helper.create_circle(center=(-41.75, 0), d=1.5)

    if full_court:
        # Reflect x coordinates over y axis
        net = net.append(transform.reflect(net, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        net = transform.rotate(net, rotation_dir)

    return net
Пример #12
0
def get_free_throw_circles(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the free-throw circles
    as specified on the court diagram in the NCAA rule book

    Returns
    -------
    free_throw_circles: a pandas dataframe of the free-throw circle
    """
    # The free-throw circle is 6' in diameter from the center of the free-throw
    # line (exterior)
    free_throw_circle = helper.create_circle(
        center=(-28, 0), start=-1 / 2, end=1 / 2,
        d=12).append(pd.DataFrame({
            'x': [-28],
            'y': [6]
        })).append(
            helper.create_circle(center=(-28, 0),
                                 start=1 / 2,
                                 end=-1 / 2,
                                 d=12 - (4 / 12))).append(
                                     pd.DataFrame({
                                         'x': [-28],
                                         'y': [-6]
                                     }))

    if full_court:
        # Reflect x coordinates over y axis
        free_throw_circle = free_throw_circle.append(
            transform.reflect(free_throw_circle, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        free_throw_circle = transform.rotate(free_throw_circle, rotation_dir)

    return free_throw_circle
Пример #13
0
def get_m_three_pt_lines(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the three-point line
    as specified in Rule 1, Section 7 of the NCAA rule book. These points are
    the men's three-point line after being moved back prior to the 2019-2020
    season

    Returns
    -------
    m_three_pt_lines: a pandas dataframe of the three-point line
    """
    # First, a bit of math is needed to determine the starting and ending
    # angles of the three-point arc, relative to 0 radians. Since in the end,
    # the angle is what matters, the units of measure do not. Inches are easier
    # to use for this calculation. The angle begins 9' 10 3/8" from the
    # interior edge of the endline
    start_x = (9 * 12) + 10 + (3 / 8)

    # However, the rule book describes the arc as having a radius of 22' 1.75"
    # from the center of the basket. The basket's center is 63" away from the
    # interior of the endline, so this must be subtracted from our starting x
    # position to get the starting x position *relative to the center of the
    # basket*
    start_x -= 63
    radius_outer = (22 * 12) + 1.75

    # From here, the calculation is relatively straightforward. To determine
    # the angle, the inverse cosine is needed. It will be multiplied by pi
    # so that it can be passed to the create_circle() function
    start_angle_outer = math.acos(start_x / radius_outer) / np.pi
    end_angle_outer = -start_angle_outer

    # The same method can be used for the inner angles, however, since the
    # inner radius will be traced from bottom to top, the angle must be
    # negative to start
    radius_inner = (22 * 12) + 1.75 - 2
    start_angle_inner = -math.acos(start_x / radius_inner) / np.pi
    end_angle_inner = -start_angle_inner

    # According to the rulebook, the three-point line is 21' 7 7/8" in the
    # corners
    m_three_pt_line = pd.DataFrame({
        'x': [-47],
        'y': [21 + ((7 + (7 / 8)) / 12)]
    }).append(
        helper.create_circle(
            center=(-41.75, 0),
            d=2 * (((22 * 12) + 1.75) / 12),
            start=start_angle_outer,
            end=end_angle_outer)).append(
                pd.DataFrame({
                    'x': [-47, -47, -47 + (((9 * 12) + 10 + (3 / 8)) / 12)],
                    'y': [
                        -21 - ((7 + (7 / 8)) / 12),
                        -21 - ((7 + (7 / 8)) / 12) + (2 / 12),
                        -21 - ((7 + (7 / 8)) / 12) + (2 / 12)
                    ]
                })).append(
                    helper.create_circle(
                        center=(-41.75, 0),
                        d=2 * ((((22 * 12) + 1.75) / 12) - (2 / 12)),
                        start=start_angle_inner,
                        end=end_angle_inner)).append(
                            pd.DataFrame({
                                'x': [
                                    -47 + (((9 * 12) + 10 + (3 / 8)) / 12),
                                    -47, -47
                                ],
                                'y': [
                                    21 + ((7 + (7 / 8)) / 12) - (2 / 12),
                                    21 + ((7 + (7 / 8)) / 12) - (2 / 12),
                                    21 + ((7 + (7 / 8)) / 12)
                                ]
                            }))

    if full_court:
        # Reflec the x coordinates over the y axis
        m_three_pt_line = m_three_pt_line.append(
            transform.reflect(m_three_pt_line, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        m_three_pt_line = transform.rotate(rotation_dir=rotation_dir,
                                           df=m_three_pt_line)

    return m_three_pt_line
Пример #14
0
def get_free_throw_lanes(full_court=True, rotate=False, rotation_dir='ccw'):
    """
    Generate the dataframe for the points that comprise the bounding box of the
    free throw lane as specified in Rule 1, Section 6, Articles 1, 2, 3, and 4
    of the NCAA rule book

    Returns
    -------
    free_throw_lanes: a pandas dataframe of the free throw lanes
    painted_areas: a pandas dataframe of the painted areas
    """
    # The free throw lane goes from the endline inwards a distance of 18' 10"
    # (interior) and 19' (exterior) with a width of 6'

    # The first set of blocks are 7' from the interior of the baseline, and
    # measure 1' in width

    # The second set of blocks are 3' from the first block, and
    # measure 2" in width

    # The third set of blocks are 3' from the second block, and
    # measure 2" in width

    # The fourth set of blocks are 3' from the third block, and
    # measure 2" in width
    free_throw_lane = pd.DataFrame({
        'x': [
            # Start
            -47,

            # First block lower
            -40,
            -40,
            -39,
            -39,

            # Second block lower
            -36,
            -36,
            -36 + (2 / 12),
            -36 + (2 / 12),

            # Third block lower
            -33 + (2 / 12),
            -33 + (2 / 12),
            -33 + (4 / 12),
            -33 + (4 / 12),

            # Fourth block lower
            -30 + (4 / 12),
            -30 + (4 / 12),
            -30 + (6 / 12),
            -30 + (6 / 12),

            # End
            -28,

            # Cross
            -28,

            # Fourth block upper
            -30 + (6 / 12),
            -30 + (6 / 12),
            -30 + (4 / 12),
            -30 + (4 / 12),

            # Third block upper
            -33 + (2 / 12),
            -33 + (2 / 12),
            -33 + (4 / 12),
            -33 + (4 / 12),

            # Second block upper
            -36,
            -36,
            -36 + (2 / 12),
            -36 + (2 / 12),

            # First block upper
            -40,
            -40,
            -39,
            -39,

            # End of exterior
            -47,

            # Interior
            -47,
            -28 - (2 / 12),
            -28 - (2 / 12),
            -47,
            -47,
            -47
        ],
        'y': [
            -6,

            # First block lower
            -6,
            -6 - (8 / 12),
            -6 - (8 / 12),
            -6,

            # Second block lower
            -6,
            -6 - (8 / 12),
            -6 - (8 / 12),
            -6,

            # Third block lower
            -6,
            -6 - (8 / 12),
            -6 - (8 / 12),
            -6,

            # Fourth block lower
            -6,
            -6 - (8 / 12),
            -6 - (8 / 12),
            -6,

            # End
            -6,

            # Cross
            6,

            # Fourth block upper
            6,
            6 + (8 / 12),
            6 + (8 / 12),
            6,

            # Third block upper
            6,
            6 + (8 / 12),
            6 + (8 / 12),
            6,

            # Second block upper
            6,
            6 + (8 / 12),
            6 + (8 / 12),
            6,

            # First block upper
            6,
            6 + (8 / 12),
            6 + (8 / 12),
            6,

            # End of exterior
            6,

            # Interior
            6 - (2 / 12),
            6 - (2 / 12),
            -6 + (2 / 12),
            -6 + (2 / 12),
            6,
            -6
        ]
    })

    if full_court:
        # Reflect the x coordinates over the y axis
        free_throw_lane = free_throw_lane.append(
            transform.reflect(free_throw_lane, over_y=True))

    # Rotate the coordinates if necessary
    if rotate:
        free_throw_lane = transform.rotate(free_throw_lane, rotation_dir)

    return free_throw_lane