def test_make_simple() -> None:
    """
        Tests if Polygon class method make_simple works correctly.
    """
    polygon_1 = Polygon([
        Point(1, 1),
        Point(5, 6),
        Point(5, 3),
        Point(2, 5),
        Point(4, 8),
        Point(2, 3),
        Point(4, 1),
        Point(3, 4)
    ])

    simple = Polygon([
        Point(4, 1),
        Point(5, 3),
        Point(5, 6),
        Point(3, 4),
        Point(2, 3),
        Point(4, 8),
        Point(2, 5),
        Point(1, 1)
    ])

    polygon_1.make_simple()

    assert simple == polygon_1
def test_make_convex() -> None:
    """
        Tests if Polygon class method make_convex works correctly.
    """
    polygon = Polygon([
        Point(1, 1),
        Point(5, 6),
        Point(5, 3),
        Point(2, 5),
        Point(4, 8),
        Point(2, 3),
        Point(4, 1),
        Point(3, 4)
    ])

    convex = Polygon([
        Point(1, 1),
        Point(4, 1),
        Point(5, 3),
        Point(5, 6),
        Point(4, 8),
        Point(2, 5)
    ])

    polygon.make_convex_hull()

    assert convex == polygon
Exemple #3
0
def flip_edge(triangulation: Triangulation, edge: LineSegment) -> None:
    """
    If edge is illegal, replaces it with its pair and recursivly flips
    neighboring edges if they need flipping, else leaves this as they are.

    Args:
        triangulation: Current triangulation.
        edge: Potential illegal edge.

    """
    pair, faces = find_pair_edge(triangulation, edge)

    quad = Polygon([edge.first, pair.first, edge.second])
    quad.make_simple()
    quad.points.append(pair.second)

    if not empty_circle(quad) and len(faces) == 2:
        triangulation.remove(faces[0])
        triangulation.remove(faces[1])
        triangulation.add(Triangle(pair.first, pair.second, edge.first))
        triangulation.add(Triangle(pair.first, pair.second, edge.second))

        for triangle in faces:
            for _edge in triangle.get_sides():
                if not _edge.is_equal_undirected(pair) and \
                        not _edge.is_equal_undirected(edge):
                    flip_edge(triangulation, _edge)
Exemple #4
0
def contains_point() -> None:
    polygon = Polygon(points[0: len(points) - 1])
    polygon.draw(canvas)
    if polygon.does_contain(points[-1]):
        messagebox.showinfo("Result", "Point is INSIDE polygon")
    else:
        messagebox.showinfo("Result", "Point is OUTSIDE polygon")
Exemple #5
0
def is_convex() -> None:
    polygon = Polygon(points)
    polygon.draw(canvas)
    if polygon.is_convex():
        messagebox.showinfo("Result", "Polygon IS convex")
    else:
        messagebox.showinfo("Result", "Polygon IS NOT convex")
Exemple #6
0
def test_pick_start_segment() -> None:
    """
    Tests if pick_start_segment works correctly. One common and one edge case.
    """

    hex_1 = Polygon([
        Point(0, 0),
        Point(1, -1),
        Point(2, 0),
        Point(2, 1),
        Point(1, 2),
        Point(0, 1)
    ])

    hex_2 = Polygon([
        Point(0, 0),
        Point(1, 0),
        Point(2, 0),
        Point(2, 1),
        Point(1, 2),
        Point(0, 1)
    ])

    assert pick_start_segment(hex_1) == LineSegment(Point(0, 0), Point(1, -1))
    assert pick_start_segment(hex_2) == LineSegment(Point(2, 0), Point(2, 1))
