Пример #1
0
def test_arc2_intersect_line_ray():
    """Test the Arc2D intersect_line_ray method."""
    pt = Point2D(2, 0)
    arc = Arc2D(pt, 1, 0, math.pi)
    circle = Arc2D(pt, 1)
    seg1 = LineSegment2D(pt, Vector2D(2, 2))
    seg2 = LineSegment2D(Point2D(0, -2), Vector2D(6, 6))
    seg3 = LineSegment2D(pt, Vector2D(0.5, 0.5))

    int1 = arc.intersect_line_ray(seg1)
    assert len(int1) == 1
    assert int1[0].x == pytest.approx(2.71, rel=1e-2)
    assert int1[0].y == pytest.approx(0.71, rel=1e-2)
    int2 = circle.intersect_line_ray(seg1)
    assert len(int2) == 1
    assert int2[0].x == pytest.approx(2.71, rel=1e-2)
    assert int2[0].y == pytest.approx(0.71, rel=1e-2)
    int3 = arc.intersect_line_ray(seg2)
    assert len(int3) == 1
    assert int3[0].x == pytest.approx(2.71, rel=1e-2)
    assert int3[0].y == pytest.approx(0.71, rel=1e-2)
    int4 = circle.intersect_line_ray(seg2)
    assert len(int4) == 2
    assert int4[0].x == pytest.approx(2.71, rel=1e-2)
    assert int4[0].y == pytest.approx(0.71, rel=1e-2)
    assert int4[1].x == pytest.approx(1.29, rel=1e-2)
    assert int4[1].y == pytest.approx(-0.71, rel=1e-2)
    assert arc.intersect_line_ray(seg3) is None
Пример #2
0
def test_intersect_line_ray_colinear():
    """Test the LineSegment2D intersect_line_ray method with colinear segments."""
    pt_1 = Point2D(3.5362137509358353, -2.3574758339572237)
    vec_1 = Vector2D(2.6625609418810905, -1.7750406279207271)
    seg_1 = LineSegment2D(pt_1, vec_1)

    pt_2 = Point2D(-1.7889081328263625, 1.1926054218842419)
    vec_2 = Vector2D(1.7889081328263625, -1.1926054218842419)
    seg_2 = LineSegment2D(pt_2, vec_2)

    assert seg_1.intersect_line_ray(seg_2) is None
    seg_1 = seg_1.flip()
    assert seg_1.intersect_line_ray(seg_2) is None
    seg_2 = seg_2.flip()
    assert seg_1.intersect_line_ray(seg_2) is None

    pt_1 = Point2D(0, 0)
    vec_1 = Vector2D(1, 0)
    seg_1 = LineSegment2D(pt_1, vec_1)

    pt_2 = Point2D(0, 0)
    vec_2 = Vector2D(0, 1)
    seg_2 = LineSegment2D(pt_2, vec_2)

    assert seg_1.intersect_line_ray(seg_2) == Point2D(0, 0)

    pt_1 = Point2D(1, 0)
    vec_1 = Vector2D(-1, 0)
    seg_1 = LineSegment2D(pt_1, vec_1)

    assert seg_1.intersect_line_ray(seg_2) == Point2D(0, 0)

    pt_2 = Point2D(0, 1)
    vec_2 = Vector2D(0, -1)
    seg_2 = LineSegment2D(pt_2, vec_2)

    assert seg_1.intersect_line_ray(seg_2) == Point2D(0, 0)

    pt_1 = Point2D(0, -1)
    vec_1 = Vector2D(0, 1)
    seg_1 = LineSegment2D(pt_1, vec_1)

    assert seg_1.intersect_line_ray(seg_2) is None

    pt_2 = Point2D(0, 0)
    vec_2 = Vector2D(-1, 0)
    seg_2 = LineSegment2D(pt_2, vec_2)

    assert seg_1.intersect_line_ray(seg_2) == Point2D(0, 0)

    pt_2 = Point2D(-1, 0)
    vec_2 = Vector2D(1, 0)
    seg_2 = LineSegment2D(pt_2, vec_2)

    assert seg_1.intersect_line_ray(seg_2) == Point2D(0, 0)
Пример #3
0
def test_equality():
    """Test the equality of LineSegment2D objects."""
    pt = Point2D(2, 0)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)
    seg_dup = seg.duplicate()
    seg_alt = LineSegment2D(Point2D(2, 0.1), vec)

    assert seg is seg
    assert seg is not seg_dup
    assert seg == seg_dup
    assert hash(seg) == hash(seg_dup)
    assert seg != seg_alt
    assert hash(seg) != hash(seg_alt)
