def draw_square_blackhole(): img = SVGImage(1000, 800, center_origin=True, show_borders_and_origin=False, animate=False, animation_speed=0.01) o = [[-200, -200, 200, -200], [200, -200, 200, 200], [200, 200, -200, 200], [-200, 200, -200, -200]] angle = 10 sx = 1.1 sy = 0.8 origin = [0, 0] iterations = 60 for _ in range(iterations): for i, line in enumerate(o): x1, y1, x2, y2 = line img.add_line(x1, y1, x2, y2, width=2) x1, y1 = rotate((x1, y1), angle, origin) x2, y2 = rotate((x2, y2), angle, origin) x1, y1 = scale((x1, y1), sx, sy) x2, y2 = scale((x2, y2), sx, sy) o[i] = [x1, y1, x2, y2] img.save("img/square_blackhole.svg")
def draw_square_snail(): img = SVGImage(1000, 800, center_origin=True, show_borders_and_origin=False, animate=False, animation_speed=0.01) o = [[0, 0, 10, 0], [10, 0, 10, 10], [10, 10, 0, 10], [0, 10, 0, 0]] angle = 25 sx = 1.1 sy = 1.1 tx = 1 ty = 2 origin = [0, 0] iterations = 37 for _ in range(iterations): for i, line in enumerate(o): x1, y1, x2, y2 = line img.add_line(x1, y1, x2, y2, width=2) x1, y1 = rotate((x1, y1), angle, origin) x2, y2 = rotate((x2, y2), angle, origin) x1, y1 = scale((x1, y1), sx, sy) x2, y2 = scale((x2, y2), sx, sy) x1, y1 = translate((x1, y1), tx, ty) x2, y2 = translate((x2, y2), tx, ty) o[i] = [x1, y1, x2, y2] img.save("img/square_snail.svg")
def draw_square_shaered(): img = SVGImage(1200, 400, center_origin=True, show_borders_and_origin=False, animate=False, animation_speed=0.01) o = [[-50, -50, 50, -50], [50, -50, 50, 50], [50, 50, -50, 50], [-50, 50, -50, -50]] angle = -10 sx = 0.9 sy = 0.9 sh = 1.3 tx = 50 ty = 50 origin = [0, 0] iterations = 40 for _ in range(iterations): for i, line in enumerate(o): x1, y1, x2, y2 = line img.add_line(x1, y1, x2, y2, width=2) x1, y1 = shear((x1, y1), sh) x2, y2 = shear((x2, y2), sh) x1, y1 = rotate((x1, y1), angle, origin) x2, y2 = rotate((x2, y2), angle, origin) x1, y1 = scale((x1, y1), sx, sy) x2, y2 = scale((x2, y2), sx, sy) x1, y1 = translate((x1, y1), tx, ty) x2, y2 = translate((x2, y2), tx, ty) o[i] = [x1, y1, x2, y2] img.save("img/square_sheared.svg")
def pentagram_absolute(): img = SVGImage(center_origin=True, show_borders_and_origin=False, animate=True, animation_speed=0.5) def draw_polygon_pentagram_absolute(img, line_width=1): n = 5 center_to_side = 200 center_angle = 360 / n offset_angle = 90 - center_angle x = 0 y = 0 points = [(x, y)] ## Draw polygon for i in range(1, n + 2): nx = math.cos( math.radians(i * center_angle + offset_angle)) * center_to_side ny = math.sin( math.radians(i * center_angle + offset_angle)) * center_to_side points.append((nx, ny)) if i != 1: img.add_line(x, y, nx, ny, width=line_width) x = nx y = ny # remove center and last duplicate points = points[1:-1] ## draw pentagram last = 0 for _ in range(n): point_1 = points[last] point_2 = points[(last + 2) % n] last = (last + 2) % n img.add_line(point_1[0], point_1[1], point_2[0], point_2[1], width=line_width) draw_polygon_pentagram_absolute(img, 5) img.save("img/pentagram_absolute_animated.svg")
def draw_lines_and_intersects(): img = SVGImage(IMG_WIDTH, IMG_HEIGHT, center_origin=False, show_borders_and_origin=False, animate=False, animation_speed=ANIMATION_SPEED) lines = [] ## draw lines for i in range(LINE_COUNT): line = get_random_line(LINE_LENGTH) lines.append(line) img.add_line(*line, width=LINE_WIDTH) ## draw intersections for line in lines: for i in lines: if line == i: continue if intersect(line, i): px, py = get_intersect(line, i) img.add_circle(px, py, INTERSECT_RADIUS, color="black", fill="red") img.save("img/line_intersections.svg")
def draw_star(): def draw_star_part(y1, y1_step, x2_step, x2_is_negative=False): x2 = 0 while x2 <= HEIGHT: img.add_line(0, y1, -x2 if x2_is_negative else x2, 0) y1 += y1_step x2 += x2_step img = SVGImage(W, H, center_origin=True, show_borders_and_origin=False, animate=False, animation_speed=0.01) draw_star_part(HEIGHT, -4, 4) draw_star_part(HEIGHT, -8, 8, x2_is_negative=True) draw_star_part(-HEIGHT, 16, 16, x2_is_negative=True) draw_star_part(-HEIGHT, 32, 32) img.save("img/test_svg_star.svg")
def draw_rectangle(): # non-abstracted code for rectangle rect_img = SVGImage(W, H, center_origin=True, show_borders_and_origin=False, animate=False, animation_speed=0.05) x1 = -HEIGHT y2 = HEIGHT while x1 <= HEIGHT: rect_img.add_line(x1, HEIGHT, HEIGHT, y2) x1 += 8 y2 -= 8 x1 = HEIGHT y2 = HEIGHT while -x1 <= HEIGHT: rect_img.add_line(x1, HEIGHT, -HEIGHT, y2) x1 -= 13 y2 -= 13 x1 = -HEIGHT y2 = HEIGHT while x1 <= HEIGHT: rect_img.add_line(x1, -HEIGHT, -HEIGHT, y2) x1 += 21 y2 -= 21 x1 = -HEIGHT y2 = -HEIGHT while x1 <= HEIGHT: rect_img.add_line(x1, -HEIGHT, HEIGHT, y2) x1 += 34 y2 += 34 rect_img.save("img/test_svg_rect.svg")
def draw_maze(filename, maze_side, missing_walls, show_start_end=True, animate=False, img_size=500, line_width=2): """ Draws maze into svg image. Checks if there should not be missing wall in @missing_walls. """ size = img_size width = line_width img = SVGImage(size, size, center_origin=False, show_borders_and_origin=False, animate=animate, animation_speed=0.05) # draw borders img.add_line(0, 0, 0, size, width=2 * width) img.add_line(0, size, size, size, width=2 * width) img.add_line(size, size, size, 0, width=2 * width) img.add_line(size, 0, 0, 0, width=2 * width) # draw start and end # start is always upper-top and end always bottom-right if show_start_end: img.add_circle(size / maze_side / 2, size / maze_side / 2, size / maze_side / 4, fill="green") img.add_circle(maze_side * (size / maze_side) - (size / maze_side / 2), maze_side * (size / maze_side) - (size / maze_side / 2), size / maze_side / 4, fill="red") # draw vertical walls for row in range(maze_side): for col in range(maze_side - 1): current_wall = ((row, col), (row, col + 1)) if current_wall in missing_walls or current_wall[:: -1] in missing_walls: continue x0 = (col + 1) * (size / maze_side) y0 = row * (size / maze_side) x1 = x0 y1 = (row + 1) * (size / maze_side) img.add_line(x0, y0, x1, y1, width=width) # draw horizontal walls for row in range(maze_side - 1): for col in range(maze_side): current_wall = ((row, col), (row + 1, col)) if current_wall in missing_walls or current_wall[:: -1] in missing_walls: continue x0 = col * (size / maze_side) y0 = (row + 1) * (size / maze_side) x1 = (col + 1) * (size / maze_side) y1 = y0 img.add_line(x0, y0, x1, y1, width=width) img.save(filename)
class Turtle(object): def __init__(self, width=800, height=600, center_origin=False, show_borders_and_origin=False, animate=False, animation_speed=0.1): self.img = SVGImage(width, height, center_origin=center_origin, show_borders_and_origin=show_borders_and_origin, animate=animate, animation_speed=animation_speed) # current turtle state self.x = 0 self.y = 0 # angle in degrees self.angle = 0 self.is_pendown = True def save(self, path): self.img.save(path) def reset(self): self.x = 0 self.y = 0 self.angle = 0 def reset_angle(self): self.angle = 0 def set_x(self, x): self.x = x def set_y(self, y): self.y = y def set_angle(self, angle): self.angle = angle def get_x(self): return self.x def get_y(self): return self.y def get_angle(self): return self.angle def forward(self, steps, color="black", width=1, debug=False): """ steps: in pixels """ print(self.x, self.y, self.angle) if debug else None nx = self.x + math.cos(math.radians(self.angle)) * steps ny = self.y + math.sin(math.radians(self.angle)) * steps if self.is_pendown: self.img.add_line(self.x, self.y, nx, ny, color=color, width=width) self.x = nx self.y = ny print(self.x, self.y, self.angle) if debug else None def back(self, steps, color="black", width=1, debug=False): """ steps: in pixels """ print(self.x, self.y, self.angle) if debug else None self.forward(-steps, color=color, width=width) print(self.x, self.y, self.angle) if debug else None def right(self, angle): """ angle: in degrees """ self.angle -= angle def left(self, angle): """ angle: in degrees """ self.angle += angle def penup(self): """ stop drawing """ self.is_pendown = False def pendown(self): """ start drawing """ self.is_pendown = True
def draw_convex_hull(): def generate_points(number): points = [] for _ in range(number): x = get_random_number(BUFFER, IMG_WIDTH - BUFFER) y = get_random_number(BUFFER, IMG_HEIGHT - BUFFER) points.append((x, y)) return points def get_lines(points): if len(points) < 1: return [] ## final lines to be drawn lines = [] ## get the leftmost and rightmost point first = points[0] last = points[0] for point in points: if point[0] < first[0]: first = point if point[0] > last[0]: last = point point1 = first direction = "right" while True: candidate = None candidate_angle = 360 for point2 in points: if point1 == point2: continue angle = get_angle(point1, point2, direction) if angle <= candidate_angle: candidate = point2 candidate_angle = angle lines.append(candidate + point1) point1 = candidate if candidate == last and direction == "right": direction = "left" if candidate == first and direction == "left": break return lines def draw_points(points): for point in points: img.add_circle(point[0], point[1], POINTS_RADIUS, color="black", fill="red") def draw_lines(lines): for line in lines: img.add_line(*line, width=LINE_WIDTH) ## Draw the stuff img = SVGImage(IMG_WIDTH, IMG_HEIGHT, center_origin=False, show_borders_and_origin=False, animate=True, animation_speed=ANIMATION_SPEED) points = generate_points(POINTS_NUM) draw_points(points) print(points) while len(points) > 0: lines = get_lines(points) draw_lines(lines) ## remove used points for line in lines: x1, y1, _, _ = line print(line) points.remove((x1, y1)) print(points) img.save("img/convex_hull_concentric_animate.svg")
def draw_maze(img_file, no_wallss, img_size=400, animate=True, levels=4, side_length=50): """ Draws maze. """ def draw_triangle(img, x=0, y=0, side_length=50, drop_ab=False, drop_bc=False, drop_ca=False): """ Draws triangle with side @side_length. Bottom left corner is at the @x,@y coordinates. Able to not draw specific side of triangle by setting @drop_* to True. """ ax = x ay = y bx = x + side_length by = y cx = x + side_length / 2 cy = y - (math.sqrt(3) / 2) * side_length if not drop_ab: img.add_line(ax, ay, bx, by) if not drop_bc: img.add_line(bx, by, cx, cy) if not drop_ca: img.add_line(cx, cy, ax, ay) img = SVGImage(img_size, img_size, center_origin=False, show_borders_and_origin=False, animate=animate, animation_speed=0.05) x = img_size / 2 - side_length / 2 y = (math.sqrt(3) / 2) * side_length current_node_id = 1 # node id of the triangle we are drawing for level in range(levels + 1): current_x = x for triangle in range(level + 1): # draw only walls that are not in @no_walls drop_ab, drop_bc, drop_ca = False, False, False for wall in no_walls: node_id, neighbor_id = wall if node_id == current_node_id: if node_id == neighbor_id + 1: # dropping wall to the left (ac) drop_ca = True if node_id == neighbor_id - 1: # dropping wall to the right (bc) drop_bc = True if node_id + 1 < neighbor_id: # dropping wall to the bottom (ab) drop_ab = True draw_triangle(img, x=current_x, y=y, side_length=side_length, drop_ab=drop_ab, drop_bc=drop_bc, drop_ca=drop_ca) current_x += side_length if triangle < level: current_node_id += 2 x -= side_length / 2 y += (math.sqrt(3) / 2) * side_length current_node_id += 1 img.save(img_file)
def draw_triangulation(): img = SVGImage(IMG_WIDTH, IMG_HEIGHT, center_origin=False, show_borders_and_origin=True, animate=True, animation_speed=ANIMATION_SPEED) def generate_points(number): points = [] for i in range(number): x = get_random_number(BUFFER, IMG_WIDTH - BUFFER) y = get_random_number(BUFFER, IMG_HEIGHT - BUFFER) points.append((x, y)) return points points = generate_points(POINTS_NUM) #points = [(200, 200), (400, 150), (500, 400), (450, 700), (300, 600)] #points = [(200, 200), (400, 150), (500, 400), (450, 700)] #points = [(341, 518), (653, 605), (363, 476), (676, 308)] print(points) def shorten_line(line, step=10): x1, y1, x2, y2 = list(line) if x2 > x1: x = x2 - x1 x1 += x / step x2 -= x / step else: x = x1 - x2 x1 -= x / step x2 += x / step if y2 > y1: y = y2 - y1 y1 += y / step y2 -= y / step else: y = y1 - y2 y1 -= y / step y2 += y / step return (x1, y1, x2, y2) def intersect_some_collected(line, collected): for i in collected: a = shorten_line(i) b = shorten_line(line) if intersect(a, b): print("III", line, i) return True return False def get_lines(points): collected = [] for point1 in points: for point2 in points: if point1 == point2: continue if point1 + point2 in collected: continue if point2 + point1 in collected: continue line = point1 + point2 if not intersect_some_collected(line, collected): collected.append(line) print(collected) return collected lines = get_lines(points) """ lines = [ (200, 200, 450, 700)] x = (300, 600, 400, 150) print(intersect_some_collected(x, lines)) print(intersect(lines[0], x)) img.add_line(*x, width=LINE_WIDTH*4) img.add_circle(330.7692307692308, 461.53846153846155, POINTS_RADIUS, fill="red") """ ## draw points for point in points: img.add_circle(point[0], point[1], POINTS_RADIUS, color="black", fill="red") ## draw lines for line in lines: img.add_line(*line, width=LINE_WIDTH) img.save("img/triangulation_animate.svg")
group_set.append(init_group) sx = 0.9 sy = 0.9 iterations = 30 pp(group_set) for _ in range(iterations): new_group_set = [] while len(group_set) > 0: group = group_set.pop() new_group = [] for item in group: new_item = {"lines": [], "attractor": None} for line in item["lines"]: img.add_line(*line) x1, y1, x2, y2 = line # TODO: second retangle is scaling by different point x1, y1 = lingebra.scale((x1, y1), sx, sy, item["attractor"]) x2, y2 = lingebra.scale((x2, y2), sx, sy, item["attractor"]) new_line = [x1, y1, x2, y2] new_item["lines"].append(new_line) ## set the new lines new_item["attractor"] = item["attractor"] ## keep the original attractor new_group.append(new_item) new_group_set.append(new_group) group_set = new_group_set pp(group_set) img.save("img/mrcm_test.svg")