def isosceles(width, height, filled=False): tip = (0, height) left = (-width / 2.0, 0) right = (width / 2.0, 0) return Polygon([tip, left, right, tip], filled=filled)
def rectangle(width, height): corners = [] corners.append((-width / 2.0, -height / 2.0)) corners.append((-width / 2.0, height / 2.0)) corners.append((width / 2.0, height / 2.0)) corners.append((width / 2.0, -height / 2.0)) corners.append((-width / 2.0, -height / 2.0)) return Polygon(corners)
def fan(radius, start_angle, end_angle, height, segments=100, filled=False): """A Fan is a slice of a donut seen from above (when you can see the hole in the middle). All angles are assumed to be in radians.""" if start_angle > end_angle: end_angle += math.pi * 2 arc1 = arc_circle(radius - height / 2, start_angle, end_angle, segments) arc2 = arc_circle(radius + height / 2, start_angle, end_angle, segments) points = list(arc1.points) + list(reversed(arc2.points)) return Polygon(points)
def star_outline(width, height, num_points=5): '''Constructs a star shape in outline. ''' corners = [] pi_div_180 = math.pi / 180.0 half_width = width * 0.5 half_height = height * 0.5 degrees = degrees_offset = 90 even = True degrees_incr = 360.0 / float(num_points * 2) quarter_width = half_width * 0.5 quarter_height = half_height * 0.5 while degrees < 360.0 + degrees_offset: alpha = degrees * pi_div_180 sin_alpha = math.sin(alpha) cos_alpha = math.cos(alpha) if even: w_multi = half_width h_multi = half_height even = False else: w_multi = quarter_width h_multi = quarter_height even = True point_x = (w_multi * cos_alpha) point_y = (h_multi * sin_alpha) corners.append((point_x, point_y)) degrees += degrees_incr corners.append(corners[0]) return Polygon(corners)
def circle(radius, segments=36): '''Returns a circle.''' coords = [(math.cos(math.pi * 2 / segments * r) * radius, math.sin(math.pi * 2 / segments * r) * radius) for r in range(segments)] return Polygon(coords)
def star_crisscross(width, height, num_points=5, jump_size=None, find_valid_jump_size=True): """ Draws a star with criscrossing lines. jump_size determines how many points to skip between connected points. an illegal jump size (one that does not result in a valid crisscross star) is ignored and replaced with a dot in the center of the star. """ corners = [] pi_div_180 = math.pi / 180.0 half_width = width * 0.5 half_height = height * 0.5 degrees = degrees_offset = 90 degrees_incr = 360.0 / num_points while degrees < 360.0 + degrees_offset: alpha = degrees * pi_div_180 sin_alpha = math.sin(alpha) cos_alpha = math.cos(alpha) point_x = half_width * cos_alpha point_y = half_height * sin_alpha corners.append((point_x, point_y)) degrees += degrees_incr corners.append(corners[0]) if num_points == 6: # special case, ignore jump_size # rearrange points to draw two polygons multiplier = int(num_points / 2) corners1 = [corners[0], corners[2], corners[4]] corners2 = [corners[1], corners[3], corners[5]] poly1 = Polygon(corners1) poly2 = Polygon(corners2) return Group([poly1, poly2]) else: if jump_size is None: jump_size = int(num_points / 2) if gcd(num_points, jump_size) != 1: if find_valid_jump_size: while gcd(num_points, jump_size) != 1: jump_size -= 1 else: invalid_star = [[half_width, half_height], [half_width, half_height]] return Polygon(invalid_star) point_order = [] for i in range(0, num_points): point_num = (i * jump_size) % num_points point_order.append(point_num) corners = [corners[i] for i in point_order] return Polygon(corners)