Пример #4
0
def test_subdivide():
    """Test the LineSegment2D subdivide methods."""
    pt = Point2D(2, 2)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)

    divisions = seg.subdivide(0.5)
    assert len(divisions) == 5
    assert divisions[0] == pt
    assert divisions[1] == Point2D(2, 2.5)
    assert divisions[2] == Point2D(2, 3)
    assert divisions[3] == Point2D(2, 3.5)
    assert divisions[4] == Point2D(2, 4)

    divisions = seg.subdivide([1, 0.5, 0.25])
    assert len(divisions) == 5
    assert divisions[0] == pt
    assert divisions[1] == Point2D(2, 3)
    assert divisions[2] == Point2D(2, 3.5)
    assert divisions[3] == Point2D(2, 3.75)
    assert divisions[4] == Point2D(2, 4)

    divisions = seg.subdivide_evenly(4)
    assert len(divisions) == 5
    assert divisions[0] == pt
    assert divisions[1] == Point2D(2, 2.5)
    assert divisions[2] == Point2D(2, 3)
    assert divisions[3] == Point2D(2, 3.5)
    assert divisions[4] == Point2D(2, 4)
Пример #5
0
def test_intersect_line_ray():
    """Test the LineSegment2D intersect_line_ray method."""
    pt_1 = Point2D(2, 2)
    vec_1 = Vector2D(0, 2)
    seg_1 = LineSegment2D(pt_1, vec_1)

    pt_2 = Point2D(0, 3)
    vec_2 = Vector2D(4, 0)
    seg_2 = LineSegment2D(pt_2, vec_2)

    pt_3 = Point2D(0, 0)
    vec_3 = Vector2D(1, 1)
    seg_3 = LineSegment2D(pt_3, vec_3)

    assert seg_1.intersect_line_ray(seg_2) == Point2D(2, 3)
    assert seg_1.intersect_line_ray(seg_3) is None
Пример #6
0
def test_reflect():
    """Test the LineSegment2D reflect method."""
    pt = Point2D(2, 2)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)

    origin_1 = Point2D(0, 1)
    origin_2 = Point2D(1, 1)
    normal_1 = Vector2D(0, 1)
    normal_2 = Vector2D(-1, 1).normalize()

    assert seg.reflect(normal_1, origin_1).p == Point2D(2, 0)
    assert seg.reflect(normal_1, origin_1).v == Vector2D(0, -2)
    assert seg.reflect(normal_1, origin_2).p == Point2D(2, 0)
    assert seg.reflect(normal_1, origin_2).v == Vector2D(0, -2)

    test_1 = seg.reflect(normal_2, origin_2)
    assert test_1.p == Point2D(2, 2)
    assert test_1.v.x == pytest.approx(2, rel=1e-3)
    assert test_1.v.y == pytest.approx(0, rel=1e-3)

    test_2 = seg.reflect(normal_2, origin_1)
    assert test_2.p.x == pytest.approx(1, rel=1e-3)
    assert test_2.p.y == pytest.approx(3, rel=1e-3)
    assert test_1.v.x == pytest.approx(2, rel=1e-3)
    assert test_1.v.y == pytest.approx(0, rel=1e-3)
Пример #7
0
def test_linesegment2_to_from_dict():
    """Test the to/from dict of LineSegment2D objects."""
    pt = Point2D(2, 0)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)
    seg_dict = seg.to_dict()
    new_seg = LineSegment2D.from_dict(seg_dict)
    assert isinstance(new_seg, LineSegment2D)
    assert new_seg.to_dict() == seg_dict
Пример #8
0
    def custom_hour_lines2d(self, hour_labels):
        """Get a list of LineSegment2D for a list of numbers representing hour labels.

        Args:
            hour_labels: An array of numbers from 0 to 24 representing the hours
                to display. (eg. [0, 3, 6, 9, 12, 15, 18, 21, 24])
        """
        _hour_points, _hour_text = self._compute_hour_line_pts(hour_labels)
        vec = Vector2D(self._num_x * self._x_dim)
        return [LineSegment2D(pt, vec) for pt in _hour_points]
Пример #9
0
def test_scale_world_origin():
    """Test the LineSegment2D scale method with None origin."""
    pt = Point2D(2, 2)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)

    new_seg = seg.scale(2)
    assert new_seg.p == Point2D(4, 4)
    assert new_seg.v == Point2D(0, 4)
    assert new_seg.length == 4
