def below(self, objects: Set[Object]) -> Set[Object]:
        """
        Returns the set of objects in the same boxes that are below the given objects. That is, if
        the input is a set of two objects, one in each box, we will return a union of the objects
        below the first object in the first box, and those below the second object in the second box.
        """
        objects_per_box = self._separate_objects_by_boxes(objects)
        return_set = set()
        for box in objects_per_box:
            # max_y_loc corresponds to the bottom-most object.
            max_y_loc = max([obj.y_loc for obj in objects_per_box[box]])
            for candidate_obj in box.objects:
                if candidate_obj.y_loc > max_y_loc:
                    return_set.add(candidate_obj)
        return return_set
def below ( self , objects : Set [ Object ] ) -> Set [ Object ] : objects_per_box = self . _separate_objects_by_boxes ( objects ) return_set = set ( ) for box in objects_per_box : max_y_loc = max ( [ obj . y_loc for obj in objects_per_box [ box ] ] ) for candidate_obj in box . objects : if candidate_obj . y_loc > max_y_loc : return_set . add ( candidate_obj ) return return_set
Returns the set of objects in the same boxes that are below the given objects. That is, if
        the input is a set of two objects, one in each box, we will return a union of the objects
        below the first object in the first box, and those below the second object in the second box.