/** * Using the viewport bounds and combined wms layer extents, determines an appropriate bounding * box by projecting the viewport into the request CRS, intersecting the bounds, and returning the * result. * * @param wmsLayers all adjacent wms layers we are requesting * @param viewport map editor bounds and crs * @param requestCRS coordinate reference system supported by the server * @return the bbox to ask the server for * @throws MismatchedDimensionException * @throws TransformException * @throws FactoryException */ public static ReferencedEnvelope calculateRequestBBox( List<Layer> wmsLayers, ReferencedEnvelope viewport, CoordinateReferenceSystem requestCRS, String version) throws MismatchedDimensionException, TransformException, FactoryException { /* The bounds of all wms layers on this server combined */ ReferencedEnvelope layersBBox = getLayersBoundingBox(requestCRS, wmsLayers, version); if (isEnvelopeNull(layersBBox)) { // the wms server has no bounds WMSPlugin.log("Zero width/height envelope: wmsLayers = " + layersBBox); // $NON-NLS-1$ layersBBox = null; // alternatively, we could impose a reprojected -180,180,-90,90 } /* The viewport bounds projected to the request crs */ ReferencedEnvelope reprojectedViewportBBox = viewport.transform(requestCRS, true); if (isEnvelopeNull(reprojectedViewportBBox)) { // viewport couldn't be reprojected WMSPlugin.log( "Zero width/height envelope: reprojected viewport from " + viewport //$NON-NLS-1$ + " to " + requestCRS + " returned " + reprojectedViewportBBox); //$NON-NLS-1$ //$NON-NLS-2$ } // alternative for better accuracy: new ReferencedEnvelope(JTS.transform(viewport, null, // CRS.findMathTransform(viewportCRS, crs, true), 4), crs); /* The intersection of the viewport and the combined wms layers */ Envelope interestBBox; if (layersBBox == null) { interestBBox = reprojectedViewportBBox; } else { interestBBox = reprojectedViewportBBox.intersection(layersBBox); } if (isEnvelopeNull(interestBBox)) { // outside of bounds, do not draw WMSPlugin.trace( "Bounds of the data are outside the bounds of the viewscreen."); //$NON-NLS-1$ return NILL_BOX; } /* The bounds of the request we are going to make */ ReferencedEnvelope requestBBox = new ReferencedEnvelope(interestBBox, requestCRS); return requestBBox; }
/** * Determines the dimensions of the image to request, usually 1:1 to display, but sometimes more * (too fuzzy) or less (image too large) when reprojecting. * * @param maxDimensions TODO * @param viewport * @param request * @param context * @return * @throws RenderException */ public static Dimension calculateImageDimensions( Dimension displaySize, Dimension maxDimensions, Envelope viewport, Envelope request) throws RenderException { double xScale = request.getWidth() / viewport.getWidth(); double yScale = request.getHeight() / viewport.getHeight(); // TODO: adjust height and width when we are reprojecting to make things less fuzzy int width = (int) (xScale * displaySize.getWidth()); int height = (int) (yScale * displaySize.getHeight()); // ensure we don't exceed the dimensions the server will allow int maxWidth = (int) maxDimensions.getWidth(); if ((maxWidth > 0) && (width > maxWidth)) { width = maxWidth; } int maxHeight = (int) maxDimensions.getHeight(); if ((maxHeight > 0) && (height > maxHeight)) { height = maxHeight; } WMSPlugin.trace( "WMS request image dimensions: " + width + ", " + height); // $NON-NLS-1$ //$NON-NLS-2$ return new Dimension(width, height); }
public synchronized void render( Graphics2D destination, ReferencedEnvelope bounds, IProgressMonitor monitor) throws RenderException { int endLayerStatus = ILayer.DONE; try { if (bounds == null || bounds.isNull()) { bounds = getContext().getImageBounds(); } if (monitor.isCanceled()) return; getContext().setStatus(ILayer.WAIT); WebMapServer wms = getWMS(); GetMapRequest request = wms.createGetMapRequest(); // put in default exception format we understand as a client // (if suppoted by the server) WMSCapabilities capabilities = wms.getCapabilities(); if (capabilities .getRequest() .getGetMap() .getFormats() .contains(GetMapRequest.EXCEPTION_XML)) { request.setExceptions(GetMapRequest.EXCEPTION_XML); } setImageFormat(wms, request); if (monitor.isCanceled()) return; double currScale = getContext().getViewportModel().getScaleDenominator(); List<ILayer> layers = getLayers(); for (int i = layers.size() - 1; i >= 0; i--) { ILayer ilayer = layers.get(i); Layer layer; double minScale = 0; double maxScale = Double.MAX_VALUE; layer = ilayer.getResource(org.geotools.data.ows.Layer.class, null); // check if there are min/max scale rules StyleBlackboard sb = (StyleBlackboard) ilayer.getStyleBlackboard(); Style style = (Style) sb.lookup(Style.class); if (style != null) { Rule rule = style.getFeatureTypeStyles()[0].getRules()[0]; minScale = rule.getMinScaleDenominator(); maxScale = rule.getMaxScaleDenominator(); } if (currScale >= minScale && currScale <= maxScale) { // check for a wms style StyleImpl wmsStyle = (StyleImpl) ilayer.getStyleBlackboard().get(WMSStyleContent.WMSSTYLE); if (wmsStyle != null) { request.addLayer(layer, wmsStyle); } else { request.addLayer(layer); } } } if (monitor.isCanceled()) return; List<Layer> wmsLayers = getWMSLayers(); if (wmsLayers == null || wmsLayers.isEmpty()) { endLayerStatus = ILayer.WARNING; return; } // figure out request CRS String requestCRScode = findRequestCRS(wmsLayers, getViewportCRS(), getContext().getMap()); // TODO: make findRequestCRS more efficient (we are running CRS.decode at *least* twice) CoordinateReferenceSystem requestCRS = CRS.decode(requestCRScode); // figure out viewport // ReferencedEnvelope viewport; // Envelope viewportBBox = getViewportBBox(); // CoordinateReferenceSystem viewportCRS = getViewportCRS(); // if (viewportBBox == null) { // // change viewport to world // viewportBBox = new Envelope(-180, 180, -90, 90); // if (!DefaultGeographicCRS.WGS84.equals(viewportCRS)) { // reproject // viewport = new ReferencedEnvelope(viewportBBox, // DefaultGeographicCRS.WGS84); // viewportBBox = viewport.transform(viewportCRS, true); // } // } ReferencedEnvelope requestBBox = null; Envelope backprojectedBBox = null; // request bbox projected to the viewport crs // viewport = new ReferencedEnvelope(viewportBBox, viewportCRS); // requestBBox = calculateRequestBBox(wmsLayers, viewport, requestCRS); requestBBox = calculateRequestBBox(wmsLayers, bounds, requestCRS, capabilities.getVersion()); // check that a request is needed (not out of a bounds, invalid, etc) if (requestBBox == NILL_BOX) { endLayerStatus = ILayer.WARNING; return; } assert requestBBox.getCoordinateReferenceSystem().equals(requestCRS); if (requestBBox.getCoordinateReferenceSystem().equals(getViewportCRS())) { backprojectedBBox = (Envelope) requestBBox; } else { backprojectedBBox = (Envelope) requestBBox.transform(getViewportCRS(), true); } if (WMSPlugin.isDebugging(Trace.RENDER)) { WMSPlugin.trace("Viewport CRS: " + getViewportCRS().getName()); // $NON-NLS-1$ WMSPlugin.trace("Request CRS: " + requestCRS.getName()); // $NON-NLS-1$ WMSPlugin.trace("Context Image bounds: " + getContext().getImageBounds()); // $NON-NLS-1$ WMSPlugin.trace("Request BBox bounds: " + requestBBox); // $NON-NLS-1$ WMSPlugin.trace("Backprojected request bounds: " + backprojectedBBox); // $NON-NLS-1$ } Service wmsService = capabilities.getService(); Dimension maxDimensions = new Dimension(wmsService.getMaxWidth(), wmsService.getMaxHeight()); // Dimension imageDimensions = // calculateImageDimensions(getContext().getMapDisplay() // .getDisplaySize(), maxDimensions, getViewportBBox(), backprojectedBBox); Dimension imageDimensions = calculateImageDimensions( getContext().getImageSize(), maxDimensions, bounds, backprojectedBBox); if (imageDimensions.height < 1 || imageDimensions.width < 1) { endLayerStatus = ILayer.WARNING; return; } request.setDimensions( imageDimensions.width + "", imageDimensions.height + ""); // $NON-NLS-1$ //$NON-NLS-2$ // epsg could be under identifiers or authority. Set<ReferenceIdentifier> identifiers = requestCRS.getIdentifiers(); String srs = identifiers.isEmpty() ? EPSG_4326 : identifiers.iterator().next().toString(); request.setSRS(srs); // EPSG_4326 request.setBBox(requestBBox); // request.setBBox(requestBBox.getMinX() + "," + requestBBox.getMinY()+ "," + // requestBBox.getMaxX()+ "," + requestBBox.getMaxY()); if (monitor.isCanceled()) return; setFilter(wms, request); // request.setProperty("DACS_ACS", null); BufferedImage image = readImage(wms, request, monitor); if (monitor.isCanceled()) return; if (image == null) { Exception e = new RuntimeException(Messages.BasicWMSRenderer2_unable_to_decode_image); throw wrapException(e); } // backprojectedBBox or viewportBBox renderGridCoverage(destination, backprojectedBBox, imageDimensions, requestBBox, image); } catch (Exception e) { if (e instanceof RenderException) throw (RenderException) e; throw new RenderException(e); } finally { getContext().setStatus(endLayerStatus); if (endLayerStatus == ILayer.DONE) { // clear the status message (rendering was successful) getContext().setStatusMessage(null); } } }