# 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: geomeppy/utilities.py
# def almostequal(first, second, places=7):
#     # type: (Any, Any, int) -> bool
#     """Tests a range of types for near equality."""
#     try:
#         # try converting to float first
#         first = float(first)
#         second = float(second)
#         # test floats for near-equality
#         if round(abs(second - first), places) != 0:
#             return False
#         else:
#             return True
#     except ValueError:
#         # handle non-float types
#         return str(first) == str(second)
#     except TypeError:
#         # handle iterables
#         return all([almostequal(a, b, places) for a, b in zip(first, second)])


from typing import Any, Iterator  # noqa
from .vectors import Vector3D
from ..utilities import almostequal
    from .polygons import Polygon3D  # noqa
    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.
        """

# 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: geomeppy/utilities.py
# def almostequal(first, second, places=7):
#     # type: (Any, Any, int) -> bool
#     """Tests a range of types for near equality."""
#     try:
#         # try converting to float first
#         first = float(first)
#         second = float(second)
#         # test floats for near-equality
#         if round(abs(second - first), places) != 0:
#             return False
#         else:
#             return True
#     except ValueError:
#         # handle non-float types
#         return str(first) == str(second)
#     except TypeError:
#         # handle iterables
#         return all([almostequal(a, b, places) for a, b in zip(first, second)])


# Path: geomeppy/geom/segments.py
from typing import Any, Iterator  # noqa
from .vectors import Vector3D
from ..utilities import almostequal
    from .polygons import Polygon3D  # noqa

    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):