Example #1
0
 def test_restore(self):
     cp1 = ControlPoint(Point(11, 12), Vector(13, 4), Vector(15, 6),
                        'sharp')
     cp2 = ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6))
     cp1.restore(cp2)
     self.assertEqual(cp1, cp2)
     self.assertIsNot(cp1.c, cp2.c)
Example #2
0
 def test_picklers(self):
     data = [
         BBox(1, 2, 3, 4),
         Point(1, 2),
         Vector(3, 4),
         ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6), 'sharp'),
         Pen('red', 1.5),
         Brush('blue'),
         PenBrush(Pen('green', 0.5), '#808080'),
         Transform((1.6, 2.5, 3.4, 4.3, 5.2, 6.1)),
         ElemRectangle('r1', PenBrush('red'), Point(1, 2), Point(-3, -4)),
     ]
     data_dict = {}
     for datum in data:
         name = type(datum).__name__
         data_dict[name] = datum
         with self.subTest(name=name):
             self.assertMatch(datum, case=name)
     self.assertMatch(data, case='all as list')
     self.assertMatch(data_dict, case='all as dict')
     self.assertMatch([Point(1, 2), Point(3, 4)], case='point list')
     self.assertMatch([Point(1, 2), Vector(3, 4)], case='point-vector list')
     self.assertMatch(dict(p1=Point(1, 2), p2=Point(3, 4)),
                      case='point dict')
     self.assertMatch([Point(1, 2), Vector(3, 4), '5,6', 7.8],
                      case='point-vector-str-float list')
Example #3
0
    def __init__(self, draw_func, image_size=(500, 500), draw_bbox=(-250, -250, 250, 250),
                 steps=20, t_low=0.0, t_high=1.0,
                 frame_display_time=0.1,
                 show_steps=False):
        """
        :param draw_func: a function of (DrawingContext, step_time)
        :param image_size: size of images
        :param draw_bbox: bounding box of drawing space (used by draw_func)
        :param steps: number of steps (minus one) to go from t_low to t_high
        :param t_low: starting step time
        :param t_high: ending step time
        :param frame_display_time: number of seconds to display each animation frame
        :param show_steps: debugging, show each step as separate image
        """

        self.draw_func = draw_func
        self.image_size = Point(*image_size)
        self.model_bbox = BBox(draw_bbox)
        self.steps = steps
        self.background = 'grey'
        assert(t_low != t_high)
        self.t_low = t_low
        self.t_high = t_high
        self.frame_display_time = frame_display_time
        self.show_steps = show_steps

        self.images: List[Image.Image] = []
Example #4
0
 def test_fixed(self):
     cp = ControlPoint(PointRelative(1, 2, Point(3, 4)), Vector(3, 4),
                       Vector(5, 6))
     self.assertNotEqual(
         cp, ControlPoint(Point(4, 6), Vector(3, 4), Vector(5, 6)))
     self.assertEqual(cp.fixed(),
                      ControlPoint(Point(4, 6), Vector(3, 4), Vector(5, 6)))
Example #5
0
 def test_init(self):
     cp = ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6))
     self.assertEqual(cp.c, Point(1, 2))
     self.assertEqual(cp.dl, Vector(3, 4))
     self.assertEqual(cp.dr, Vector(5, 6))
     self.assertEqual(cp.kind, 'smooth')
     self.assertEqual(cp.l, Point(4, 6))
     self.assertEqual(cp.r, Point(6, 8))
Example #6
0
 def test_transform(self):
     cp = ControlPoint(Point(0, 0), Vector(1, 1), Vector(-1, -1),
                       'very-smooth')
     t = Transform().translate(1, 1).rotate(90).scale(2, 2)
     cpt = cp.transform(t)
     self.assertAlmostEqual(cpt.c, Point(2, -2))
     self.assertAlmostEqual(cpt.dl, Vector(2, -2))
     self.assertAlmostEqual(cpt.dr, Vector(-2, 2))
     self.assertEqual(cpt.kind, 'very-smooth')