Пример #10
0
def test_closest_points_between_line():
    """Test the LineSegement2D distance_to_point method."""
    pt_1 = Point2D(2, 2)
    vec_1 = Vector2D(0, 2)
    seg_1 = LineSegment2D(pt_1, vec_1)

    pt_2 = Point2D(0, 3)
    vec_2 = Vector2D(1, 0)
    seg_2 = LineSegment2D(pt_2, vec_2)

    pt_3 = Point2D(0, 0)
    vec_3 = Vector2D(1, 1)
    seg_3 = LineSegment2D(pt_3, vec_3)

    assert seg_1.closest_points_between_line(seg_2) == (Point2D(2, 3), Point2D(1, 3))
    assert seg_1.closest_points_between_line(seg_3) == (Point2D(2, 2), Point2D(1, 1))

    assert seg_1.distance_to_line(seg_2) == 1
    assert seg_1.distance_to_line(seg_3) == pytest.approx(1.41421, rel=1e-3)
Пример #11
0
def test_equivalent():
    """Testing the equivalence of LineSegment2D objects."""
    seg1 = LineSegment2D(Point2D(0.5, 0.5), Vector2D(1.5, 2.5))
    # LineSegment2D (<0.50, 0.50> to <2.00, 3.00>)

    # Test equal seg1, same order
    seg2 = LineSegment2D(Point2D(0.5, 0.5), Vector2D(1.5, 2.5))
    assert seg1.is_equivalent(seg2, 1e-10)

    # Test equal, diff order
    seg2 = LineSegment2D(Point2D(2.00, 3.00), Vector2D(-1.5, -2.5))
    assert seg1.is_equivalent(seg2, 1e-10)

    # Test not equal first point
    seg2 = LineSegment2D(Point2D(2.001, 3.00), Vector2D(-1.5, -2.5))
    assert not seg1.is_equivalent(seg2, 1e-10)

    # Test not equal second point
    seg2 = LineSegment2D(Point2D(0.5001, 0.5), Vector2D(1.5, 2.5))
    assert not seg1.is_equivalent(seg2, 1e-10)
Пример #12
0
def test_distance_to_point():
    """Test the LineSegment2D distance_to_point method."""
    pt = Point2D(2, 2)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)

    near_pt = Point2D(3, 3)
    assert seg.distance_to_point(near_pt) == 1
    near_pt = Point2D(2, 0)
    assert seg.distance_to_point(near_pt) == 2
    near_pt = Point2D(2, 5)
    assert seg.distance_to_point(near_pt) == 1
Пример #13
0
def test_closest_point():
    """Test the LineSegment2D closest_point method."""
    pt = Point2D(2, 2)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)

    near_pt = Point2D(3, 3)
    assert seg.closest_point(near_pt) == Point2D(2, 3)
    near_pt = Point2D(2, 0)
    assert seg.closest_point(near_pt) == Point2D(2, 2)
    near_pt = Point2D(2, 5)
    assert seg.closest_point(near_pt) == Point2D(2, 4)
Пример #14
0
def test_move():
    """Test the LineSegment2D move method."""
    pt = Point2D(2, 0)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)

    vec_1 = Vector2D(2, 2)
    new_seg = seg.move(vec_1)
    assert new_seg.p == Point2D(4, 2)
    assert new_seg.v == vec
    assert new_seg.p1 == Point2D(4, 2)
    assert new_seg.p2 == Point2D(4, 4)
def test_intersect_line_ray():
    """Test the Polygon2D intersect_line_ray method."""
    pts = (Point2D(0, 0), Point2D(2, 0), Point2D(2, 2), Point2D(0, 2))
    polygon = Polygon2D(pts)

    ray_1 = Ray2D(Point2D(-1, 1), Vector2D(1, 0))
    ray_2 = Ray2D(Point2D(1, 1), Vector2D(1, 0))
    ray_3 = Ray2D(Point2D(1, 1), Vector2D(11, 0))
    ray_4 = Ray2D(Point2D(-1, 1), Vector2D(-1, 0))

    assert len(polygon.intersect_line_ray(ray_1)) == 2
    assert len(polygon.intersect_line_ray(ray_2)) == 1
    assert len(polygon.intersect_line_ray(ray_3)) == 1
    assert len(polygon.intersect_line_ray(ray_4)) == 0

    line_1 = LineSegment2D(Point2D(-1, 1), Vector2D(0.5, 0))
    line_2 = LineSegment2D(Point2D(-1, 1), Vector2D(2, 0))
    line_3 = LineSegment2D(Point2D(-1, 1), Vector2D(3, 0))

    assert len(polygon.intersect_line_ray(line_1)) == 0
    assert len(polygon.intersect_line_ray(line_2)) == 1
    assert len(polygon.intersect_line_ray(line_3)) == 2
