# Path: geomeppy/geom/polygons.py
# class Polygon(Clipper2D, MutableSequence):
# class Polygon2D(Polygon):
# class Polygon3D(Clipper3D, Polygon):
#     def n_dims(self):
#     def vector_class(self):
#     def normal_vector(self):
#     def __init__(self, vertices):
#     def __repr__(self):
#     def __len__(self):
#     def __delitem__(self, key):
#     def __getitem__(self, key):
#     def __setitem__(self, key, value):
#     def __add__(self, other):  # type: (Polygon) -> Union[None, Polygon]
#     def __sub__(self, other):
#     def insert(self, key, value):
#     def area(self):
#     def bounding_box(self):
#     def buffer(self, distance=None, join_style=2):
#     def centroid(self):
#     def edges(self):
#     def invert_orientation(self):
#     def is_convex(self):
#     def points_matrix(self):
#     def vertices_list(self):
#     def xs(self):
#     def ys(self):
#     def zs(self):
#     def __eq__(self, other):
#     def normal_vector(self):
#     def project_to_3D(self, example3d):
#     def zs(self):
#     def __eq__(self, other):
#     def zs(self):
#     def normal_vector(self):
#     def distance(self):
#     def projection_axis(self):
#     def is_horizontal(self):
#     def is_clockwise(self, viewpoint):
#     def is_coplanar(self, other):
#     def outside_point(self, entry_direction="counterclockwise"):
#     def order_points(self, starting_position):
#     def project_to_2D(self):
#     def normalize_coords(self, ggr):
#     def from_wkt(self, wkt_poly):
# def break_polygons(poly, hole):
# def section(first, last, coords):
# def project(pt, proj_axis):
# def project_inv(
#     pt, proj_axis, a, v
# ):  # type: (np.ndarray, int, np.float64, Vector3D) -> Any
# def project_to_2D(vertices, proj_axis):
# def project_to_3D(
#     vertices, proj_axis, a, v
# ):  # type: (np.ndarray, int, np.float64, Vector3D) -> List[Tuple[np.float64, np.float64, np.float64]]
# def normalize_coords(
#     poly, outside_pt, ggr=None
# ):  # type: (Polygon3D, Vector3D, Union[List, None, Idf_MSequence]) -> Polygon3D
# def set_entry_direction(poly, outside_pt, ggr=None):
# def set_starting_position(poly, ggr=None):
# def intersect(poly1, poly2):
# def is_hole(surface, possible_hole):
# def bounding_box(polygons):
# def is_convex_polygon(polygon):  # noqa
# 
# 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/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 geomeppy.geom.polygons import (
    break_polygons,
    Polygon2D,
    Polygon3D,
    Vector2D,
    Vector3D,
)
from geomeppy.geom.segments import Segment
from geomeppy.utilities import almostequal
"""Tests for polygons."""


def test_polygon_repr():
    # type: () -> None
    s2D = Polygon2D([(0, 0), (2, 0), (2, 0), (0, 0)])  # vertical
    assert eval(repr(s2D)) == s2D


# Path: geomeppy/geom/polygons.py
# class Polygon(Clipper2D, MutableSequence):
# class Polygon2D(Polygon):
# class Polygon3D(Clipper3D, Polygon):
#     def n_dims(self):
#     def vector_class(self):
#     def normal_vector(self):
#     def __init__(self, vertices):
#     def __repr__(self):
#     def __len__(self):
#     def __delitem__(self, key):
#     def __getitem__(self, key):
#     def __setitem__(self, key, value):
#     def __add__(self, other):  # type: (Polygon) -> Union[None, Polygon]
#     def __sub__(self, other):
#     def insert(self, key, value):
#     def area(self):
#     def bounding_box(self):
#     def buffer(self, distance=None, join_style=2):
#     def centroid(self):
#     def edges(self):
#     def invert_orientation(self):
#     def is_convex(self):
#     def points_matrix(self):
#     def vertices_list(self):
#     def xs(self):
#     def ys(self):
#     def zs(self):
#     def __eq__(self, other):
#     def normal_vector(self):
#     def project_to_3D(self, example3d):
#     def zs(self):
#     def __eq__(self, other):
#     def zs(self):
#     def normal_vector(self):
#     def distance(self):
#     def projection_axis(self):
#     def is_horizontal(self):
#     def is_clockwise(self, viewpoint):
#     def is_coplanar(self, other):
#     def outside_point(self, entry_direction="counterclockwise"):
#     def order_points(self, starting_position):
#     def project_to_2D(self):
#     def normalize_coords(self, ggr):
#     def from_wkt(self, wkt_poly):
# def break_polygons(poly, hole):
# def section(first, last, coords):
# def project(pt, proj_axis):
# def project_inv(
#     pt, proj_axis, a, v
# ):  # type: (np.ndarray, int, np.float64, Vector3D) -> Any
# def project_to_2D(vertices, proj_axis):
# def project_to_3D(
#     vertices, proj_axis, a, v
# ):  # type: (np.ndarray, int, np.float64, Vector3D) -> List[Tuple[np.float64, np.float64, np.float64]]
# def normalize_coords(
#     poly, outside_pt, ggr=None
# ):  # type: (Polygon3D, Vector3D, Union[List, None, Idf_MSequence]) -> Polygon3D
# def set_entry_direction(poly, outside_pt, ggr=None):
# def set_starting_position(poly, ggr=None):
# def intersect(poly1, poly2):
# def is_hole(surface, possible_hole):
# def bounding_box(polygons):
# def is_convex_polygon(polygon):  # noqa
# 
# 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/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: tests/test_polygons.py
from geomeppy.geom.polygons import (
    break_polygons,
    Polygon2D,
    Polygon3D,
    Vector2D,
    Vector3D,
)
from geomeppy.geom.segments import Segment
from geomeppy.utilities import almostequal

"""Tests for polygons."""


def test_polygon_repr():
    # type: () -> None
    s2D = Polygon2D([(0, 0), (2, 0), (2, 0), (0, 0)])  # vertical
    assert eval(repr(s2D)) == s2D


    s3D = Polygon3D([(0, 0, 0), (2, 0, 0), (2, 2, 0), (0, 2, 0)])  # vertical