def test_reflect_line(): pt = PathTiler() pt.move_to(100, 100) pt.reflect_line(Point(50, -50), Point(150, 50)) pt.line_to(100, 50) pt.line_to(100, 100) assert pt.paths == [ [Point(100.0, 100.0), Point(150, 0), Point(200, 0)], ]
def test_rel_line_to(): pt = PathTiler() pt.translate(1000, 2000) pt.move_to(0, 0) pt.rel_line_to(100, 200) assert pt.paths == [ [Point(1000.0, 2000.0), Point(1100.0, 2200.0)], ]
def test_translation(): pt = PathTiler() pt.move_to(100, 100) pt.translate(1000, 2000) pt.line_to(10, 20) assert pt.paths == [ [Point(100.0, 100.0), Point(1010.0, 2020.0)], ]
def test_reflect_xy(): pt = PathTiler() pt.move_to(100, 100) pt.reflect_xy(1000, 2000) pt.line_to(200, 200) assert pt.paths == [ [Point(100.0, 100.0), Point(1800, 3800)], ]
def single_tiler(): """Make a PathTiler right for drawing just one unit.""" tiler = PathTiler(dwg) # TODO: make this work for other symmetries tiler.pc.translate(2 * tilew * math.sqrt(3) / 2, tilew) tiler.pc.reflect_xy(0, 0) return tiler
def draw_it(tilew, dwg, combined=True, fat=True, color=(0, 0, 0), line_width=2, offset=None): tiler = PathTiler(dwg) draw = ThreeStarsDesign(tilew) draw.draw(tiler) paths = tiler.paths if combined: paths = combine_paths(tiler.paths) if offset is not None: paths = [p.offset_path(offset) for p in paths] if fat: line_width = tilew / 12 styles = [ (line_width, (0, 0, 0)), (line_width * .7, (1, 1, 1)), ] else: styles = [(line_width, color)] dwg.multi_stroke(paths, styles)
def straps(**opt): """Draw with over-under straps""" dwg = start_drawing(opt, name="straps", bg=(.8, .8, .8)) tilew = int(dwg.width / opt['tiles']) if opt['strap_width'] > 0: strap_kwargs = dict(width=tilew * opt['strap_width'] / 100, random_factor=0) else: strap_kwargs = dict(width=tilew / 60, random_factor=4.9) tiler = PathTiler(dwg) design_class = get_design(opt['design']) draw = design_class(tilew) draw.draw(tiler) paths_all = combine_paths(tiler.paths) paths = clip_paths(paths_all, dwg.perimeter().bounds()) if opt['perturb']: paths = perturb_paths(paths, opt['perturb']) if should_debug('world'): debug_world(dwg, paths_styles=[ (paths_all, dict(width=1, rgb=(.75, .75, .75))), (paths, dict(width=1.5, rgb=(1, 0, 0))), ]) straps = strapify(paths, **strap_kwargs) with dwg.style(rgb=(1, 1, 1)): for strap in straps: strap.sides[0].draw(dwg) strap.sides[1].draw(dwg, append=True, reverse=True) dwg.close_path() dwg.fill() with dwg.style(rgb=(0, 0, 0), width=2): for strap in straps: for side in strap.sides: side.draw(dwg) dwg.stroke() dwg.finish()
def draw_it(TILEW, dwg, combined=True, fat=True, color=(0, 0, 0), line_width=2, offset=None): pt = PathTiler() draw = ThreeStarsDesign(TILEW) draw.draw(pt, dwg.get_size()) paths = pt.paths if combined: paths = combine_paths(pt.paths) if offset is not None: paths = [offset_path(p, offset) for p in paths] if fat: LINE_WIDTH = TILEW / 12 styles = [ (LINE_WIDTH, (0, 0, 0)), (LINE_WIDTH*.7, (1, 1, 1)), ] else: styles = [(line_width, color)] dwg.multi_stroke(paths, styles)
def candystripe(**opt): """Draw with crazy colors and a white stripe""" dwg = start_drawing(opt, name="candy") tilew = int(dwg.width / opt['tiles']) tiler = PathTiler(dwg) design_class = get_design(opt['design']) draw = design_class(tilew) draw.draw(tiler) paths = combine_paths(tiler.paths) LINE_WIDTH = tilew / 4 dwg.multi_stroke( paths, [ #(LINE_WIDTH, (0, 0, 0)), (LINE_WIDTH - 2, random_color), #(7, (0, 0, 0)), (5, (1, 1, 1)), ]) dwg.finish()
def diagram(**opt): """Draw the underlying structure of a design""" width, height = opt['size'] tilew = int(width / opt['tiles']) dwg = Drawing(width, height, name="diagram") design_class = get_design(opt['design']) draw = design_class(tilew) # The full pattern. tiler = PathTiler(dwg) draw.draw(tiler) with dwg.style(rgb=(.5, .5, .5)): draw_paths(tiler.paths, dwg) dwg.stroke() # The symmetry. tiler = PathTiler(dwg) tiler.tile_p6m(draw.draw_tiler_unit, tilew) with dwg.style(rgb=(1, .75, .75), width=1, dash=[5, 5]): draw_paths(tiler.paths, dwg) dwg.stroke() def single_tiler(): """Make a PathTiler right for drawing just one unit.""" tiler = PathTiler(dwg) # TODO: make this work for other symmetries tiler.pc.translate(2 * tilew * math.sqrt(3) / 2, tilew) tiler.pc.reflect_xy(0, 0) return tiler # The tiler unit. tiler = single_tiler() draw.draw_tiler_unit(tiler.pc) with dwg.style(rgb=(1, 0, 0), width=3): draw_paths(tiler.paths, dwg) dwg.stroke() # The design. tiler = single_tiler() draw.draw_tile(tiler.pc) with dwg.style(rgb=(0, 0, 0), width=6): draw_paths(tiler.paths, dwg) dwg.stroke() dwg.finish()
def candystripe(**opt): width, height = opt['size'] TILEW = int(width / opt['tiles']) dwg = Drawing(width, height, name="candy") pt = PathTiler() design_class = get_design(opt['design']) draw = design_class(TILEW) draw.draw(pt, dwg.get_size()) paths = combine_paths(pt.paths) LINE_WIDTH = TILEW / 4 dwg.multi_stroke( paths, [ #(LINE_WIDTH, (0, 0, 0)), (LINE_WIDTH - 2, random_color), #(7, (0, 0, 0)), (5, (1, 1, 1)), ]) dwg.finish()
def straps(**opt): width, height = opt['size'] TILEW = int(width / opt['tiles']) if opt['strap_width'] > 0: strap_kwargs = dict(width=TILEW * opt['strap_width'] / 100, random_factor=0) else: strap_kwargs = dict(width=TILEW / 60, random_factor=4.9) dwg = Drawing(width, height, name="straps", bg=(.8, .8, .8)) pt = PathTiler() design_class = get_design(opt['design']) draw = design_class(TILEW) draw.draw(pt, dwg.get_size()) paths = combine_paths(pt.paths) if should_debug('world'): debug_world(paths, width, height) straps = strapify(paths, **strap_kwargs) with dwg.style(rgb=(1, 1, 1)): for strap in straps: replay_path(strap.sides[0], dwg) replay_path(strap.sides[1][::-1], dwg, append=True) dwg.close_path() dwg.fill() with dwg.style(rgb=(0, 0, 0), width=2): for strap in straps: for side in strap.sides: replay_path(side, dwg) dwg.stroke() dwg.finish()
def talk_pictures(): size = (883, 683) tilew = int(DWGW / 3) dwgnum = iter(itertools.count()) def dwg_name(slug): return f'three_stars_{next(dwgnum):03d}_{slug}' dwg = Drawing(*size, name=dwg_name('start'), bg=(.85, .85, .85)) draw_it(tilew, dwg) dwg.finish() dwg = Drawing(*size, name=dwg_name('thin')) draw_it(tilew, dwg, fat=False) dwg.finish() dwg = Drawing(*size, name=dwg_name('symmetry')) tiler = PathTiler(dwg) draw = ThreeStarsDesign(tilew) tiler.tile_p6m(draw.draw_tiler_unit, tilew) with dwg.style(rgb=(1, .15, .15), width=1, dash=[5, 5]): draw_paths(tiler.paths, dwg) dwg.stroke() dwg.finish() def single_tiler(): tiler = PathTiler(dwg) tiler.pc.translate(2 * tilew * SQRT3 / 2, tilew) tiler.pc.reflect_xy(0, 0) return tiler dwg = Drawing(*size, name=dwg_name('triangle')) tiler = PathTiler(dwg) draw = ThreeStarsDesign(tilew) tiler.tile_p6m(draw.draw_tiler_unit, tilew) with dwg.style(rgb=(1, .5, .5), width=1, dash=[5, 5]): draw_paths(tiler.paths, dwg) dwg.stroke() tiler = single_tiler() draw.draw_tiler_unit(tiler.pc) with dwg.style(rgb=(1, 0, 0), width=3): draw_paths(tiler.paths, dwg) dwg.stroke() dwg.finish() dwg = Drawing(*size, name=dwg_name('design')) tiler = PathTiler(dwg) draw = ThreeStarsDesign(tilew) tiler.tile_p6m(draw.draw_tiler_unit, tilew) with dwg.style(rgb=(1, .5, .5), width=1, dash=[5, 5]): draw_paths(tiler.paths, dwg) dwg.stroke() tiler = single_tiler() draw.draw_tiler_unit(tiler.pc) with dwg.style(rgb=(1, 0, 0), width=3): draw_paths(tiler.paths, dwg) dwg.stroke() tiler = single_tiler() draw.draw_tile(tiler.pc) with dwg.style(rgb=(0, 0, 0), width=6): draw_paths(tiler.paths, dwg) dwg.stroke() dwg.finish() dwg = Drawing(*size, name=dwg_name('lined')) draw_it(tilew, dwg, fat=False, color=(.5, .5, .5)) tiler = PathTiler(dwg) draw = ThreeStarsDesign(tilew) tiler.tile_p6m(draw.draw_tiler_unit, tilew) with dwg.style(rgb=(1, .75, .75), width=1, dash=[5, 5]): draw_paths(tiler.paths, dwg) dwg.stroke() tiler = single_tiler() draw.draw_tile(tiler.pc) with dwg.style(rgb=(0, 0, 0), width=6): draw_paths(tiler.paths, dwg) dwg.stroke() dwg.finish() dwg = Drawing(*size, name=dwg_name('chaos')) draw_it(tilew, dwg, fat=False, color=random_color, combined=False, line_width=8) dwg.finish() dwg = Drawing(*size, name=dwg_name('joined')) draw_it(tilew, dwg, fat=False, color=random_color, combined=True, line_width=8) dwg.finish()
def test_two_segments(): pt = PathTiler() pt.move_to(100, 100) pt.line_to(150, 200) pt.move_to(17, 17) pt.rel_line_to(100, 200) pt.close_path() assert pt.paths == [ [Point(100.0, 100.0), Point(150.0, 200.0)], [Point(17.0, 17.0), Point(117.0, 217.0), Point(17.0, 17.0)], ]
def test_do_nothing(): pt = PathTiler() assert pt.paths == []
def talk_pictures(): size = (883, 683) TILEW = int(DWGW/3) dwgnum = iter(itertools.count()) def dwg_name(slug): return f'three_stars_{next(dwgnum):03d}_{slug}' dwg = Drawing(*size, name=dwg_name('start'), bg=(.85, .85, .85)) draw_it(TILEW, dwg) dwg.finish() dwg = Drawing(*size, name=dwg_name('thin')) draw_it(TILEW, dwg, fat=False) dwg.finish() dwg = Drawing(*size, name=dwg_name('symmetry')) pt = PathTiler() draw = ThreeStarsDesign(TILEW) pt.tile_p6m(draw.draw_triangle, dwg.get_size(), TILEW) with dwg.style(rgb=(1, .15, .15), width=1, dash=[5, 5]): pt.replay_paths(dwg) dwg.stroke() dwg.finish() def single_tiler(): pt = PathTiler() pt.translate(2 * TILEW * SQRT3 / 2, TILEW) pt.reflect_xy(0, 0) return pt dwg = Drawing(*size, name=dwg_name('triangle')) pt = PathTiler() draw = ThreeStarsDesign(TILEW) pt.tile_p6m(draw.draw_triangle, dwg.get_size(), TILEW) with dwg.style(rgb=(1, .5, .5), width=1, dash=[5, 5]): pt.replay_paths(dwg) dwg.stroke() pt = single_tiler() draw.draw_triangle(pt) with dwg.style(rgb=(1, 0, 0), width=3): pt.replay_paths(dwg) dwg.stroke() dwg.finish() dwg = Drawing(*size, name=dwg_name('design')) pt = PathTiler() draw = ThreeStarsDesign(TILEW) pt.tile_p6m(draw.draw_triangle, dwg.get_size(), TILEW) with dwg.style(rgb=(1, .5, .5), width=1, dash=[5, 5]): pt.replay_paths(dwg) dwg.stroke() pt = single_tiler() draw.draw_triangle(pt) with dwg.style(rgb=(1, 0, 0), width=3): pt.replay_paths(dwg) dwg.stroke() pt = single_tiler() draw.draw_tile(pt) with dwg.style(rgb=(0, 0, 0), width=6): pt.replay_paths(dwg) dwg.stroke() dwg.finish() dwg = Drawing(*size, name=dwg_name('lined')) draw_it(TILEW, dwg, fat=False, color=(.5, .5, .5)) pt = PathTiler() draw = ThreeStarsDesign(TILEW) pt.tile_p6m(draw.draw_triangle, dwg.get_size(), TILEW) with dwg.style(rgb=(1, .75, .75), width=1, dash=[5, 5]): pt.replay_paths(dwg) dwg.stroke() pt = single_tiler() draw.draw_tile(pt) with dwg.style(rgb=(0, 0, 0), width=6): pt.replay_paths(dwg) dwg.stroke() dwg.finish() dwg = Drawing(*size, name=dwg_name('chaos')) draw_it(TILEW, dwg, fat=False, color=random_color, combined=False, line_width=8) dwg.finish() dwg = Drawing(*size, name=dwg_name('joined')) draw_it(TILEW, dwg, fat=False, color=random_color, combined=True, line_width=8) dwg.finish()
def single_tiler(): pt = PathTiler() pt.translate(2 * TILEW * SQRT3 / 2, TILEW) pt.reflect_xy(0, 0) return pt
def test_save_restore(): pt = PathTiler() pt.move_to(100, 100) pt.translate(1000, 2000) pt.line_to(10, 20) pt.save() pt.translate(1, 2) pt.move_to(1, 2) pt.line_to(2, 4) pt.restore() pt.move_to(1, 2) pt.line_to(2, 4) assert pt.paths == [ [Point(100.0, 100.0), Point(1010.0, 2020.0)], [Point(1002.0, 2004.0), Point(1003.0, 2006.0)], [Point(1001.0, 2002.0), Point(1002.0, 2004.0)], ]
def single_tiler(): tiler = PathTiler(dwg) tiler.pc.translate(2 * tilew * SQRT3 / 2, tilew) tiler.pc.reflect_xy(0, 0) return tiler