def test_translate_override_bounds(): # Translate a paper that has overridden bounds. The bounds update as well. paper = Paper() paper.override_bounds(0, 0, 1, 1) paper.translate((3, 4)) assert_equal( paper.bounds(), Bounds(3, 4, 4, 5) ) # When bounds=False is passed, then the bounds do not update. paper = Paper() paper.override_bounds(0, 0, 1, 1) paper.translate((3, 4), bounds=False) assert_equal(paper.bounds(), Bounds(0, 0, 1, 1)) # This also works if the bounds are not overridden. p = Pen() p.fill_mode() p.move_to((0.5, 0.5)) p.circle(0.5) assert_equal(p.paper.bounds(), Bounds(0, 0, 1, 1)) p.paper.translate((3, 4), bounds=False) assert_equal(p.paper.bounds(), Bounds(0, 0, 1, 1)) assert_equal(p.last_path().bounds(), Bounds(3, 4, 4, 5))
def test_center_on_xy(): p = Pen() p.stroke_mode(2.0) p.move_to((0, 0)) p.turn_to(0) p.line_forward(4) p.move_to((2, 1)) p.circle(1) p.paper.center_on_x(0) assert_equal( p.paper.svg_elements(0), [ '<path d="M-2,-1 L-2,1 L2,1 L2,-1 L-2,-1 z" fill="#000000" />', '<path d="M2,-1 A 2,2 0 0 0 -2,-1 A 2,2 0 0 0 2,-1 z" fill="#000000" />', ] ) p.paper.center_on_y(0) assert_equal( p.paper.svg_elements(1), [ ( '<path d="M-2.0,0.0 L-2.0,2.0 L2.0,2.0 L2.0,0.0 L-2.0,0.0 z" ' 'fill="#000000" />' ), ( '<path d="M2.0,0.0 A 2.0,2.0 0 0 0 -2.0,0.0 ' 'A 2.0,2.0 0 0 0 2.0,0.0 z" fill="#000000" />' ), ] )
def test_center_on_xy(): p = Pen() p.stroke_mode(2.0) p.move_to((0, 0)) p.turn_to(0) p.line_forward(4) p.move_to((2, 1)) p.circle(1) p.paper.center_on_x(0) assert_equal(p.paper.svg_elements(0), [ '<path d="M-2,-1 L-2,1 L2,1 L2,-1 L-2,-1 z" fill="#000000" />', '<path d="M2,-1 A 2,2 0 0 0 -2,-1 A 2,2 0 0 0 2,-1 z" fill="#000000" />', ]) p.paper.center_on_y(0) assert_equal(p.paper.svg_elements(1), [ ('<path d="M-2.0,0.0 L-2.0,2.0 L2.0,2.0 L2.0,0.0 L-2.0,0.0 z" ' 'fill="#000000" />'), ('<path d="M2.0,0.0 A 2.0,2.0 0 0 0 -2.0,0.0 ' 'A 2.0,2.0 0 0 0 2.0,0.0 z" fill="#000000" />'), ])
def test_override_bounds_copy(): # Get the bounds of a Paper, modify them, then set them back changed. paper = Paper() paper.override_bounds(0, 0, 1, 1) bounds = paper.bounds() bounds.right = 5 assert_equal(paper.bounds(), Bounds(0, 0, 1, 1)) paper.override_bounds(bounds) assert_equal(paper.bounds(), Bounds(0, 0, 5, 1)) # This works on non-overridden Papers as well. paper = Paper() p = Pen() p.fill_mode() p.move_to((0.5, 0.5)) p.circle(0.5) bounds = p.paper.bounds() bounds.right = 5 assert_equal(p.paper.bounds(), Bounds(0, 0, 1, 1)) p.paper.override_bounds(bounds) assert_equal(p.paper.bounds(), Bounds(0, 0, 5, 1))
def test_translate(): p = Pen() p.stroke_mode(1.0) p.move_to((0, 0)) p.turn_to(0) p.line_forward(3) p.arc_left(90, 3) p.turn_left(90) p.move_forward(3) p.fill_mode() p.circle(0.5) p.move_forward(3) p.square(1) p.paper.translate((1, 1)) assert_equal(p.paper.svg_elements(1), [ ('<path d="M1.0,-1.5 L1.0,-0.5 L4.0,-0.5 A 3.5,3.5 0 0 0 ' '7.5,-4.0 L6.5,-4.0 A 2.5,2.5 0 0 1 4.0,-1.5 L1.0,-1.5 z" ' 'fill="#000000" />'), ('<path d="M4.5,-4.0 A 0.5,0.5 0 0 0 3.5,-4.0 ' 'A 0.5,0.5 0 0 0 4.5,-4.0 z" fill="#000000" />'), ('<path d="M0.5,-3.5 L1.5,-3.5 L1.5,-4.5 L0.5,-4.5 L0.5,-3.5 z" ' 'fill="#000000" />'), ])
def test_translate(): p = Pen() p.stroke_mode(1.0) p.move_to((0, 0)) p.turn_to(0) p.line_forward(3) p.arc_left(90, 3) p.turn_left(90) p.move_forward(3) p.fill_mode() p.circle(0.5) p.move_forward(3) p.square(1) p.paper.translate((1, 1)) assert_equal( p.paper.svg_elements(1), [ ( '<path d="M1.0,-1.5 L1.0,-0.5 L4.0,-0.5 A 3.5,3.5 0 0 0 ' '7.5,-4.0 L6.5,-4.0 A 2.5,2.5 0 0 1 4.0,-1.5 L1.0,-1.5 z" ' 'fill="#000000" />' ), ( '<path d="M4.5,-4.0 A 0.5,0.5 0 0 0 3.5,-4.0 ' 'A 0.5,0.5 0 0 0 4.5,-4.0 z" fill="#000000" />' ), ( '<path d="M0.5,-3.5 L1.5,-3.5 L1.5,-4.5 L0.5,-4.5 L0.5,-3.5 z" ' 'fill="#000000" />' ), ] )
def test_circle_bounds(): p = Pen() p.fill_mode() p.move_to((1, 1)) p.circle(1.5) assert_equal( p.paper.bounds(), Bounds(-0.5, -0.5, 2.5, 2.5) )
def draw(): p = Pen() p.fill_mode() p.move_to((0, 0)) p.circle(2) paper1 = p.paper p = Pen() p.fill_mode() p.move_to((3, 0)) p.circle(1) paper2 = p.paper return paper1, paper2
def test_translate_override_bounds(): # Translate a paper that has overridden bounds. The bounds update as well. paper = Paper() paper.override_bounds(0, 0, 1, 1) paper.translate((3, 4)) assert_equal(paper.bounds(), Bounds(3, 4, 4, 5)) # When bounds=False is passed, then the bounds do not update. paper = Paper() paper.override_bounds(0, 0, 1, 1) paper.translate((3, 4), bounds=False) assert_equal(paper.bounds(), Bounds(0, 0, 1, 1)) # This also works if the bounds are not overridden. p = Pen() p.fill_mode() p.move_to((0.5, 0.5)) p.circle(0.5) assert_equal(p.paper.bounds(), Bounds(0, 0, 1, 1)) p.paper.translate((3, 4), bounds=False) assert_equal(p.paper.bounds(), Bounds(0, 0, 1, 1)) assert_equal(p.last_path().bounds(), Bounds(3, 4, 4, 5))
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
return numpy.column_stack((t, c, s)) def draw_parametric_func(pen, f, t_range): txy_values = f(t_range) t, x, y = txy_values[0] pen.move_to((x, y)) for t, x, y in txy_values[1:]: pen.line_to((x, y)) mod = t % 1.0 if float_equal(mod, 0) or float_equal(mod, 1.0): pen.circle(0.01) step = 0.01 t_range = numpy.arange(-4 + step, 4, step) pen = Pen() pen.stroke_mode(0.01, 'green') draw_parametric_func(pen, euler_spiral_parametric, t_range) pen.fill_mode('green') pen.move_to((0.5, 0.5)) pen.circle(0.01) pen.move_to((-0.5, -0.5)) pen.circle(0.01) print(pen.paper.format_svg(5, resolution=500)) # TODO: euler spiral solver to end at a particular point. newton-raphson method for root finding convergence?
from canoepaddle import Pen p = Pen() p.fill_mode('green') p.move_to((0, 0)) p.turn_to(0) radius = 0.01 for _ in range(200): p.circle(radius) p.turn_left(20) new_radius = radius * 1.05 p.move_forward(radius + new_radius) radius = new_radius print(p.paper.format_svg())
from canoepaddle import Pen p = Pen() def arm(inner=1.5, outer=3): p.stroke_mode(1.0) p.move_forward(inner) p.turn_right(90) p.arc_right(200, radius=outer) p.fill_mode() p.circle(0.5) # Makeshift round endcaps. orientation = 70 p.stroke_mode(1.0) p.move_to((0, 0)) p.circle(1.5) p.move_to((0, 0)) p.turn_to(orientation) arm() p.move_to((0, 0)) p.turn_to(180 + orientation) arm() print(p.paper.format_svg())
return numpy.column_stack((t, c, s)) def draw_parametric_func(pen, f, t_range): txy_values = f(t_range) t, x, y = txy_values[0] pen.move_to((x, y)) for t, x, y in txy_values[1:]: pen.line_to((x, y)) mod = t % 1.0 if float_equal(mod, 0) or float_equal(mod, 1.0): pen.circle(0.01) step = 0.01 t_range = numpy.arange(-4 + step, 4, step) pen = Pen() pen.stroke_mode(0.01, 'green') draw_parametric_func(pen, euler_spiral_parametric, t_range) pen.fill_mode('green') pen.move_to((0.5, 0.5)) pen.circle(0.01) pen.move_to((-0.5, -0.5)) pen.circle(0.01) print(pen.paper.format_svg(5, resolution=500)) #TODO: euler spiral solver to end at a particular point. newton-raphson method for root finding convergence?