def boards(full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframe for the points that comprise the boards as specified in Rule 1.3 of the NHL rule book Parameters ---------- full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature Returns ------- boards: a pandas dataframe of coordinates needed to plot the boards """ boards = pd.DataFrame({ 'x': [0], 'y': [42.5] }).append(create.circle(center=(-72, 14.5), start=.5, end=1, d=56)).append( pd.DataFrame({ 'x': [-100], 'y': [0] })).append(create.circle( center=(-72, -14.5), start=1, end=1.5, d=56)).append( pd.DataFrame({ 'x': [0, 0], 'y': [-42.5, -42.5 - (2 / 12)] })).append( create.circle(center=(-72, -14.5), start=1.5, end=1, d=56 + (4 / 12))).append( pd.DataFrame({ 'x': [-100 - (2 / 12)], 'y': [0] })).append( create.circle( center=(-72, 14.5), start=1, end=.5, d=56 + (4 / 12))).append( pd.DataFrame({ 'x': [0, 0], 'y': [42.5 + (2 / 12), 42.5] })) # Reflect the x coordinates over the y axis if full_surf: boards = boards.append(transform.reflect(boards, over_y=True)) # Rotate the coordinates if necessary if rotate: boards = transform.rotate(boards, rotation_dir) return boards
def outer_center_circle(full_surf = True, rotate = False, rotation_dir = 'ccw'): """ Generate the dataframe for the points that comprise the outer center circle as in the court diagram on page 8 of the NBA rule book Parameters ---------- full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature Returns ------- outer_center_circle: A pandas dataframe containing the points that comprise the center circle of the court """ # Draw the outer semicircle at half court. It has an outer radius of 6' # and thickness of 2" outer_center_circle = create.circle( d = 12 - (4/12), start = 1/2, end = 3/2 ).append( pd.DataFrame({ 'x': [0], 'y': [-12] }) ).append( create.circle( d = 12, start = 3/2, end = 1/2 ) ).append( pd.DataFrame({ 'x': [0], 'y': [12] }) ) # Reflect the x coordinates over the y axis if full_surf: outer_center_circle = outer_center_circle.append( transform.reflect(outer_center_circle, over_y = True) ) # Rotate the coordinates if necessary if rotate: outer_center_circle = transform.rotate( outer_center_circle, rotation_dir ) return outer_center_circle
def net(full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframe for the points that comprise the rings as specified in the court diagram of the WNBA rule book Parameters ---------- full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature 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 = create.circle(center=(-41.75, 0), d=1.5) # Reflect the x coordinates over the y axis if full_surf: net = net.append(transform.reflect(net, over_y=True)) # Rotate the coordinates if necessary if rotate: net = transform.rotate(net, rotation_dir) return net
def goal_line(full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframe for the points that comprise the goal line as specified in Rule 1.7 of the NHL rule book Parameters ---------- full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature Returns ------- goal_line: a pandas dataframe of coordinates needed to plot the goal line """ # The goal line is a little tricky. It is 11' away from the boards (or 89' # from the center), but follows the curvature of the boards in the corner. # To get the curvature, a similar calculation to that of the face-off spot # interior can be performed theta1 = math.asin((17 - (1 / 12)) / 28) / np.pi theta2 = math.asin((17 + (1 / 12)) / 28) / np.pi goal_line = create.circle(center=(-72, 14.5), start=.5 + theta1, end=.5 + theta2, d=56).append( create.circle(center=(-72, -14.5), start=1.5 - theta2, end=1.5 - theta1, d=56)).append( create.circle( center=(-72, 14.5), start=.5 + theta1, end=.5 + theta2, d=56).iloc[0]) # Reflect the x coordinates over the y axis if full_surf: goal_line = goal_line.append(transform.reflect(goal_line, over_y=True)) # Rotate the coordinates if necessary if rotate: goal_line = transform.rotate(goal_line, rotation_dir) return goal_line
def referee_crease(full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframe for the points that comprise the referee's crease as specified in Rule 1.7 of the NHL rule book Parameters ---------- full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature Returns ------- referee_crease: a pandas dataframe of coordinates needed to plot the referee's crease """ # The referee's crease is located at center ice in front of the penalty # timekeeper's seat. It is a 2" thick, 10' radius semi-circle referee_crease = create.circle( center=(0, -42.5), start=.5, end=1, d=20).append(pd.DataFrame({ 'x': [-10 + (2 / 12)], 'y': [-42.5] })).append( create.circle(center=(0, -42.5), start=1, end=.5, d=20 - (4 / 12))).append( pd.DataFrame({ 'x': [0], 'y': [10] })) # Reflect the x coordinates over the y axis if full_surf: referee_crease = referee_crease.append( transform.reflect(referee_crease, over_y=True)) # Rotate the coordinates if necessary if rotate: referee_crease = transform.rotate(referee_crease, rotation_dir) return referee_crease
def goal(full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframe for the points that comprise the goals as specified in the court diagram of the WNBA rule book Parameters ---------- full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature 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( 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] })) # Reflect the x coordinates over the y axis if full_surf: goal = goal.append(transform.reflect(goal, over_y=True)) # Rotate the coordinates if necessary if rotate: goal = transform.rotate(goal, rotation_dir) return goal
def faceoff_spot( center=(0, 0), full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframe for the points that comprise the face-off spots as specified in Rule 1.9 of the NHL rule book Parameters ---------- center: a tuple containing the center coordinates of the spot to be drawn full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature Returns ------- spot_dict: a dictionary with keys of 'center' and 'spot', where 'center' corresponds to the center coordinates of a face-off spot, and 'spot' is a pandas dataframe of coordinates to plot to make a face-off spot """ # Center faceoff spot if center == (0, 0): # The center face-off spot is 12" in diameter spot = create.circle(center=(0, 0), start=1 / 2, end=3 / 2, d=1) # Reflect the x coordinates over the y axis if full_surf: spot = create.circle(center=(0, 0), start=1 / 2, end=5 / 2, d=1) # Rotate the coordinates if necessary if rotate: spot = transform.rotate(spot, rotation_dir) spot_dict = { 'center': center, 'spot_outer': spot, 'spot_inner': pd.DataFrame({ 'x': [], 'y': [] }) } return spot_dict else: # The non-center face-off spots are 2' in diameter, with a 3" gap # between the top and bottom of the spot and the strip in the center. # First, find the angle at which to start the trace for the interior # of the spot. # The spot has a radius of 1', and a thickness of 2", so the inner # radius is 10". Since there is a 3" gap at theta = 180deg, this # indicates that the stripe's curve starts at x = -7" from the center. # Using trigonometry, the angle can be computed theta = math.asin(7 / 10) / np.pi # To draw this evenly, it's easiest to create two dataframes: one is # the underlying red spot of diameter 2', and the other being the # white inner portion described in the rule book. The starting point # is found using theta calculated above spot_outer = create.circle(center=(0, 0), start=0, end=2, d=2) spot_inner = create.circle(center=(0, 0), start=.5 + theta, end=1.5 - theta, d=2 - (4 / 12)).append( create.circle(center=(0, 0), start=.5 + theta, end=1.5 - theta, d=2 - (4 / 12)).iloc[0]) spot_inner = spot_inner.append( transform.reflect(spot_inner, over_y=True)) # Rotate the coordinates if necessary if rotate: spot_outer = transform.rotate(spot_outer, rotation_dir) spot_inner = transform.rotate(spot_inner, rotation_dir) spot_outer = transform.translate(spot_outer, translate_x=center[0], translate_y=center[1]) spot_inner = transform.translate(spot_inner, translate_x=center[0], translate_y=center[1]) spot_dict = { 'center': center, 'spot_outer': spot_outer, 'spot_inner': spot_inner } return spot_dict
def goal_crease(full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframe for the points that comprise the goal crease outline and blue inner area as specified in Rule 1.7 of the NHL rule book Parameters ---------- full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature Returns ------- goal_crease_dict: a dictionary with keys of 'goal_crease_outline' and 'goal_crease_inner', where 'goal_crease_outline' is a pandas dataframe that corresponds to the coordinates of the red outline of the goal crease, and 'goal_crease_inner' is a pandas dataframe of coordinates of the boundary of the blue interior of the goal crease """ theta = math.asin(4 / 6) / np.pi goal_crease_outline = pd.DataFrame({ 'x': [-89 + (1 / 12), -89 + 4.5 + (1 / 12)], 'y': [4, 4] }).append(create.circle( center=(-89, 0), start=theta, end=-theta, d=12)).append( pd.DataFrame({ 'x': [ -89 + (1 / 12), -89 + (1 / 12), -85 + (1 / 12), -85 + (1 / 12), -85 + (3 / 12), -85 + (3 / 12) ], 'y': [ -4, -4 + (2 / 12), -4 + (2 / 12), -4 + (7 / 12), -4 + (7 / 12), -4 + (2 / 12) ] })).append( create.circle(center=(-89, 0), start=-theta, end=theta, d=12 - (4 / 12))).append( pd.DataFrame({ 'x': [ -85 + (3 / 12), -85 + (3 / 12), -85 + (1 / 12), -85 + (1 / 12), -89 + (1 / 12), -89 + (1 / 12) ], 'y': [ 4 - (2 / 12), 4 - (7 / 12), 4 - (7 / 12), 4 - (2 / 12), 4 - (2 / 12), 4 ] })) goal_crease_inner = pd.DataFrame({ 'x': [ -89 + (1 / 12), -85 + (1 / 12), -85 + (1 / 12), -85 + (3 / 12), -85 + (3 / 12) ], 'y': [ -4 + (2 / 12), -4 + (2 / 12), -4 + (7 / 12), -4 + (7 / 12), -4 + (2 / 12) ] }).append( create.circle(center=(-89, 0), start=-theta, end=theta, d=12 - (4 / 12))).append( pd.DataFrame({ 'x': [ -85 + (3 / 12), -85 + (3 / 12), -85 + (1 / 12), -85 + (1 / 12), -89 + (1 / 12), -89 + (1 / 12) ], 'y': [ 4 - (2 / 12), 4 - (7 / 12), 4 - (7 / 12), 4 - (2 / 12), 4 - (2 / 12), -4 + (2 / 12) ] })) # Reflect the x coordinates over the y axis if full_surf: goal_crease_outline = goal_crease_outline.append( transform.reflect(goal_crease_outline, over_y=True)) goal_crease_inner = goal_crease_inner.append( transform.reflect(goal_crease_inner, over_y=True)) # Rotate the coordinates if necessary if rotate: goal_crease_outline = transform.rotate(goal_crease_outline, rotation_dir) goal_crease_inner = transform.rotate(goal_crease_inner, rotation_dir) goal_crease_dict = { 'goal_crease_outline': goal_crease_outline, 'goal_crease_inner': goal_crease_inner } return goal_crease_dict
def faceoff_circle( center=(0, 0), full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframe for the points that comprise the face-off circles as specified in Rule 1.9 of the NHL rule book Parameters ---------- center: a tuple containing the center coordinates of the spot to be drawn full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature Returns ------- faceoff_circle_dict: a dictionary with keys of 'center' and 'spot', where 'center' corresponds to the center coordinates of the face-off spot, and 'spot' is a pandas dataframe of coordinates needed to plot a face-off circle """ # The center circle has no external hash marks, so this circle just needs # to be a circle of 2" thickness if center == (0, 0): faceoff_circle = create.circle( center=(0, 0), start=.5, end=1.5, d=30).append( pd.DataFrame({ 'x': [0, 0], 'y': [-15, -15 + (2 / 12)] })).append( create.circle(center=(0, 0), start=1.5, end=.5, d=30 - (4 / 12))).append( pd.DataFrame({ 'x': [0, 0], 'y': [15 - (2 / 12), 15] })) else: # Similar to the method described above, the starting angle to draw the # outer ring can be computed. The hash marks are 5' 11" (71") apart on # the exterior, so taking where this hash mark meets the circle to be # the center, the starting angle is computed as follows theta1 = math.asin((35.5 / 12) / 15) / np.pi # The same process gives the angle to find the point on the interior # of the hash mark, which are 5' 7" (67") apart theta2 = math.asin((33.5 / 12) / 15) / np.pi # Since the hash mark will be plotted on the top of the circle, the # starting angle will be theta + pi/2 faceoff_circle = create.circle( center=(0, 0), start=.5 + theta1, end=1.5 - theta1, d=30).append( pd.DataFrame({ 'x': [ -35.5 / 12, -33.5 / 12, ], 'y': [-17, -17] })).append( create.circle( center=(0, 0), start=1.5 - theta2, end=1.5, d=30)).append( pd.DataFrame({ 'x': [0], 'y': [-15 + (2 / 12)] })).append( create.circle( center=(0, 0), start=1.5, end=.5, d=30 - (4 / 12))).append( pd.DataFrame({ 'x': [0], 'y': [15] })).append( create.circle( center=(0, 0), start=.5, end=.5 + theta2, d=30)).append( pd.DataFrame({ 'x': [ -33.5 / 12, -35.5 / 12, ], 'y': [17, 17] })).append( create.circle( center=(0, 0), start=.5 + theta1, end=1.5 - theta1, d=30).iloc[0]) # If the faceoff circle being drawn is the center circle, and only half # the ice is desired, return the semi-circle that is present if center == (0, 0) and not full_surf: pass # If the spot is in the neutral zone, there should not be a circle around # it elif abs(center[0]) == 20: faceoff_circle = pd.DataFrame({'x': [], 'y': []}) else: # In all other cases, the entire circle should be generated, so the # current points set needs to be reflected over the y axis faceoff_circle = faceoff_circle.append( transform.reflect(faceoff_circle, over_y=True)) faceoff_circle = transform.translate(faceoff_circle, translate_x=center[0], translate_y=center[1]) # Rotate the coordinates if necessary. This is more for consistency # than necessity as a rotated circle is visually the same if rotate: faceoff_circle = transform.rotate(faceoff_circle, rotation_dir) faceoff_circle_dict = {'center': center, 'faceoff_circle': faceoff_circle} return faceoff_circle_dict
def restricted_area_arc(full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframe for the points that comprise the restricted-area arcs as specified in the WNBA rule book Parameters ---------- full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature Returns ------- restricted_area_arcs: a pandas dataframe of the restricted-area arcs """ # Following the same process as for the three-point line, the restricted # area arc's starting and ending angle can be computed start_y = -4 - (2 / 12) # The rule book describes the arc as having a radius of 4' radius_outer = 4 + (2 / 12) # From here, the calculation is relatively straightforward. To determine # the angle, the inverse sine is needed. It will be multiplied by pi # so that it can be passed to the create_circle() function start_angle_outer = math.asin(start_y / 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 = 4 start_angle_inner = -math.asin((start_y + (2 / 12)) / radius_inner) / np.pi end_angle_inner = -start_angle_inner # 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( create.circle(center=(-41.75, 0), d=8 + (4 / 12), start=start_angle_outer, end=end_angle_outer)).append( pd.DataFrame({ 'x': [-43, -43], 'y': [4 + (2 / 12), 4] })).append( create.circle(center=(-41.75, 0), d=8, start=start_angle_inner, end=end_angle_inner)).append( pd.DataFrame({ 'x': [-43, -43], 'y': [-4, -4 - (2 / 12)] })) # Reflect the x coordinates over the y axis if full_surf: 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, restricted_area_arc) return restricted_area_arc
def three_point_line(full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframe for the points that comprise the three-point line as specified in the WNBA rule book Parameters ---------- full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature Returns ------- three_point_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 3' from the interior edge # of the sideline start_y = (22 * 12) # The rule book describes the arc as having a radius of 23' 9" radius_outer = (22 * 12) + 1.75 # From here, the calculation is relatively straightforward. To determine # the angle, the inverse sine is needed. It will be multiplied by pi # so that it can be passed to the create_circle() function start_angle_outer = math.asin(start_y / 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.asin((start_y - 2) / 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 three_point_line = pd.DataFrame({ 'x': [-47], 'y': [22] }).append( create.circle(center=(-41.75, 0), d=2 * (radius_outer / 12), start=start_angle_outer, end=end_angle_outer)).append( pd.DataFrame({ 'x': [-47, -47], 'y': [-22, -22 + (2 / 12)] })).append( create.circle(center=(-41.75, 0), d=2 * (radius_inner / 12), start=start_angle_inner, end=end_angle_inner)).append( pd.DataFrame({ 'x': [-47, -47], 'y': [22 - (2 / 12), 22] })) # Reflect the x coordinates over the y axis if full_surf: three_point_line = three_point_line.append( transform.reflect(three_point_line, over_y=True)) # Rotate the coordinates if necessary if rotate: three_point_line = transform.rotate(rotation_dir, three_point_line) return three_point_line
def free_throw_circle(full_surf=True, rotate=False, rotation_dir='ccw'): """ Generate the dataframes for the points that comprise the free-throw circles as specified in page 8 of the WNBA rule book Parameters ---------- full_surf: a bool indicating whether or not this feature is needed for a full-surface representation rotate: a bool indicating whether or not this feature needs to be rotated rotation_dir: a string indicating which direction to rotate the feature Returns ------- free_throw_circles_dict: a dictionary with keys 'solid' and 'dash_x', where x is a number that corresponds to a dashed section of the free throw circle """ # Per the WNBA rule book, the solid portion of the circle extends along an # arc of length 12.29" behind the free-throw line. The angle theta must be # calculated to determine where to start. It can be determined via the # relationship s = r*theta, where s is the arc length, r is the radius, and # theta is the angle (in radians) # First, define s to be the arc length in feet s = 12.29 / 12 # The outer radius is 6' r = 6 # Theta is therefore s/r, but since the create.circle() function takes an # angle in radians/pi, this must be divided out as well theta = (s / r) / np.pi # Since the circle must extend theta radians past +/-pi/2, theta must be # added/subtracted from 1/2 accordingly start_angle = (-1 / 2) - theta end_angle = (1 / 2) + theta # The free-throw circle is 6' in diameter from the center of the free-throw # line (exterior) free_throw_circle_solid = create.circle( center=(-28 - (1 / 12), 0), start=start_angle, end=end_angle, d=12).append( create.circle(center=(-28 - (1 / 12), 0), start=end_angle, end=start_angle, d=12 - (4 / 12))).append( create.circle(center=(-28 - (1 / 12), 0), start=start_angle, end=end_angle, d=12).iloc[0]) # Reflect the x coordinates over the y axis if full_surf: free_throw_circle_solid = free_throw_circle_solid.append( transform.reflect(free_throw_circle_solid, over_y=True)) # Rotate the coordinates if necessary if rotate: free_throw_circle_solid = transform.rotate(free_throw_circle_solid, rotation_dir) # The dashed sections of the free-throw circle are all of length 15.5", and # are spaced 15.5" from each other. Following a similar process as above, # the starting and ending angles can be computed # First, compute the arc length in feet s = 15.5 / 12 # The outer radius is 6' r = 6 # Finally, compute the angle traced by the dashed lines theta_dashes = (s / r) / np.pi # This theta must be added to start_angle above to get the starting angle # for each dash, and added twice to get the ending angle for each dash. # This pattern can be repeated, taking the end angle of the previous dash # as the start angle for the following dash dash_1_start_angle = start_angle - theta_dashes dash_1_end_angle = start_angle - (2 * theta_dashes) dash_2_start_angle = dash_1_end_angle - theta_dashes dash_2_end_angle = dash_1_end_angle - (2 * theta_dashes) dash_3_start_angle = dash_2_end_angle - theta_dashes dash_3_end_angle = dash_2_end_angle - (2 * theta_dashes) free_throw_circle_dash_1 = create.circle( center=(-28 - (1 / 12), 0), start=dash_1_start_angle, end=dash_1_end_angle, d=12).append( create.circle(center=(-28 - (1 / 12), 0), start=dash_1_end_angle, end=dash_1_start_angle, d=12 - (4 / 12))).append( create.circle(center=(-28 - (1 / 12), 0), start=dash_1_start_angle, end=dash_1_end_angle, d=12).iloc[0]) free_throw_circle_dash_2 = create.circle( center=(-28 - (1 / 12), 0), start=dash_2_start_angle, end=dash_2_end_angle, d=12).append( create.circle(center=(-28 - (1 / 12), 0), start=dash_2_end_angle, end=dash_2_start_angle, d=12 - (4 / 12))).append( create.circle(center=(-28 - (1 / 12), 0), start=dash_2_start_angle, end=dash_2_end_angle, d=12).iloc[0]) free_throw_circle_dash_3 = create.circle( center=(-28 - (1 / 12), 0), start=dash_3_start_angle, end=dash_3_end_angle, d=12).append( create.circle(center=(-28 - (1 / 12), 0), start=dash_3_end_angle, end=dash_3_start_angle, d=12 - (4 / 12))).append( create.circle(center=(-28 - (1 / 12), 0), start=dash_3_start_angle, end=dash_3_end_angle, d=12).iloc[0]) # The remaining dashes are just the reflections of dashes 1, 2, and 3 over # the x axis free_throw_circle_dash_4 = transform.reflect(free_throw_circle_dash_3, over_x=True, over_y=False) free_throw_circle_dash_5 = transform.reflect(free_throw_circle_dash_2, over_x=True, over_y=False) free_throw_circle_dash_6 = transform.reflect(free_throw_circle_dash_1, over_x=True, over_y=False) # Reflect the x coordinates over the y axis if full_surf: free_throw_circle_dash_1 = free_throw_circle_dash_1.append( transform.reflect(free_throw_circle_dash_1, over_y=True)) free_throw_circle_dash_2 = free_throw_circle_dash_2.append( transform.reflect(free_throw_circle_dash_2, over_y=True)) free_throw_circle_dash_3 = free_throw_circle_dash_3.append( transform.reflect(free_throw_circle_dash_3, over_y=True)) free_throw_circle_dash_4 = free_throw_circle_dash_4.append( transform.reflect(free_throw_circle_dash_4, over_y=True)) free_throw_circle_dash_5 = free_throw_circle_dash_5.append( transform.reflect(free_throw_circle_dash_5, over_y=True)) free_throw_circle_dash_6 = free_throw_circle_dash_6.append( transform.reflect(free_throw_circle_dash_6, over_y=True)) # Rotate the coordinates if necessary if rotate: free_throw_circle_dash_1 = transform.rotate(free_throw_circle_dash_1, rotation_dir) free_throw_circle_dash_2 = transform.rotate(free_throw_circle_dash_2, rotation_dir) free_throw_circle_dash_3 = transform.rotate(free_throw_circle_dash_3, rotation_dir) free_throw_circle_dash_4 = transform.rotate(free_throw_circle_dash_4, rotation_dir) free_throw_circle_dash_5 = transform.rotate(free_throw_circle_dash_5, rotation_dir) free_throw_circle_dash_6 = transform.rotate(free_throw_circle_dash_6, rotation_dir) free_throw_circle_dict = { 'solid': free_throw_circle_solid, 'dash_1': free_throw_circle_dash_1, 'dash_2': free_throw_circle_dash_2, 'dash_3': free_throw_circle_dash_3, 'dash_4': free_throw_circle_dash_4, 'dash_5': free_throw_circle_dash_5, 'dash_6': free_throw_circle_dash_6 } return free_throw_circle_dict