# Path: geomeppy/geom/segments.py
# class Segment(object):
#     """Line segment in 3D."""
# 
#     def __init__(self, *vertices):
#         # type: (*Vector3D) -> None
#         self.vertices = vertices
#         self.p1 = vertices[0]
#         self.p2 = vertices[1]
# 
#     def __repr__(self):
#         # type: () -> str
#         class_name = type(self).__name__
#         return "{}({}, {})".format(class_name, self.p1, self.p2)
# 
#     def __neg__(self):
#         # type: () -> Segment
#         return Segment(self.p2, self.p1)
# 
#     def __iter__(self):
#         # type: () -> Iterator
#         return (i for i in self.vertices)
# 
#     def __eq__(self, other):
#         # type: (Any) -> bool
#         return self.__dict__ == other.__dict__
# 
#     def _is_collinear(self, other):
#         # type: (Segment) -> bool
#         """Test if a segment is collinear with another segment
# 
#         :param other: The other segment.
#         :return: True if the segments are collinear else False.
#         """
#         if almostequal(other, self) or almostequal(other, -self):
#             return True
#         a = self.p1 - other.p1
#         b = self.p1 - other.p2
#         angle_between = a.cross(b)
#         if almostequal(angle_between, Vector3D(0, 0, 0)):
#             return True
#         a = self.p2 - other.p1
#         b = self.p2 - other.p2
#         angle_between = a.cross(b)
#         if almostequal(angle_between, Vector3D(0, 0, 0)):
#             return True
#         return False
# 
#     def _on_poly_edge(self, poly):
#         # type: (Polygon3D) -> bool
#         """Test if segment lies on any edge of a polygon
# 
#         :param poly: The polygon to test against.
#         :returns: True if segment lies on any edge of the polygon, else False.
#         """
#         for edge in poly.edges:
#             if self._is_collinear(edge):
#                 return True
#         return False
# 
# Path: geomeppy/geom/vectors.py
# class Vector3D(Vector2D):
#     """Three dimensional point."""
# 
#     def __init__(
#         self,
#         x,  # type: Union[float, np.float64]
#         y,  # type: Union[float, np.float64]
#         z=0,  # type: Union[float, np.float64]
#     ):
#         # type: (...) -> None
#         super(Vector3D, self).__init__(x, y, z)
#         self.z = float(z)
#         self.args = [self.x, self.y, self.z]
# 
#     def __repr__(self):
#         # type: () -> str
#         class_name = type(self).__name__
#         return "{}({!r}, {!r}, {!r})".format(class_name, *self.args)
# 
#     def __hash__(self):
#         # type: () -> int
#         return hash(self.x) ^ hash(self.y) ^ hash(self.z)


from geomeppy.geom.segments import Segment
from geomeppy.geom.vectors import Vector3D
"""Tests for Segment class, representing a line segment."""


def test_segment_repr():
    # type: () -> None
    edge = Segment(Vector3D(0, 0, 0), Vector3D(2, 0, 0))
    assert eval(repr(edge)) == edge


def test_collinear():
    # type: () -> None
    # same line
    edge1 = Segment(Vector3D(0, 0, 0), Vector3D(1, 1, 1))
    edge2 = Segment(Vector3D(0, 0, 0), Vector3D(1, 1, 1))
    assert edge1._is_collinear(edge2)

    # opposite direction line
    edge1 = Segment(Vector3D(1, 1, 1), Vector3D(0, 0, 0))
    edge2 = Segment(Vector3D(0, 0, 0), Vector3D(1, 1, 1))
    assert edge1._is_collinear(edge2)

    # edge1 is longer
    edge1 = Segment(Vector3D(0, 0, 0), Vector3D(4, 4, 4))
    edge2 = Segment(Vector3D(1, 1, 1), Vector3D(2, 2, 2))
    assert edge1._is_collinear(edge2)

    # same start point, different lengths
    edge1 = Segment(Vector3D(0, 0, 0), Vector3D(1, 1, 1))

