Package org.geoserver.geopkg

Source Code of org.geoserver.geopkg.GeoPackageGetMapOutputFormat$GeopackageWrapper

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.geopkg;

import static org.geoserver.geopkg.GeoPkg.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.logging.Logger;

import org.geoserver.catalog.ResourceInfo;
import org.geoserver.gwc.GWC;
import org.geoserver.ows.util.OwsUtils;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.ServiceException;
import org.geoserver.wms.GetMapRequest;
import org.geoserver.wms.MapLayerInfo;
import org.geoserver.wms.RasterCleaner;
import org.geoserver.wms.WMS;
import org.geoserver.wms.WebMap;
import org.geoserver.wms.WebMapService;
import org.geoserver.tiles.AbstractTilesGetMapOutputFormat;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.geopkg.GeoPackage;
import org.geotools.geopkg.Tile;
import org.geotools.geopkg.TileEntry;
import org.geotools.geopkg.TileMatrix;
import org.geotools.referencing.CRS;
import org.geotools.util.logging.Logging;
import org.geowebcache.grid.Grid;
import org.geowebcache.grid.GridSet;
import org.geowebcache.grid.GridSubset;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.google.common.collect.Sets;
import com.vividsolutions.jts.geom.Envelope;

/**
*
* WMS GetMap Output Format for GeoPackage
*
* @author Justin Deoliveira, Boundless
*
*/
public class GeoPackageGetMapOutputFormat extends AbstractTilesGetMapOutputFormat {

    static Logger LOGGER = Logging.getLogger("org.geoserver.geopkg");

    public GeoPackageGetMapOutputFormat(WebMapService webMapService, WMS wms, GWC gwc) {
        super(MIME_TYPE, "." + EXTENSION, Sets.newHashSet(NAMES), webMapService, wms, gwc);
    }
   
    private static class GeopackageWrapper implements TilesFile {

        GeoPackage geopkg;

        TileEntry e;
       
        public GeopackageWrapper(GeoPackage geopkg, TileEntry e) throws IOException {
            this.geopkg = geopkg;
            this.e = e;
        }

        public GeopackageWrapper() throws IOException {           
            this(new GeoPackage(), new TileEntry());
            geopkg.init();
        }

        @Override
        public void setMetadata(String name, ReferencedEnvelope box, String imageFormat, int srid,
                List<MapLayerInfo> mapLayers, int[] minmax, GridSubset gridSubset)
                throws IOException, ServiceException {

            e.setTableName(name);
            if (mapLayers.size() == 1) {
                ResourceInfo r = mapLayers.get(0).getResource();
                if (e.getIdentifier() == null) {
                    e.setIdentifier(r.getTitle());
                }
                if (e.getDescription() == null){
                    e.setDescription(r.getAbstract());
                }
            }
            e.setBounds(box);
            e.setSrid(srid);

            GridSet gridSet = gridSubset.getGridSet();
            for (int z = minmax[0]; z < minmax[1]; z++) {
                Grid g = gridSet.getGrid(z);

                TileMatrix m = new TileMatrix();
                m.setZoomLevel(z);
                m.setMatrixWidth((int) g.getNumTilesWide());
                m.setMatrixHeight((int) g.getNumTilesHigh());
                m.setTileWidth(gridSubset.getTileWidth());
                m.setTileHeight(gridSubset.getTileHeight());

                // TODO: not sure about this
                m.setXPixelSize(g.getResolution());
                m.setYPixelSize(g.getResolution());
                // m.setXPixelSize(gridSet.getPixelSize());
                // m.setYPixelSize(gridSet.getPixelSize());

                e.getTileMatricies().add(m);
            }

            // figure out the actual bounds of the tiles to be renderered
            LOGGER.fine("Creating tile entry" + e.getTableName());
            geopkg.create(e);

        }

        @Override
        public void addTile(int zoom, int x, int y, byte[] data) throws IOException {
            Tile t = new Tile();
            t.setZoom(zoom);
            t.setColumn(x);
            t.setRow(y);
            t.setData(data);
            geopkg.add(e, t);
        }

        @Override
        public File getFile() {
            return geopkg.getFile();
        }

        @Override
        public void close() {
            geopkg.close();
        }
    }
  
    @Override
    protected TilesFile createTilesFile() throws IOException{
      return new GeopackageWrapper();
    }
   
