Exemple #1
0
 def test_max_width_height_diag(self):
     for i in range(1, 101):
         sizes = [(j, i + 1 - j) for j in range(1, i + 1)]
         pos = rpack.pack(sizes, max_width=i)
         w, _ = rpack.bbox_size(sizes, pos)
         self.assertEqual(w, i)
         pos = rpack.pack(sizes, max_height=i)
         _, h = rpack.bbox_size(sizes, pos)
         self.assertEqual(h, i)
Exemple #2
0
 def test_max_width_height_both2(self):
     sizes = [(2736, 3648), (2736, 3648), (3648, 2736), (2736, 3648), (2736, 3648)]
     max_height = max_width = 14130
     pos = rpack.pack(sizes, max_width=max_width, max_height=max_height)
     self.assertLessEqual(max(*rpack.bbox_size(sizes, pos)), max_width)
     index = rpack._core.overlapping(sizes, pos)
     self.assertFalse(index)
Exemple #3
0
def _bbox_rpack(component_sizes, pad_x=1.0, pad_y=1.0):
    """Compute bounding boxes for individual components
    by arranging them as densly as possible.

    Depends on `rectangle-packer`.
    """
    try:
        import rpack
    except ImportError:
        raise ImportError(
            "Using the 'components layout' requires the installation of "
            "the `rectangle-packer`. You can install it with "
            "`pip install rectangle-packer`.")

    dimensions = [_get_bbox_dimensions(n, power=0.8) for n in component_sizes]
    # rpack only works on integers; sizes should be in descending order
    dimensions = [(int(width + pad_x), int(height + pad_y))
                  for (width, height) in dimensions[::-1]]
    origins = rpack.pack(dimensions)
    outer_dimensions = rpack.enclosing_size(dimensions, origins)
    aspect_ratio = outer_dimensions[0] / outer_dimensions[1]
    if aspect_ratio > 1:
        scale_width, scale_height = 1, aspect_ratio
    else:
        scale_width, scale_height = aspect_ratio, 1
    bboxes = [(
        x,
        y,
        width * scale_width - pad_x,
        height * scale_height - pad_y,
    ) for (x, y), (width, height) in zip(origins, dimensions)]
    return bboxes[::-1]
Exemple #4
0
 def test_max_width_height_both3(self):
     sizes = [(3, 4), (3, 4), (4, 3), (3, 4), (3, 4)]
     max_height = max_width = 9
     pos = rpack.pack(sizes, max_width=max_width, max_height=max_height)
     self.assertLessEqual(max(*rpack.bbox_size(sizes, pos)), max_width)
     index = rpack._core.overlapping(sizes, pos)
     self.assertFalse(index)
def get_packed(boxes):
    sizes = [(int(box[2] - box[0]), int(box[3] - box[1])) for box in boxes]
    heights = [int(box[3] - box[1]) for box in boxes]
    #arr = np.array(sizes, dtype=[('w', int), ('h', int)])
    arr = np.array(heights)

    sorted_ind = np.argsort(arr)
    sorted_ind = list(sorted_ind[::-1])
    sorted_sizes = sorted(sizes, key=lambda x: x[1], reverse=True)
    #sorted_sizes = np.sort(arr, order='h')
    #sorted_sizes = sorted_sizes[::-1]
    #sorted_sizes = list(sorted_sizes)
    #from IPython import embed
    #embed()
    positions = rpack.pack(sorted_sizes)
    shape = rpack.enclosing_size(sorted_sizes, positions)
    new_img = np.zeros((shape[1], shape[0], 3))
    for i in range(len(positions)):
        x, y = positions[i]
        w, h = sorted_sizes[i]
        box = boxes[sorted_ind[i]]
        img = cv2.imread(box[4])
        img = np.array(img)
        new_img[y:y + h, x:x + w, :] = img[int(box[1]):int(box[1]) + h,
                                           int(box[0]):int(box[0] + w)]
    return new_img
def _get_component_bboxes(component_sizes, pad_x=1., pad_y=1.):
    dimensions = [_get_bbox_dimensions(n, power=0.8) for n in component_sizes]
    # rpack only works on integers; sizes should be in descending order
    dimensions = [(int(width + pad_x), int(height + pad_y)) for (width, height) in dimensions[::-1]]
    origins = rpack.pack(dimensions)
    bboxes = [(x, y, width-pad_x, height-pad_y) for (x,y), (width, height) in zip(origins, dimensions)]
    return bboxes[::-1]
