def test_join_paths_reference(): # Join paths in such a way that a single path object must be # used as both the "left" and "right" path in different joins. p = Pen() p.fill_mode() p.move_to((3, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((0, 0)) p.break_stroke() p.move_to((4, 0)) p.line_to((3, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((4, 0)) p.line_to((5, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M5,0 L4,0 L3,0 L2,0 L1,0 L0,0' )
def test_two_pens_one_paper(): paper = Paper() p1 = Pen(paper) p2 = Pen(paper) p1.fill_mode() p2.fill_mode() p1.move_to((0, 0)) p2.move_to((0, 0)) p1.line_to((0, 1)) p2.line_to((2, 0)) assert_path_data(paper, 0, ['M0,0 L0,-1', 'M0,0 L2,0'])
def test_two_pens_one_paper(): paper = Paper() p1 = Pen(paper) p2 = Pen(paper) p1.fill_mode() p2.fill_mode() p1.move_to((0, 0)) p2.move_to((0, 0)) p1.line_to((0, 1)) p2.line_to((2, 0)) assert_path_data( paper, 0, ['M0,0 L0,-1', 'M0,0 L2,0'] )
def test_line_segment_bounds(): # Fill mode segment. p = Pen() p.fill_mode() p.move_to((1, 0)) p.line_to((2, 3)) line = p.last_segment() assert_equal( line.bounds(), Bounds(1, 0, 2, 3) ) # Stroke mode segment. p = Pen() p.stroke_mode(sqrt2) p.move_to((0, 0)) p.line_to((5, 5)) line = p.last_segment() assert_equal( line.bounds(), Bounds(-0.5, -0.5, 5.5, 5.5) )
def test_join_paths_reference(): # Join paths in such a way that a single path object must be # used as both the "left" and "right" path in different joins. p = Pen() p.fill_mode() p.move_to((3, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((0, 0)) p.break_stroke() p.move_to((4, 0)) p.line_to((3, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((4, 0)) p.line_to((5, 0)) p.paper.join_paths() assert_path_data(p, 0, 'M5,0 L4,0 L3,0 L2,0 L1,0 L0,0')
def test_join_paths(): # Join two paths starting from the same point. p = Pen() p.fill_mode() p.move_to((1, 0)) p.line_to((0, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M0,0 L1,0 L2,0', ) # Join two paths that end in the same point. p = Pen() p.fill_mode() p.move_to((1, 0)) p.line_to((0, 0)) p.break_stroke() p.move_to((2, 0)) p.line_to((1, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M0,0 L1,0 L2,0', ) # Join three paths going left in normal order. p = Pen() p.fill_mode() p.move_to((3, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((2, 0)) p.line_to((1, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((0, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M3,0 L2,0 L1,0 L0,0', ) # Join three paths going right in normal order. p = Pen() p.fill_mode() p.move_to((0, 0)) p.line_to((1, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((2, 0)) p.line_to((3, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M0,0 L1,0 L2,0 L3,0', ) # Join three paths going left in reverse order. p = Pen() p.fill_mode() p.move_to((1, 0)) p.line_to((0, 0)) p.break_stroke() p.move_to((2, 0)) p.line_to((1, 0)) p.break_stroke() p.move_to((3, 0)) p.line_to((2, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M0,0 L1,0 L2,0 L3,0', ) # Join three paths going right in reverse order. p = Pen() p.fill_mode() p.move_to((2, 0)) p.line_to((3, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((0, 0)) p.line_to((1, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M3,0 L2,0 L1,0 L0,0', ) # Join multiple paths together. p = Pen() p.fill_mode() p.move_to((1, 0)) p.line_to((0, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((1, 1)) p.break_stroke() p.move_to((1, 1)) p.line_to((2, 1)) p.break_stroke() p.move_to((2, 2)) p.line_to((2, 1)) p.break_stroke() p.paper.join_paths() assert_path_data( p, 0, 'M0,0 L1,0 L1,-1 L2,-1 L2,-2' ) # Join three paths so one path must reverse multiple times. p = Pen() p.fill_mode() p.move_to((2, 0)) p.line_to((1, 0)) p.break_stroke() p.move_to((2, 0)) p.line_to((3, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((0, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M3,0 L2,0 L1,0 L0,0', )
def test_join_paths_loop(): # Already looped paths should not be affected by join_paths. p = Pen() p.fill_mode() p.move_to((0, 0)) p.square(2) target = 'M-1,1 L1,1 L1,-1 L-1,-1 L-1,1 z' assert_path_data(p, 0, target) p.paper.join_paths() assert_path_data(p, 0, target) # Loops can also be created by joining paths. p = Pen() p.fill_mode() p.move_to((0, 0)) p.line_to((1, 0)) p.line_to((1, 1)) p.break_stroke() p.line_to((0, 1)) p.line_to((0, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M1,-1 L1,0 L0,0 L0,-1 L1,-1 z' ) # The joins can get complicated. p = Pen() p.fill_mode() p.move_to((3, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 2)) p.break_stroke() p.move_to((4, 0)) p.line_to((3, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((4, 0)) p.line_to((2, 2)) p.paper.join_paths() assert_path_data( p, 0, 'M1,0 L2,-2 L4,0 L3,0 L2,0 L1,0 z', )
def test_join_paths(): # Join two paths starting from the same point. p = Pen() p.fill_mode() p.move_to((1, 0)) p.line_to((0, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M0,0 L1,0 L2,0', ) # Join two paths that end in the same point. p = Pen() p.fill_mode() p.move_to((1, 0)) p.line_to((0, 0)) p.break_stroke() p.move_to((2, 0)) p.line_to((1, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M0,0 L1,0 L2,0', ) # Join three paths going left in normal order. p = Pen() p.fill_mode() p.move_to((3, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((2, 0)) p.line_to((1, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((0, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M3,0 L2,0 L1,0 L0,0', ) # Join three paths going right in normal order. p = Pen() p.fill_mode() p.move_to((0, 0)) p.line_to((1, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((2, 0)) p.line_to((3, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M0,0 L1,0 L2,0 L3,0', ) # Join three paths going left in reverse order. p = Pen() p.fill_mode() p.move_to((1, 0)) p.line_to((0, 0)) p.break_stroke() p.move_to((2, 0)) p.line_to((1, 0)) p.break_stroke() p.move_to((3, 0)) p.line_to((2, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M0,0 L1,0 L2,0 L3,0', ) # Join three paths going right in reverse order. p = Pen() p.fill_mode() p.move_to((2, 0)) p.line_to((3, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((0, 0)) p.line_to((1, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M3,0 L2,0 L1,0 L0,0', ) # Join multiple paths together. p = Pen() p.fill_mode() p.move_to((1, 0)) p.line_to((0, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((1, 1)) p.break_stroke() p.move_to((1, 1)) p.line_to((2, 1)) p.break_stroke() p.move_to((2, 2)) p.line_to((2, 1)) p.break_stroke() p.paper.join_paths() assert_path_data(p, 0, 'M0,0 L1,0 L1,-1 L2,-1 L2,-2') # Join three paths so one path must reverse multiple times. p = Pen() p.fill_mode() p.move_to((2, 0)) p.line_to((1, 0)) p.break_stroke() p.move_to((2, 0)) p.line_to((3, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((0, 0)) p.paper.join_paths() assert_path_data( p, 0, 'M3,0 L2,0 L1,0 L0,0', )
def test_join_paths_loop(): # Already looped paths should not be affected by join_paths. p = Pen() p.fill_mode() p.move_to((0, 0)) p.square(2) target = 'M-1,1 L1,1 L1,-1 L-1,-1 L-1,1 z' assert_path_data(p, 0, target) p.paper.join_paths() assert_path_data(p, 0, target) # Loops can also be created by joining paths. p = Pen() p.fill_mode() p.move_to((0, 0)) p.line_to((1, 0)) p.line_to((1, 1)) p.break_stroke() p.line_to((0, 1)) p.line_to((0, 0)) p.paper.join_paths() assert_path_data(p, 0, 'M1,-1 L1,0 L0,0 L0,-1 L1,-1 z') # The joins can get complicated. p = Pen() p.fill_mode() p.move_to((3, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 2)) p.break_stroke() p.move_to((4, 0)) p.line_to((3, 0)) p.break_stroke() p.move_to((1, 0)) p.line_to((2, 0)) p.break_stroke() p.move_to((4, 0)) p.line_to((2, 2)) p.paper.join_paths() assert_path_data( p, 0, 'M1,0 L2,-2 L4,0 L3,0 L2,0 L1,0 z', )
continue else: point_occupancy[a] += 1 b = random.choice(points) if point_occupancy[b] >= 2: continue else: point_occupancy[b] += 1 yield a, b if __name__ == '__main__': while True: p = Pen() p.stroke_mode(0.01) for a, b in gen_lines(200, 100): p.move_to(a) p.line_to(b) p.break_stroke() try: p.paper.join_paths() except AssertionError: print(p.log()) break else: print(p.paper.format_svg(6, resolution=1000)) break
def draw(): p = Pen() center_radius = 3.0 start_radius = radius = 100 start_width = width = 3.0 ratio = (1 / 2) ** (1/5) series = [] while radius > center_radius / sqrt2: series.append((radius, width)) radius *= ratio width *= ratio p.move_to((0, 0)) for radius, width in series: p.stroke_mode(width, 'black') p.circle(radius) # Parametric conic spirals. p.move_to((0, 0)) def spiral(theta): b = (1 / 2) ** (-2 / math.pi) r = start_radius * (b ** (-theta)) x = r * math.cos(theta) y = r * math.sin(theta) z = start_radius - r return (x, y, z) def spiral_top1(t): x, y, z = spiral(t) return x, y def spiral_top2(t): x, y, z = spiral(t) x = -x y = -y return x, y # Top spirals. p.stroke_mode(start_width, 'black') p.parametric(spiral_top1, 0, 4*math.pi, .1) p.parametric(spiral_top2, 0, 4*math.pi, .1) # Blank out the bottom triangle. p.fill_mode('white') p.move_to((0, 0)) s = start_radius + start_width p.line_to((-s, -s)) p.line_to((+s, -s)) p.line_to((0, 0)) # Horizontal lines for the bottom triangle. for radius, width in series: p.stroke_mode(width, 'black') p.move_to((-radius, -radius)) p.line_to( (+radius, -radius), start_slant=45, end_slant=-45, ) # Front spirals. def spiral_front1(t): x, y, z = spiral(t) return (x, z - start_radius) def spiral_front2(t): x, y, z = spiral(t) x = -x y = -y return (x, z - start_radius) p.move_to((0, 0)) p.stroke_mode(start_width, 'black') p.parametric(spiral_front1, 0, math.pi, .1) p.parametric(spiral_front2, math.pi, 2*math.pi, .1) p.parametric(spiral_front1, 2*math.pi, 3*math.pi, .1) # Fill in the center. p.move_to((0, 0)) p.fill_mode('black') p.circle(center_radius) return p.paper
def draw(): p = Pen() center_radius = 3.0 start_radius = radius = 100 start_width = width = 3.0 ratio = (1 / 2) ** (1/5) series = [] while radius > center_radius / sqrt2: series.append((radius, width)) radius *= ratio width *= ratio p.move_to((0, 0)) for radius, width in series: p.stroke_mode(width, 'black') p.circle(radius) # Parametric conic spirals. p.move_to((0, 0)) def spiral(theta): b = (1 / 2) ** (-2 / math.pi) r = start_radius * (b ** (-theta)) x = r * math.cos(theta) y = r * math.sin(theta) z = start_radius - r return (x, y, z) def spiral_top1(t): x, y, z = spiral(t) return x, y def spiral_top2(t): x, y, z = spiral(t) x = -x y = -y return x, y # Top spirals. p.stroke_mode(start_width, 'black') p.parametric(spiral_top1, 0, 4*math.pi, .1) p.parametric(spiral_top2, 0, 4*math.pi, .1) # Blank out the bottom triangle. p.fill_mode('white') p.move_to((0, 0)) s = start_radius + start_width p.line_to((-s, -s)) p.line_to((+s, -s)) p.line_to((0, 0)) # Horizontal lines for the bottom triangle. for radius, width in series: p.stroke_mode(width, 'black') p.move_to((-radius, -radius)) p.line_to( (+radius, -radius), start_slant=45, end_slant=-45, ) # Front spirals. def spiral_front1(t): x, y, z = spiral(t) return (x, z - start_radius) def spiral_front2(t): x, y, z = spiral(t) x = -x y = -y return (x, z - start_radius) p.move_to((0, 0)) p.stroke_mode(start_width, 'black') p.parametric(spiral_front1, 0, math.pi, .1) p.parametric(spiral_front2, math.pi, 2*math.pi, .1) p.parametric(spiral_front1, 2*math.pi, 3*math.pi, .1) # Fill in the center. p.move_to((0, 0)) p.fill_mode('black') p.circle(center_radius) return p.paper
continue else: point_occupancy[a] += 1 b = random.choice(points) if point_occupancy[b] >= 2: continue else: point_occupancy[b] += 1 yield a, b if __name__ == '__main__': while True: p = Pen() p.stroke_mode(0.01) for a, b in gen_lines(200, 100): p.move_to(a) p.line_to(b) p.break_stroke() try: p.paper.join_paths() except AssertionError: print(p.log()) break else: print(p.paper.format_svg(6, resolution=1000)) break