All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mapfish.print.map.readers.TileableMapReader Maven / Gradle / Ivy

/*
 * Copyright (C) 2013  Camptocamp
 *
 * This file is part of MapFish Print
 *
 * MapFish Print is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MapFish Print is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MapFish Print.  If not, see .
 */

package org.mapfish.print.map.readers;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.mapfish.print.RenderingContext;
import org.mapfish.print.Transformer;
import org.mapfish.print.map.ParallelMapTileLoader;
import org.mapfish.print.map.renderers.TileRenderer;
import org.mapfish.print.utils.PJsonObject;

public abstract class TileableMapReader extends HTTPMapReader {

    protected TileCacheLayerInfo tileCacheLayerInfo;

    protected TileableMapReader(RenderingContext context, PJsonObject params) {
        super(context, params);
    }

    protected void renderTiles(TileRenderer formatter, Transformer transformer, URI commonUri, ParallelMapTileLoader parallelMapTileLoader) throws IOException, URISyntaxException {
        final List urls = new ArrayList(1);
        final double offsetX;
        final double offsetY;
        final long bitmapTileW;
        final long bitmapTileH;
        int nbTilesW = 0;

        double minGeoX = transformer.getRotatedMinGeoX();
        double minGeoY = transformer.getRotatedMinGeoY();
        double maxGeoX = transformer.getRotatedMaxGeoX();
        double maxGeoY = transformer.getRotatedMaxGeoY();

        if (tileCacheLayerInfo != null) {
            try {
            //tiled
            transformer = fixTiledTransformer(transformer);
            } catch (CloneNotSupportedException ex) {
                Logger.getLogger(TileableMapReader.class.getName()).log(Level.SEVERE, null, ex);
            }

            if (transformer == null) {
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("Resolution out of bounds.");
                }
                urls.add(null);
            }

            bitmapTileW = tileCacheLayerInfo.getWidth();
            bitmapTileH = tileCacheLayerInfo.getHeight();
            final double tileGeoWidth = transformer.getResolution() * bitmapTileW;
            final double tileGeoHeight = transformer.getResolution() * bitmapTileH;


            // TODO I would like to do this sort of thing by extension points for plugins

            // the tileMinGeoSize is not calculated the same way in TileCache
            // and KaMap, so they are treated differently here.
            final float tileMinGeoX;
            final float tileMinGeoY;
            if (this instanceof KaMapCacheMapReader || this instanceof KaMapMapReader) {
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("Kamap min geo x and y calculation used");
                }
                tileMinGeoX = (float) (Math.floor((minGeoX) / tileGeoWidth) * tileGeoWidth);
                tileMinGeoY = (float) (Math.floor((minGeoY) / tileGeoHeight) * tileGeoHeight);
            } else {
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("Default min geo x and y calculation used");
                }
                tileMinGeoX = (float) (tileCacheLayerInfo.getOriginX() + (Math.floor(
                    (minGeoX - tileCacheLayerInfo.getOriginX()) / tileGeoWidth
                ) * tileGeoWidth));
                tileMinGeoY = (float) (tileCacheLayerInfo.getOriginY() + (Math.floor(
                    (minGeoY - tileCacheLayerInfo.getOriginY()) / tileGeoHeight
                ) * tileGeoHeight));
            }

            offsetX = (minGeoX - tileMinGeoX) / transformer.getResolution();
            offsetY = (minGeoY - tileMinGeoY) / transformer.getResolution();
            for (float geoY = tileMinGeoY; geoY < maxGeoY; geoY += tileGeoHeight) {
                nbTilesW = 0;
                for (float geoX = tileMinGeoX; geoX < maxGeoX; geoX += tileGeoWidth) {
                    nbTilesW++;
                    if (tileCacheLayerInfo.isVisible(geoX, geoY, geoX + tileGeoWidth, geoY + tileGeoHeight)) {
                        urls.add(getTileUri(commonUri, transformer, geoX, geoY, geoX + tileGeoWidth, geoY + tileGeoHeight, bitmapTileW, bitmapTileH));
                    } else {
                        if (LOGGER.isDebugEnabled()) {
                            LOGGER.debug("Tile out of bounds: " + getTileUri(commonUri, transformer, geoX, geoY, geoX + tileGeoWidth, geoY + tileGeoHeight, bitmapTileW, bitmapTileH));
                        }
                        urls.add(null);
                    }
                }
            }

        } else {
            //single tile
            nbTilesW = 1;
            offsetX = 0;
            offsetY = 0;
            bitmapTileW = transformer.getRotatedBitmapW();
            bitmapTileH = transformer.getRotatedBitmapH();
            urls.add(getTileUri(commonUri, transformer, minGeoX, minGeoY, maxGeoX, maxGeoY, bitmapTileW, bitmapTileH));
        }
        formatter.render(transformer, urls, parallelMapTileLoader, context, opacity, nbTilesW, offsetX, offsetY, bitmapTileW, bitmapTileH);
    }

    /**
     * fix the resolution to something compatible with the resolutions available in tilecache.
     */
    private Transformer fixTiledTransformer(Transformer transformer) throws CloneNotSupportedException {
        double resolution;

        // if clientResolution is passed from client use it explicitly if available otherwise calculate nearest resolution
        if (this.context.getCurrentPageParams().has("clientResolution")) {
            float clientResolution = this.context.getCurrentPageParams().getFloat("clientResolution");
            boolean hasServerResolution = false;
            for (double serverResolution : this.tileCacheLayerInfo.getResolutions()) {
                if (serverResolution == clientResolution) {
                    hasServerResolution = true;
                }
            }
            if (!hasServerResolution) {
                return null;
            }
            else {
                resolution = clientResolution;
            }
        }
        else {
            double targetResolution = transformer.getGeoW() / transformer.getStraightBitmapW();
            TileCacheLayerInfo.ResolutionInfo resolutionInfo = tileCacheLayerInfo.getNearestResolution(targetResolution);
            resolution = resolutionInfo.value;
        }

        transformer = transformer.clone();
        transformer.setResolution(resolution);
        return transformer;
    }

    /**
     * Adds the query parameters for the given tile.
     */
    protected abstract URI getTileUri(URI commonUri, Transformer transformer, double minGeoX, double minGeoY, double maxGeoX, double maxGeoY, long w, long h) throws URISyntaxException, UnsupportedEncodingException;
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy