Exemplo n.º 1
0
 def test_draw_totally_out_of_bounds(self):
     p = _MockSTPlotter()
     h = geom.HalfRibbon(geom.Ray((0, 1), (2, 3)), geom.Ray((0, 1), (0, 2)))
     h.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)
Exemplo n.º 2
0
 def test_draw_endpoints_one_endpoint_out_of_bounds(self):
     p = _MockSTPlotter()
     h = geom.HalfRibbon(geom.Ray((0, 1), (2, 0.5)),
                         geom.Ray((0, 1), (0, -0.5)),
                         draw_options={'edgecolor': 'None'})
     h.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), 1)
     p.polygons_equal(self, p.polygons[0], ([(0, 0), (0, 1), (2, 1),
                                             (2, 0.5), (1, 0)], None, {}))
Exemplo n.º 3
0
 def test_draw_totally_out_of_bounds(self):
     ray = geom.Ray((1, 1), (2, 3))
     p = _MockSTPlotter()
     ray.draw(p, tlim=(-1, 2), xlim=(0, 2))
     self.assertEqual(len(p.points), 0)
     self.assertEqual(len(p.segments), 0)
     self.assertEqual(len(p.polygons), 0)
Exemplo n.º 4
0
 def test_boundary_intersections_exterior_endpoint(self):
     ray = geom.Ray((0, 1), (0.5, -1))
     tlim = (0, 1)
     xlim = (0, 1)
     self.assertEqual(ray._boundary_intersections(tlim, xlim), [(0.5, -1),
                                                                (0.5, 0),
                                                                (0.5, 1)])
Exemplo n.º 5
0
 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())
Exemplo n.º 6
0
 def test_draw_endpoint_in_bounds(self):
     ray = geom.Ray((1, 1), (0, 1))
     p = _MockSTPlotter()
     ray.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], ((0, 1), (1, 2), None, {}))
Exemplo n.º 7
0
 def test_extrapolate_color(self):
     gradln = grad.gradient_line((1/3, 1/3), (2/3, 2/3),
         (2/3, 0, 1/3, 1), (1/3, 0, 2/3, 1), divisions=1)
     self.assertEqual(len(gradln), 5)
     self.assertEqual(gradln[0], geom.Ray((-1, -1), (0, 0)))
     _tuple_eq(self, gradln[0].draw_options['color'], (1, 0, 0, 1))
     self.assertEqual(gradln[1][0], (0, 0))
     self.assertEqual(gradln[1][1], (1/3, 1/3))
     _tuple_eq(self, gradln[1].draw_options['color'], (5/6, 0, 1/6, 1))
     self.assertEqual(gradln[2][0], (1/3, 1/3))
     self.assertEqual(gradln[2][1], (2/3, 2/3))
     _tuple_eq(self, gradln[2].draw_options['color'], (3/6, 0, 3/6, 1))
     self.assertEqual(gradln[3][0], (2/3, 2/3))
     self.assertEqual(gradln[3][1], (1, 1))
     _tuple_eq(self, gradln[3].draw_options['color'], (1/6, 0, 5/6, 1))
     self.assertEqual(gradln[4], geom.Ray((1, 1), (1, 1)))
     _tuple_eq(self, gradln[4].draw_options['color'], (0, 0, 1, 1))
Exemplo n.º 8
0
 def test_longitudinal_gradient_ribbon(self):
     gradribbon = grad.longitudinal_gradient_ribbon(
         ((0, 0), (1, 0)), ((0, 1), (1, 1)),
         (1, 0, 0, 1), (0, 0, 1, 1), divisions=1)
     self.assertEqual(len(gradribbon), 3)
     self.assertEqual(gradribbon[0][0], geom.Ray((-1, 0), (0.5, 0)))
     self.assertEqual(gradribbon[0][1], geom.Ray((-1, 0), (0.5, 1)))
     _tuple_eq(self, gradribbon[0].draw_options['facecolor'], (1, 0, 0, 1))
     self.assertEqual(gradribbon[1][0], (0, 0))
     self.assertEqual(gradribbon[1][1], (1.5, 0))
     self.assertEqual(gradribbon[1][2], (1.5, 1))
     self.assertEqual(gradribbon[1][3], (0, 1))
     _tuple_eq(self, gradribbon[1].draw_options['facecolor'],
         (1/2, 0, 1/2, 1))
     self.assertEqual(gradribbon[2][0], geom.Ray((1, 0), (1, 0)))
     self.assertEqual(gradribbon[2][1], geom.Ray((1, 0), (1, 1)))
     _tuple_eq(self, gradribbon[2].draw_options['facecolor'], (0, 0, 1, 1))