def triangulate(polygon: Polygon, parent: Node) -> Node:
    """
    Performs recursive triangulation of a polygon. Incomplete triangulations
    are put in tree that has parent as root. Complete triangulations are leaf
    nodes of that tree.

    Args:
        polygon: Polygon that will be triangulated.
        parent: Root of tree that will contain triangulations

    Returns: Leaf nodes if polygon is actually triangle.
    """
    if len(polygon.points) == 3:
        child = Node(extend_triangulation(parent, polygon.points[:3]))
        parent.add_child(child)

        return child

    segment = pick_start_segment(polygon)
    polygon.points = rearrange_points(segment, polygon)

    for point in polygon.points[2:]:
        first_triangle = Triangle(segment.first, segment.second, point)

        remainders = polygon_remainders(first_triangle, polygon)
        sub_root = triangulate(Polygon([segment.first, segment.second, point]),
                               parent)
        triangulate(remainders[0], sub_root)

        if remainders[1]:
            second_remainder_root = Node([])
            triangulate(remainders[1], second_remainder_root)

            merge_triangulations(sub_root, second_remainder_root)
def test_empty_circle() -> None:
    """ Tests if empty_circle method works correctly. """

    a, b, c, d = [Point(4, 3), Point(-1, 2), Point(1, 1), Point(2, 1)]

    poly = Polygon([a, b, c])
    poly.make_simple()
    poly.points.append(d)

    assert empty_circle(poly)
def all_triangulations(polygon: Polygon) -> List[List[Triangle]]:
    """
    Wrapper function for recursive "triangulate" function.
    
    Args:
        polygon: Polygon that will be triangulated.

    Returns:
        List of all possible triangulations of this polygon.
    """
    polygon.make_simple()
    tree = Tree(Node([]))
    triangulate(polygon, tree.root)

    return [node.data for node in tree.get_leaf_nodes()]
def test_delaunay_triangulation() -> None:
    """ Tests if delaunay_triangulation method works correctly. """

    a, b, c, d = [Point(4, 3), Point(-1, 2), Point(1, 1), Point(2, 1)]
    polygon = Polygon([a, b, c, d])
    triangulation = delaunay_triangulation(polygon)
    assert triangulation.triangles == [Triangle(c, a, d), Triangle(c, a, b)]
 def from_tuples(self, *args):
     vertices = []
     for arg in args:
         vertices.append(arg)
     if not self.__validate_vlist(vertices):
         raise ValueError()
     return Polygon(vertices)
Exemple #12
0
class DecoratedPolygon:
    def __init__(self, vlist):
        corrected_vlist = self.__correct(vlist)
        self.polygon = Polygon(corrected_vlist)

    @property
    def vlist(self):
        return self.polygon.vlist

    def area(self):
        return self.polygon.area()

    def set_areaAlg(self, alg):
        self.polygon.set_areaAlg(alg)

    def __correct(self, vlist):
        new_vlist = vlist
        if new_vlist[-1] != new_vlist[0]:
            new_vlist.append(new_vlist[0])
        return new_vlist
def test_orientation() -> None:
    """
        Tests if Polygon class method orientation works correctly.
    """
    polygon_1 = Polygon([
        Point(1, 1),
        Point(5, 6),
        Point(5, 3),
        Point(2, 5),
        Point(4, 8),
        Point(2, 3),
        Point(4, 1),
        Point(3, 4)
    ])

    polygon_2 = Polygon([
        Point(1, 1),
        Point(2, 3),
        Point(2, 5),
        Point(5, 3),
        Point(4, 8),
        Point(5, 6),
        Point(4, 1),
        Point(3, 4)
    ])

    assert polygon_1.orientation() == 1
    assert polygon_2.orientation() == -1
def test_number_of_intersections() -> None:
    """
        Tests if Polygon class method number_of_intersections works correctly.
    """
    line_segment_intersect = LineSegment(first=Point(0, 0),
                                         second=Point(10, 10))
    line_segment_no_intersect = LineSegment(first=Point(0, 0),
                                            second=Point(-10, -10))

    polygon = Polygon([
        Point(1, 1),
        Point(5, 6),
        Point(5, 3),
        Point(2, 5),
        Point(4, 8),
        Point(2, 3),
        Point(4, 1),
        Point(3, 4)
    ])

    assert polygon.intersection_count(line_segment_intersect) == (6, False)
    assert polygon.intersection_count(line_segment_no_intersect) == (0, False)
