def get_bounding_boxes(df_shapes, shape_i_columns):
    '''
    Return a `pandas.DataFrame` indexed by `shape_i_columns` (i.e., each row
    corresponds to a single shape/polygon), containing the following columns:

     - `width`: The width of the widest part of the shape.
     - `height`: The height of the tallest part of the shape.
    '''
    xy_groups = df_shapes.groupby(shape_i_columns)[['x', 'y']]
    xy_min = xy_groups.agg('min')
    xy_max = xy_groups.agg('max')

    shapes = (xy_max - xy_min).rename(columns={'x': 'width', 'y': 'height'})
    return xy_min.join(shapes)