Exemplo n.º 9
0
 def test_auto_draw_lims(self):
     ray = geom.Ray((1, -1), (2, 3))
     self.assertEqual(ray._auto_draw_lims(), ((2, 3), (2, 3)))
Exemplo n.º 10
0
 def test_init_error_on_antiparallel(self):
     self.assertRaises(ValueError, geom.HalfRibbon, geom.Ray((0, 1),
                                                             (0, 0)),
                       geom.Ray((0, -1), (2, 3)))
Exemplo n.º 11
0
 def test_ghost_intersection(self):
     ray = geom.Ray((1, 0), (2, 1))
     line = geom.Line((0, 1), (1, 0))
     self.assertIsNone(ray.intersect(line))
Exemplo n.º 12
0
 def test_actual_intersection_tangent(self):
     ray = geom.Ray((1, 0), (1, 1))
     line = geom.Line((0, 1), (1, 0))
     self.assertEqual(ray.intersect(line), (1, 1))
Exemplo n.º 13
0
 def test_actual_intersection_full_crossing(self):
     ray = geom.Ray((1, 0), (0, 1))
     line = geom.Line((0, 1), (1, 0))
     self.assertEqual(ray.intersect(line), (1, 1))
Exemplo n.º 14
0
 def test_str(self):
     self.assertEqual(str(geom.Ray((0, 1), (2, 3))),
                      'Ray( [t, x] = [2, 3] + k*[0, 1] where k >= 0 )')
Exemplo n.º 15
0
 def test_intersect_parallel(self):
     ray = geom.Ray((1, 1), (0, 0))
     line = geom.Line((2, 2), (0, 1))
     self.assertIsNone(ray.intersect(line))
Exemplo n.º 16
0
 def test_eq(self):
     self.assertEqual(geom.Ray((1, 1), (2, 3)), geom.Ray((1, 1), (2, 3)))
Exemplo n.º 17
0
def gradient_line(point1,
                  point2,
                  color1,
                  color2,
                  divisions=100,
                  extrapolate_color=True,
                  draw_options=geom.geomrc['draw_options']):
    """A line with a color gradient. The gradient transition will happen over
    a finite range in spacetime, and be monochromatic at either end.

    Args:
        point1 (specrel.geom.STVector or iterable): Starting point of the
            gradient.
        point2 (specrel.geom.STVector or iterable): Ending point of the
            gradient.
        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.
        extrapolate_color (bool, optional): Flag for whether or not to
            extrapolate the color gradient across the line past the specified
            endpoints so that the color change spans as far as possible across
            the line.
        draw_options (dict, optional): See `specrel.geom.LorentzTransformable`.

    Returns:
        specrel.geom.Collection:
            Collection containing the color gradient increments, in the order:

            1. `specrel.geom.Ray` before `point1` with `color1`.
            2. Line segments changing color from `point1` to `point2`.
            3. `specrel.geom.Ray` after `point2` with `color2`.
    """
    # Copy draw_options and remove color if it's there
    draw_options = dict(draw_options)
    draw_options.pop('color', None)

    # If extrapolating color, calculate the color gradient extremes
    if extrapolate_color:
        point1, point2, color1, color2, divisions = _colorgrad_extremes(
            point1, point2, color1, color2, divisions)

    # Color gradient calculator for the given points and colors
    def this_colorgrad(x):
        return _calc_colorgrad(x, point1, point2, color1, color2)

    # Line direction vector
    direc = geom.STVector(point2) - geom.STVector(point1)

    grad = geom.Collection()
    # Monochromatic ray at the tail end of the gradient line
    grad.append(
        geom.Ray(-direc,
                 point1,
                 draw_options={
                     'color': color1,
                     **draw_options
                 }))
    # The line segments comprising the color gradient
    for i in range(divisions):
        start_point, _ = this_colorgrad(i / divisions)
        end_point, _ = this_colorgrad((i + 1) / divisions)
        _, grad_color = this_colorgrad((i + 1 / 2) / divisions)
        grad.append(
            geom.line_segment(start_point,
                              end_point,
                              draw_options={
                                  'color': grad_color,
                                  **draw_options
                              }))
    # Monochromatic ray at the head end of the gradient line
    grad.append(
        geom.Ray(direc, point2, draw_options={
            'color': color2,
            **draw_options
        }))
    return grad
