def recursive_xy_divide(elems, avg_font_size):
log = logging.getLogger(__name__)<EOL>log.info(avg_font_size)<EOL>objects = list(elems.mentions)<EOL>objects.extend(elems.segments)<EOL>bboxes = []<EOL>def divide(objs, bbox, h_split=True, is_single=False):<EOL><INDENT>"""<STR_LIT>"""<EOL>if not objs:<EOL><INDENT>return []<EOL><DEDENT>axis = <NUM_LIT:1> if h_split else <NUM_LIT:0><EOL>intervals, groups = project_onto(objs, axis, avg_font_size)<EOL>single_child = len(groups) == <NUM_LIT:1><EOL>if is_single and single_child:<EOL><INDENT>bboxes.append(bbox)<EOL>return objs<EOL><DEDENT>else:<EOL><INDENT>children = []<EOL>for interval, group in zip(intervals, groups):<EOL><INDENT>sub_bbox = np.array(bbox)<EOL>sub_bbox[[axis, axis + <NUM_LIT:2>]] = interval<EOL>child = divide(group, sub_bbox, not h_split, single_child)<EOL>children.append(child)<EOL><DEDENT>return children<EOL><DEDENT><DEDENT>full_page_bbox = (<NUM_LIT:0>, <NUM_LIT:0>, elems.layout.width, elems.layout.height)<EOL>objects = [o for o in objects if inside(full_page_bbox, o.bbox)]<EOL>log.info("<STR_LIT>", avg_font_size)<EOL>tree = divide(objects, full_page_bbox) if objects else []<EOL>return bboxes, tree<EOL>
Recursively group/divide the document by white stripes
by projecting elements onto alternating axes as intervals.

avg_font_size: the minimum gap size between elements below
which we consider interval continuous.