private TileRange createTileRange( WMTSource wmtSource, WMTRenderJob renderJob, Map<String, Tile> tileList) { TileRange range; TileSet tileset = new WMTTileSetWrapper(wmtSource); String value = CatalogPlugin.getDefault() .getPreferenceStore() .getString(PreferenceConstants.P_WMSCTILE_CACHING); if (value.equals(WMSCTileCaching.ONDISK.toString())) { String dir = CatalogPlugin.getDefault() .getPreferenceStore() .getString(PreferenceConstants.P_WMSCTILE_DISKDIR); WMTTileImageReadWriter tileReadWriter = new WMTTileImageReadWriter(dir); range = new TileRangeOnDisk( null, tileset, renderJob.getMapExtentTileCrs(), tileList, requestTileWorkQueue, writeTileWorkQueue, tileReadWriter); } else { range = new TileRangeInMemory( null, tileset, renderJob.getMapExtentTileCrs(), tileList, requestTileWorkQueue); } return range; }
/** * Clears the area of the tile on the graphics * * @param graphics graphics to draw onto * @param style raster symbolizer * @throws FactoryException * @throws TransformException * @throws RenderException */ private void renderBlankTile(Graphics2D graphics, WMTTile tile, WMTRenderJob renderJob) throws Exception { if (tile == null) { return; } // get the bounds of the tile and convert to necessary viewport projection Envelope bnds = renderJob.projectTileToMapCrs(tile.getExtent()); // determine screen coordinates of tiles Point upperLeft = getContext().worldToPixel(new Coordinate(bnds.getMinX(), bnds.getMinY())); Point bottomRight = getContext().worldToPixel(new Coordinate(bnds.getMaxX(), bnds.getMaxY())); Rectangle tileSize = new Rectangle(upperLeft); tileSize.add(bottomRight); // render try { graphics.setBackground(new Color(255, 255, 255, 0)); // set the tile transparent for now graphics.clearRect(tileSize.x, tileSize.y, tileSize.width, tileSize.height); if (TESTING) { /* for testing draw border around tiles */ graphics.setColor(Color.BLACK); graphics.drawLine( (int) tileSize.getMinX(), (int) tileSize.getMinY(), (int) tileSize.getMinX(), (int) tileSize.getMaxY()); graphics.drawLine( (int) tileSize.getMinX(), (int) tileSize.getMinY(), (int) tileSize.getMaxX(), (int) tileSize.getMinY()); graphics.drawLine( (int) tileSize.getMaxX(), (int) tileSize.getMinY(), (int) tileSize.getMaxX(), (int) tileSize.getMaxY()); graphics.drawLine( (int) tileSize.getMinX(), (int) tileSize.getMaxY(), (int) tileSize.getMaxX(), (int) tileSize.getMaxY()); } } catch (Throwable t) { WMTPlugin.log("Error Rendering Blank tile. Painting Tile: " + tile.getId(), t); // $NON-NLS-1$ } }
private Map<String, Tile> checkTooManyTiles( ILayer layer, WMTSource wmtSource, WMTLayerProperties layerProperties, WMTRenderJob renderJob, Map<String, Tile> tileList) { int tilesCount = tileList.size(); if (tilesCount > WMTRenderJob.getTileLimitWarning()) { // too many tiles, let's use the recommended zoom-level (if it wasn't already used) Boolean selectionAutomatic = layerProperties.getSelectionAutomatic(); if ((selectionAutomatic != null) && (selectionAutomatic == false)) { tileList.clear(); tileList = wmtSource.cutExtentIntoTiles( renderJob, WMTRenderJob.getScaleFactor(), true, layerProperties); tilesCount = tileList.size(); } // show a warning about this layer.setStatus(ILayer.WARNING); layer.setStatusMessage(Messages.Render_Warning_TooManyTiles); WMTPlugin.trace("[BasicWMTRender.render] Set WARNING_TOO_MANY_TILES"); // $NON-NLS-1$ } if (tilesCount > WMTRenderJob.getTileLimitError()) { // this is just too much, cancel WMTPlugin.trace("[BasicWMTRender.render] Set ERROR_TOO_MANY_TILES"); // $NON-NLS-1$ return Collections.emptyMap(); } return tileList; }
/** * @see net.refractions.udig.render.internal.wmsc.basic#renderTile(Graphics2D graphics, WMTTile * tile, CoordinateReferenceSystem crs, RasterSymbolizer style) * @param graphics * @param tile * @param style * @throws FactoryException * @throws TransformException * @throws RenderException */ private void renderTile( Graphics2D graphics, WMTTile tile, RasterSymbolizer style, WMTRenderJob renderJob) throws Exception { if (tile == null || tile.getBufferedImage() == null) { return; } // create a gridcoverage from the tile image GridCoverageFactory factory = new GridCoverageFactory(); // get the tile bounds in the CRS the tiles were drawn in ReferencedEnvelope tileBndsMercatorRef = renderJob.projectTileToTileProjectedCrs(tile.getExtent()); GridCoverage2D coverage = (GridCoverage2D) factory.create( "GridCoverage", tile.getBufferedImage(), tileBndsMercatorRef); // $NON-NLS-1$ Envelope2D coveragebounds = coverage.getEnvelope2D(); // bounds of tile ReferencedEnvelope bnds = new ReferencedEnvelope( coveragebounds.getMinX(), coveragebounds.getMaxX(), coveragebounds.getMinY(), coveragebounds.getMaxY(), renderJob.getCrsTilesProjected()); // reproject tile bounds to map CRS bnds = renderJob.projectTileProjectedToMapCrs(bnds); // determine screen coordinates of tiles Point upperLeft = getContext().worldToPixel(new Coordinate(bnds.getMinX(), bnds.getMinY())); Point bottomRight = getContext().worldToPixel(new Coordinate(bnds.getMaxX(), bnds.getMaxY())); Rectangle tileSize = new Rectangle(upperLeft); tileSize.add(bottomRight); // render try { CoordinateReferenceSystem crs = getContext().getCRS(); AffineTransform worldToScreen = RendererUtilities.worldToScreenTransform(bnds, tileSize, crs); GridCoverageRenderer paint = new GridCoverageRenderer(crs, bnds, tileSize, worldToScreen); paint.paint(graphics, coverage, style); if (TESTING) { // if(true){ /* for testing draw border around tiles */ graphics.setColor(Color.BLACK); graphics.drawLine( (int) tileSize.getMinX(), (int) tileSize.getMinY(), (int) tileSize.getMinX(), (int) tileSize.getMaxY()); graphics.drawLine( (int) tileSize.getMinX(), (int) tileSize.getMinY(), (int) tileSize.getMaxX(), (int) tileSize.getMinY()); graphics.drawLine( (int) tileSize.getMaxX(), (int) tileSize.getMinY(), (int) tileSize.getMaxX(), (int) tileSize.getMaxY()); graphics.drawLine( (int) tileSize.getMinX(), (int) tileSize.getMaxY(), (int) tileSize.getMaxX(), (int) tileSize.getMaxY()); graphics.drawString( tile.getId(), ((int) tileSize.getMaxX() - 113), ((int) tileSize.getMaxY() - 113)); } } catch (Throwable t) { WMTPlugin.log("Error Rendering tile. Painting Tile " + tile.getId(), t); // $NON-NLS-1$ } }
private void renderNotRenderedTiles( Graphics2D destination, IProgressMonitor monitor, WMTRenderJob renderJob, TileRange range, RasterSymbolizer style, int tileWorth, int thisid, Set<String> notRenderedTiles, Set<String> renderedTiles) throws Exception { checkCancelState(monitor, thisid, false); // set the listener on the tile range range.addListener(listener); // load the missing tiles by sending requests for them range.loadTiles(monitor); // block until all the missing tiles have come through (and draw them // as they are added to the blocking queue while (!notRenderedTiles.isEmpty()) { // check that the rendering is not canceled checkCancelState(monitor, thisid, true); if (testing) { System.out.println("BLOCKED: " + thisid); // $NON-NLS-1$ System.out.println( "waiting on: " + notRenderedTiles.size() + " tiles"); // $NON-NLS-1$ //$NON-NLS-2$ } Tile tile = null; try { Object element = null; /* get the next tile that is ready to render, * check after 1 sec if the rendering was canceled */ while ((element = tilesToDraw_queue.poll(1000, TimeUnit.MILLISECONDS)) == null) { checkCancelState(monitor, thisid, true); } tile = (Tile) element; if (testing) { System.out.println("removed from queue: " + tile.getId()); // $NON-NLS-1$ } } catch (InterruptedException ex) { if (testing) { System.out.println("InterruptedException trying to take: " + ex); // $NON-NLS-1$ } } if (testing) { System.out.println("UNBLOCKED!!!: " + thisid); // $NON-NLS-1$ } // check that the rendering is not canceled again after block checkCancelState(monitor, thisid, true); // check that the tile's bounds are within the current // context's bounds (if it's not, don't bother drawing it) and also // only draw tiles that haven't already been drawn (panning fast // can result in listeners being notified the same tile is ready multiple // times but we don't want to draw it more than once per render cycle) // ReferencedEnvelope viewbounds = getContext().getViewportModel().getBounds(); ReferencedEnvelope viewbounds = renderJob.projectMapToTileCrs(context.getViewportModel().getBounds()); if (tile != null && tile.getBufferedImage() != null && viewbounds != null && viewbounds.intersects(tile.getBounds()) && !renderedTiles.contains(tile.getId()) && notRenderedTiles.contains(tile.getId())) { try { renderedTiles.add(tile.getId()); renderTile(destination, (WMTTile) tile, style, renderJob); } catch (Exception exc) { WMTPlugin.log( "[BasicWMTRender.render] renderTile failed (2): " + tile.getId(), exc); // $NON-NLS-1$ } monitor.worked(tileWorth); // inc the monitor work by 1 tile setState(RENDERING); // tell renderer new data is ready } // remove the tile from the not rendered list regardless // of whether it was actually drawn (this is to prevent // this render cycle from blocking endlessly waiting for tiles // that either didn't return or had some error) notRenderedTiles.remove(tile.getId()); } }
public void render(Graphics2D destination, Envelope bounds, IProgressMonitor monitor) throws RenderException { WMTPlugin.trace("[BasicWMTRender.render] is called"); // $NON-NLS-1$ if (monitor == null) { monitor = new NullProgressMonitor(); } monitor.beginTask("Render WMT", 100); // $NON-NLS-1$ setState(STARTING); ILayer layer = null; try { layer = getContext().getLayer(); // assume everything will work fine layer.setStatus(ILayer.DONE); layer.setStatusMessage(""); // $NON-NLS-1$ WMTSource wmtSource = getWmtSourceFromLayer(layer); if (wmtSource == null) throw new UnsupportedOperationException(Messages.Render_Error_NoSource); // Layer properties WMTLayerProperties layerProperties = new WMTLayerProperties((StyleBlackboard) layer.getStyleBlackboard()); // Get map extent, which should be drawn ReferencedEnvelope mapExtent = getRenderBounds(); if (mapExtent == null) { mapExtent = context.getViewportModel().getBounds(); } // Scale double scale = getContext().getViewportModel().getScaleDenominator(); WMTPlugin.trace("[BasicWMTRender.render] Scale: " + scale); // $NON-NLS-1$ WMTRenderJob renderJob = null; try { renderJob = WMTRenderJob.createRenderJob(mapExtent, scale, wmtSource); } catch (Exception exc) { throw new UnsupportedOperationException(Messages.Render_Error_Projection); } // Find tiles Map<String, Tile> tileList = wmtSource.cutExtentIntoTiles( renderJob, WMTRenderJob.getScaleFactor(), false, layerProperties); // if we have nothing to display, return if (tileList.isEmpty()) { throw new UnsupportedOperationException(Messages.Render_Error_NoData); } // check if this are too many tiles if ((tileList = checkTooManyTiles(layer, wmtSource, layerProperties, renderJob, tileList)) .isEmpty()) { throw new UnsupportedOperationException(Messages.Render_Error_TooManyTiles); } // Download and display tiles // look up the preference for caching tiles on-disk or in // memory and use the proper tilerange for that. TileRange range = createTileRange(wmtSource, renderJob, tileList); // create an empty raster symbolizer for rendering RasterSymbolizer style = styleBuilder.createRasterSymbolizer(); // setup how much each tile is worth for the monitor work % int tileCount = range.getTileCount(); int tileWorth = (tileCount / 100) * tileCount; int thisid = 0; if (testing) { staticid++; thisid = staticid; } // first render any tiles that are ready and render non-ready tiles with blank images Map<String, Tile> tiles = range.getTiles(); Set<String> notRenderedTiles = new HashSet<String>(); Set<String> renderedTiles = new HashSet<String>(); renderReadyTiles( destination, monitor, renderJob, style, tileWorth, thisid, tiles, notRenderedTiles, renderedTiles); setState(RENDERING); // if the tilerange is not already completed, then load // the missing tiles if (!notRenderedTiles.isEmpty()) { renderNotRenderedTiles( destination, monitor, renderJob, range, style, tileWorth, thisid, notRenderedTiles, renderedTiles); } if (testing) { System.out.println("DONE!!!: " + thisid); // $NON-NLS-1$ } } catch (UnsupportedOperationException doneExc) { setDone(monitor); layer.setStatus(ILayer.ERROR); layer.setStatusMessage(doneExc.getMessage()); WMTPlugin.log("[BasicWMTRenderer.render] Error: ", doneExc); // $NON-NLS-1$ return; } catch (CancellationException cancelExc) { return; } catch (Exception ex) { WMTPlugin.log("[BasicWMTRenderer.render] Unexpected Error: ", ex); // $NON-NLS-1$ } setDone(monitor); }