/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/
package org.geomajas.gwt2.plugin.print.wms.client;
import java.util.ArrayList;
import java.util.List;
import org.geomajas.configuration.client.ClientLayerInfo;
import org.geomajas.geometry.Bbox;
import org.geomajas.geometry.service.BboxService;
import org.geomajas.gwt2.client.map.MapPresenter;
import org.geomajas.gwt2.client.map.layer.Layer;
import org.geomajas.gwt2.client.map.layer.tile.TileConfiguration;
import org.geomajas.gwt2.client.map.render.Tile;
import org.geomajas.gwt2.client.service.TileService;
import org.geomajas.gwt2.plugin.print.client.layerbuilder.PrintableLayersModelBuilder;
import org.geomajas.gwt2.plugin.print.wms.server.dto.WmsClientLayerInfo;
import org.geomajas.gwt2.plugin.wms.client.WmsClient;
import org.geomajas.gwt2.plugin.wms.client.layer.WmsLayer;
import org.geomajas.layer.tile.RasterTile;
import org.geomajas.layer.tile.TileCode;
import org.geomajas.plugin.rasterizing.command.dto.RasterLayerRasterizingInfo;
/**
* Builder for WMS layer.
*
* @author Jan De Moerloose
*/
public class WmsLayerBuilder implements PrintableLayersModelBuilder {
@Override
public boolean supports(Layer object) {
return object instanceof WmsLayer;
}
@Override
public ClientLayerInfo build(MapPresenter mapPresenter, Layer layer, Bbox worldBounds, double resolution) {
WmsLayer tileBasedLayer = (WmsLayer) layer;
TileConfiguration tileConfig = tileBasedLayer.getTileConfiguration();
WmsClientLayerInfo info = new WmsClientLayerInfo();
List<RasterTile> tiles = new ArrayList<RasterTile>();
for (Tile tile : getTiles(tileBasedLayer, mapPresenter.getViewPort().getCrs(), resolution, worldBounds)) {
tiles.add(toRasterTile(tile));
}
info.setTiles(tiles);
info.setTileHeight(tileBasedLayer.getTileConfiguration().getTileHeight());
info.setTileWidth(tileBasedLayer.getTileConfiguration().getTileWidth());
info.setScale(1 / getActualResolution(tileConfig, resolution));
info.setId(tileBasedLayer.getId());
RasterLayerRasterizingInfo rasterInfo = new RasterLayerRasterizingInfo();
rasterInfo.setShowing(tileBasedLayer.isShowing());
rasterInfo.setCssStyle(tileBasedLayer.getOpacity() + "");
info.getWidgetInfo().put(RasterLayerRasterizingInfo.WIDGET_KEY, rasterInfo);
return info;
}
private RasterTile toRasterTile(Tile tile) {
RasterTile rTile = new RasterTile(tile.getBounds(), tile.getCode().toString());
rTile.setCode(new TileCode(tile.getCode().getTileLevel(), tile.getCode().getX(), tile.getCode().getY()));
rTile.setUrl(tile.getUrl());
return rTile;
}
private List<Tile> getTiles(WmsLayer layer, String crs, double resolution, Bbox worldBounds) {
TileConfiguration tileConfig = layer.getTileConfiguration();
Bbox maxBounds = layer.getMaxBounds();
worldBounds = BboxService.intersection(worldBounds, maxBounds);
List<Tile> tiles = new ArrayList<Tile>();
if (worldBounds != null) {
List<org.geomajas.gwt2.client.map.render.TileCode> codes = TileService.getTileCodesForBounds(tileConfig,
worldBounds, resolution);
if (!codes.isEmpty()) {
double actualResolution = tileConfig.getResolution(codes.get(0).getTileLevel());
for (org.geomajas.gwt2.client.map.render.TileCode code : codes) {
Bbox bounds = TileService.getWorldBoundsForTile(tileConfig, code);
Tile tile = new Tile(getScreenBounds(actualResolution, bounds));
tile.setCode(code);
tile.setUrl(WmsClient.getInstance().getWmsService().getMapUrl(layer.getConfiguration(),
bounds, tileConfig.getTileWidth(), tileConfig.getTileHeight()));
tiles.add(tile);
}
}
}
return tiles;
}
private double getActualResolution(TileConfiguration tileConfig, double resolution) {
int tileLevel = tileConfig.getResolutionIndex(resolution);
double actualResolution = tileConfig.getResolution(tileLevel);
return actualResolution;
}
private Bbox getScreenBounds(double resolution, Bbox worldBounds) {
return new Bbox(Math.round(worldBounds.getX() / resolution), -Math.round(worldBounds.getMaxY() / resolution),
Math.round(worldBounds.getMaxX() / resolution) - Math.round(worldBounds.getX() / resolution),
Math.round(worldBounds.getMaxY() / resolution) - Math.round(worldBounds.getY() / resolution));
}
}