def polygon_remainders(triangle: Triangle, polygon: Polygon) -> List[Polygon]:
    """
    From a given polygon, and a triangle within it, creates smaller remainder or
    two of them (depending on the position of the triangle within the polygon.)
    
    Args:
        triangle: Triangle object that lies within polygon.
        polygon: Convex polygon.

    Returns:
        One or two smaller polygon remainders.
    """
    diagonals = [
        segment for segment in triangle.get_sides()
        if polygon.has_diagonal(segment)
    ]

    if len(diagonals) == 1:
        remainder_points = list(polygon.points)
        triangle_points = triangle.get_points()

        for point in triangle_points:
            if not diagonals[0].does_contain(point):
                remainder_points.remove(point)

        return [Polygon(remainder_points), None]

    else:
        if diagonals[1].does_contain(diagonals[0].first):
            common_point = diagonals[0].first
        else:
            common_point = diagonals[0].second

        common_point_index = polygon.points.index(common_point)

        return [
            Polygon(polygon.points[1:common_point_index + 1]),
            Polygon([polygon.points[0]] + polygon.points[common_point_index:])
        ]
def test_is_empty() -> None:
    """
        Tests if Polygon class method is_empty works correctly.
        Two common and one edge case.
    """
    polygon = Polygon([
        Point(1, 1),
        Point(5, 6),
        Point(5, 3),
        Point(2, 5),
        Point(4, 8),
        Point(2, 3),
        Point(4, 1),
        Point(3, 4)
    ])

    no_points = []
    points_out = [Point(0, 0), Point(10, 10), Point(0, 6), Point(-1, 12)]
    points_in = [Point(0, 0), Point(4, 4), Point(0, 6), Point(-1, 12)]

    assert polygon.is_empty(no_points)
    assert polygon.is_empty(points_out)
    assert not polygon.is_empty(points_in)
def test_does_intersect() -> None:
    """
        Tests if Polygon class method does_intersect works correctly.
        Two common and one edge case.
    """
    polygon = Polygon([
        Point(1, 1),
        Point(5, 6),
        Point(5, 3),
        Point(2, 5),
        Point(4, 8),
        Point(2, 3),
        Point(4, 1),
        Point(3, 4)
    ])

    line_segment_intersect = LineSegment(Point(0, 2), Point(2, 2))
    line_segment_no_intersect = LineSegment(Point(0, 0), Point(-5, 2))
    line_segment_match = LineSegment(polygon.points[4], polygon.points[5])

    assert polygon.does_intersect(line_segment_intersect)
    assert not polygon.does_intersect(line_segment_no_intersect)
    assert polygon.does_intersect(line_segment_match)
def test_does_contain() -> None:
    """
        Tests if Polygon class method does_contain works correctly.
        Two common and one edge case.
    """
    polygon = Polygon([
        Point(1, 1),
        Point(5, 6),
        Point(5, 3),
        Point(2, 5),
        Point(4, 8),
        Point(2, 3),
        Point(4, 1),
        Point(3, 4)
    ])

    point_in = Point(4, 4)
    point_out = Point(0, 0)
    point_edge = Point(5, 3)

    assert polygon.does_contain(point_in)
    assert not polygon.does_contain(point_out)
    assert polygon.does_contain(point_edge)
Exemple #19
0
def delaunay_triangulation(polygon: Polygon) -> Triangulation:
    """
    Generates Delaunay triangulation from a given set of points.

    Args:
        polygon: Polygon object that contains list of points in 2D plane.

    Returns: Triangulation object containing list of triangles that form
             Delaunay triangulation of passed polygon.

    """
    polygon.make_simple()
    start_point = find_start_point(polygon.points)
    polygon.points = sort_other_points(polygon.points, start_point)

    first, second, third = polygon.points[:3]
    triangulation = Triangulation([Triangle(first, second, third)])

    for point in polygon.points[3:]:
        index = polygon.points.index(point)
        add_triangles(triangulation, point, polygon.points[:index])

    return triangulation
