def test_intersect_equal_lines_diff_direction_diff_point(self): line1 = geom.Line((1, 1), (2, 3)) line2 = geom.Line((2, 2), (3, 4)) intersection = line1.intersect(line2) self.assertIsInstance(intersection, geom.Line) self.assertEqual(intersection.direction(), line1.direction()) self.assertEqual(intersection.point(), line1.point())
def test_lorentz_transform(self): v = 3 / 5 group_transformed = geom.lorentz_transformed( geom.PointGroup([(0, 1), (2, 3)]), v) line_transformed = geom.lorentz_transformed(geom.Line((0, 1), (2, 3)), v) ribbon_transformed = geom.lorentz_transformed( geom.Ribbon(geom.Line((0, 1), (2, 3)), geom.Line((0, 1), (0, 0))), v) self.collection.lorentz_transform(v) self.assertAlmostEqual(self.collection[0][0], group_transformed[0]) self.assertAlmostEqual(self.collection[0][1], group_transformed[1]) self.assertAlmostEqual(self.collection[1].direction(), line_transformed.direction()) self.assertAlmostEqual(self.collection[1].point(), line_transformed.point()) self.assertAlmostEqual(self.collection[2][0].direction(), ribbon_transformed[0].direction()) self.assertAlmostEqual(self.collection[2][0].point(), ribbon_transformed[0].point()) self.assertAlmostEqual(self.collection[2][1].direction(), ribbon_transformed[1].direction()) self.assertAlmostEqual(self.collection[2][1].point(), ribbon_transformed[1].point())
def test_str_within_precision(self): self.assertEqual( str(geom.Line((0.001, 1.001), (2.001, 2.999), precision=3)), 'Line( [t, x] = [2.001, 2.999] + k*[0.001, 1.001] )') self.assertEqual( str(geom.Line((0.0001, 1.0001), (2.0001, 2.9999), precision=3)), 'Line( [t, x] = [2.0, 3.0] + k*[0.0, 1.0] )')
def test_draw_out_of_bounds(self): p = _MockSTPlotter() ribbon = geom.Ribbon(geom.Line((0, 1), (2, 3)), geom.Line((0, 1), (0, 0))) ribbon.draw(p, tlim=(4, 5), xlim=(0, 1)) self.assertEqual(len(p.segments), 0) self.assertEqual(len(p.polygons), 0)
def test_draw(self): p = _MockSTPlotter() ribbon = geom.Ribbon(geom.Line((0, 1), (2, 3)), geom.Line((0, 1), (0, 0)), tag='test', draw_options={ 'facecolor': 'red', 'label': 'test2' }) ribbon.draw(p, tlim=(-2, 3), xlim=(0, 1)) self.assertEqual(len(p.points), 0) self.assertEqual(len(p.segments), 2) self.assertEqual(len(p.polygons), 1) p.polygons_equal(self, p.polygons[0], ([(0, 0), (0, 1), (2, 1), (2, 0)], 'test', { 'facecolor': 'red', 'label': 'test2' })) p.segments_equal(self, p.segments[0], ((2, 0), (2, 1), None, { 'color': geom.geomrc['ribbon.default_edgecolor'], 'zorder': 1 })) p.segments_equal(self, p.segments[1], ((0, 0), (0, 1), None, { 'color': geom.geomrc['ribbon.default_edgecolor'], 'zorder': 1 })) self.assertEqual(p.tlim, (-2, 3)) self.assertEqual(p.xlim, (0, 1))
def __init__(self, left_start_pos, length=0, velocity=0, start_time=0, tag=geom.geomrc['tag'], draw_options=geom.geomrc['draw_options']): super().__init__( geom.Line((1, velocity), (start_time, left_start_pos)), geom.Line((1, velocity), (start_time, left_start_pos + length)), tag=tag, draw_options=draw_options )
def test_draw_no_edges(self): p = _MockSTPlotter() ribbon = geom.Ribbon(geom.Line((0, 1), (2, 3)), geom.Line((0, 1), (0, 0)), draw_options={'edgecolor': 'None'}) ribbon.draw(p, tlim=(-2, 3), xlim=(0, 1)) self.assertEqual(len(p.segments), 0) self.assertEqual(len(p.polygons), 1)
def __init__(self, start_time, duration=0, unit_delay=0, start_pos=0, tag=geom.geomrc['tag'], draw_options=geom.geomrc['draw_options']): super().__init__( geom.Line((unit_delay, 1), (start_time, start_pos)), geom.Line((unit_delay, 1), (start_time + duration, start_pos)), tag=tag, draw_options=draw_options )
def test_get_vertices_flat_lines(self): ribbon = geom.Ribbon( geom.Line((0, 1), (1, 0)), geom.Line((0, 1), (2, 0)), ) self.assertEqual(ribbon._get_vertices((0, 3), (0, 3)), [(1, 0), (1, 3), (2, 3), (2, 0)])
def test_get_vertices_exact_boundary(self): ribbon = geom.Ribbon( geom.Line((0, 1), (1, 0)), geom.Line((0, 1), (3, 0)), ) self.assertEqual(ribbon._get_vertices((0, 3), (0, 3)), [(1, 0), (1, 3), (3, 3), (3, 0)])
def test_get_vertices_both_lines_out_of_bounds(self): ribbon = geom.Ribbon( geom.Line((1, 1), (3, 0)), geom.Line((1, 1), (0, 3)), ) self.assertEqual(ribbon._get_vertices((0, 2), (0, 2)), [(0, 0), (0, 2), (2, 2), (2, 0)])
def test_get_vertices_line_on_corner(self): ribbon = geom.Ribbon( geom.Line((1, 1), (1, 0)), geom.Line((1, 1), (0, 2)), ) self.assertEqual(ribbon._get_vertices((0, 2), (0, 2)), [(0, 0), (0, 2), (2, 2), (2, 1), (1, 0)])
def stgrid(tlim, xlim, origin=geom.geomrc['origin'], t_spacing=1, x_spacing=1, axis_draw_options=geom.geomrc['draw_options'], grid_draw_options=geom.geomrc['draw_options']): """Spacetime grid with some spacing on some range Args: tlim (tuple): Minimum and maximum time values for the grid. xlim (tuple): Minimum and maximum position values for the grid. origin (tuple, optional): (t, x) value defining the grid "center". t_spacing (float, optional): The spacing between grid lines of constant time. x_spacing (float, optional): The spacing between grid lines of constant position. axis_draw_options (dict, optional): Draw options for the axis lines passing through the origin. See `specrel.geom.LorentzTransformable` for details. grid_draw_options (dict, optional): Draw options for the grid lines not including the axis lines. See `specrel.geom.LorentzTransformable` for details. Returns: specrel.geom.Collection: collection of grid lines in the order `[constant t lines in ascending order of t, constant x lines in ascending order of x, t axis, x axis]` """ # Default draw options if none are specified axis_draw_options = {'color': 'black', 'linewidth': 2, **axis_draw_options} grid_draw_options = {'color': 'darkgray', 'linewidth': 1, **grid_draw_options} gridlines = geom.Collection() # Add all the minor grid lines that fit within the limits down_steps = math.ceil((tlim[0] - origin[0]) / t_spacing) up_steps = math.floor((tlim[1] - origin[0]) / t_spacing) left_steps = math.ceil((xlim[0] - origin[1]) / x_spacing) right_steps = math.floor((xlim[1] - origin[1]) / x_spacing) for tstep in range(down_steps, up_steps+1): if tstep != 0: # Add axes later gridlines.append( geom.Line((0, 1), (origin[0] + tstep*t_spacing, origin[1]), draw_options=grid_draw_options)) for xstep in range(left_steps, right_steps+1): if xstep != 0: gridlines.append( geom.Line((1, 0), (origin[0], origin[1] + xstep*x_spacing), draw_options=grid_draw_options)) # Add the axes if in range if origin[0] >= tlim[0] and origin[0] <= tlim[1]: gridlines.append( geom.Line((0, 1), origin, draw_options=axis_draw_options)) if origin[1] >= xlim[0] and origin[1] <= xlim[1]: gridlines.append( geom.Line((1, 0), origin, draw_options=axis_draw_options)) return gridlines
def lateral_gradient_ribbon(direction, point1, point2, color1, color2, divisions=100, draw_options=geom.geomrc['draw_options']): """A `specrel.geom.Ribbon`-esque object with a lateral color gradient (across the finite direction). Args: direction (specrel.geom.STVector or iterable): Direction vector for the gradient. point1 (specrel.geom.STVector or iterable): A point that the first edge of the ribbon passes through. point2 (specrel.geom.STVector or iterable): A point that the second edge of the ribbon passes through. color1 (color): A Matplotlib color for the gradient starting color. color2 (color): A Matplotlib color for the gradient ending color. divisions (int, optional): The number of line segment divisions in the gradient. More divisions means a smoother gradient. draw_options (TYPE, optional): See `specrel.geom.LorentzTransformable`. Returns: specrel.geom.Collection: Collection containing the `specrel.geom.Ribbon` objects of slowly changing color from `point1` to `point2`. """ # Copy draw_options and remove color, facecolor, and edgecolor if they're # there draw_options = dict(draw_options) draw_options.pop('color', None) draw_options.pop('facecolor', None) draw_options.pop('edgecolor', None) # Color gradient calculator for the given points and colors def this_colorgrad(x): return _calc_colorgrad(x, point1, point2, color1, color2) grad = geom.Collection() # Ribbons comprising the color gradient, as we move from point1 to point2 for i in range(divisions): start_point, _ = this_colorgrad(i / divisions) # Overlap bands by half a division, except the last one end_point, _ = this_colorgrad(min((i + 1 + 1 / 2) / divisions, 1)) _, grad_color = this_colorgrad((i + 1 / 2) / divisions) # Explicitly turn off edge coloring grad.append( geom.Ribbon(geom.Line(direction, start_point), geom.Line(direction, end_point), draw_options={ 'facecolor': grad_color, 'edgecolor': 'None', **draw_options })) return grad
def test_init(self): ribbon = geom.Ribbon(geom.Line((0, 1), (2, 3)), geom.Line((0, 1), (0, 0)), tag='test', draw_options={'color': 'red'}) self.assertEqual(ribbon[0].direction().t, 0) self.assertEqual(ribbon[0].direction().x, 1) self.assertEqual(ribbon[0].point().t, 2) self.assertEqual(ribbon[0].point().x, 3) self.assertEqual(ribbon[1].direction().t, 0) self.assertEqual(ribbon[1].direction().x, 1) self.assertEqual(ribbon[1].point().t, 0) self.assertEqual(ribbon[1].point().x, 0) self.assertEqual(ribbon.tag, 'test') self.assertEqual(ribbon.draw_options, {'color': 'red'})
def test_init_with_override(self): line = geom.Line(geom.STVector(0, 1, precision=7), geom.STVector(2, 3, precision=7), precision=5, tag='test') self.assertEqual(line.precision(), 5) self.assertEqual(line.tag, 'test')
def test_draw_out_of_bounds(self): line = geom.Line((1, 1), (2, 3)) p = _MockSTPlotter() line.draw(p, tlim=(2, 3), xlim=(0, 1)) self.assertEqual(len(p.points), 0) self.assertEqual(len(p.segments), 0) self.assertEqual(len(p.polygons), 0)
def setUp(self): trans = geom.Line((1, 0), (0, 0)) xlim = (0, 2) tlim = (0, 2) time = 1 anim_opt = {'tlim': tlim, 'xlim': xlim, 'time': time} self.multi = canim.MultiTransformAnimator( [ { 'animator_options': { 'stanimator': sanim.WorldlineAnimator, **anim_opt }, 'transformable': trans, }, { 'animator_options': { 'stanimator': sanim.ObjectAnimator, **anim_opt }, 'transformable': trans, }, ], -4 / 5, fps=1, transition_duration=2, display_current_velocity=True, display_current_velocity_decimals=3) self.multi.init_func()
def test_lorentz_transform_origin_1_1(self): line = geom.Line((2, 3), (3, 4)) line.lorentz_transform(3 / 5, origin=(1, 1)) self.assertAlmostEqual(line.direction().t, 1 / 4) self.assertAlmostEqual(line.direction().x, 9 / 4) self.assertAlmostEqual(line.point().t, 1 / 4 + 1) self.assertAlmostEqual(line.point().x, 9 / 4 + 1)
def test_intersect_equal_lines_diff_direction_diff_point(self): ray = geom.Ray((1, 1), (2, 3)) line = geom.Line((2, 2), (3, 4)) intersection = ray.intersect(line) self.assertIsInstance(intersection, geom.Ray) self.assertEqual(intersection.direction(), ray.direction()) self.assertEqual(intersection.point(), ray.point())
def test_boundary_intersections_diag(self): line = geom.Line((1, 1), (0.5, 0)) tlim = (0, 1) xlim = (0, 1) self.assertEqual(line._boundary_intersections(tlim, xlim), [(0, -0.5), (0.5, 0), (1, 0.5), (1.5, 1)])
def test_draw_in_bounds(self): line = geom.Line((1, 1), (2, 3)) p = _MockSTPlotter() line.draw(p, tlim=(-1, 2), xlim=(0, 2)) self.assertEqual(len(p.points), 0) self.assertEqual(len(p.segments), 1) self.assertEqual(len(p.polygons), 0) p.segments_equal(self, p.segments[0], ((-1, 0), (1, 2), None, {})) self.assertEqual(p.tlim, (-1, 2)) self.assertEqual(p.xlim, (0, 2))
def test_init(self): line = geom.Line((0, 1), (2, 3), precision=7, tag='test', draw_options={'color': 'red'}) self.assertEqual(line.direction().t, 0) self.assertEqual(line.direction().x, 1) self.assertEqual(line.point().t, 2) self.assertEqual(line.point().x, 3) self.assertEqual(line.precision(), 7) self.assertEqual(line.tag, 'test') self.assertEqual(line.draw_options, {'color': 'red'})
def test_stgrid(self): grid = phy.stgrid((-1, 1), (-1, 1)) self.assertEqual(len(grid), 6) self.assertEqual(grid[0], geom.Line((0, 1), (-1, 0))) self.assertEqual(grid[1], geom.Line((0, 1), (1, 0))) self.assertEqual(grid[2], geom.Line((1, 0), (0, -1))) self.assertEqual(grid[3], geom.Line((1, 0), (0, 1))) self.assertEqual(grid[4], geom.Line((0, 1), (0, 0))) self.assertEqual(grid[5], geom.Line((1, 0), (0, 0)))
def setUp(self): trans = geom.Line((1, 1), (0, 0)) xlim = (0, 2) tlim = (0, 2) draw_options = {'tlim': tlim, 'xlim': xlim} self.multi = canim.MultiTimeAnimator([{ 'animator': sanim.WorldlineAnimator, 'transformable': trans, 'draw_options': draw_options, }, { 'animator': sanim.ObjectAnimator, 'transformable': trans, 'draw_options': draw_options, }], fps=1, ct_per_sec=1, tlim=tlim, display_current_time=True, display_current_time_decimals=3) self.multi.init_func()
def test_lateral_gradient_ribbon(self): gradribbon = grad.lateral_gradient_ribbon((1, 0), (0, 0), (0, 1), (1, 0, 0, 1), (0, 0, 1, 1), divisions=3) self.assertEqual(len(gradribbon), 3) self.assertEqual(gradribbon[0][0], geom.Line((1, 0), (0, 0))) self.assertEqual(gradribbon[0][1], geom.Line((1, 0), (0, 3/6))) _tuple_eq(self, gradribbon[0].draw_options['facecolor'], (5/6, 0, 1/6, 1)) self.assertEqual(gradribbon[1][0], geom.Line((1, 0), (0, 1/3))) self.assertEqual(gradribbon[1][1], geom.Line((1, 0), (0, 5/6))) _tuple_eq(self, gradribbon[1].draw_options['facecolor'], (3/6, 0, 3/6, 1)) self.assertEqual(gradribbon[2][0], geom.Line((1, 0), (0, 2/3))) self.assertEqual(gradribbon[2][1], geom.Line((1, 0), (0, 1))) _tuple_eq(self, gradribbon[2].draw_options['facecolor'], (1/6, 0, 5/6, 1))
def setUp(self): trans = geom.Line((1, 1), (0, 0)) xlim = (0, 3) tlim = (0, 3) draw_options = {'tlim': tlim, 'xlim': xlim} multi = canim.MultiTimeAnimator([{ 'animator': sanim.WorldlineAnimator, 'transformable': trans, 'draw_options': draw_options, }, { 'animator': sanim.ObjectAnimator, 'transformable': trans, 'draw_options': draw_options, }], fps=1, ct_per_sec=1, tlim=tlim, display_current_time=True, display_current_time_decimals=3, title='Title') self.rew = canim.Rewinder(multi, end_pause=2) self.rew.init_func()
def test_point_not_inside(self): ribbon = geom.Ribbon(geom.Line((1, 1), (0, 2)), geom.Line((1, 1), (0, 0))) self.assertFalse(ribbon._point_inside((0, 3)))
def test_cannot_append(self): self.assertRaises(TypeError, geom.Line((0, 1), (2, 3)).append, geom.STVector(1, 1))
def test_point_on_boundary(self): ribbon = geom.Ribbon(geom.Line((1, 1), (0, 2)), geom.Line((1, 1), (0, 0))) self.assertTrue(ribbon._point_inside((0, 2)))