private void layerGridSubSets(StringBuilder str, TileLayer layer) { Iterator<GridSubset> gridSubsets = layer.getGridSubsets().values().iterator(); while (gridSubsets.hasNext()) { GridSubset gridSubset = gridSubsets.next(); str.append(" <TileMatrixSetLink>"); str.append(" <TileMatrixSet>" + gridSubset.getName() + "</TileMatrixSet>\n"); if (!gridSubset.fullGridSetCoverage()) { String[] levelNames = gridSubset.getGridNames(); long[][] wmtsLimits = gridSubset.getWMTSCoverages(); str.append(" <TileMatrixSetLimits>\n"); for (int i = 0; i < levelNames.length; i++) { str.append(" <TileMatrixLimits>\n"); str.append(" <TileMatrix>" + levelNames[i] + "</TileMatrix>\n"); str.append(" <MinTileRow>" + wmtsLimits[i][1] + "</MinTileRow>\n"); str.append(" <MaxTileRow>" + wmtsLimits[i][3] + "</MaxTileRow>\n"); str.append(" <MinTileCol>" + wmtsLimits[i][0] + "</MinTileCol>\n"); str.append(" <MaxTileCol>" + wmtsLimits[i][2] + "</MaxTileCol>\n"); str.append(" </TileMatrixLimits>\n"); } str.append(" </TileMatrixSetLimits>\n"); } str.append(" </TileMatrixSetLink>"); } }
private void capabilityVendorSpecificTileset( StringBuilder str, TileLayer layer, GridSubset grid, String formatStr, String styleName) throws GeoWebCacheException { String srsStr = grid.getSRS().toString(); StringBuilder resolutionsStr = new StringBuilder(); double[] res = grid.getResolutions(); for (int i = 0; i < res.length; i++) { resolutionsStr.append(Double.toString(res[i]) + " "); } String[] bs = boundsPrep(grid.getCoverageBestFitBounds()); str.append(" <TileSet>\n"); str.append(" <SRS>" + srsStr + "</SRS>\n"); str.append( " <BoundingBox SRS=\"" + srsStr + "\" minx=\"" + bs[0] + "\" miny=\"" + bs[1] + "\" maxx=\"" + bs[2] + "\" maxy=\"" + bs[3] + "\" />\n"); str.append(" <Resolutions>" + resolutionsStr.toString() + "</Resolutions>\n"); str.append(" <Width>" + grid.getTileWidth() + "</Width>\n"); str.append(" <Height>" + grid.getTileHeight() + "</Height>\n"); str.append(" <Format>" + formatStr + "</Format>\n"); str.append(" <Layers>" + layer.getName() + "</Layers>\n"); str.append(" <Styles>").append(ServletUtils.URLEncode(styleName)).append("</Styles>\n"); str.append(" </TileSet>\n"); }
public void apply(ConveyorTile convTile) throws RequestFilterException { TileLayer tl = convTile.getLayer(); // SRS srs = convTile.getSRS(); GridSubset gridSubset = tl.getGridSubset(convTile.getGridSetId()); int z = (int) convTile.getTileIndex()[2]; long[] gridCoverage = gridSubset.getCoverage(z); // Figure out the radius long width = gridCoverage[2] - gridCoverage[0]; long height = gridCoverage[3] - gridCoverage[1]; // Rounding must always err on the side of // caution if you want to use KML hierarchies long maxRad = 0; if (width > height) { maxRad = (width / 4) + 1; } else { maxRad = (height / 4) + 1; } // Figure out how the requested bounds relate long midX = gridCoverage[0] + width / 2; long midY = gridCoverage[1] + height / 2; long xDist = midX - convTile.getTileIndex()[0]; long yDist = midY - convTile.getTileIndex()[1]; long rad = Math.round(Math.sqrt(xDist * xDist + yDist * yDist)); if (rad > maxRad) { throw new BlankTileException(this); } }
private void layerWGS84BoundingBox(StringBuilder str, TileLayer layer) { GridSubset subset = layer.getGridSubsetForSRS(SRS.getEPSG4326()); if (subset != null) { double[] coords = subset.getOriginalExtent().getCoords(); str.append(" <ows:WGS84BoundingBox>\n"); str.append(" <ows:LowerCorner>" + coords[0] + " " + coords[1] + "</ows:LowerCorner>\n"); str.append(" <ows:UpperCorner>" + coords[2] + " " + coords[3] + "</ows:UpperCorner>\n"); str.append(" </ows:WGS84BoundingBox>\n"); } }
private void vendorSpecificTileset( final Translator tx, final TileLayer layer, final GridSubset grid, final String format) { String srsStr = grid.getSRS().toString(); StringBuilder resolutionsStr = new StringBuilder(); double[] res = grid.getResolutions(); for (int i = 0; i < res.length; i++) { resolutionsStr.append(Double.toString(res[i]) + " "); } String[] bs = boundsPrep(grid.getCoverageBestFitBounds()); tx.start("TileSet"); tx.start("SRS"); tx.chars(srsStr); tx.end("SRS"); AttributesImpl atts; atts = new AttributesImpl(); atts.addAttribute("", "SRS", "SRS", "", srsStr); atts.addAttribute("", "minx", "minx", "", bs[0]); atts.addAttribute("", "miny", "miny", "", bs[1]); atts.addAttribute("", "maxx", "maxx", "", bs[2]); atts.addAttribute("", "maxy", "maxy", "", bs[3]); tx.start("BoundingBox", atts); tx.end("BoundingBox"); tx.start("Resolutions"); tx.chars(resolutionsStr.toString()); tx.end("Resolutions"); tx.start("Width"); tx.chars(String.valueOf(grid.getTileWidth())); tx.end("Width"); tx.start("Height"); tx.chars(String.valueOf(grid.getTileHeight())); tx.end("Height"); tx.start("Format"); tx.chars(format); tx.end("Format"); tx.start("Layers"); tx.chars(layer.getName()); tx.end("Layers"); // TODO ignoring styles for now tx.start("Styles"); tx.end("Styles"); tx.end("TileSet"); }
Envelope findTileBounds(GridSubset gridSubset, BoundingBox bbox, int z) { long[] i = gridSubset.getCoverageIntersection(z, bbox); BoundingBox b1 = gridSubset.boundsFromIndex(new long[] {i[0], i[1], i[4]}); BoundingBox b2 = gridSubset.boundsFromIndex(new long[] {i[2], i[3], i[4]}); return new Envelope( Math.min(b1.getMinX(), b2.getMinX()), Math.max(b1.getMaxX(), b2.getMaxX()), Math.min(b1.getMinY(), b2.getMinY()), Math.max(b1.getMaxY(), b2.getMaxY())); }
Integer findMaxZoomAuto(GridSubset gridSubset, Integer minZoom, WMSMapContent map) { BoundingBox bbox = bbox(map); int zoom = minZoom; int ntiles = 0; while (ntiles < 256 && zoom < gridSubset.getGridSet().getNumLevels()) { long[] intersect = gridSubset.getCoverageIntersection(zoom, bbox); ntiles += (intersect[2] - intersect[0] + 1) * (intersect[3] - intersect[1] + 1); zoom++; } return zoom; }
protected void determineSourceResolution() { xResolution = reqBounds.getWidth() / reqWidth; yResolution = reqBounds.getHeight() / reqHeight; double tmpResolution; // We use the smallest one if (yResolution < xResolution) { tmpResolution = yResolution; } else { tmpResolution = xResolution; } log.debug( "x res: " + xResolution + " y res: " + yResolution + " tmpResolution: " + tmpResolution); // Cut ourselves 0.5% slack double compResolution = 1.005 * tmpResolution; double[] resArray = gridSubset.getResolutions(); for (srcIdx = 0; srcIdx < resArray.length; srcIdx++) { srcResolution = resArray[srcIdx]; if (srcResolution < compResolution) { break; } } if (srcIdx >= resArray.length) { srcIdx = resArray.length - 1; } log.debug("z: " + srcIdx + " , resolution: " + srcResolution + " (" + tmpResolution + ")"); // At worst, we have the best resolution possible }
@Test public void testParseMaplinkAndLayersWithGeoJSONFromJsonTest() throws IOException, ParseException, com.vividsolutions.jts.io.ParseException { XMLConfiguration config = shared.getConfig(); TileLayer tileLayer = config.getTileLayer(layerTemplate); GridSubset gridSubset = tileLayer.getGridSubset(gridSubsetName); MapLayerJSONParser layerJsonParser = new MapLayerJSONParser(props); MaplinkGeoJsonParser parser = new MaplinkGeoJsonParser(); parser.setDebug(true); InputStream inp = MapProducer.class.getResourceAsStream("geojsPrintTest.json"); try { assertTrue(MapLinkGeoJsonParseContext.Default.getPm().buildMap); Map<String, ?> root = parser.parse(inp); assertTrue(root.size() != 0); assertTrue(root.get("layers") != null); assertTrue(root.get("maplink") != null); assertTrue(root.get("state") != null); assertTrue(root.get("layers") != null); MapLink mapLink = layerJsonParser.parseMapLinkJSON(root, shared.getGf(), gridSubset.getResolutions()); assertTrue(mapLink != null); } finally { inp.close(); } }
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}; }
protected void renderCanvas() throws OutsideCoverageException, GeoWebCacheException, IOException { // Now we loop over all the relevant tiles and write them to the canvas, // Starting at the bottom, moving to the right and up // Bottom row of tiles, in tile coordinates long starty = srcRectangle[1]; // gridy is the tile row index for (long gridy = starty; gridy <= srcRectangle[3]; gridy++) { int tiley = 0; int canvasy = (int) (srcRectangle[3] - gridy) * gridSubset.getTileHeight(); int tileHeight = gridSubset.getTileHeight(); if (canvOfs.top > 0) { // Add padding canvasy += canvOfs.top; } else { // Top tile is cut off if (gridy == srcRectangle[3]) { // This one starts at the top, so canvasy remains 0 tileHeight = tileHeight + canvOfs.top; tiley = -canvOfs.top; } else { // Offset that the first tile contributed, // rather, we subtract what it did not contribute canvasy += canvOfs.top; } } if (gridy == srcRectangle[1] && canvOfs.bottom < 0) { // Check whether we only use part of the first tiles (bottom row) // Offset is negative, slice the bottom off the tile tileHeight += canvOfs.bottom; } long startx = srcRectangle[0]; for (long gridx = startx; gridx <= srcRectangle[2]; gridx++) { long[] gridLoc = {gridx, gridy, srcIdx}; ConveyorTile tile = new ConveyorTile( sb, layer.getName(), gridSubset.getName(), gridLoc, ImageMime.png, fullParameters, null, null); // Check whether this tile is to be rendered at all try { layer.applyRequestFilters(tile); } catch (RequestFilterException e) { log.debug(e.getMessage()); continue; } layer.getTile(tile); BufferedImage tileImg = ImageIO.read(tile.getBlob().getInputStream()); int tilex = 0; int canvasx = (int) (gridx - startx) * gridSubset.getTileWidth(); int tileWidth = gridSubset.getTileWidth(); if (canvOfs.left > 0) { // Add padding canvasx += canvOfs.left; } else { // Leftmost tile is cut off if (gridx == srcRectangle[0]) { // This one starts to the left top, so canvasx remains 0 tileWidth = tileWidth + canvOfs.left; tilex = -canvOfs.left; } else { // Offset that the first tile contributed, // rather, we subtract what it did not contribute canvasx += canvOfs.left; } } if (gridx == srcRectangle[2] && canvOfs.right < 0) { // Check whether we only use part of the first tiles (bottom row) // Offset is negative, slice the bottom off the tile tileWidth = tileWidth + canvOfs.right; } // TODO We should really ensure we can never get here if (tileWidth == 0 || tileHeight == 0) { log.debug("tileWidth: " + tileWidth + " tileHeight: " + tileHeight); continue; } // Cut down the tile to the part we want if (tileWidth != gridSubset.getTileWidth() || tileHeight != gridSubset.getTileHeight()) { log.debug( "tileImg.getSubimage(" + tilex + "," + tiley + "," + tileWidth + "," + tileHeight + ")"); tileImg = tileImg.getSubimage(tilex, tiley, tileWidth, tileHeight); } // Render the tile on the big canvas log.debug( "drawImage(subtile," + canvasx + "," + canvasy + ",null) " + Arrays.toString(gridLoc)); gfx.drawImage(tileImg, canvasx, canvasy, null); // imageObserver } } gfx.dispose(); }
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; }
private static String tableRows( TileLayerDispatcher tileLayerDispatcher, GridSetBroker gridSetBroker) throws GeoWebCacheException { StringBuffer buf = new StringBuffer(); Set<String> layerList = new TreeSet<String>(tileLayerDispatcher.getLayerNames()); for (String layerName : layerList) { TileLayer layer = tileLayerDispatcher.getTileLayer(layerName); buf.append( "<tr><td style=\"min-width: 100px;\"><strong>" + layer.getName() + "</strong><br />\n"); buf.append("<a href=\"rest/seed/" + layer.getName() + "\">Seed this layer</a>\n"); buf.append("</td><td>" + layer.isEnabled() + "</td>"); buf.append("<td><table width=\"100%\">"); int count = 0; for (String gridSetId : layer.getGridSubsets()) { GridSubset gridSubset = layer.getGridSubset(gridSetId); String gridSetName = gridSubset.getName(); if (gridSetName.length() > 20) { gridSetName = gridSetName.substring(0, 20) + "..."; } buf.append("<tr><td style=\"width: 170px;\">").append(gridSetName); buf.append("</td><td>OpenLayers: ["); Iterator<MimeType> mimeIter = layer.getMimeTypes().iterator(); boolean prependComma = false; while (mimeIter.hasNext()) { MimeType mime = mimeIter.next(); if (mime instanceof ImageMime) { if (prependComma) { buf.append(", "); } else { prependComma = true; } buf.append(generateDemoUrl(layer.getName(), gridSubset.getName(), (ImageMime) mime)); } } buf.append("]</td><td>\n"); if (gridSubset.getName().equals(gridSetBroker.WORLD_EPSG4326.getName())) { buf.append(" KML: ["); String prefix = ""; prependComma = false; Iterator<MimeType> kmlIter = layer.getMimeTypes().iterator(); while (kmlIter.hasNext()) { MimeType mime = kmlIter.next(); if (mime instanceof ImageMime || mime == XMLMime.kml) { if (prependComma) { buf.append(", "); } else { prependComma = true; } buf.append( "<a href=\"" + prefix + "service/kml/" + layer.getName() + "." + mime.getFileExtension() + ".kml\">" + mime.getFileExtension() + "</a>"); } else if (mime == XMLMime.kmz) { if (prependComma) { buf.append(", "); } else { prependComma = true; } buf.append( "<a href=\"" + prefix + "service/kml/" + layer.getName() + ".kml.kmz\">kmz</a>"); } } buf.append("]"); } else { // No Google Earth support } buf.append("</td></tr>"); count++; } // if(count == 0) { // buf.append("<tr><td colspan=\"2\"><i>None</i></td></tr>\n"); // } buf.append("</table></td>\n"); buf.append("</tr>\n"); } return buf.toString(); }
GridSubset findBestGridSubset(WMSMapContent map) { GetMapRequest req = map.getRequest(); Map formatOpts = req.getFormatOptions(); GridSetBroker gridSetBroker = gwc.getGridSetBroker(); GridSet gridSet = null; // first check format options to see if explicitly specified if (formatOpts.containsKey("gridset")) { gridSet = gridSetBroker.get(formatOpts.get("gridset").toString()); } // next check srs if (gridSet == null) { gridSet = gridSetBroker.get(req.getSRS().toUpperCase()); } if (gridSet != null) { return GridSubsetFactory.createGridSubSet(gridSet); } CoordinateReferenceSystem crs = map.getCoordinateReferenceSystem(); // look up epsg code Integer epsgCode = null; try { epsgCode = CRS.lookupEpsgCode(crs, false); } catch (Exception e) { throw new ServiceException("Unable to determine epsg code for " + crs, e); } if (epsgCode == null) { throw new ServiceException("Unable to determine epsg code for " + crs); } SRS srs = SRS.getSRS(epsgCode); // figure out the appropriate grid sub set Set<GridSubset> gridSubsets = new LinkedHashSet<GridSubset>(); for (MapLayerInfo l : req.getLayers()) { TileLayer tl = gwc.getTileLayerByName(l.getName()); if (tl == null) { throw new ServiceException("No tile layer for " + l.getName()); } List<GridSubset> theseGridSubsets = tl.getGridSubsetsForSRS(srs); if (gridSubsets.isEmpty()) { gridSubsets.addAll(theseGridSubsets); } else { gridSubsets.retainAll(theseGridSubsets); } if (gridSubsets.isEmpty()) { throw new ServiceException( "No suitable " + epsgCode + " grid subset for " + req.getLayers()); } } if (gridSubsets.size() > 1) { if (LOGGER.isLoggable(Level.WARNING)) { StringBuilder msg = new StringBuilder("Found multiple grid subsets: "); for (GridSubset gs : gridSubsets) { msg.append(gs.getName()).append(", "); } msg.setLength(msg.length() - 2); msg.append(". Choosing first."); LOGGER.warning(msg.toString()); } } return gridSubsets.iterator().next(); }
/** * Make sure when seeding a given zoom level, the correct tiles are sent to the {@link * StorageBroker} * * @throws Exception */ @SuppressWarnings("serial") public void testSeedStoredTiles() throws Exception { WMSLayer tl = createWMSLayer("image/png"); // create an image to be returned by the mock WMSSourceHelper // / final byte[] fakeWMSResponse = createFakeSourceImage(tl); // WMSSourceHelper that on makeRequest() returns always the saqme fake image WMSSourceHelper mockSourceHelper = new MockWMSSourceHelper(); // EasyMock.createMock(WMSSourceHelper.class); // expect(mockSourceHelper.makeRequest((WMSMetaTile) // anyObject())).andReturn(fakeWMSResponse) // .anyTimes(); // replay(mockSourceHelper); tl.setSourceHelper(mockSourceHelper); final String gridSetId = tl.getGridSubsets().iterator().next(); final int zoomLevel = 2; SeedRequest req = createRequest(tl, TYPE.SEED, zoomLevel, zoomLevel); /* * Create a mock storage broker that has never an image in its blob store and that captures * the TileObject the seeder requests it to store for further test validation */ final StorageBroker mockStorageBroker = EasyMock.createMock(StorageBroker.class); Capture<TileObject> storedObjects = new Capture<TileObject>() { /** Override because setValue with anyTimes() resets the list of values */ @Override public void setValue(TileObject o) { super.getValues().add(o); } }; expect(mockStorageBroker.put(capture(storedObjects))).andReturn(true).anyTimes(); expect(mockStorageBroker.get((TileObject) anyObject())).andReturn(false).anyTimes(); replay(mockStorageBroker); TileRange tr = TileBreeder.createTileRange(req, tl); TileRangeIterator trIter = new TileRangeIterator(tr, tl.getMetaTilingFactors()); boolean reseed = false; SeedTask task = new SeedTask(mockStorageBroker, trIter, tl, reseed, false); task.setTaskId(1L); task.setThreadInfo(new AtomicInteger(), 0); /* * HACK: avoid SeedTask.getCurrentThreadArrayIndex failure. */ Thread.currentThread().setName("pool-fake-thread-1"); /* * Call the seed process */ task.doAction(); final GridSubset gridSubset = tl.getGridSubset(gridSetId); /* * Make sure the seed process asked for the expected tiles to be stored */ final long expectedSavedTileCount; final long[] coveredGridLevels = gridSubset.getCoverage(zoomLevel); // seeding should not include edge tiles produced by the meta tiling that don't fall into // the gridsubset's coverage long starty = coveredGridLevels[1]; long startx = coveredGridLevels[0]; expectedSavedTileCount = (coveredGridLevels[2] - startx + 1) * (coveredGridLevels[3] - starty + 1); List<TileObject> storedTiles = storedObjects.getValues(); final int seededTileCount = storedTiles.size(); assertEquals(expectedSavedTileCount, seededTileCount); Set<Tuple<Long>> tileKeys = new TreeSet<Tuple<Long>>(); Set<Tuple<Long>> expectedTiles = new TreeSet<Tuple<Long>>(); for (long x = startx; x <= coveredGridLevels[2]; x++) { for (long y = starty; y <= coveredGridLevels[3]; y++) { expectedTiles.add(new Tuple<Long>(x, y, (long) zoomLevel)); } } for (TileObject obj : storedTiles) { tileKeys.add(new Tuple<Long>(obj.getXYZ()[0], obj.getXYZ()[1], obj.getXYZ()[2])); } assertEquals(expectedTiles, tileKeys); }
protected void determineCanvasLayout() { // Find the spatial extent of the tiles needed to cover the desired extent srcRectangle = gridSubset.getCoverageIntersection(srcIdx, reqBounds); srcBounds = gridSubset.boundsFromRectangle(srcRectangle); // We now have the complete area, lets figure out our offsets // Positive means that there is blank space to the first tile, // negative means we will not use the entire tile boundOfs.left = srcBounds.getMinX() - reqBounds.getMinX(); boundOfs.bottom = srcBounds.getMinY() - reqBounds.getMinY(); boundOfs.right = reqBounds.getMaxX() - srcBounds.getMaxX(); boundOfs.top = reqBounds.getMaxY() - srcBounds.getMaxY(); canvasSize[0] = (int) Math.round(reqBounds.getWidth() / this.srcResolution); canvasSize[1] = (int) Math.round(reqBounds.getHeight() / this.srcResolution); PixelOffsets naiveOfs = new PixelOffsets(); // Calculate the corresponding pixel offsets. We'll stick to sane, // i.e. bottom left, coordinates at this point naiveOfs.left = (int) Math.round(boundOfs.left / this.srcResolution); naiveOfs.bottom = (int) Math.round(boundOfs.bottom / this.srcResolution); naiveOfs.right = (int) Math.round(boundOfs.right / this.srcResolution); naiveOfs.top = (int) Math.round(boundOfs.top / this.srcResolution); // Find the offsets on the opposite sides. This is dependent of how the first two were rounded. // First, find a tile boundary near the canvas edge, then make sure it's on the correct // side to match the corresponding boundOfs, then take the modulo of the naive rounding // based on the boundOfs, then subtract the two and apply the difference to the boundOfs. int tileWidth = this.gridSubset.getTileWidth(); int tileHeight = this.gridSubset.getTileHeight(); canvOfs.left = naiveOfs.left; canvOfs.bottom = naiveOfs.bottom; canvOfs.right = (canvasSize[0] - canvOfs.left) % tileWidth; // Find nearby tile boundary canvOfs.right = (Integer.signum(naiveOfs.right) * tileWidth + canvOfs.right) % tileWidth; // Ensure same sign as naive calculation canvOfs.right = canvOfs.right - (naiveOfs.right % tileWidth) + naiveOfs.right; // Find adjustment from naive and apply to naive calculation canvOfs.top = (canvasSize[1] - canvOfs.bottom) % tileHeight; // Find nearby tile boundary canvOfs.top = (Integer.signum(naiveOfs.top) * tileHeight + canvOfs.top) % tileHeight; // Ensure same sign as naive calculation canvOfs.top = canvOfs.top - (naiveOfs.top % tileHeight) + naiveOfs.top; // Find adjustment from naive and apply to naive calculation // postconditions assert Math.abs(canvOfs.left - naiveOfs.left) <= 1; assert Math.abs(canvOfs.bottom - naiveOfs.bottom) <= 1; assert Math.abs(canvOfs.right - naiveOfs.right) <= 1; assert Math.abs(canvOfs.top - naiveOfs.top) <= 1; if (log.isDebugEnabled()) { log.debug("intersection rectangle: " + Arrays.toString(srcRectangle)); log.debug("intersection bounds: " + srcBounds + " (" + reqBounds + ")"); log.debug( "Bound offsets: " + Arrays.toString( new double[] {boundOfs.left, boundOfs.bottom, boundOfs.right, boundOfs.top})); log.debug( "Canvas size: " + Arrays.toString(canvasSize) + "(" + reqWidth + "," + reqHeight + ")"); log.debug( "Canvas offsets: " + Arrays.toString( new int[] {canvOfs.left, canvOfs.bottom, canvOfs.right, canvOfs.top})); } }
/** * Initializes the layer, creating internal structures for calculating grid location and so forth. * * <p>Subclasses shall implement {@link #initializeInternal(GridSetBroker)} for anything else */ @Override public final boolean initialize(GridSetBroker gridSetBroker) { if (this.expireCacheList == null) { this.expireCacheList = new ArrayList<ExpirationRule>(1); if (this.expireCache == null) { expireCacheList.add(new ExpirationRule(0, GWCVars.CACHE_NEVER_EXPIRE)); } else { int expireCacheInt = Integer.parseInt(expireCache); if (expireCacheInt == GWCVars.CACHE_USE_WMS_BACKEND_VALUE) { saveExpirationHeaders = true; } expireCacheList.add(new ExpirationRule(0, expireCacheInt)); } } if (this.expireClientsList == null) { this.expireClientsList = new ArrayList<ExpirationRule>(1); if (this.expireClients == null) { expireClientsList.add(new ExpirationRule(0, 7200)); } else { int expireClientsInt = Integer.parseInt(expireClients); if (expireClientsInt == GWCVars.CACHE_USE_WMS_BACKEND_VALUE) { saveExpirationHeaders = true; } else if (expireClientsInt == GWCVars.CACHE_NEVER_EXPIRE) { // One year should do expireClientsInt = 3600 * 24 * 365; } expireClientsList.add(new ExpirationRule(0, expireClientsInt)); } } try { // mimetypes this.formats = new ArrayList<MimeType>(); if (mimeFormats != null) { for (String fmt : mimeFormats) { formats.add(MimeType.createFromFormat(fmt)); } } if (formats.size() == 0) { formats.add(0, MimeType.createFromFormat("image/png")); formats.add(1, MimeType.createFromFormat("image/jpeg")); } } catch (GeoWebCacheException gwce) { log.error(gwce.getMessage()); gwce.printStackTrace(); } if (subSets == null) { subSets = new HashMap<String, GridSubset>(); } if (this.gridSubsets != null) { Iterator<XMLGridSubset> iter = gridSubsets.iterator(); while (iter.hasNext()) { XMLGridSubset xmlGridSubset = iter.next(); GridSubset gridSubset = xmlGridSubset.getGridSubSet(gridSetBroker); if (gridSubset == null) { log.error( xmlGridSubset.getGridSetName() + " is not known by the GridSetBroker, skipping for layer " + name); } else { subSets.put(gridSubset.getName(), gridSubset); } } this.gridSubsets = null; } // Convert version 1.1.x and 1.0.x grid objects if (grids != null && !grids.isEmpty()) { Iterator<XMLOldGrid> iter = grids.values().iterator(); while (iter.hasNext()) { GridSubset converted = iter.next().convertToGridSubset(gridSetBroker); subSets.put(converted.getSRS().toString(), converted); } // Null it for the garbage collector grids = null; } if (this.subSets.size() == 0) { subSets.put( gridSetBroker.WORLD_EPSG4326.getName(), GridSubsetFactory.createGridSubSet(gridSetBroker.WORLD_EPSG4326)); subSets.put( gridSetBroker.WORLD_EPSG3857.getName(), GridSubsetFactory.createGridSubSet(gridSetBroker.WORLD_EPSG3857)); } return initializeInternal(gridSetBroker); }
private void capabilityLayerInner(StringBuilder str, TileLayer layer) throws GeoWebCacheException { if (layer.isQueryable()) { str.append(" <Layer queryable=\"1\">\n"); } else { str.append(" <Layer>\n"); } str.append(" <Name>" + layer.getName() + "</Name>\n"); if (layer.getMetaInformation() != null) { LayerMetaInformation metaInfo = layer.getMetaInformation(); str.append(" <Title>" + metaInfo.getTitle() + "</Title>\n"); str.append(" <Abstract>" + metaInfo.getDescription() + "</Abstract>\n"); } else { str.append(" <Title>" + layer.getName() + "</Title>\n"); } TreeSet<SRS> srsSet = new TreeSet<SRS>(); StringBuilder boundingBoxStr = new StringBuilder(); for (String gridSetId : layer.getGridSubsets()) { GridSubset curGridSubSet = layer.getGridSubset(gridSetId); SRS curSRS = curGridSubSet.getSRS(); if (!srsSet.contains(curSRS)) { str.append(" <SRS>" + curSRS.toString() + "</SRS>\n"); // Save bounding boxes for later String[] bs = boundsPrep(curGridSubSet.getCoverageBestFitBounds()); boundingBoxStr.append( " <BoundingBox SRS=\"" + curGridSubSet.getSRS().toString() + "\" minx=\"" + bs[0] + "\" miny=\"" + bs[1] + "\" maxx=\"" + bs[2] + "\" maxy=\"" + bs[3] + "\"/>\n"); srsSet.add(curSRS); } } GridSubset epsg4326GridSubSet = layer.getGridSubsetForSRS(SRS.getEPSG4326()); if (null != epsg4326GridSubSet) { String[] bs = boundsPrep(epsg4326GridSubSet.getCoverageBestFitBounds()); str.append( " <LatLonBoundingBox minx=\"" + bs[0] + "\" miny=\"" + bs[1] + "\" maxx=\"" + bs[2] + "\" maxy=\"" + bs[3] + "\"/>\n"); } // Bounding boxes gathered earlier str.append(boundingBoxStr); // WMS 1.1 Dimensions if (layer.getParameterFilters() != null) { StringBuilder dims = new StringBuilder(); StringBuilder extents = new StringBuilder(); for (ParameterFilter parameterFilter : layer.getParameterFilters()) { if (parameterFilter instanceof WMSDimensionProvider) { ((WMSDimensionProvider) parameterFilter).appendDimensionElement(dims, " "); ((WMSDimensionProvider) parameterFilter).appendExtentElement(extents, " "); } } if (dims.length() > 0 && extents.length() > 0) { str.append(dims); str.append(extents); } } // TODO style? str.append(" </Layer>\n"); }
@Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testParseMaplinkAndLayersWithGeoJSONFromJsonEmbedded() throws IOException, ParseException, com.vividsolutions.jts.io.ParseException { XMLConfiguration config = shared.getConfig(); TileLayer tileLayer = config.getTileLayer(layerTemplate); GridSubset gridSubset = tileLayer.getGridSubset(gridSubsetName); MapLayerJSONParser layerJsonParser = new MapLayerJSONParser(props); MaplinkGeoJsonParser parser = new MaplinkGeoJsonParser(); parser.setDebug(true); InputStream inp = MapProducer.class.getResourceAsStream("action_route_parcel.json"); try { assertTrue(MapLinkGeoJsonParseContext.Default.getPm().buildMap); Map<String, ?> root = parser.parse(inp); assertTrue(root.size() != 0); assertTrue(root.get("layers") != null); assertTrue(root.get("maplink") != null); assertTrue(root.get("state") != null); assertTrue(root.get("layers") != null); assertTrue(((List<Map<String, Object>>) root.get("layers")).size() == 11); assertTrue( "geojson".equals(((List<Map<String, Object>>) root.get("layers")).get(10).get("type"))); assertTrue( ((List<Map<String, Object>>) root.get("layers")).get(10).get(".data") instanceof FeatureCollection); FeatureCollection fc10 = (FeatureCollection) ((List<Map<String, Object>>) root.get("layers")).get(10).get(".data"); FeatureIterator fi = fc10.features(); assertTrue(fi.hasNext()); Feature f = fc10.features().next(); assertTrue(f != null); assertTrue(f.getProperty("prop0") != null); assertTrue(f.getProperty("prop0").getValue() != null); Object pv = f.getProperty("prop0").getValue(); assertTrue(pv instanceof String); assertTrue("value0forPoints".equals(pv)); assertTrue(f.getDefaultGeometryProperty() != null); GeometryAttribute g = f.getDefaultGeometryProperty(); assertTrue(g.getValue() != null); Object gv = g.getValue(); assertTrue(gv instanceof Point); Point pt = (Point) gv; System.out.println(pt.toText()); Style style = null; new FeatureLayer(fc10, style); MapLink mapLink = layerJsonParser.parseMapLinkJSON(root, shared.getGf(), gridSubset.getResolutions()); /* assertions */ assertTrue(mapLink != null); assertTrue(mapLink.getScale() != null); assertTrue(mapLink.getCentre() != null); assertTrue(Double.valueOf(530163).equals(mapLink.getCentre().getX())); assertTrue(Double.valueOf(6754057).equals(mapLink.getCentre().getY())); assertTrue(Integer.valueOf(11).equals(mapLink.getZoom())); assertTrue(mapLink.getMapLinkLayers() != null); assertTrue(mapLink.getMapLinkLayers().size() == 4); assertTrue("base_35".equals(mapLink.getMapLinkLayers().get(0).getLayerid())); assertTrue(mapLink.getMapLinkLayers().get(0).getGeom() == null); } finally { inp.close(); } }
@Override public synchronized void addGridSubset(GridSubset gridSubset) { removeGridSubset(gridSubset.getName()); gridSubsets.add(new XMLGridSubset(gridSubset)); subSets.put(gridSubset.getName(), gridSubset); }
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; } } } } }