Exemple #20
0
def test_polygon_remainders() -> None:
    """
    Tests if polygon_remainders works correctly. Tests two possible cases.
    """

    hexagon = Polygon([
        Point(0, 0),
        Point(1, 0),
        Point(2, 0),
        Point(2, 1),
        Point(1, 2),
        Point(0, 1)
    ])

    triangle_1 = Triangle(Point(2, 0), Point(2, 1), Point(1, 2))
    triangle_2 = Triangle(Point(1, 0), Point(2, 0), Point(1, 2))

    remainders_1 = [
        Polygon(
            [Point(0, 0),
             Point(1, 0),
             Point(2, 0),
             Point(1, 2),
             Point(0, 1)]), None
    ]

    remainders_2 = [
        Polygon([Point(1, 0),
                 Point(2, 0),
                 Point(2, 1),
                 Point(1, 2)]),
        Polygon([Point(0, 0), Point(1, 2),
                 Point(0, 1)])
    ]

    assert polygon_remainders(triangle_1, hexagon) == remainders_1
    assert polygon_remainders(triangle_2, hexagon) == remainders_2
Exemple #21
0
def test_all_triangulations() -> None:
    """
    Tests if all_triangulations works correctly.
    """
    quad = Polygon([Point(0, 0), Point(1, -1), Point(2, 0), Point(2, 1)])

    all_triangs = [[
        Triangle(Point(1, -1), Point(2, 0), Point(2, 1)),
        Triangle(Point(1, -1), Point(2, 1), Point(0, 0))
    ],
                   [
                       Triangle(Point(1, -1), Point(2, 0), Point(0, 0)),
                       Triangle(Point(2, 0), Point(2, 1), Point(0, 0))
                   ]]

    assert all_triangulations(quad) == all_triangs
Exemple #22
0
def test_triangulate() -> None:
    """
    Tests if rearrange_points works correctly.
    """

    quad = Polygon([Point(0, 0), Point(1, -1), Point(2, 0), Point(2, 1)])
    root = Node([])
    triangulate(quad, root)

    triangulation_1 = [
        Triangle(Point(0, 0), Point(1, -1), Point(2, 0)),
        Triangle(Point(0, 0), Point(2, 0), Point(2, 1))
    ]
    triangulation_2 = [
        Triangle(Point(0, 0), Point(1, -1), Point(2, 1)),
        Triangle(Point(1, -1), Point(2, 0), Point(2, 1))
    ]

    assert Tree(root).get_leaf_nodes()[0].data == triangulation_1
    assert Tree(root).get_leaf_nodes()[1].data == triangulation_2
Exemple #23
0
def test_rearrange_points() -> None:
    """
    Tests if rearrange_points works correctly.
    """

    hexagon = Polygon([
        Point(0, 0),
        Point(1, -1),
        Point(2, 0),
        Point(2, 1),
        Point(1, 2),
        Point(0, 1)
    ])

    segment = LineSegment(Point(1, -1), Point(2, 0))

    assert rearrange_points(segment, hexagon) == [
        Point(1, -1),
        Point(2, 0),
        Point(2, 1),
        Point(1, 2),
        Point(0, 1),
        Point(0, 0)
    ]
def test_is_convex() -> None:
    """
        Tests if Polygon class method is_convex works correctly.
    """
    polygon = Polygon([
        Point(1, 1),
        Point(5, 6),
        Point(5, 3),
        Point(2, 5),
        Point(4, 8),
        Point(2, 3),
        Point(4, 1),
        Point(3, 4)
    ])

    convex = Polygon(
        [Point(1, 1),
         Point(3, 3),
         Point(0, 5),
         Point(-1, 4),
         Point(-1, 2)])

    assert not polygon.is_convex()
    assert convex.is_convex()
 def from_list(self, vlist):
     if self.__validate_vlist(vlist):
         return Polygon(vlist)
     else:
         raise ValueError()