Example #7
0
    def test_bez_self_intersect(self):
        # bez_split(cp1: 'ControlPoint', cp2: 'ControlPoint', t=0.5) -> Tuple[ForwardRef('ControlPoint'), ForwardRef('ControlPoint'), ForwardRef('ControlPoint')]
        curve = [
            ControlPoint(Point(0, 0), Vector(0, 1), Vector(0, -1)),
            ControlPoint(Point(2, 0), Vector(0, -1), Vector(0, 1)),
        ]
        self.assertEqual([], bez_self_intersect(curve))

        curve = [
            ControlPoint(Point(0, 0), Vector(0, -1), Vector(0, 1)),
            ControlPoint(Point(2, 0), Vector(0, -1), Vector(0, 1)),
        ]
        expected = [[
            ControlPoint(Point(1.0, 0.0), Vector(0.5, 0.25),
                         Vector(0.5, -0.25), 'sharp'),
            ControlPoint(Point(2, 0), Vector(0.0, -0.5), Vector(0.0, 0.5),
                         'smooth')
        ],
                    [
                        ControlPoint(Point(1.0, 0.0), Vector(-0.5, 0.25),
                                     Vector(-0.5, -0.25), 'sharp'),
                        ControlPoint(Point(0, 0), Vector(0.0, -0.5),
                                     Vector(0.0, 0.5), 'smooth')
                    ]]

        self.assertEqual(expected, bez_self_intersect(curve))
Example #8
0
 def test_repr_str(self):
     cp = ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6))
     self.assertEqual("(Point(1, 2), Vector(3, 4), Vector(5, 6), 'smooth')",
                      str(cp))
     self.assertEqual(
         "ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6), 'smooth')",
         repr(cp))
Example #9
0
 def test_path_translate(self):
     path = [Point(0, 0), Point(1, 2)]
     self.assertEqual([Point(1, 3), Point(2, 5)],
                      path_translate(path, Vector(1, 3), as_pt=True))
     self.assertEqual([(1, 3), (2, 5)], path_translate(path, Vector(1, 3)))
     self.assertEqual([Point(-1, -3), Point(0, -1)],
                      path_translate(path, Point(-1, -3), as_pt=True))
     self.assertEqual([(-1, -3), (0, -1)],
                      path_translate(path, Point(-1, -3)))
Example #10
0
 def test_pt(self):
     pt1 = Point(1, 1)
     pt2 = Point(1, 1)
     pt3 = Point(1, 1.000000001)
     pt4 = Point(-1, 1.01)
     self.assertEqual(pt1, pt2)
     self.assertNotEqual(pt1, pt3)
     self.assertAlmostEqual(pt1, pt3)
     # TODO-self.assertNotAlmostEqual(pt1, pt4)
     with self.assertRaisesRegex(AssertionError, 'Point.* == Point'):
         self.assertNotEqual(pt1, pt2)
     with self.assertRaisesRegex(AssertionError,
                                 'Point.* != Point.*1.000000001'):
         self.assertEqual(pt1, pt3)
     with self.assertRaisesRegex(AssertionError,
                                 'y: 1 != 1.01 within 7 places'):
         self.assertAlmostEqual(pt1, pt4)
Example #11
0
 def test_circle(self):
     # circle(r, c=Point(0, 0)) -> List[Tuple[float, float]]
     pts = circle(1)
     self.assertEqual(361, len(pts))
     self.assertAlmostEqual(pts[180], (-1, 0))
     self.assertAlmostEqual(pts[0], pts[-1])
     pts = circle(1, Point(1, 0))
     self.assertEqual(361, len(pts))
     self.assertAlmostEqual(pts[180], (0, 0))
     self.assertAlmostEqual(pts[0], pts[-1])
Example #12
0
 def test_cp(self):
     cp1 = ControlPoint(Point(1, 1), Vector(1, 1), Vector(-1, 1))
     cp2 = ControlPoint(Point(1, 1), Vector(1, 1), Vector(-1, 1))
     cp3 = ControlPoint(Point(1, 1), Vector(1, 1), Vector(-1, 1.000000001))
     cp4 = ControlPoint(Point(1, 1), Vector(1, 1), Vector(-1, 1.01))
     self.assertEqual(cp1, cp2)
     self.assertNotEqual(cp1, cp3)
     self.assertAlmostEqual(cp1, cp3)
     # TODO-self.assertNotAlmostEqual(cp1, cp4)
     with self.assertRaisesRegex(
             AssertionError,
             'ControlPoint.*Point.*Vector.*Vector.*== ControlPoint.*Point.*Vector.*Vector'
     ):
         self.assertNotEqual(cp1, cp2)
     with self.assertRaisesRegex(
             AssertionError,
             'ControlPoint.*Point.*Vector.*Vector.*!= ControlPoint.*Point.*Vector.*Vector.*1.000000001'
     ):
         self.assertEqual(cp1, cp3)
     with self.assertRaisesRegex(AssertionError,
                                 'y: 1 != 1.01 within 7 places'):
         self.assertAlmostEqual(cp1, cp4)
