Пример #1
0
class CanvasPolygon:
    def __init__(self, data):
        self.data = data
        # self.polygon
        # self.canvas
        if self.isValid():
            shapes = json.loads(self.data['_shapes'])
            for shape in shapes['objects']:
                if shape['type'] == 'image':
                    self.canvas = getCanvasSize(shape)
                if shape['type'] == 'rect':
                    self.polygon = Polygon(getRectangleCoordinates(shape))
                if shape['type'] == 'polygon':
                    self.polygon = Polygon(getPolygonPoints(shape))
    

    def scale(self, original_image):
        width, height = original_image.size
        exif = getExifDictionary(original_image)
        log.debug('exif data of the image is: %s',exif)
        orientation = exif['Orientation']
        # get orientation from EXIF data of the image
        log.debug('orientation is: %s',orientation)
        log.debug('polygon canvas %s and points %s before:',self.canvas,self.polygon.points)
        # orientation: 
        #   1 - top left (nothing),
        #   6 - top right (270), 
        #   3 - bottom left (180)
        #   8 - bottom right (90)
        canvas_width = self.canvas['width']
        canvas_height = self.canvas['height']
        if orientation == 1:
            log.debug('orientation is 1')
            self.polygon.points = self.polygon.points
            self.polygon.scale(1.0*width/self.canvas['width'],1.0*height/self.canvas['height'])
        elif orientation == 6:
            log.debug('orientation is 6')
            self.polygon.points = [{'x':p['y'],'y':self.canvas['height']-p['x']} for p in self.polygon.points]
            self.canvas['height'] = canvas_width
            self.canvas['width'] = canvas_height
            self.polygon.scale(1.0*height/self.canvas['width'],1.0*width/self.canvas['height'])
        elif orientation == 3:
            log.debug('orientation is 3')
            self.polygon.points = [{'x':self.canvas['height']-p['x'],'y':self.canvas['weight']-p['y']} for p in self.polygon.points]
            self.polygon.scale(1.0*width/self.canvas['width'],1.0*height/self.canvas['height'])
        elif orientation == 8:
            log.debug('orientation is 8')
            self.polygon.points = [{'x':self.canvas['weight']-p['y'],'y':p['x']} for p in self.polygon.points]
            self.canvas['height'] = canvas_width
            self.canvas['width'] = canvas_height
            self.polygon.scale(1.0*height/self.canvas['width'],1.0*width/self.canvas['height'])
        else:
            log.debug('orientation is different')
            self.polygon.scale(1.0*width/self.canvas['width'],1.0*height/self.canvas['height'])
        log.debug('polygon canvas %s and points %s after:',self.canvas,self.polygon.points)
    def isValid(self):
        if '_shapes' in self.data:
            return True
        else:
            return False
Пример #2
0
def main():
    sides = int(input("how many sides do you want? "))
    side_length = int(
        input("what do you want the length of the sides to be? "))
    poly = Polygon(sides, side_length)
    print(poly.get_area())

    print("Your polygon's apothem is " + str(poly.apothem))
    print("Your polygon's perimeter is " + str(poly.perimeter))
    print("Your polygon's area is " + str(poly.area))
Пример #3
0
 def __init__(self, data):
     self.data = data
     # self.polygon
     # self.canvas
     if self.isValid():
         shapes = json.loads(self.data['_shapes'])
         for shape in shapes['objects']:
             if shape['type'] == 'image':
                 self.canvas = getCanvasSize(shape)
             if shape['type'] == 'rect':
                 self.polygon = Polygon(getRectangleCoordinates(shape))
             if shape['type'] == 'polygon':
                 self.polygon = Polygon(getPolygonPoints(shape))