Exemple #26
0
from db.dal import save_triangulations
from structures.point import Point
from structures.polygon import Polygon
from triangulations.triangulations import all_triangulations

_5gon = Polygon([Point(4, 2), Point(1, 0), Point(2, 4),
                 Point(0, 2), Point(3, 0)])

_6gon = Polygon([Point(0, 3), Point(3, 0), Point(3, 6),
                 Point(1, 1), Point(6, 2), Point(5, 4)])

_7gon = Polygon([Point(3, 1), Point(4, 6), Point(1, 1), Point(0, 4),
                 Point(2, 8), Point(2, 0), Point(0, 3), ])

_8gon = Polygon([Point(0, 0), Point(4, 4), Point(2, 3), Point(5, 2),
                 Point(0, 1), Point(1, 0), Point(4, 1), Point(5, 3)])

_9gon = Polygon([Point(0, 0), Point(4, 4), Point(2, 1), Point(3, 9),
                 Point(5, 5), Point(0, 3), Point(3, 2), Point(4, 8),
                 Point(1, 5)])

_10gon = Polygon([Point(1, 0), Point(5, 4), Point(2, 0), Point(3, 8),
                  Point(5, 3), Point(0, 3), Point(4, 2), Point(4, 6),
                  Point(0, 5), Point(1, 7)])

_11gon = Polygon([Point(1, 1), Point(5, 4), Point(2, 0), Point(3, 8),
                  Point(4, 1), Point(0, 3), Point(5, 3), Point(4, 6),
                  Point(0, 6), Point(2, 9), Point(1, 9)])

print("{}: {}".format(len(_5gon.points), len(all_triangulations(_5gon))))
print("{}: {}".format(len(_6gon.points), len(all_triangulations(_6gon))))
Exemple #27
0
        vertices = self._polygon.vlist
        area = 0.0
        for i in range(0, len(vertices) - 3):
            area += self.__calc_triang_area(vertices[i], vertices[i + 1],
                                            vertices[i + 2])
        return fabs(area)

    def __calc_triang_area(self, v1, v2, v3):
        l1 = (v2[0] - v1[0], v2[1] - v1[1])
        l2 = (v3[0] - v1[0], v3[1] - v1[1])
        cross = (0, 0, l1[0] * l2[1] - l1[1] * l2[0])
        area = sqrt(cross[0]**2 + cross[1]**2 + cross[2]**2) / 2
        return area


if __name__ == "__main__":
    # Making us some pretty triangle
    poly = Polygon([(0, 0), (0.866, 0.5), (1, 0)])

    # Wanna know its area. Bridge will call specific area function
    poly.set_areaAlg(OnlyTriangleAreaAlg(poly))
    print(poly.area())

    # Now it's some messed up non-convex polygon. Ouch
    poly = Polygon([(0, 0), (1, 0), (2, 1), (3, 4), (3, 5), (2, 2), (1, 2),
                    (0, 0)])

    # Need new algorithm for that
    poly.set_areaAlg(GeneralAreaAlg(poly))
    print(poly.area())
Exemple #28
0
def make_simple_polygon() -> None:
    polygon = Polygon(points)
    polygon.make_simple()
    polygon.draw(canvas)
Exemple #29
0
def make_convex_hull() -> None:
    polygon = Polygon(points)
    polygon.make_convex_hull()
    polygon.draw(canvas)
Exemple #30
0
def delaunay() -> None:
    polygon = Polygon(points)
    triangulation = delaunay_triangulation(polygon)
    for triangle in triangulation.triangles:
        triangle.draw(canvas)