Example #13
0
 def test_path_rotate(self):
     # path_rotate_ccw(path: Iterable[ForwardRef('BasePoint')], angle, as_pt=False) -> List[Union[ForwardRef('BasePoint'), Tuple[float, float]]]
     path = [Point(0, 1), Point(1, 0)]
     self.assertAlmostEqual([Point(-1, 0), Point(0, 1)],
                            path_rotate_ccw(path, 90, as_pt=True))
     self.assertAlmostEqual([(-1, 0), (0, 1)], path_rotate_ccw(path, 90))
     v = sqrt(2) / 2
     self.assertAlmostEqual([Point(-v, v), Point(v, v)],
                            path_rotate_ccw(path, 45, as_pt=True))
Example #14
0
 def test_copy(self):
     cp = ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6))
     cp.c.restore(Point(0, 0))
     self.assertEqual(ControlPoint(Point(0, 0), Vector(3, 4), Vector(5, 6)),
                      cp)
     cp = ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6))
     cpc = cp.copy()
     cp.c.restore(Point(0, 0))
     self.assertEqual(ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6)),
                      cpc)
Example #15
0
 def test_eq(self):
     cp = ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6))
     self.assertEqual(cp,
                      ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6)))
     self.assertNotEqual(cp, "not even close")
     self.assertNotEqual(
         cp, ControlPoint(Point(1, 1), Vector(3, 4), Vector(5, 6)))
     self.assertNotEqual(
         cp, ControlPoint(Point(1, 2), Vector(1, 4), Vector(5, 6)))
     self.assertNotEqual(
         cp, ControlPoint(Point(1, 2), Vector(3, 4), Vector(1, 6)))
     self.assertNotEqual(
         cp, ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6), 'sharp'))
Example #16
0
 def test_pt(self):
     zz = Point(0, 0)
     pt1 = PointRelative(1, 1, zz)
     pt2 = PointRelative(1, 1, zz)
     pt3 = PointRelative(1, 1.000000001, zz)
     pt4 = PointRelative(-1, 1.01, zz)
     self.assertEqual(pt1, pt2)
     self.assertNotEqual(pt1, pt3)
     self.assertAlmostEqual(pt1, pt3)
     # TODO-self.assertNotAlmostEqual(pt1, pt4)
     with self.assertRaisesRegex(AssertionError,
                                 'PointRelative.* == PointRelative'):
         self.assertNotEqual(pt1, pt2)
     with self.assertRaisesRegex(
             AssertionError,
             'PointRelative.* != PointRelative.*1.000000001'):
         self.assertEqual(pt1, pt3)
     with self.assertRaisesRegex(AssertionError,
                                 'y: 1 != 1.01 within 7 places'):
         self.assertAlmostEqual(pt1, pt4)
Example #17
0
 def test_bbox(self):
     cp = ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6))
     self.assertEqual(BBox(1, 2, 6, 8), cp.bbox())
     cp = ControlPoint(Point(1, 2), Vector(-3, -4), Vector(5, 6))
     self.assertEqual(BBox(-2, -2, 6, 8), cp.bbox())
Example #18
0
def circle(r, c=Point(0, 0)) -> XYList:
    """Generate a circle of radius r about c as a list of x,y pairs"""
    steps = 360
    return [(r * cos(t) + c.x, r * sin(t) + c.y)
            for t in t_range(steps, 0, tau)]
Example #19
0
 def test_reversed(self):
     cp = ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6))
     cr = cp.reversed()
     self.assertEqual(cp.c, cr.c)
     self.assertEqual(cp.l, cr.r)
     self.assertEqual(cp.r, cr.l)
Example #20
0
def cross(r, c=Point(0, 0)) -> XYList:
    """Generate a cross of radius r about c as a list of x,y pairs"""
    r *= sqrt(2) / 2
    vx = Vector(r, r)
    vy = Vector(-r, r)
    return [p.xy() for p in [c - vx, c + vx, c, c - vy, c + vy]]
Example #21
0
def plus(r, c=Point(0, 0)) -> XYList:
    """Generate a plus sign of radius r about c as a list of x,y pairs"""
    vx = Vector(r, 0)
    vy = Vector(0, r)
    return [p.xy() for p in [c - vx, c + vx, c, c - vy, c + vy]]
Example #22
0
 def test_check_point_list(self):
     check_point_list([])
     check_point_list([Point(0, 0)])
     check_point_list([Point(0, 0), PointRelative(1, 2, Point(3, 4))])