    /**
     * Add tiles to an existing GeoPackage
     *
     * @param geopkg
     * @param map
     * @throws IOException
     */
    public void addTiles(GeoPackage geopkg, TileEntry e, GetMapRequest req, String name) throws IOException{
        addTiles(new GeopackageWrapper(geopkg,e), req, name);
    }
   
   
    /**
     * Special method to add tiles using Geopackage's own grid matrix system rather than GWC gridsubsets
     *
     * @param tiles
     * @param mapLayers
     * @param map
     * @throws IOException
     * @throws ServiceException
     */
    public void addTiles(GeoPackage geopkg, TileEntry e, GetMapRequest request, List<TileMatrix> matrices, String name)
            throws IOException, ServiceException {
               
        List<MapLayerInfo> mapLayers = request.getLayers();
       
        SortedMap<Integer, TileMatrix> matrixSet = new TreeMap<Integer, TileMatrix>();
        for (TileMatrix matrix : matrices){
            matrixSet.put(matrix.getZoomLevel(), matrix);
        }

        if (mapLayers.isEmpty()) {
            return;
        }

        // Get the RasterCleaner object
        RasterCleaner cleaner = GeoServerExtensions.bean(RasterCleaner.class);

        // figure out the actual bounds of the tiles to be renderered
        ReferencedEnvelope bbox = bounds(request);
       
        //set metadata
        e.setTableName(name);
        e.setBounds(bbox);
        e.setSrid(srid(request));
        e.getTileMatricies().addAll(matrices);
        LOGGER.fine("Creating tile entry" + e.getTableName());
        geopkg.create(e);
       
        GetMapRequest req = new GetMapRequest();
        OwsUtils.copy(request, req, GetMapRequest.class);
        req.setLayers(mapLayers);
       
        Map formatOpts = req.getFormatOptions();

        Integer minZoom = null;
        if (formatOpts.containsKey("min_zoom")) {
            minZoom = Integer.parseInt(formatOpts.get("min_zoom").toString());
        }

        Integer maxZoom = null;
        if (formatOpts.containsKey("max_zoom")) {
            maxZoom = Integer.parseInt(formatOpts.get("max_zoom").toString());
        } else if (formatOpts.containsKey("num_zooms")) {
            maxZoom = minZoom + Integer.parseInt(formatOpts.get("num_zooms").toString());
        }
       
        if (minZoom != null || maxZoom != null) {
            matrixSet = matrixSet.subMap(minZoom, maxZoom);
        }

        String imageFormat = formatOpts.containsKey("format") ? parseFormatFromOpts(formatOpts)
                : findBestFormat(request);
               
        CoordinateReferenceSystem crs = getCoordinateReferenceSystem(request);
        if (crs==null) {
            String srs = getSRS(request);
            try {
                crs = CRS.decode(srs);
            } catch (Exception ex) {
                throw new ServiceException(ex);
            }
        }
        double xSpan = crs.getCoordinateSystem().getAxis(0).getMaximumValue() - crs.getCoordinateSystem().getAxis(0).getMinimumValue();
        double ySpan = crs.getCoordinateSystem().getAxis(1).getMaximumValue() - crs.getCoordinateSystem().getAxis(1).getMinimumValue();
        double xOffset = crs.getCoordinateSystem().getAxis(0).getMinimumValue();
        double yOffset = crs.getCoordinateSystem().getAxis(1).getMinimumValue();
   
       
        req.setFormat(imageFormat);
        req.setCrs(crs);
       
        //column and row bounds
        Integer minColumn = null, maxColumn = null, minRow = null, maxRow = null;
        if (formatOpts.containsKey("min_column")) {
            minColumn = Integer.parseInt(formatOpts.get("min_column").toString());
        }
        if (formatOpts.containsKey("max_column")) {
            maxColumn = Integer.parseInt(formatOpts.get("max_column").toString());
        }
        if (formatOpts.containsKey("min_row")) {
            minRow = Integer.parseInt(formatOpts.get("min_row").toString());
        }
        if (formatOpts.containsKey("max_row")) {
            maxRow = Integer.parseInt(formatOpts.get("max_row").toString());
        }

        for (TileMatrix matrix : matrixSet.values()) {

            req.setWidth(matrix.getTileWidth());
            req.setHeight(matrix.getTileHeight());
           
            //long[] intersect = gridSubset.getCoverageIntersection(z, bbox);
            double resX = xSpan / matrix.getMatrixWidth();
            double resY = ySpan / matrix.getMatrixHeight();
           
            long minX = Math.round(Math.floor((bbox.getMinX()-xOffset) / resX));
            long minY = Math.round(Math.floor((bbox.getMinY()-yOffset) / resY));
            long maxX = Math.round(Math.ceil((bbox.getMaxX()-xOffset) / resX));
            long maxY = Math.round(Math.ceil((bbox.getMaxY()-yOffset) / resY));
           
            minX = minColumn == null? minX : Math.max(minColumn, minX);
            maxX = maxColumn == null? maxX : Math.min(maxColumn, maxX);
            minY = minRow == null? minY : Math.max(minRow, minY);
            maxY = maxRow == null? maxY : Math.min(maxRow, maxY);
           
            for (long x = minX; x < maxX; x++) {
                for (long y = minY; y < maxY; y++) {
                    req.setBbox(new Envelope( xOffset + x * resX , xOffset + (x+1) * resX, yOffset + y * resY, yOffset + (y+1) * resY));
                    WebMap result = webMapService.getMap(req);
                    Tile t = new Tile();
                    t.setZoom(matrix.getZoomLevel());
                    t.setColumn((int) x);
                    t.setRow((int) y);
                    t.setData(toBytes(result));
                    geopkg.add(e, t);
                    // Cleanup
                    cleaner.finished(null);
                }
            }
        }
    }

}
TOP

Related Classes of org.geoserver.geopkg.GeoPackageGetMapOutputFormat$GeopackageWrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.