Пример #16
0
def test_scale():
    """Test the LineSegment2D scale method."""
    pt = Point2D(2, 2)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)

    origin_1 = Point2D(0, 2)
    origin_2 = Point2D(1, 1)
    new_seg = seg.scale(2, origin_1)
    assert new_seg.p == Point2D(4, 2)
    assert new_seg.v == Point2D(0, 4)
    assert new_seg.length == 4

    new_seg = seg.scale(2, origin_2)
    assert new_seg.p == Point2D(3, 3)
    assert new_seg.v == Point2D(0, 4)
Пример #17
0
def test_rotate():
    """Test the LineSegment2D rotate method."""
    pt = Point2D(2, 2)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)
    origin_1 = Point2D(0, 2)

    test_1 = seg.rotate(math.pi, origin_1)
    assert test_1.p.x == pytest.approx(-2, rel=1e-3)
    assert test_1.p.y == pytest.approx(2, rel=1e-3)
    assert test_1.v.x == pytest.approx(0, rel=1e-3)
    assert test_1.v.y == pytest.approx(-2, rel=1e-3)

    test_2 = seg.rotate(math.pi / 2, origin_1)
    assert test_2.p.x == pytest.approx(0, rel=1e-3)
    assert test_2.p.y == pytest.approx(4, rel=1e-3)
    assert test_2.v.x == pytest.approx(-2, rel=1e-3)
    assert test_2.v.y == pytest.approx(0, rel=1e-3)
Пример #18
0
def test_linesegment2_immutability():
    """Test the immutability of LineSegment2D objects."""
    pt = Point2D(2, 0)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)

    assert isinstance(seg, LineSegment2D)
    with pytest.raises(AttributeError):
        seg.p.x = 3
    with pytest.raises(AttributeError):
        seg.v.x = 3
    with pytest.raises(AttributeError):
        seg.p = Point2D(0, 0)
    with pytest.raises(AttributeError):
        seg.v = Vector2D(2, 2)

    seg_copy = seg.duplicate()
    assert seg.p == seg_copy.p
    assert seg.v == seg_copy.v
Пример #19
0
def test_linesegment2_init():
    """Test the initalization of LineSegment2D objects and basic properties."""
    pt = Point2D(2, 0)
    vec = Vector2D(0, 2)
    seg = LineSegment2D(pt, vec)
    str(seg)  # test the string representation of the line segment

    assert seg.p == Point2D(2, 0)
    assert seg.v == Vector2D(0, 2)
    assert seg.p1 == Point2D(2, 0)
    assert seg.p2 == Point2D(2, 2)
    assert seg.midpoint == Point2D(2, 1)
    assert seg.point_at(0.25) == Point2D(2, 0.5)
    assert seg.point_at_length(1) == Point2D(2, 1)
    assert seg.length == 2

    flip_seg = seg.flip()
    assert flip_seg.p == Point2D(2, 2)
    assert flip_seg.v == Vector2D(0, -2)
Пример #20
0
 def month_lines2d(self):
     """Get a list of LineSegment2D for the month intervals of the chart."""
     if not self._month_points:
         self._compute_month_line_pts()
     vec = Vector2D(0, self._num_y * self._y_dim)
     return [LineSegment2D(pt, vec) for pt in self._month_points]
Пример #21
0
 def hour_lines2d(self):
     """Get a list of LineSegment2D for the 6-hour intervals of the chart."""
     if not self._hour_points:
         self._compute_static_hour_line_pts()
     vec = Vector2D(self._num_x * self._x_dim)
     return [LineSegment2D(pt, vec) for pt in self._hour_points]