Example #23
0
class SimpleAnimation(object):
    """Master animation object."""

    def __init__(self, draw_func, image_size=(500, 500), draw_bbox=(-250, -250, 250, 250),
                 steps=20, t_low=0.0, t_high=1.0,
                 frame_display_time=0.1,
                 show_steps=False):
        """
        :param draw_func: a function of (DrawingContext, step_time)
        :param image_size: size of images
        :param draw_bbox: bounding box of drawing space (used by draw_func)
        :param steps: number of steps (minus one) to go from t_low to t_high
        :param t_low: starting step time
        :param t_high: ending step time
        :param frame_display_time: number of seconds to display each animation frame
        :param show_steps: debugging, show each step as separate image
        """

        self.draw_func = draw_func
        self.image_size = Point(*image_size)
        self.model_bbox = BBox(draw_bbox)
        self.steps = steps
        self.background = 'grey'
        assert(t_low != t_high)
        self.t_low = t_low
        self.t_high = t_high
        self.frame_display_time = frame_display_time
        self.show_steps = show_steps

        self.images: List[Image.Image] = []

    def next_step(self) -> StepContext:
        """Create images, call draw_func for each step"""

        this_image = Image.new('RGBA', self.image_size.xy(), self.background)
        xf = Transform.canvas_fit(self.image_size.xy(), zoom=1.0, zero_zero=(0, self.image_size.y))
        xf.scale_bbox(self.model_bbox, BBox(0, 0, *self.image_size))
        dc = DrawingContext(this_image, xf)
        return StepContext(self, dc)

    def finish_step(self, dc: DrawingContext):
        if self.show_steps:
            dc.show()
        self.images.append(dc.image())

    def animate(self):
        """Create images, call draw_func for each step"""

        step_size = (self.t_high - self.t_low) / self.steps
        for step in range(self.steps+1):
            with self.next_step() as dc:
                step_t = self.t_low + step * step_size
                self.draw_func(dc, step_t)
            if self.show_steps:
                dc.show()
            self.images.append(dc.image())

    def save_animation(self, output):
        if not output:
            output = TMP_ANIM
            print('Output to %r' % output)
        images = self.images
        ms_per_frame = int(self.frame_display_time * 1000)
        # palette = self.make_palette(images)
        # images = [rgb_to_transparent(img, palette_image=palette) for img in images]
        if sys.platform == 'darwin':
            images[0].save('/tmp/images.png')
            images[0].save(output, save_all=True, append_images=images[1:], disposal=1, duration=ms_per_frame, loop=0)
            # images[0].save(output, save_all=True, append_images=images[1:], disposal=2, duration=ms_per_frame, loop=0)
            # os.system('qlmanage -p %r 2&>/dev/null' % output)
            import pygifsicle
            pygifsicle.optimize(output, '/tmp/anim_opt.gif')
            # platform.quicklook('/tmp/anim_opt.gif')
            os.system('qlmanage -p %r 2&>/dev/null' % '/tmp/anim_opt.gif')
        elif sys.platform == 'linux':
            # TODO-this only works on WSL--need to check for Microsoft in uname(?)
            images[0].save('/tmp/images.png')
            images[0].save(output, save_all=True, append_images=images[1:], disposal=1, duration=ms_per_frame, loop=0)
            os.system('cmd.exe /c "/linux%s"' % output)
        else:
            raise NotImplementedError('Unknown platform: %s' % sys.platform)
Example #24
0
def arc(r, sa, ea, c=Point(0, 0), steps=-1) -> XYList:
    """Generate an arc of radius r about c as a list of x,y pairs"""
    steps = int(abs(ea - sa) + 1) if steps < 0 else steps
    return [(r * cos(t) + c.x, r * sin(t) + c.y)
            for t in t_range(steps, radians(sa), radians(ea))]
Example #25
0
 def test_path_to_xy(self):
     self.assertEqual([Point(0, 0), Point(1, 2)],
                      path_from_xy([(0, 0), (1, 2)]))
Example #26
0
 def test_assertAlmostEqual_point_list(self):
     """Test that List[Point] works with assertAlmostEqual.  Should be tested in x7-testing, but easier here"""
     self.assertAlmostEqual([Point(0, 0)], [Point(0, 0)])
     self.assertAlmostEqual([Point(0, 0)], [Point(1e-9, -1e-9)])
Example #27
0
 def test_round(self):
     cp1 = ControlPoint(Point(1.123, 2.247), Vector(2.55, 4.499),
                        Vector(5.3, 6.0))
     cp2 = ControlPoint(Point(1, 2), Vector(3, 4), Vector(5, 6))
     self.assertEqual(cp2, cp1.round(0))
Example #28
0
def path_from_xy(xy: XYList) -> PointList:
    """Convert XYList to PointList"""
    return [Point(*p) for p in xy]