Exemplo n.º 18
0
v_away = 1/2
v_message = 4
t_send = 1
person1 = phy.MovingObject(0, velocity=-v_away,
    draw_options={'color': 'red', 'label': 'Person 1', 'markersize': 15})
person2 = phy.MovingObject(0, velocity=v_away,
    draw_options={'color': 'blue', 'label': 'Person 2', 'markersize': 15})
# Extensions of the messages to all time, even though they don't exist for all
# time. The lines are useful for intersection calculations
joke_alltime = phy.MovingObject(person2.center_pos(t_send), start_time=t_send,
    velocity=-v_message)
# Get the left edge of the MovingObject; since it's a point object it's just
# the worldline
joke_sent = joke_alltime.left().intersect(person1.left())
# The actual joke object to draw
joke = geom.Ray((-1, v_message), joke_sent, tag='*Joke*',
    draw_options={'color': 'red', 'linestyle': '--', 'marker': '>'})
# Mark the point of receipt
joke_received = joke.intersect(person2.left())
joke_received.draw_options = {
    'color': 'limegreen',
    'marker': '*',
    'markersize': 10,
    'label': 'Joke received'
}
# Repeat for the response stuff
response_alltime = phy.MovingObject(person1.center_pos(t_send),
    start_time=t_send, velocity=v_message, tag='Hahaha!',
    draw_options={'color': 'blue', 'linestyle': '--', 'marker': '<'})
response_sent = response_alltime.left().intersect(person2.left())
response = geom.Ray((-1, -v_message), response_sent, tag='Hahaha!',
    draw_options={'color': 'blue', 'linestyle': '--', 'marker': '<'})
Exemplo n.º 19
0
 def test_neq_opp_dir(self):
     self.assertNotEqual(geom.Ray((1, 1), (2, 3)), geom.Ray((-1, -1),
                                                            (2, 3)))
Exemplo n.º 20
0
 def test_neq_diff_point(self):
     self.assertNotEqual(geom.Ray((1, 1), (2, 3)), geom.Ray((1, 1), (1, 2)))
Exemplo n.º 21
0
 def test_eq_scaled_dir(self):
     self.assertEqual(geom.Ray((1, 1), (2, 3)), geom.Ray((2, 2), (2, 3)))
Exemplo n.º 22
0
)
# Add a few more frills to the drawing
door_draw_options = {'linestyle': '--', 'marker': '|', 'markersize': 10}
garage[0].draw_options = door_draw_options
garage[1].draw_options = door_draw_options

# Time range
t_start = 0
# End when the ladder totally clears the garage
t_end = ladder.time_for_left_pos(garage.right_pos(0))
# Time when the garage doors are opened/closd
t_transition = ladder.time_for_left_pos(garage.left_pos(0))

# Whole period when each door is closed
closed_draw_options = {'color': 'red', 'marker': '|', 'markersize': 10}
left_closed = geom.Ray((1, 0), (t_transition, garage.left_pos(0)),
    draw_options=closed_draw_options)
right_closed = geom.Ray((-1, 0), (t_transition, garage.right_pos(0)),
    draw_options=closed_draw_options)

