def _merge_region_changes(self, y, merge): """Handle changes caused by one or more regions being merged into one.""" built = [] once = False for change in merge: old = change['old'] new = change['new'] below = new[0] collect = [] if old[0].left == below.left and old[-1].right == below.right: for above in old: collect += above.zones self._regions.remove(above) zone = data.Zone(left=below.left, right=below.right, top=y, maybe_left=old[0].right, maybe_right=old[-1].left) collect.append(zone) else: for above in old: if below.left < above.left and below.right == above.right: zone = data.Zone(left=below.left, right=below.right, top=y, maybe_right=above.left) self._insert_into(zone, collect) elif below.left == above.left and below.right > above.right: zone = data.Zone(left=below.left, right=below.right, top=y, maybe_left=above.right) self._insert_into(zone, collect) elif below.left == above.left and below.right < above.right: built += self._finish_zones_on_the_right( y, above, below.right) elif below.left > above.left and below.right == above.right: built += self._finish_zones_on_the_left( y, above, below.left) elif below.left < above.left and below.right < above.right: built += self._cull_static_zones(y, above) elif below.left > above.left and below.right > above.right: built += self._cull_static_zones(y, above) else: raise RuntimeError('TODO unknown above=%r below=%r' % (above, below)) collect += above.zones self._regions.remove(above) region = data.Region(below.left, below.right) region.zones = collect self._insert_into(region, self._regions) return built
def test_edge_smaller_on_left_but_same_on_right(self): # |..rrrrrr......| # |....eeee......| self.add_region(top=3, left=40, right=56) self.set_zones(0, [ data.Zone(left=40, right=52, top=1), data.Zone(left=40, right=56, top=3, maybe_left=52) ]) self.assertEqual(self.regions(), '[<Region L=40 R=56>]') self.assertEqual( self.zones(), '[<Zone L=40 R=52 T=1>,' ' <Zone L=[40, 52] R=56 T=3>]') self.insert_span(y=6, left=44, right=56) self.assertEqual(self.regions(), '[<Region L=44 R=56>]') self.assertEqual(self.zones(), '[<Zone L=[44, 52] R=56 T=3>]') self.assertEqual(self.built(), '[<Zone L=40 R=52 T=1 B=6>]')
def test_edge_same_on_left_but_smaller_on_right(self): # |..rrrrrr......| # |..eeee........| self.add_region(top=3, left=40, right=54) self.set_zones(0, [ data.Zone(left=46, right=54, top=1), data.Zone(left=40, right=54, top=3, maybe_right=46) ]) self.assertEqual(self.regions(), '[<Region L=40 R=54>]') self.assertEqual( self.zones(), '[<Zone L=46 R=54 T=1>,' ' <Zone L=40 R=[46, 54] T=3>]') self.insert_span(y=6, left=40, right=48) self.assertEqual(self.regions(), '[<Region L=40 R=48>]') self.assertEqual(self.zones(), '[<Zone L=40 R=[46, 48] T=3>]') self.assertEqual(self.built(), '[<Zone L=46 R=54 T=1 B=6>]')
def _add_zones_to_empty_regions(self, y): """Regions without zones have a single zone added.""" for r in self._regions: if r.zones == []: r.zones.append(data.Zone(left=r.left, right=r.right, top=y))
def add_region(self, top, left, right): region = data.Region(left=left, right=right) region.zones.append(data.Zone(left=left, right=right, top=top)) self.processor._regions.append(region)