Exemple #7
0
def pack(allRect, canvasSize):
    #stores width and height from allRect which was given
    rects = [(rect.width, rect.height) for rect in allRect]
    location = rpack.pack(rects)
    #zip of tuple iterators to place in appropriate locations when drawn
    for locat, rect in zip(location, allRect):
        rect.x = locat[0]
        rect.y = locat[1]
Exemple #8
0
def pack(allRect, canvasSize):  # uses rectangle-packer to sort rectangles
    rects = [(rect.width, rect.height) for rect in allRect]
    available = rpack.pack(rects)

    for position, rect in zip(available,
                              allRect):  # sets positions for rectangles
        rect.x = position[0]
        rect.y = position[1]
Exemple #9
0
def pack(allRect, canvasSize):
    rects = [(rect.width, rect.height) for rect in allRect]

    positions = rpack.pack(rects)

    for position, rect in zip(positions, allRect):
        rect.x = position[0]
        rect.y = position[1]
Exemple #10
0
def test(n):
    random.seed(0)
    sizes = [(random.randint(1, 1000), random.randint(1, 1000)) for _ in range(n)]
    pos = rpack.pack(sizes)
    assert not rpack._core.overlapping(sizes, pos)
    w, h = rpack._core.bbox_size(sizes, pos)
    p = rpack._core.packing_density(sizes, pos)
    print(f'encl (w={w} x h={h}), area={w*h}, rho={p}')
def average_time(nr_rectangles):
    N = 10
    t0 = time.time()
    for i in range(N):
        sizes = [(randint(10, 120), randint(10, 120))
                 for _ in range(nr_rectangles)]
        positions = rpack.pack(sizes)
    t1 = time.time()
    return (t1 - t0) / N
Exemple #12
0
 def test_max_width_height_both4(self):
     sizes = [(3, 4), (3, 4), (4, 3), (3, 4), (3, 4)]
     max_width, max_height = (16, 4)
     pos = rpack.pack(sizes, max_width=max_width, max_height=max_height)
     w, h = rpack.bbox_size(sizes, pos)
     self.assertLessEqual(w, max_width)
     self.assertLessEqual(h, max_height)
     index = rpack._core.overlapping(sizes, pos)
     self.assertFalse(index)
Exemple #13
0
 def test_no_overlap(self):
     """Make sure no rectangles overlap"""
     for i in range(10, 101, 10):
         with self.subTest(seed=i):
             random.seed(i)
             sizes = [(random.randint(1, i), random.randint(1, i))
                      for _ in range(110 - i)]
             pos = rpack.pack(sizes)
             self.assertFalse(rpack._core.overlapping(sizes, pos))
def pack(rect_list):

    tempList = []
    pos = []

    for i in rect_list:
        tempList.append((int(i.get_h()), int(i.get_w())))

    pos = rpack.pack(tempList)

    return pos
Exemple #15
0
 def test_backwards_compatible(self):
     for i in range(10):
         random.seed(i)
         sizes = [(random.randint(1, 50), random.randint(1, 50)) for _ in range(20)]
         pos1 = rpack._rpack.pack(sizes)
         self.assertFalse(rpack._core.overlapping(sizes, pos1))
         pos2 = rpack.pack(sizes)
         self.assertFalse(rpack._core.overlapping(sizes, pos2))
         self.assertLessEqual(
             rpack._core.packing_density(sizes, pos1),
             rpack._core.packing_density(sizes, pos2))
Exemple #16
0
def _get_component_bboxes(component_sizes, pad_x=1., pad_y=1.):
    dimensions = [_get_bbox_dimensions(n, power=0.8) for n in component_sizes]
    # rpack only works on integers
    dimensions = [(int(width + pad_x), int(height + pad_y)) for (width, height) in dimensions]
    # rpack works best if the heights are in descending order
    dimensions = dimensions[::-1]
    origins = rpack.pack(dimensions)
    bboxes = [(x, y, width-pad_x, height-pad_y) for (x,y), (width, height) in zip(origins, dimensions)]
    # reverse order to match order of components
    bboxes = bboxes[::-1]
    return bboxes
