'Calculate the Bounds of a list of Point Features, suitable for
setting map bounds. If no features are supplied, the current map
configuration bounds will be returned.
e.g. When a map is displayed that focuses on a collection of points,
the map is zoomed to show just the region bounding the points.
e.g. To use in GPX export for correct zooming
Ensure a minimum size of bounding box, and that the points
are inset from the border.
@param features: A list of point features
@param bbox_min_size: Minimum bounding box - gives a minimum width
and height in degrees for the region shown.
Without this, a map showing a single point would not show any
extent around that point.
@param bbox_inset: Bounding box insets - adds a small amount of
distance outside the points.
Without this, the outermost points would be on the bounding
box, and might not be visible.
@return: An appropriate map bounding box, as a dict:
dict(lon_min=lon_min, lat_min=lat_min,
lon_max=lon_max, lat_max=lat_max)
@ToDo: Support Polygons (separate function?)'

def get_bounds(self, features=None, parent=None, bbox_min_size=None, bbox_inset=None):

    if features:
        lon_min = 180
        lat_min = 90
        lon_max = (-180)
        lat_max = (-90)
        try:
            lon = features[0].lon
            simple = True
        except (AttributeError, KeyError):
            simple = False
        for feature in features:
            try:
                if simple:
                    lon = feature.lon
                    lat = feature.lat
                else:
                    lon = feature.gis_location.lon
                    lat = feature.gis_location.lat
            except AttributeError:
                continue
            if ((lon is None) or (lat is None)):
                continue
            lon_min = min(lon, lon_min)
            lat_min = min(lat, lat_min)
            lon_max = max(lon, lon_max)
            lat_max = max(lat, lat_max)
        settings = current.deployment_settings
        bbox_min_size = (bbox_min_size or settings.get_gis_bbox_inset())
        delta_lon = ((bbox_min_size - (lon_max - lon_min)) / 2.0)
        if (delta_lon > 0):
            lon_min -= delta_lon
            lon_max += delta_lon
        delta_lat = ((bbox_min_size - (lat_max - lat_min)) / 2.0)
        if (delta_lat > 0):
            lat_min -= delta_lat
            lat_max += delta_lat
        bbox_inset = (bbox_inset or settings.get_gis_bbox_inset())
        lon_min -= bbox_inset
        lon_max += bbox_inset
        lat_min -= bbox_inset
        lat_max += bbox_inset
    else:
        config = GIS.get_config()
        if (config.lat_min is not None):
            lat_min = config.lat_min
        else:
            lat_min = (-90)
        if (config.lon_min is not None):
            lon_min = config.lon_min
        else:
            lon_min = (-180)
        if (config.lat_max is not None):
            lat_max = config.lat_max
        else:
            lat_max = 90
        if (config.lon_max is not None):
            lon_max = config.lon_max
        else:
            lon_max = 180
    return dict(lon_min=lon_min, lat_min=lat_min, lon_max=lon_max, lat_max=lat_max)
