diff --git a/masque/test/test_pack2d.py b/masque/test/test_pack2d.py index 5390a4c..914c23e 100644 --- a/masque/test/test_pack2d.py +++ b/masque/test/test_pack2d.py @@ -1,4 +1,4 @@ -from ..utils.pack2d import maxrects_bssf, pack_patterns +from ..utils.pack2d import maxrects_bssf, guillotine_bssf_sas, pack_patterns from ..library import Library from ..pattern import Pattern @@ -25,6 +25,34 @@ def test_maxrects_bssf_reject() -> None: assert 0 not in rejects +def test_maxrects_bssf_exact_fill_rejects_remaining() -> None: + rects = [[20, 20], [1, 1]] + containers = [[0, 0, 20, 20]] + + locs, rejects = maxrects_bssf(rects, containers, presort=False, allow_rejects=True) + + assert tuple(locs[0]) == (0.0, 0.0) + assert rejects == {1} + + +def test_maxrects_bssf_presort_reject_mapping() -> None: + rects = [[10, 12], [19, 14], [13, 11]] + containers = [[0, 0, 20, 20]] + + _locs, rejects = maxrects_bssf(rects, containers, presort=True, allow_rejects=True) + + assert rejects == {0, 2} + + +def test_guillotine_bssf_sas_presort_reject_mapping() -> None: + rects = [[2, 1], [17, 15], [16, 11]] + containers = [[0, 0, 20, 20]] + + _locs, rejects = guillotine_bssf_sas(rects, containers, presort=True, allow_rejects=True) + + assert rejects == {2} + + def test_pack_patterns() -> None: lib = Library() p1 = Pattern() @@ -49,3 +77,20 @@ def test_pack_patterns() -> None: # p1 size 10x10, effectively 12x12 # p2 size 5x5, effectively 7x7 # Both should fit in 20x20 + + +def test_pack_patterns_reject_names_match_original_patterns() -> None: + lib = Library() + for name, (lx, ly) in { + "p0": (10, 12), + "p1": (19, 14), + "p2": (13, 11), + }.items(): + pat = Pattern() + pat.rect((1, 0), xmin=0, xmax=lx, ymin=0, ymax=ly) + lib[name] = pat + + pat, rejects = pack_patterns(lib, ["p0", "p1", "p2"], [[0, 0, 20, 20]], spacing=(0, 0)) + + assert set(rejects) == {"p0", "p2"} + assert set(pat.refs) == {"p1"} diff --git a/masque/utils/pack2d.py b/masque/utils/pack2d.py index a99b01e..248f408 100644 --- a/masque/utils/pack2d.py +++ b/masque/utils/pack2d.py @@ -60,6 +60,12 @@ def maxrects_bssf( degenerate = (min_more & max_less).any(axis=0) regions = regions[~degenerate] + if regions.shape[0] == 0: + if allow_rejects: + rejected_inds.add(rect_ind) + continue + raise MasqueError(f'Failed to find a suitable location for rectangle {rect_ind}') + ''' Place the rect ''' # Best short-side fit (bssf) to pick a region region_sizes = regions[:, 2:] - regions[:, :2] @@ -102,7 +108,7 @@ def maxrects_bssf( if presort: unsort_order = rect_order.argsort() rect_locs = rect_locs[unsort_order] - rejected_inds = set(unsort_order[list(rejected_inds)]) + rejected_inds = {int(rect_order[ii]) for ii in rejected_inds} return rect_locs, rejected_inds @@ -187,7 +193,7 @@ def guillotine_bssf_sas( if presort: unsort_order = rect_order.argsort() rect_locs = rect_locs[unsort_order] - rejected_inds = set(unsort_order[list(rejected_inds)]) + rejected_inds = {int(rect_order[ii]) for ii in rejected_inds} return rect_locs, rejected_inds