class WMSLayer extends AbstractModel implements ImageProvider<TileImageKey> {

    public Collection<GeographicBoundingBox> generateFixedGrid(int level)
    {
        Vector2d cellDimensions = myLayerCellDimensions.get(level);

        final double minLat;
        final double minLon;
        final double maxLat;
        final double maxLon;
        GeographicBoundingBox bbox = myDataTypeInfo.getWmsConfig().getLayerConfig().getBoundingBoxConfig()
                .getGeographicBoundingBox();
        if (bbox == null || bbox.getDeltaLonD() > WORLD_WIDTH || bbox.getDeltaLatD() > WORLD_HEIGHT)
        {
            minLat = -WORLD_HEIGHT * 0.5;
            minLon = -WORLD_WIDTH * 0.5;
            maxLat = WORLD_HEIGHT * 0.5;
            maxLon = WORLD_WIDTH * 0.5;
        }
        else
        {
            minLat = bbox.getLowerLeft().getLatLonAlt().getLatD();
            minLon = bbox.getLowerLeft().getLatLonAlt().getLonD();
            maxLat = bbox.getUpperRight().getLatLonAlt().getLatD();
            maxLon = bbox.getUpperRight().getLatLonAlt().getLonD();
        }

        double lat1 = Math.floor((minLat + WORLD_HEIGHT * .5) / cellDimensions.getY()) * cellDimensions.getY()
                - WORLD_HEIGHT * .5;
        double lastLat = Math.ceil((maxLat + WORLD_HEIGHT * .5) / cellDimensions.getY()) * cellDimensions.getY()
                - WORLD_HEIGHT * .5;

        double baseLon = Math.floor((minLon + WORLD_WIDTH * .5) / cellDimensions.getX()) * cellDimensions.getX()
                - WORLD_WIDTH * .5;
        double lastLon = Math.ceil((maxLon + WORLD_WIDTH * .5) / cellDimensions.getX()) * cellDimensions.getX()
                - WORLD_WIDTH * .5;

        // Make sure we haven't exceed the map bounds
        lat1 = Math.max(lat1, -WORLD_HEIGHT * 0.5);
        baseLon = Math.max(baseLon, -WORLD_WIDTH * 0.5);

        int cols = (int)Math.round((lastLon - baseLon) / cellDimensions.getX());
        int rows = (int)Math.round((lastLat - lat1) / cellDimensions.getY());

        List<GeographicBoundingBox> results = new ArrayList<>(rows * cols);

        for (int row = 0; row < rows; row++)
        {
            double lat2 = lat1 + cellDimensions.getY();
            double lon1 = baseLon;
            for (int col = 0; col < cols; col++)
            {
                double lon2 = lon1 + cellDimensions.getX();
                LatLonAlt lowerLeft = LatLonAlt.createFromDegrees(lat1, lon1);
                LatLonAlt upperRight = LatLonAlt.createFromDegrees(lat2, lon2);
                results.add(new GeographicBoundingBox(lowerLeft, upperRight));
                lon1 = lon2;
            }
            lat1 = lat2;
        }

        return results;
    }

    public  WMSLayer(Builder builder);

}