# Exact event of closing/opening each door
close_event_draw_options = {
    'color': 'red',
    'marker': 'v',
    'markersize': 10,
    'label': 'Close door',
}
open_event_draw_options = {
    'color': 'limegreen',
    'marker': '^',
    'markersize': 10,
    'label': 'Open door',
Exemplo n.º 23
0
def longitudinal_gradient_ribbon(line1_endpoints,
                                 line2_endpoints,
                                 color1,
                                 color2,
                                 divisions=100,
                                 extrapolate_color=True,
                                 draw_options=geom.geomrc['draw_options']):
    """A `specrel.geom.Ribbon`-esque object with a longitudinal color gradient
    (across the infinite direction).

    Args:
        line1_endpoints (list): list of two `specrel.geom.STVector`-convertible
            points defining the start and end positions of the gradient along
            the first edge of the ribbon.
        line2_endpoints (list): Same as `line1_endpoints`, but for the second
            edge of the ribbon.
        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.
        extrapolate_color (bool, optional): Flag for whether or not to
            extrapolate the color gradient across the ribbon past the specified
            endpoints so that the color change spans as far as possible across
            the ribbon.
        draw_options (TYPE, optional): See `specrel.geom.LorentzTransformable`.

    Returns:
        specrel.geom.Collection:
            Collection containing the color gradient increments, in the order:

            1. `specrel.geom.HalfRibbon` with `color1` before both line starting
                points.
            2. Polygons changing color from starts of the lines to the ends.
            3. `specrel.geom.HalfRibbon` with `color2` after both line ending
                points.
    """
    # 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)

    # If extrapolating color, calculate the color gradient extremes
    if extrapolate_color:
        point1, point2, color1, color2, divisions = _colorgrad_extremes(
            *line1_endpoints, color1, color2, divisions)
        line1_endpoints = (point1, point2)
        point1, point2, _, _, _ = _colorgrad_extremes(*line2_endpoints, color1,
                                                      color2, divisions)
        line2_endpoints = (point1, point2)

    # Color gradient calculators for each line with the given colors
    def line1_colorgrad(x):
        return _calc_colorgrad(x, *line1_endpoints, color1, color2)

    def line2_colorgrad(x):
        return _calc_colorgrad(x, *line2_endpoints, color1, color2)

    # Direction vectors of each line
    direc1 = geom.STVector(line1_endpoints[1]) - geom.STVector(
        line1_endpoints[0])
    direc2 = geom.STVector(line2_endpoints[1]) - geom.STVector(
        line2_endpoints[0])
    grad = geom.Collection()
    # Form the monochromatic half ribbon at the tail end of the gradient
    # Overlap with the first polygon by half a division to mitigate any
    # boundary gaps
    start_point1, _ = line1_colorgrad(1 / (2 * divisions))
    start_point2, _ = line2_colorgrad(1 / (2 * divisions))
    grad.append(
        geom.HalfRibbon(
            geom.Ray(-direc1, start_point1),
            geom.Ray(-direc2, start_point2),
            # Explicitly turn off edge coloring
            draw_options={
                'facecolor': color1,
                'edgecolor': 'None',
                **draw_options
            }))
    # Interior polygons comprising the color gradient
    for i in range(divisions):
        start_point1, _ = line1_colorgrad(i / divisions)
        # Overlap bands by half a division
        end_point1, _ = line1_colorgrad((i + 1 + 1 / 2) / divisions)
        start_point2, _ = line2_colorgrad(i / divisions)
        end_point2, _ = line2_colorgrad((i + 1 + 1 / 2) / divisions)
        _, grad_color = line1_colorgrad((i + 1 / 2) / divisions)
        grad.append(
            geom.polygon([start_point1, end_point1, end_point2, start_point2],
                         draw_options={
                             'facecolor': grad_color,
                             **draw_options
                         }))
    # Monochromatic half ribon at the head end of the gradient
    grad.append(
        geom.HalfRibbon(geom.Ray(direc1, line1_endpoints[1]),
                        geom.Ray(direc2, line2_endpoints[1]),
                        draw_options={
                            'facecolor': color2,
                            'edgecolor': 'None',
                            **draw_options
                        }))
    return grad