public void addZoomLevel(ReferencedEnvelope bbox, int tileWidth, int tileHeight) { List<Grid> list = grids.getModelObject(); final Grid newGrid = new Grid(); if (list.isEmpty()) { BoundingBox extent = new BoundingBox(bbox.getMinX(), bbox.getMinY(), bbox.getMaxX(), bbox.getMaxY()); final int levels = 1; GridSet tmpGridset = GridSetFactory.createGridSet( "stub", SRS.getEPSG4326(), extent, false, levels, 1D, GridSetFactory.DEFAULT_PIXEL_SIZE_METER, tileWidth, tileHeight, false); Grid grid = tmpGridset.getGridLevels()[0]; newGrid.setResolution(grid.getResolution()); newGrid.setScaleDenominator(grid.getScaleDenominator()); } else { Grid prev = list.get(list.size() - 1); newGrid.setResolution(prev.getResolution() / 2); newGrid.setScaleDenominator(prev.getScaleDenominator() / 2); } list.add(newGrid); grids.setModelObject(list); // TileMatrixSetEditor.this.convertInput(); }
@Test public void testCascadeGetLegendGraphics() throws Exception { // setup the layer WMSLayer layer = createWMSLayer("image/png"); final byte[] responseBody = new String("Fake body").getBytes(); layer.setSourceHelper( new WMSHttpHelper() { @Override public GetMethod executeRequest( URL url, Map<String, String> queryParams, Integer backendTimeout) throws HttpException, IOException { GetMethod response = EasyMock.createMock(GetMethod.class); expect(response.getStatusCode()).andReturn(200); expect(response.getResponseBodyAsStream()) .andReturn(new ByteArrayInputStream(responseBody)); expect(response.getResponseCharSet()).andReturn("UTF-8"); expect(response.getResponseHeader("Content-Type")) .andReturn(new Header("Content-Type", "image/png")); response.releaseConnection(); expectLastCall(); replay(response); return response; } }); MockLockProvider lockProvider = new MockLockProvider(); layer.setLockProvider(lockProvider); // setup the conveyor tile final StorageBroker mockStorageBroker = EasyMock.createMock(StorageBroker.class); String layerId = layer.getName(); MockHttpServletRequest servletReq = new MockHttpServletRequest(); servletReq.setQueryString( "REQUEST=GetLegendGraphic&VERSION=1.0.0&FORMAT=image/png&WIDTH=20&HEIGHT=20&LAYER=topp:states"); MockHttpServletResponse servletResp = new MockHttpServletResponse(); long[] gridLoc = {0, 0, 0}; // x, y, level MimeType mimeType = layer.getMimeTypes().get(0); GridSet gridSet = gridSetBroker.WORLD_EPSG4326; String gridSetId = gridSet.getName(); ConveyorTile tile = new ConveyorTile( mockStorageBroker, layerId, gridSetId, gridLoc, mimeType, null, servletReq, servletResp); // proxy the request, and check the response layer.proxyRequest(tile); assertEquals(200, servletResp.getStatus()); assertEquals("Fake body", servletResp.getContentAsString()); assertEquals("image/png", servletResp.getContentType()); }
@Override public void validate(IValidatable<Set<XMLGridSubset>> validatable) { if (!validate) { return; } Set<XMLGridSubset> gridSubsets = validatable.getValue(); if (gridSubsets == null || gridSubsets.size() == 0) { error(validatable, "GridSubsetsEditor.validation.empty"); return; } final GWC gwc = GWC.get(); for (XMLGridSubset subset : gridSubsets) { final String gridSetName = subset.getGridSetName(); final Integer zoomStart = subset.getZoomStart(); final Integer zoomStop = subset.getZoomStop(); final BoundingBox extent = subset.getExtent(); if (gridSetName == null) { throw new IllegalStateException("GridSet name is null"); } if (zoomStart != null && zoomStop != null) { if (zoomStart.intValue() > zoomStop.intValue()) { error(validatable, "GridSubsetsEditor.validation.zoomLevelsError"); return; } } final GridSetBroker gridSetBroker = gwc.getGridSetBroker(); final GridSet gridSet = gridSetBroker.get(gridSetName); if (null == gridSet) { error(validatable, "GridSubsetsEditor.validation.gridSetNotFound", gridSetName); return; } if (extent != null) { if (extent.isNull() || !extent.isSane()) { error(validatable, "GridSubsetsEditor.validation.invalidBounds"); } final BoundingBox fullBounds = gridSet.getOriginalExtent(); final boolean intersects = fullBounds.intersects(extent); if (!intersects) { error(validatable, "GridSubsetsEditor.validation.boundsOutsideCoverage"); } } } }
@Test public void testSeedMetaTiled() throws Exception { WMSLayer layer = createWMSLayer("image/png"); WMSSourceHelper mockSourceHelper = new MockWMSSourceHelper(); MockLockProvider lockProvider = new MockLockProvider(); layer.setSourceHelper(mockSourceHelper); layer.setLockProvider(lockProvider); final StorageBroker mockStorageBroker = EasyMock.createMock(StorageBroker.class); Capture<TileObject> captured = new Capture<TileObject>(); expect(mockStorageBroker.put(EasyMock.capture(captured))).andReturn(true).anyTimes(); replay(mockStorageBroker); String layerId = layer.getName(); HttpServletRequest servletReq = new MockHttpServletRequest(); HttpServletResponse servletResp = new MockHttpServletResponse(); long[] gridLoc = {0, 0, 0}; // x, y, level MimeType mimeType = layer.getMimeTypes().get(0); GridSet gridSet = gridSetBroker.WORLD_EPSG4326; String gridSetId = gridSet.getName(); ConveyorTile tile = new ConveyorTile( mockStorageBroker, layerId, gridSetId, gridLoc, mimeType, null, servletReq, servletResp); boolean tryCache = false; layer.seedTile(tile, tryCache); assertEquals(1, captured.getValues().size()); TileObject value = captured.getValue(); assertNotNull(value); assertEquals("image/png", value.getBlobFormat()); assertNotNull(value.getBlob()); assertTrue(value.getBlob().getSize() > 0); verify(mockStorageBroker); // check the lock provider was called in a symmetric way lockProvider.verify(); lockProvider.clear(); }
private GeoServerTileLayer mockTileLayer(String layerName, List<String> gridSetNames) throws Exception { GeoServerTileLayer tileLayer = mock(GeoServerTileLayer.class); when(tld.layerExists(eq(layerName))).thenReturn(true); when(tld.getTileLayer(eq(layerName))).thenReturn(tileLayer); when(tileLayer.getName()).thenReturn(layerName); when(tileLayer.isEnabled()).thenReturn(true); final MimeType mimeType1 = MimeType.createFromFormat("image/png"); final MimeType mimeType2 = MimeType.createFromFormat("image/jpeg"); when(tileLayer.getMimeTypes()).thenReturn(ImmutableList.of(mimeType1, mimeType2)); Map<String, GridSubset> subsets = Maps.newHashMap(); Multimap<SRS, GridSubset> bySrs = LinkedHashMultimap.create(); GridSetBroker broker = gridSetBroker; for (String gsetName : gridSetNames) { GridSet gridSet = broker.get(gsetName); XMLGridSubset xmlGridSubset = new XMLGridSubset(); String gridSetName = gridSet.getName(); xmlGridSubset.setGridSetName(gridSetName); GridSubset gridSubSet = xmlGridSubset.getGridSubSet(broker); subsets.put(gsetName, gridSubSet); bySrs.put(gridSet.getSrs(), gridSubSet); when(tileLayer.getGridSubset(eq(gsetName))).thenReturn(gridSubSet); } for (SRS srs : bySrs.keySet()) { List<GridSubset> list = ImmutableList.copyOf(bySrs.get(srs)); when(tileLayer.getGridSubsetsForSRS(eq(srs))).thenReturn(list); } when(tileLayer.getGridSubsets()).thenReturn(subsets.keySet()); // sanity check for (String gsetName : gridSetNames) { assertTrue(tileLayer.getGridSubsets().contains(gsetName)); assertNotNull(tileLayer.getGridSubset(gsetName)); } return tileLayer; }
Integer findClosestZoom(GridSet gridSet, WMSMapContent map) { double reqScale = RendererUtilities.calculateOGCScale(bounds(map), gridSet.getTileWidth(), null); int i = 0; double error = Math.abs(gridSet.getGrid(i).getScaleDenominator() - reqScale); while (i < gridSet.getNumLevels() - 1) { Grid g = gridSet.getGrid(i + 1); double e = Math.abs(g.getScaleDenominator() - reqScale); if (e > error) { break; } else { error = e; } i++; } return Math.max(i, 0); }
int[] findMinMaxZoom(GridSubset gridSubset, WMSMapContent map) { GridSet gridSet = gridSubset.getGridSet(); Map formatOpts = map.getRequest().getFormatOptions(); Integer minZoom = null; if (formatOpts.containsKey("min_zoom")) { minZoom = Integer.parseInt(formatOpts.get("min_zoom").toString()); } if (minZoom == null) { minZoom = findClosestZoom(gridSet, map); } 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 (maxZoom == null) { // walk down until we hit too many tiles maxZoom = findMaxZoomAuto(gridSubset, minZoom, map); } if (maxZoom < minZoom) { throw new ServiceException( format("maxZoom (%d) can not be less than minZoom (%d)", maxZoom, minZoom)); } // end index if (maxZoom > gridSet.getNumLevels()) { LOGGER.warning( format( "Max zoom (%d) can't be greater than number of zoom levels (%d)", maxZoom, gridSet.getNumLevels())); maxZoom = gridSet.getNumLevels(); } return new int[] {minZoom, maxZoom}; }
private void tileMatrixSet(StringBuilder str, GridSet gridSet) { str.append(" <TileMatrixSet>\n"); str.append(" <ows:Identifier>" + gridSet.getName() + "</ows:Identifier>\n"); // If the following is not good enough, please get in touch and we will try to fix it :) str.append( " <ows:SupportedCRS>urn:ogc:def:crs:EPSG::" + gridSet.getSrs().getNumber() + "</ows:SupportedCRS>\n"); // TODO detect these str.append(" // <WellKnownScaleSet>urn:ogc:def:wkss:GlobalCRS84Pixel</WellKnownScaleSet>\n"); Grid[] grids = gridSet.getGrids(); for (int i = 0; i < grids.length; i++) { double[] tlCoordinates = gridSet.getOrderedTopLeftCorner(i); tileMatrix( str, grids[i], tlCoordinates, gridSet.getTileWidth(), gridSet.getTileHeight(), gridSet.isScaleWarning()); } str.append(" </TileMatrixSet>\n"); }
@Test public void testSeedJpegPngMetaTiled() throws Exception { WMSLayer layer = createWMSLayer("image/vnd.jpeg-png"); WMSSourceHelper mockSourceHelper = new WMSSourceHelper() { @Override protected void makeRequest( TileResponseReceiver tileRespRecv, WMSLayer layer, Map<String, String> wmsParams, MimeType expectedMimeType, Resource target) throws GeoWebCacheException { int width = Integer.parseInt(wmsParams.get("WIDTH")); int height = Integer.parseInt(wmsParams.get("HEIGHT")); assertEquals(768, width); assertEquals(768, height); BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); Graphics2D graphics = img.createGraphics(); graphics.setColor(Color.BLACK); // fill an L shaped set of tiles, making a few partially filled graphics.fillRect(0, 0, width, 300); graphics.fillRect(0, 0, 300, height); graphics.dispose(); ByteArrayOutputStream output = new ByteArrayOutputStream(); try { ImageIO.write(img, "PNG", output); ImageIO.write(img, "PNG", new java.io.File("/tmp/meta.png")); } catch (IOException e) { throw new RuntimeException(e); } try { target.transferFrom( Channels.newChannel(new ByteArrayInputStream(output.toByteArray()))); } catch (IOException e) { throw new RuntimeException(e); } } }; MockLockProvider lockProvider = new MockLockProvider(); layer.setSourceHelper(mockSourceHelper); layer.setLockProvider(lockProvider); final StorageBroker mockStorageBroker = EasyMock.createMock(StorageBroker.class); Capture<TileObject> captured = new Capture<TileObject>(CaptureType.ALL); expect(mockStorageBroker.put(EasyMock.capture(captured))) .andAnswer( new IAnswer<Boolean>() { @Override public Boolean answer() throws Throwable { TileObject to = (TileObject) EasyMock.getCurrentArguments()[0]; assertEquals("image/vnd.jpeg-png", to.getBlobFormat()); assertNotNull(to.getBlob()); assertTrue(to.getBlob().getSize() > 0); String format = ImageMime.jpegPng.getMimeType(to.getBlob()); long[] xyz = to.getXYZ(); assertEquals(10, xyz[2]); // check the ones in the full black area are jpeg, the others png if (xyz[0] == 900 || xyz[1] == 602) { assertEquals("image/jpeg", format); } else { assertEquals("image/png", format); } return true; } }) .anyTimes(); replay(mockStorageBroker); String layerId = layer.getName(); HttpServletRequest servletReq = new MockHttpServletRequest(); HttpServletResponse servletResp = new MockHttpServletResponse(); long[] gridLoc = {900, 600, 10}; // x, y, level MimeType mimeType = layer.getMimeTypes().get(0); GridSet gridSet = gridSetBroker.WORLD_EPSG4326; String gridSetId = gridSet.getName(); ConveyorTile tile = new ConveyorTile( mockStorageBroker, layerId, gridSetId, gridLoc, mimeType, null, servletReq, servletResp); boolean tryCache = false; layer.seedTile(tile, tryCache); assertEquals(9, captured.getValues().size()); verify(mockStorageBroker); // check the lock provider was called in a symmetric way lockProvider.verify(); lockProvider.clear(); }
private static String generateHTML( TileLayer layer, String gridSetStr, String formatStr, boolean asPlugin) throws GeoWebCacheException { String layerName = layer.getName(); GridSubset gridSubset = layer.getGridSubset(gridSetStr); BoundingBox bbox = gridSubset.getGridSetBounds(); BoundingBox zoomBounds = gridSubset.getOriginalExtent(); String res = "resolutions: " + Arrays.toString(gridSubset.getResolutions()) + ",\n"; String units = "units: \"" + gridSubset.getGridSet().guessMapUnits() + "\",\n"; String openLayersPath; if (asPlugin) { openLayersPath = "../openlayers/OpenLayers.js"; } else { openLayersPath = "../openlayers/OpenLayers.js"; } String page = "<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>\n" + "<meta http-equiv=\"imagetoolbar\" content=\"no\">\n" + "<title>" + layerName + " " + gridSubset.getName() + " " + formatStr + "</title>\n" + "<style type=\"text/css\">\n" + "body { font-family: sans-serif; font-weight: bold; font-size: .8em; }\n" + "body { border: 0px; margin: 0px; padding: 0px; }\n" + "#map { width: 85%; height: 85%; border: 0px; padding: 0px; }\n" + "</style>\n" + "<script src=\"" + openLayersPath + "\"></script> \n" + "<script type=\"text/javascript\"> \n" + "var map, demolayer; \n" + " // sets the chosen modifiable parameter \n" + " function setParam(name, value){ \n" + " str = \"demolayer.mergeNewParams({\" + name + \": '\" + value + \"'})\" \n" + " // alert(str); \n" + " eval(str); \n" + " } \n" + "OpenLayers.DOTS_PER_INCH = " + gridSubset.getDotsPerInch() + ";\n" + "OpenLayers.Util.onImageLoadErrorColor = 'transparent';\n" + "function init(){\n" + "var mapOptions = { \n" + res + "projection: new OpenLayers.Projection('" + gridSubset.getSRS().toString() + "'),\n" + "maxExtent: new OpenLayers.Bounds(" + bbox.toString() + "),\n" + units + "controls: []\n" + "};\n" + "map = new OpenLayers.Map('map', mapOptions );\n" + "map.addControl(new OpenLayers.Control.PanZoomBar({\n" + " position: new OpenLayers.Pixel(2, 15)\n" + "}));\n" + "map.addControl(new OpenLayers.Control.Navigation());\n" + "map.addControl(new OpenLayers.Control.Scale($('scale')));\n" + "map.addControl(new OpenLayers.Control.MousePosition({element: $('location')}));\n" + "demolayer = new OpenLayers.Layer.WMS(\n" + "\"" + layerName + "\",\"../service/wms\",\n" + "{layers: '" + layerName + "', format: '" + formatStr + "' },\n" + "{ tileSize: new OpenLayers.Size(" + gridSubset.getTileWidth() + "," + gridSubset.getTileHeight() + ")"; /* * If the gridset has a top left tile origin, lets tell that to open layers. Otherwise it'll * calculate tile bounds based on the bbox bottom left corner, leading to misaligned * requests. */ GridSet gridSet = gridSubset.getGridSet(); if (gridSet.isTopLeftAligned()) { page += ",\n tileOrigin: new OpenLayers.LonLat(" + bbox.getMinX() + ", " + bbox.getMaxY() + ")"; } page += "});\n" + "map.addLayer(demolayer);\n" + "map.zoomToExtent(new OpenLayers.Bounds(" + zoomBounds.toString() + "));\n" + "// The following is just for GetFeatureInfo, which is not cached. Most people do not need this \n" + "map.events.register('click', map, function (e) {\n" + " document.getElementById('nodelist').innerHTML = \"Loading... please wait...\";\n" + " var params = {\n" + " REQUEST: \"GetFeatureInfo\",\n" + " EXCEPTIONS: \"application/vnd.ogc.se_xml\",\n" + " BBOX: map.getExtent().toBBOX(),\n" + " X: e.xy.x,\n" + " Y: e.xy.y,\n" + " INFO_FORMAT: 'text/html',\n" + " QUERY_LAYERS: map.layers[0].params.LAYERS,\n" + " FEATURE_COUNT: 50,\n" + " Layers: '" + layerName + "',\n" + " Styles: '',\n" + " Srs: '" + gridSubset.getSRS().toString() + "',\n" + " WIDTH: map.size.w,\n" + " HEIGHT: map.size.h,\n" + " format: \"" + formatStr + "\" };\n" + " OpenLayers.loadURL(\"../service/wms\", params, this, setHTML, setHTML);\n" + " OpenLayers.Event.stop(e);\n" + " });\n" + "}\n" + "function setHTML(response){\n" + " document.getElementById('nodelist').innerHTML = response.responseText;\n" + "};\n" + "</script>\n" + "</head>\n" + "<body onload=\"init()\">\n" + "<div id=\"params\">" + makeModifiableParameters(layer) + "</div>\n" + "<div id=\"map\"></div>\n" + "<div id=\"nodelist\"></div>\n" + "</body>\n" + "</html>"; return page; }
void addTileLayers(GeoPackage geopkg, List<MapLayerInfo> mapLayers, WMSMapContent map) throws IOException { if (mapLayers.isEmpty()) { return; } // figure out a name for the file entry String tileEntryName = null; Map formatOpts = map.getRequest().getFormatOptions(); if (formatOpts.containsKey("tileset_name")) { tileEntryName = (String) formatOpts.get("tileset_name"); } if (tileEntryName == null) { tileEntryName = map.getTitle(); } if (tileEntryName == null && mapLayers.size() == 1) { Iterator<MapLayerInfo> it = mapLayers.iterator(); tileEntryName = it.next().getLayerInfo().getName(); } GridSubset gridSubset = findBestGridSubset(map); int[] minmax = findMinMaxZoom(gridSubset, map); BoundingBox bbox = bbox(map); TileEntry e = new TileEntry(); e.setTableName(tileEntryName); if (mapLayers.size() == 1) { ResourceInfo r = mapLayers.get(0).getResource(); e.setIdentifier(r.getTitle()); e.setDescription(r.getAbstract()); } e.setBounds( new ReferencedEnvelope( findTileBounds(gridSubset, bbox, minmax[0]), map.getCoordinateReferenceSystem())); e.setSrid(srid(map)); 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); // create a prototype getmap request GetMapRequest req = new GetMapRequest(); OwsUtils.copy(map.getRequest(), req, GetMapRequest.class); req.setLayers(mapLayers); String imageFormat = formatOpts.containsKey("format") ? parseFormatFromOpts(formatOpts) : findBestFormat(map); req.setFormat(imageFormat); req.setWidth(gridSubset.getTileWidth()); req.setHeight(gridSubset.getTileHeight()); // count tiles as we generate them int ntiles = 0; // flag determining if tile row indexes we store in database should be inverted boolean flipy = Boolean.valueOf((String) formatOpts.get("flipy")); for (int z = minmax[0]; z < minmax[1]; z++) { long[] intersect = gridSubset.getCoverageIntersection(z, bbox); for (long x = intersect[0]; x <= intersect[2]; x++) { for (long y = intersect[1]; y <= intersect[3]; y++) { BoundingBox box = gridSubset.boundsFromIndex(new long[] {x, y, z}); req.setBbox(new Envelope(box.getMinX(), box.getMaxX(), box.getMinY(), box.getMaxY())); Tile t = new Tile(); t.setZoom(z); t.setColumn((int) x); t.setRow((int) (flipy ? gridSubset.getNumTilesHigh(z) - (y + 1) : y)); WebMap result = webMapService.getMap(req); t.setData(toBytes(result)); geopkg.add(e, t); // images we encode are actually kept around, we need to clean them up if (ntiles++ == TILE_CLEANUP_INTERVAL) { cleanUpImages(); ntiles = 0; } } } } }