Given a 'section' bounding box and a dictionary of 'subsections', checks: 1) That each subsection is within the main section and that no two subsections overlap. - If there is a problem, returns a tuple of the names of the offending subsections. 2) That the
(section, subsections)
| 721 | return True |
| 722 | |
| 723 | def check_and_fix_subsections(section, subsections): |
| 724 | """ |
| 725 | Given a 'section' bounding box and a dictionary of 'subsections', |
| 726 | checks: |
| 727 | |
| 728 | 1) That each subsection is within the main section and that |
| 729 | no two subsections overlap. |
| 730 | - If there is a problem, returns a tuple of the names of |
| 731 | the offending subsections. |
| 732 | |
| 733 | 2) That the subsections fully occupy the area of 'section'. |
| 734 | - If not, greedily expand each subsection (in the order |
| 735 | left->right->top->bottom), and return a dictionary of |
| 736 | the updated bounding boxes for the subsections. |
| 737 | |
| 738 | 3) Otherwise, returns an empty tuple if nothing is wrong. |
| 739 | |
| 740 | :param section: dict with keys "left", "top", "width", "height". |
| 741 | :param subsections: dict mapping name -> dict with "left", "top", "width", "height". |
| 742 | :return: Either |
| 743 | - tuple of subsection names that are out of bounds or overlapping, |
| 744 | - dict of expanded bounding boxes if they do not fully occupy 'section', |
| 745 | - or an empty tuple if everything is correct. |
| 746 | """ |
| 747 | |
| 748 | # --- Utility functions --- |
| 749 | def right(rect): |
| 750 | return rect["left"] + rect["width"] |
| 751 | |
| 752 | def bottom(rect): |
| 753 | return rect["top"] + rect["height"] |
| 754 | |
| 755 | def is_overlapping(r1, r2): |
| 756 | """ |
| 757 | Returns True if rectangles r1 and r2 overlap (strictly), |
| 758 | False otherwise. |
| 759 | """ |
| 760 | return not ( |
| 761 | right(r1) <= r2["left"] |
| 762 | or r1["left"] >= right(r2) |
| 763 | or bottom(r1) <= r2["top"] |
| 764 | or r1["top"] >= bottom(r2) |
| 765 | ) |
| 766 | |
| 767 | # 1) Check each subsection is within the main section |
| 768 | names_violating = set() |
| 769 | sec_left, sec_top = section["left"], section["top"] |
| 770 | sec_right = section["left"] + section["width"] |
| 771 | sec_bottom = section["top"] + section["height"] |
| 772 | |
| 773 | for name, sub in subsections.items(): |
| 774 | # Check boundary |
| 775 | sub_left, sub_top = sub["left"], sub["top"] |
| 776 | sub_right, sub_bottom = right(sub), bottom(sub) |
| 777 | if ( |
| 778 | sub_left < sec_left |
| 779 | or sub_top < sec_top |
| 780 | or sub_right > sec_right |
nothing calls this directly
no test coverage detected