Beispiel #1
0
 def piece_contour(pid):
     offset = Point(width * (pid % nx) + width / 2,
                    height * (pid // nx) + height / 2)
     contour = [
         edges[get_epid(pid, "N")].stretch(width, height).translate(offset),
         edges[get_epid(pid, "E")].stretch(
             height, width).rotate().translate(offset + Point(width, 0)),
         edges[get_epid(pid, "S")].stretch(
             width, height).translate(offset + Point(0, height)).reverse(),
         edges[get_epid(pid, "W")].stretch(
             height, width).rotate().translate(offset).reverse()
     ]
     return list(
         itertools.chain.from_iterable(
             [edge.evaluate(10) for edge in contour]))
Beispiel #2
0
def closest_neighbour_pid(pid, point, width, height, nx):
    point = point.dot(Point(height / width, 1))
    if abs(point.x) < point.y:  # North
        return pid + nx
    elif abs(point.x) < -point.y:  # South
        return pid - nx
    elif abs(point.y) < point.x:  # East
        return pid + 1
    else:  # West
        return pid - 1
Beispiel #3
0
def make_jigsaw_cut(image_width, image_height, nx, ny):
    num_edges = 2 * nx * ny - nx - ny
    num_pieces = nx * ny
    nv = (nx - 1) * ny
    width = image_width // nx
    height = image_height // ny

    edges = make_random_edges(num_edges)

    def get_epid(pid, orientation):
        if orientation == "N" and pid >= nx:
            return pid - nx + nv
        elif orientation == "W" and pid % nx:
            return pid - (pid // nx) - 1
        elif orientation == "S" and pid < num_pieces - nx:
            return pid + nv
        elif orientation == "E" and pid % nx != nx - 1:
            return pid - (pid // nx)
        return -1

    def piece_contour(pid):
        offset = Point(width * (pid % nx) + width / 2,
                       height * (pid // nx) + height / 2)
        contour = [
            edges[get_epid(pid, "N")].stretch(width, height).translate(offset),
            edges[get_epid(pid, "E")].stretch(
                height, width).rotate().translate(offset + Point(width, 0)),
            edges[get_epid(pid, "S")].stretch(
                width, height).translate(offset + Point(0, height)).reverse(),
            edges[get_epid(pid, "W")].stretch(
                height, width).rotate().translate(offset).reverse()
        ]
        return list(
            itertools.chain.from_iterable(
                [edge.evaluate(10) for edge in contour]))

    pieces = {
        pid: Piece(pid=pid,
                   polygon={pid: (polygon := piece_contour(pid))},
                   bounding_box=bounding_box(polygon),
                   origin=(origin := Point(width * (pid % nx),
                                           height * (pid // nx))),
                   neighbours=create_neighbours(pid, num_pieces, nx),
                   members={pid},
                   width=width,
                   height=height,
                   x=random.randint(0, int(image_width * 2)) - origin.x,
                   y=random.randint(0, int(image_height * 2)) - origin.y,
                   z=pid)
        for pid in tqdm(range(num_pieces), desc="Designing pieces")
    }
Beispiel #4
0
    def move_and_snap(self, pid, dx, dy):
        piece = self.pieces[pid]
        self.quadtree.remove(piece, piece.bbox)
        piece.x += dx
        piece.y += dy

        for neighbour_pid in piece.neighbours:
            if not self.trays.is_visible(neighbour_pid):
                continue

            neighbour = self.pieces[neighbour_pid]
            dist = Point.dist(Point(piece.x, piece.y),
                              Point(neighbour.x, neighbour.y))
            if dist < self.snap_distance:
                piece.x = neighbour.x
                piece.y = neighbour.y
                neighbour.z = piece.z
                self.dispatch_event('on_snap_piece_to_position', pid, piece.x,
                                    piece.y, piece.z)

                self._merge_pieces(piece, neighbour)

        self.quadtree.insert(piece, piece.bbox)
Beispiel #5
0
    def contains(self, point: Point, nx: int) -> bool:
        point = point - self.position
        pid = point_to_pid(point, nx, self.width, self.height)
        offset = Point(self.width * (1 + pid % nx),
                       self.height * (1 + pid // nx))

        neighbour = closest_neighbour_pid(pid, point - offset, self.width,
                                          self.height, nx)

        if pid in self.members and neighbour in self.members:
            return True
        elif pid in self.members and neighbour not in self.members:
            return point_in_polygon(point, self.polygon[pid])
        elif pid not in self.members and neighbour in self.members:
            return point_in_polygon(point, self.polygon[neighbour])
        else:
            return False
Beispiel #6
0
 def position(self):
     return Point(self.x, self.y)
Beispiel #7
0
 def _pieces_at_location(self, x, y):
     for piece in self.quadtree.intersect(bbox=(x, y, x, y)):
         if self.trays.is_visible(piece.pid) and piece.contains(
                 Point(x, y), self.nx):
             yield piece