def test_no_overlap():
    """Make sure no rectangles overlap"""
    random.seed(123)
    rectangles = [(random.randint(50, 100), random.randint(50, 100))
                  for _ in range(40)]
    positions = rpack.pack(rectangles)
    for i, ((x1, y1), (w1, h1)) in enumerate(zip(positions, rectangles)):
        for j, ((x2, y2), (w2, h2)) in enumerate(zip(positions, rectangles)):
            if i != j:
                disjoint_in_x = (x1 + w1 <= x2 or x2 + w2 <= x1)
                disjoint_in_y = (y1 + h1 <= y2 or y2 + h2 <= y1)
                assert disjoint_in_x or disjoint_in_y
def test_perfect_pack():
    """Pack rectangles to perfect rectangle

    Like this::

        aaa  bb  cc  -->  aaabb
        aaa  bb           aaabb
        aaa               aaacc
    """
    rectangles = [(3, 3), (2, 2), (2, 1)]
    positions = [(0, 0), (3, 0), (3, 2)]
    assert rpack.pack(rectangles) == positions
Exemple #19
0
    def test_perfect_pack(self):
        """Pack rectangles to perfect rectangle

        Like this::

            aaa  bb  cc  -->  aaabb
            aaa  bb           aaabb
            aaa               aaacc
        """
        sizes = [(3, 3), (2, 2), (2, 1)]
        pos = [(0, 0), (3, 0), (3, 2)]
        self.assertListEqual(rpack.pack(sizes), pos)
Exemple #20
0
def _pack_components(G, layout, **kwargs):
    """Attempts to pack components using `layout` to compute component layouts,
    rotates those component layouts to minimum-area bounding rectangles,
    and then uses a rectangle packing algorithm to minimize the area of the
    overall layout.

    If `scale` is an argument, we rescale the layout after the above.

    If `dim` is an argument and not equal to 2, we don't have an
    implementation, so we pass the graph directly into `layout` and bypass
    the packing procedure
    """
    if kwargs.get('dim', 2) != 2:
        return layout(G, **kwargs)

    layouts = []
    rectangles = []
    if 'scale' in kwargs:
        subkwargs = dict(kwargs)
        scale = subkwargs['scale']
        del subkwargs['scale']
    else:
        subkwargs = kwargs
        scale = None

    for i, c in enumerate(nx.connected_components(G)):
        if len(c) > 2:
            cpos = layout(G.subgraph(c), scale=len(c)**.5, **subkwargs)
            apos = np.array(list(cpos.values()))
            rpos, dims = _rotate_to_minimize_area(apos)
            cpos = dict(zip(cpos, rpos))
            dims = [int(ceil(z) + .001) for z in dims]
        elif len(c) == 2:
            cpos = dict(zip(c, [(-.5, 0), (.5, 0)]))
            dims = [2, 1]
        else:
            cpos = dict(zip(c, [(0, 0)]))
            dims = [1, 1]
        layouts.append(cpos)
        rectangles.append(dims)

    positions = rpack.pack(rectangles)
    layout = {
        v: (vx + rx + w / 2, vy + ry + h / 2)
        for (rx, ry), (w, h), cpos in zip(positions, rectangles, layouts)
        for v, (vx, vy) in cpos.items()
    }
    if scale is not None:
        layout_array = np.array(list(layout[v] for v in G))
        return dict(zip(G, _scale_layout(layout_array, scale)))
    else:
        return layout
Exemple #21
0
 def run_once(cls):
     clk = Clock()
     results = []
     for test in cls.tests:
         test.build()
         for cmp in cls.cmps:
             clk.stop()
             done = pack(test.rects, rect_cmp=cmp[1])
             runtime = clk.get_ticks()
             er = get_enclosing_rect(done)
             cv = coverage(done, er)
             results.append(TestResult(test, cmp, runtime, cv, er))
     return results
def test_negative():
    """Negative number should raise ValueError"""
    with pytest.raises(ValueError):
        rpack.pack([(3, -5)])
    with pytest.raises(ValueError):
        rpack.pack([(-3, 5)])
    with pytest.raises(ValueError):
        rpack.pack([(-3, -5)])
Exemple #23
0
 def test_negative(self):
     """Negative number should raise ValueError"""
     with self.assertRaises(ValueError):
         rpack.pack([(3, -5)])
     with self.assertRaises(ValueError):
         rpack.pack([(-3, 5)])
     with self.assertRaises(ValueError):
         rpack.pack([(-3, -5)])