# Path: geomeppy/geom/segments.py
# class Segment(object):
#     """Line segment in 3D."""
# 
#     def __init__(self, *vertices):
#         # type: (*Vector3D) -> None
#         self.vertices = vertices
#         self.p1 = vertices[0]
#         self.p2 = vertices[1]
# 
#     def __repr__(self):
#         # type: () -> str
#         class_name = type(self).__name__
#         return "{}({}, {})".format(class_name, self.p1, self.p2)
# 
#     def __neg__(self):
#         # type: () -> Segment
#         return Segment(self.p2, self.p1)
# 
#     def __iter__(self):
#         # type: () -> Iterator
#         return (i for i in self.vertices)
# 
#     def __eq__(self, other):
#         # type: (Any) -> bool
#         return self.__dict__ == other.__dict__
# 
#     def _is_collinear(self, other):
#         # type: (Segment) -> bool
#         """Test if a segment is collinear with another segment
# 
#         :param other: The other segment.
#         :return: True if the segments are collinear else False.
#         """
#         if almostequal(other, self) or almostequal(other, -self):
#             return True
#         a = self.p1 - other.p1
#         b = self.p1 - other.p2
#         angle_between = a.cross(b)
#         if almostequal(angle_between, Vector3D(0, 0, 0)):
#             return True
#         a = self.p2 - other.p1
#         b = self.p2 - other.p2
#         angle_between = a.cross(b)
#         if almostequal(angle_between, Vector3D(0, 0, 0)):
#             return True
#         return False
# 
#     def _on_poly_edge(self, poly):
#         # type: (Polygon3D) -> bool
#         """Test if segment lies on any edge of a polygon
# 
#         :param poly: The polygon to test against.
#         :returns: True if segment lies on any edge of the polygon, else False.
#         """
#         for edge in poly.edges:
#             if self._is_collinear(edge):
#                 return True
#         return False
# 
# Path: geomeppy/geom/vectors.py
# class Vector3D(Vector2D):
#     """Three dimensional point."""
# 
#     def __init__(
#         self,
#         x,  # type: Union[float, np.float64]
#         y,  # type: Union[float, np.float64]
#         z=0,  # type: Union[float, np.float64]
#     ):
#         # type: (...) -> None
#         super(Vector3D, self).__init__(x, y, z)
#         self.z = float(z)
#         self.args = [self.x, self.y, self.z]
# 
#     def __repr__(self):
#         # type: () -> str
#         class_name = type(self).__name__
#         return "{}({!r}, {!r}, {!r})".format(class_name, *self.args)
# 
#     def __hash__(self):
#         # type: () -> int
#         return hash(self.x) ^ hash(self.y) ^ hash(self.z)


# Path: tests/test_segments.py
from geomeppy.geom.segments import Segment
from geomeppy.geom.vectors import Vector3D

"""Tests for Segment class, representing a line segment."""


def test_segment_repr():
    # type: () -> None
    edge = Segment(Vector3D(0, 0, 0), Vector3D(2, 0, 0))
    assert eval(repr(edge)) == edge


def test_collinear():
    # type: () -> None
    # same line
    edge1 = Segment(Vector3D(0, 0, 0), Vector3D(1, 1, 1))
    edge2 = Segment(Vector3D(0, 0, 0), Vector3D(1, 1, 1))
    assert edge1._is_collinear(edge2)

    # opposite direction line
    edge1 = Segment(Vector3D(1, 1, 1), Vector3D(0, 0, 0))
    edge2 = Segment(Vector3D(0, 0, 0), Vector3D(1, 1, 1))
    assert edge1._is_collinear(edge2)

    # edge1 is longer
    edge1 = Segment(Vector3D(0, 0, 0), Vector3D(4, 4, 4))
    edge2 = Segment(Vector3D(1, 1, 1), Vector3D(2, 2, 2))
    assert edge1._is_collinear(edge2)

    # same start point, different lengths
    edge1 = Segment(Vector3D(0, 0, 0), Vector3D(1, 1, 1))

    edge2 = Segment(Vector3D(0, 0, 0), Vector3D(2, 2, 2))