Пример #4
0
def triangulate(poly: Polygon, hole: Polygon = None) -> List[Triangle]:
    """
    Triangulates a polygon, potentially with a hole in it.  Uses naive O(n^2) 
    ear-clipping method.
    
    :param poly: polygon to be triangulated
    
    :param hole: hole in the polygon
    
    :return: list of triangles making up the polygon
    """
    if hole:
        poly = _remove_hole(poly, hole)

    n = poly.n
    curr_n = n
    pts = np.array(poly.pts)

    ears = {ear: [(ear - 1) % n, ear, (ear + 1) % n] for ear in poly.ears()}

    # Adjacency dict of points in poly
    adj = {i: ((i - 1) % n, (i + 1) % n) for i in range(n)}

    tris = list()
    while len(tris) < n - 2:
        # Pick a random ear, turn into triangle, and append it to triangulation
        b, ear = ears.popitem()
        tris.append(Triangle(pts[ear].tolist()))

        # Update connection of vertices adjacent to ear vertex
        a, b, c = ear
        adj[a] = (adj[a][0], c)
        adj[c] = (a, adj[c][1])

        # Update ear status of adjacent vertices
        ear_a = (adj[a][0], a, c)
        ear_c = (a, c, adj[c][1])
        if poly.is_ear(ear_a):
            ears[a] = list(ear_a)
        else:
            ears.pop(a, None)

        if poly.is_ear(ear_c):
            ears[c] = list(ear_c)
        else:
            ears.pop(c, None)

        curr_n -= 1

    return tris
Пример #5
0
def remove_point_triangulation(affected_triangles: List[Triangle], p: Point) -> Polygon:
    """
    Removes a point from affected triangles, return the resulting polygon that fills the gap.
    
    :param affected_triangles: list of the triangles containing the point to be removed
    
    :param p: point to be removed
    
    :return: polygon created by merging the affected triangles
    """

    # First we construct a dictionary that tells us adjacency of triangles
    boundaries = [set(tri.pts) for tri in affected_triangles]
    point2triangles = defaultdict(set)
    for i, bound in enumerate(boundaries):
        bound.remove(p)
        u, v = bound
        point2triangles[u].add(i)
        point2triangles[v].add(i)

    # Connect adjacent triangles, noting which point connects them
    graph = Graph()
    for u, (i, j) in point2triangles.items():
        graph.add_edge(i, j, point=u)

    # Walk around the triangles to get the new outer boundary
    # TODO: Remember to make this work.  DFS visits all nodes not all edges.  I think find_cycle works.
    #
    new_boundary = [
        graph.get_edge_data(i, j)["point"]
        for (i, j) in nx.find_cycle(graph)
        # for (i, j) in nx.dfs_edges(graph)
    ]

    return Polygon(new_boundary)
Пример #6
0
def _remove_hole(poly: Polygon, hole: Polygon) -> Polygon:
    """
    Removes hole from polygon by turning it into a single degenerate polygon 
    with a bridge edge connecting poly to interior hole 
    :param poly: 
    :param hole: 
    :return: 
    """
    possible_bridges = list(product(poly.pts, hole.pts))
    possible_bridges.sort(key=lambda b: utils.dist(*b))
    bridge = None
    for bridge in possible_bridges:
        if _seg_intersect_poly(bridge, poly):
            continue
        if _seg_intersect_poly(bridge, hole):
            continue

        break

    poly_pt, hole_pt = bridge

    # Roll back the poly points to go around polygon first, away from bridge
    poly_ix = poly.pts.index(poly_pt)
    poly_pts = list(np.roll(poly.pts, -poly_ix))

    # Reverse and roll the hole points because we must go around hole c.w. to
    # go around whole degenerate polygon ccw
    hole_pts = hole.pts[::-1]
    hole_ix = hole_pts.index(hole_pt)
    hole_pts = list(np.roll(hole_pts, -hole_ix))

    degenerate_pts = poly_pts + [poly_pt] + hole_pts + [hole_pt]
    return Polygon(degenerate_pts)