Exemple #24
0
def main(args):
    random.seed(0)
    t0 = time.time()
    while time.time() - t0 < args.duration:
        func = random.choices([randrec, randneg, randtype], [0.8, 0.1, 0.1])
        sizes = func[0]()
        try:
            pos = rpack.pack(sizes)
        except Exception:
            pass
        else:
            if pos:
                rpack.packing_density(sizes, pos)
                rpack.bbox_size(sizes, pos)
                rpack.overlapping(sizes, pos)
Exemple #25
0
def draw_pseudopage(paragraph_texts):
    paragraphs = []
    for paragraph_text in paragraph_texts:
        paragraphs.append(draw_pseudoparagraph(paragraph_text))
    sizes = [img.size for img in paragraphs]
    placements = rpack.pack(sizes)
    new_image_width = max(
        [sizes[n][0] + placements[n][0] for n in range(len(sizes))])
    new_image_height = max(
        [sizes[n][1] + placements[n][1] for n in range(len(sizes))])
    new_image = Image.new('RGB', (new_image_width, new_image_height),
                          color=(255, 255, 255))
    for n in range(len(paragraphs)):
        left, top, right, bottom = placements[n][0], placements[n][
            1], placements[n][0] + sizes[n][0], placements[n][1] + sizes[n][1]
        new_image.paste(paragraphs[n], (left, top, right, bottom))
    return new_image
Exemple #26
0
def arrange_images(normalized_posters, blur_factor, blur_radius):
    """
    Arranges images to create a collage.

    Arguments:
        norm_time_posters: tuple(float, PIL.Image)
            Normalized instances of time and area for time and posters respectively.
        blur_factor:
            Number of times to apply a blurring operation to diffuse wasted space.
        blur_radius:
            Radius of neighbourhood for use as Gaussian blurring parameter.

    Returns:
        collage: np.array
            A collage of images heuristically packed together.
    """

    # as a greedy heuristic sort by size first to minimize wasted area
    normalized_posters = sorted(
        normalized_posters, key=lambda x: x.size[0] * x.size[1], reverse=True
    )
    sizes = [x.size for x in normalized_posters]
    positions = rpack.pack(sizes)

    max_width = max(a[0] + b[0] for a, b in zip(positions, sizes))
    max_height = max(a[1] + b[1] for a, b in zip(positions, sizes))
    collage = np.full([max_height + 1, max_width + 1, 3], 255, dtype=np.uint8)
    deadspace = np.full_like(collage, True)

    # place images
    for (x, y), img in zip(positions, normalized_posters):
        dx, dy = img.size
        collage[y : y + dy, x : x + dx] = img
        deadspace[y : y + dy, x : x + dx] = False

    # identify all deadspace which looks harsh on the eyes
    deadspace = np.where(deadspace)

    # diffuse deadspace to get a softer background
    gaussian_blur = ImageFilter.GaussianBlur(radius=blur_radius)
    for _ in range(blur_factor):
        blurred = Image.fromarray(collage).filter(gaussian_blur)
        collage[deadspace] = np.array(blurred)[deadspace]

    return collage
Exemple #27
0
def candidates():
    """Find bbox with golden ratio proportions"""
    cands = list()
    try:
        i = 0
        while True:
            i += 1
            random.seed(i)
            sizes = [(random.randint(50, 1000), random.randint(50, 1000))
                     for _ in range(random.randint(30, 40))]
            pos = rpack.pack(sizes)
            rho = rpack.packing_density(sizes, pos)
            w, h = rpack.bbox_size(sizes, pos)
            if abs(w/h - 1.61803398875) < 0.01:
                print('Found candidate:', rho, 'seed', i)
                cands.append((rho, sizes, pos, i))
    except KeyboardInterrupt:
        pass
    cands.sort(reverse=True)
    return cands[0:10]
Exemple #28
0
 def test_max_width_height_long_running(self):
     random.seed(123)
     try:
         while True:
             n = random.randint(1, 20)
             m = 20
             sizes = [(random.randint(1, m), random.randint(1, m)) for _ in range(n)]
             max_width = random.randint(1, m*n + 10)
             max_height = random.randint(1, m*n + 10)
             try:
                 pos = rpack.pack(sizes, max_width=max_width, max_height=max_height)
             except rpack.PackingImpossibleError:
                 continue
             else:
                 w, h = rpack.bbox_size(sizes, pos)
                 assert w <= max_width
                 assert h <= max_height
                 assert not rpack.overlapping(sizes, pos)
     except KeyboardInterrupt:
         print("Stopped.")
