def __init__(self, boundary: Object):
        self._boundary = boundary
        self._is_plane = False
        self._contained_objects = []

        if boundary.is_model():
            (minx, maxx, miny,
             maxy, minz, maxz) = boundary.get_model_bounding_box()
        else:
            minx, maxx, miny, maxy, minz, maxz = boundary.get_bounding_box()
        self._boundary_bbox = BoundingBox(minx, maxx, miny, maxy, minz, maxz)

        height = np.abs(maxz - minz)
        if height == 0:
            height = 1.0
            self._is_plane = True
        self._area = np.abs(maxx - minx) * np.abs(maxy - miny) * height
    def add(self, obj: Object, ignore_collisions: bool = False,
            min_rotation: tuple = (0.0, 0.0, -3.14),
            max_rotation: tuple = (0.0, 0.0, 3.14),
            min_distance: float = 0.01) -> int:
        """Returns true if can add and adds it
        rotation_limits: how mush we allow it to rotate from its original
        position"""

        # Rotate the bounding box randomly
        if obj.is_model():
            bb = obj.get_model_bounding_box()
        else:
            bb = obj.get_bounding_box()
        obj_bbox = BoundingBox(*bb)
        rotation = np.random.uniform(list(min_rotation), list(max_rotation))
        obj_bbox = obj_bbox.rotate(rotation)

        if not obj_bbox.within_boundary(self._boundary_bbox, self._is_plane):
            return -1

        new_pos = self._get_position_within_boundary(obj, obj_bbox)
        obj.set_position(new_pos, self._boundary)
        obj.rotate(list(rotation))
        new_pos = np.array(new_pos)

        if not ignore_collisions:
            for contained_obj in self._contained_objects:
                # Check for collision between each child
                for cont_ob in contained_obj.get_objects_in_tree(
                        exclude_base=False):
                    for placing_ob in obj.get_objects_in_tree(
                            exclude_base=False):
                        if placing_ob.check_collision(cont_ob):
                            return -2
                dist = np.linalg.norm(
                    new_pos - contained_obj.get_position(self._boundary))
                if dist < min_distance:
                    return -3
            self._contained_objects.append(obj)
        return 1