Пример #7
0
    def __init__(self, folder, name):
        """
        Opens the json file of the country, and either collects the polygons online,
        or loads them from a file if it exists.
        :param folder: folder containing the country
        :param name: Name of the country (no need to specify ".json"
        """
        self.folder = folder
        self.name = name

        # Now we load the variable self.polygons
        try:
            with open(self.folder + self.name + ".json", "r") as f:
                self.polygons = json.load(f)
            print('Loaded from file.')
        except FileNotFoundError:
            try:
                self.polygons = self.get_polygons()
                with open(folder + self.name + ".json", "w") as f:
                    json.dump(self.polygons, f)
                print('Successfully collected the map online, {} polygons.'.
                      format(len(self.polygons)))
                logger.info("{} has been found online.".format(self.name))
            except ValueError:
                print('Something went wrong with {}.'.format(self.name))
                logger.error("{} could not be found in OSM.".format(self.name))
                self.polygons = []

        self.polygons = [Polygon(p) for p in self.polygons]
        self.simplified = [a.array for a in self.polygons]
Пример #8
0
    def _preprocess(self, subdivision: List[Polygon], plot_layers=False):
        """
        If subdivision is not triangular, then triangulate each non-triangle region.
        Then place large triangle around region, and triangulate
        :param subdivision: 
        """
        logging.debug("Preprocessing planar subdivision")
        subdivision = triangle_graph(subdivision, self.digraph)

        logging.debug("Received triangulated subdivision")

        logging.debug("Constructing convex hull")
        all_pts = {p for tri in subdivision for p in tri.pts}
        hull = quickhull(list(all_pts))
        hull = Polygon(hull)

        logging.debug("Wrapping polygon in bounding triangle")
        bounding_tri, gap_triangles = wrap_triangle(hull)

        for tri in gap_triangles:
            self.digraph.add_node(tri, original=False)

        layer = subdivision + gap_triangles
        if plot_layers:
            drawing.plot_polygons(layer, 'k-')
            plt.savefig("layer0.png")
            plt.clf()

        logging.debug("Iterating over layers")
        i = 0
        while len(layer) > 1:
            logging.debug("Current layer size: %d" % len(layer))
            layer = next_layer(layer, bounding_tri, self.digraph)
            i += 1
            if plot_layers:
                drawing.plot_polygons(layer, 'k-')
                plt.savefig("layer%d.png" % i)
                plt.clf()

        logging.debug("Final layer size: %d" % len(layer))
        self.top_layer = layer
Пример #9
0
    """
    logging.info("Running timing tests on point location")
    size = 100000
    data = list()
    for i in range(min_pts, max_pts, inc):
        logging.info("Performing tests on %d points" % i)
        tiles = generate_triangle_tiling(num_pts=i, size=size)
        locator = Kirkpatrick(tiles)
        for j in range(n_iter):
            query = Point.sample_square(size)
            start = time.time()
            locator.locate(query)
            elapsed = time.time() - start
            data.append(Point(len(tiles), elapsed))
    return data

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    tiles = [
        Polygon([
            Point(0, 0), Point(2, 0), Point(2, 2), Point(0, 2)
        ])
    ]

    locator = Kirkpatrick(tiles)

    query_point = Point(1, 1)

    located_tile = locator.locate(query_point, plot_search=True)

    print(located_tile)
Пример #10
0
        # Update ear status of adjacent vertices
        ear_a = (adj[a][0], a, c)
        ear_c = (a, c, adj[c][1])
        if poly.is_ear(ear_a):
            ears[a] = list(ear_a)
        else:
            ears.pop(a, None)

        if poly.is_ear(ear_c):
            ears[c] = list(ear_c)
        else:
            ears.pop(c, None)

        curr_n -= 1

    return tris


if __name__ == '__main__':
    poly = Polygon([
        Point(0.000000, 0.000000),
        Point(1.727261, 0.681506),
        Point(2.000000, 2.000000),
        Point(1.128893, 1.104487),
        Point(0.848083, 1.122645)
    ])

    triangles = triangulate(poly)

    drawing.plot_polygons(triangles)
    plt.show()