Exemple #29
0
    def proportional(self, min_size: int = 32, album_count: int = 100) -> None:
        """

        :param min_size: the smallest size for an album in pixels
        :param album_count: the number of albums to include in the poster
        :return: None
        """
        from rpack import pack, enclosing_size
        if self.album_data is None or len(self.album_data.index) < album_count:
            album_data = get_album_data(album_count, genre_tags=self.genre_tags)
        else:
            album_data = self.album_data
        album_sizes = album_data["msPlayed"].astype(float)
        album_sizes = album_sizes / min(album_sizes) * min_size
        album_sizes = [(int(n), int(n)) for n in album_sizes]
        new_poss = pack(album_sizes)
        self.album_data = album_data
        self.positions = new_poss
        self.album_sizes = album_sizes
        self.size = enclosing_size(album_sizes, new_poss)
Exemple #30
0
def logo(output_dir='.'):
    """Create GIF logo used in sphinx documentation"""
    random.seed(232460)
    sizes = [(random.randint(50, 1000), random.randint(50, 1000))
             for _ in range(random.randint(30, 40))]
    pos = rpack.pack(sizes)
    # Sort the rectangles so the animation will plot them from left to
    # right.
    sizes = [s for s, _ in sorted(zip(sizes, pos), key=lambda x: x[1])]
    pos.sort()
    # Create animation
    p = PlotPacking(sizes, pos, trim=True)
    for spine in p.ax.spines.values():
        spine.set_linewidth(0)
    p.animation(os.path.join(output_dir, f'logo'), 1, 0, dpi=40)
    p = PlotPacking(sizes, pos, trim=True)
    for spine in p.ax.spines.values():
        spine.set_linewidth(0)
    while p.feed():
        pass
    p.save(os.path.join(output_dir, f'logo'))
    # Post process gif to only loop animation one time.
    subprocess.run('convert -loop 1 logo.gif logo.gif', shell=True, check=True)
def plot(sizes, append=''):

    t0 = time.time()
    positions = rpack.pack(sizes)
    t1 = time.time()
    (width, height), rectangles = enclosing_size(sizes, positions)

    norm = max(width, height)

    color = cm.rainbow(np.linspace(0, 1, len(rectangles)))
    fig1 = plt.figure()
    ax1 = fig1.add_subplot(111, aspect='equal')

    ax1.set_xlim([0, norm])
    ax1.set_ylim([0, norm])
    for r, c in zip(rectangles, color):
        ax1.add_patch(
            patches.Rectangle((r.x, r.y),
                              r.width,
                              r.height,
                              facecolor=c,
                              edgecolor='k'))
    ax1.add_patch(
        patches.Rectangle((0, 0), width, height, fill=False, linewidth=2))

    ax1.invert_yaxis()

    coverage = sum(w * h for w, h in sizes) / (width * height)
    ax1.set_title(f'Area coverage: {coverage:.3f}%, t = {(t1 - t0):.3f}s')
    ax1.yaxis.set_label_position("right")
    ax1.set_ylabel(f'Enclosing height: {height}')
    ax1.set_xlabel(f'Enclosing width: {width}')

    timestamp = '{:%Y-%m-%d_%H%M%S}'.format(datetime.datetime.now())
    branch = Repository('..').head.shorthand
    plt.savefig(f'{branch}_{timestamp}_{append}.png')
    plt.clf()
Exemple #32
0
other = [Rect(
    random.randint(from_size, to_size),
    random.randint(from_size, to_size),
    i
) for i in range(ocount)]
rects.extend(other)

colors = []
for r in rects:
    colors.append((
        random.uniform(0.1, 1),
        random.uniform(0.1, 1),
        random.uniform(0.1, 1)
    ))

done = pack(rects)
cover, size = coverage(done)
print cover, size
window = pyglet.window.Window(1400, 800, resizable=True)

delta_x = 0
delta_y = 0

@window.event
def on_draw():
    window.clear()
    gl.glLoadIdentity()
    gl.glTranslatef(delta_x, delta_y, 0)
    gl.glScalef(0.5, 0.5, 1.0)
    draw_rects(done, colors)