Пример #22
0
    def next_event(self):
        """ Computes the event (change to edge) associated with each polygon vertex.

        Reflex vertices can result in split or edge events, while non-reflex vertices
        will result in only edge events.

        Returns:
            EdgeEvent associated with self.
        """
        events = []
        if self.is_reflex:
            # a reflex vertex may generate a split event
            # split events happen when a vertex hits an opposite edge,
            # splitting the polygon in two.
            log.debug("looking for split candidates for vertex %s", self)
            for edge in self.original_edges:
                if (edge.edge.is_equivalent(self.edge_left, self.tol)
                        or edge.edge.is_equivalent(self.edge_right, self.tol)):
                    continue

                log.debug('\tconsidering EDGE %s', edge)

                # A potential b is at the intersection of between our own bisector and
                # the bisector of the angle between the tested edge and any one of our
                # own edges.

                # We choose the 'less parallel' edge (in order to exclude a
                # potentially parallel edge)

                # Make normalized copies of vectors
                norm_edge_left_v = self.edge_left.v.normalize()
                norm_edge_right_v = self.edge_right.v.normalize()
                norm_edge_v = edge.edge.v.normalize()

                # Compute dot
                leftdot = abs(norm_edge_left_v.dot(norm_edge_v))
                rightdot = abs(norm_edge_right_v.dot(norm_edge_v))
                selfedge = self.edge_left if leftdot < rightdot else self.edge_right
                # otheredge = self.edge_left if leftdot > rightdot else self.edge_right

                # Make copies of edges and compute intersection
                self_edge_copy = LineSegment2D(selfedge.p, selfedge.v)
                edge_edge_copy = LineSegment2D(edge.edge.p, edge.edge.v)
                # Ray line intersection
                i = intersection2d.intersect_line2d_infinite(
                    edge_edge_copy, self_edge_copy)

                if (i is not None) and (not i.is_equivalent(
                        self.point, self.tol)):
                    # locate candidate b
                    linvec = (self.point - i).normalize()
                    edvec = edge.edge.v.normalize()
                    if linvec.dot(edvec) < 0:
                        edvec = -edvec

                    bisecvec = edvec + linvec
                    if abs(bisecvec.magnitude) < self.tol:
                        continue
                    bisector = LineSegment2D(i, bisecvec)
                    b = intersection2d.intersect_line2d(
                        self.bisector, bisector)
                    if b is None:
                        continue

                    # check eligibility of b
                    # a valid b should lie within the area limited by the edge and the
                    # bisectors of its two vertices:
                    _left_bisector_norm = edge.bisector_left.v.normalize()
                    _left_to_b_norm = (b - edge.bisector_left.p).normalize()
                    xleft = _left_bisector_norm.determinant(
                        _left_to_b_norm) > 0

                    _right_bisector_norm = edge.bisector_right.v.normalize()
                    _right_to_b_norm = (b - edge.bisector_right.p).normalize()
                    xright = _right_bisector_norm.determinant(
                        _right_to_b_norm) < 0

                    _edge_edge_norm = edge.edge.v.normalize()
                    _b_to_edge_norm = (b - edge.edge.p).normalize()
                    xedge = _edge_edge_norm.determinant(_b_to_edge_norm) < 0

                    if not (xleft and xright and xedge):
                        log.debug('\t\tDiscarded candidate %s (%s-%s-%s)', b,
                                  xleft, xright, xedge)
                        continue

                    log.debug('\t\tFound valid candidate %s', b)
                    _dist_line_to_b = LineSegment2D(
                        edge.edge.p, edge.edge.v).distance_to_point(b)
                    if _dist_line_to_b < self.tol:
                        _dist_line_to_b = 0.0
                    _new_split_event = _SplitEvent(_dist_line_to_b, b, self,
                                                   edge.edge)
                    events.append(_new_split_event)

        # Intersect line2d with line2d (does not assume lines are infinite)
        i_prev = intersection2d.intersect_line2d_infinite(
            self.prev.bisector, self.bisector)
        i_next = intersection2d.intersect_line2d_infinite(
            self.next.bisector, self.bisector)
        # Make EdgeEvent and append to events
        if i_prev is not None:
            dist_to_i_prev = LineSegment2D(
                self.edge_left.p.duplicate(),
                self.edge_left.v.duplicate()).distance_to_point(i_prev)
            if dist_to_i_prev < self.tol:
                dist_to_i_prev = 0.0
            events.append(_EdgeEvent(dist_to_i_prev, i_prev, self.prev, self))

        if i_next is not None:
            dist_to_i_next = LineSegment2D(
                self.edge_right.p.duplicate(),
                self.edge_right.v.duplicate()).distance_to_point(i_next)
            if dist_to_i_next < self.tol:
                dist_to_i_next = 0.0
            events.append(_EdgeEvent(dist_to_i_next, i_next, self, self.next))

        if not events:
            return None

        ev = min(events,
                 key=lambda event: self.point.distance_to_point(
                     event.intersection_point))

        log.info('Generated new event for %s: %s', self, ev)
        return ev
Пример #23
0
 def y_axis_lines(self):
     """Get a list of LineSegment2D for the Y-axis values of the chart."""
     if not self._y_axis_points:
         self._compute_y_axis_points()
     vec = Vector2D(len(self._months_int) * self._x_dim)
     return [LineSegment2D(pt, vec) for pt in self._y_axis_points]