private Rule createRule(Color outlineColor, Color fillColor, boolean bSelected) { Symbolizer symbolizer = null; Fill fill = null; Stroke stroke = sf.createStroke(ff.literal(outlineColor), ff.literal(LINE_WIDTH)); switch (geometryType) { case POLYGON: fill = sf.createFill(ff.literal(fillColor), ff.literal(OPACITY)); symbolizer = sf.createPolygonSymbolizer(stroke, fill, geometryAttributeName); break; case LINE: symbolizer = sf.createLineSymbolizer(stroke, geometryAttributeName); break; case POINT: fill = sf.createFill(ff.literal(fillColor), ff.literal(OPACITY)); Mark mark = sf.getTriangleMark(); mark.setFill(fill); mark.setStroke(stroke); Graphic graphic = sf.createDefaultGraphic(); graphic.graphicalSymbols().clear(); graphic.graphicalSymbols().add(mark); graphic.setSize(ff.literal(bSelected ? SELECTED_POINT_SIZE : POINT_SIZE)); symbolizer = sf.createPointSymbolizer(graphic, geometryAttributeName); } Rule rule = sf.createRule(); rule.symbolizers().add(symbolizer); return rule; }
/** * This transforms all external graphics references that are relative to absolute. This is a * workaround to be able to visualize png and svg in relative mode, which doesn't work right now * in geotools. See: http://jira.codehaus.org/browse/GEOT-3235 * * <p>This will not be necessary any more as soon as the geotools bug is fixed. * * @param relatedFile the related shapefile. * @param style the style to check. */ private void makeGraphicsAbsolute(File relatedFile, Style style) { File parentFolder = relatedFile.getParentFile(); Rule[] rules = SLDs.rules(style); for (Rule rule : rules) { Symbolizer[] onlineResource = rule.getSymbolizers(); for (Symbolizer symbolizer : onlineResource) { if (symbolizer instanceof PointSymbolizer) { PointSymbolizer pointSymbolizer = (PointSymbolizer) symbolizer; Graphic graphic = SLDs.graphic(pointSymbolizer); List<GraphicalSymbol> graphicalSymbols = graphic.graphicalSymbols(); for (GraphicalSymbol graphicalSymbol : graphicalSymbols) { if (graphicalSymbol instanceof ExternalGraphic) { ExternalGraphic externalGraphic = (ExternalGraphic) graphicalSymbol; try { URL location = externalGraphic.getLocation(); File urlToFile = URLUtils.urlToFile(location); if (urlToFile != null && !urlToFile.exists()) { File newFile = new File(parentFolder, urlToFile.getPath()); if (newFile.exists()) { externalGraphic.setLocation(newFile.toURI().toURL()); } } } catch (MalformedURLException e) { e.printStackTrace(); } } } } } } }
private static List[] getLayerRules(SimpleFeatureType ftype, Style style) { List[] result = new List[] {new ArrayList(), new ArrayList()}; final String typeName = ftype.getTypeName(); FeatureTypeStyle[] featureStyles = filterFeatureTypeStyles(style, ftype); final int length = featureStyles.length; for (int i = 0; i < length; i++) { // getting feature styles FeatureTypeStyle fts = featureStyles[i]; // get applicable rules at the current scale Rule[] ftsRules = fts.getRules(); for (int j = 0; j < ftsRules.length; j++) { // getting rule Rule r = ftsRules[j]; if (r.hasElseFilter()) { result[ELSE_RULES].add(r); } else { result[RULES].add(r); } } } return result; }
Symbolizer[] getSymbolizers(Style style) { List<Symbolizer> symbs = new ArrayList<Symbolizer>(); FeatureTypeStyle[] styles = style.getFeatureTypeStyles(); for (int i = 0; i < styles.length; i++) { FeatureTypeStyle fstyle = styles[i]; Rule[] rules = fstyle.getRules(); for (int j = 0; j < rules.length; j++) { Rule rule = rules[j]; symbs.addAll(Arrays.asList(rule.getSymbolizers())); } } return symbs.toArray(new Symbolizer[symbs.size()]); }
/** * Create a Style where features with given IDs are painted yellow, while others are painted with * the default colors. */ private Style createSelectedStyle(Set<FeatureId> IDs) { Rule selectedRule = createRule(SELECTED_COLOUR, SELECTED_COLOUR); selectedRule.setFilter(ff.id(IDs)); Rule otherRule = createRule(LINE_COLOUR, FILL_COLOUR); otherRule.setElseFilter(true); FeatureTypeStyle fts = sf.createFeatureTypeStyle(); fts.rules().add(selectedRule); fts.rules().add(otherRule); Style style = sf.createStyle(); style.featureTypeStyles().add(fts); return style; }
static Style makeStyle(StyleFactory factory, List<List<MiniRule>> ftStyles) { Style style = factory.createStyle(); for (List<MiniRule> rules : ftStyles) { FeatureTypeStyle ftStyle = factory.createFeatureTypeStyle(); for (MiniRule miniRule : rules) { if (!miniRule.symbolizers.isEmpty()) { Rule realRule = factory.createRule(); for (Symbolizer sym : miniRule.symbolizers) { realRule.symbolizers().add(sym); } ftStyle.rules().add(realRule); } } style.featureTypeStyles().add(ftStyle); } return style; }
private Style createDefaultStyle(int idx, Set<FeatureId> IDs) { Color fillColor = featureFills[idx]; Rule selectedRule = createRule(SELECTED_COLOUR, SELECTED_COLOUR, true); selectedRule.setFilter(ff.id(IDs)); Rule rule = createRule(fillColor, fillColor, false); rule.setElseFilter(true); FeatureTypeStyle fts = sf.createFeatureTypeStyle(); fts.rules().add(selectedRule); fts.rules().add(rule); Style style = sf.createStyle(); style.featureTypeStyles().add(fts); return style; }
/** * Creates a FeatureTypeStyle (core part of a SLD file). It is composed by Rules (tag <sld:Rule>) * and each Rule can contain one Filter (filters values) and one Symbolizer (what's displayed). It * Needs 2 factories: <br> * - I_FilterFactory: gives Filters (tag <ogc:Filter>) <br> * - I_SymbolizerFactory: gives Symbolizers (tag: <sld:PolygonSymbolizer> or * <sld:PointSymbolizer>) <br> * * @param filterFact Filters Factory * @param symbolizerFact Symbolizers Factory * @return FeatureTypeStyle (List of Rules) */ private FeatureTypeStyle createFeatureTypeStyle( I_FilterFactory filterFact, I_SymbolizerFactory symbolizerFact) { StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(null); FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(); Iterator<Symbolizer> symbolizers = symbolizerFact.iterator(); Iterator<Filter> filters = filterFact.iterator(); // use each factory iterator to get their items (Filter and Symbolizer) // there should be as many symbolizers as many filters while (symbolizers.hasNext() && filters.hasNext()) { // create a Rule. A Rule is composed by one Filter and one Symbolizer Rule rule = styleFactory.createRule(); Filter filter = filters.next(); rule.setSymbolizers(new Symbolizer[] {symbolizers.next()}); rule.setFilter(filter.getGISFilter()); rule.setName(filter.getName()); rule.setTitle(filter.getName()); fts.addRule(rule); } if (filters.hasNext()) { throw new RuntimeException("BUG: more filters than symbolizers"); } /* * This piece of code can be added to add a stroke around the polygons. * This rule does not include a filter, therefore, it is globally applied. */ /* StyleBuilder styleBuilder = new StyleBuilder(); Rule rule = styleFactory.createRule(); Stroke stroke = styleFactory.createStroke( styleBuilder.literalExpression(Color.BLACK), // color styleBuilder.literalExpression(1), // width styleBuilder.literalExpression(1.0)); // opacity LineSymbolizer ls = styleFactory.createLineSymbolizer(stroke, ""); rule.setSymbolizers(new Symbolizer[] {ls}); fts.addRule(rule); */ return fts; }
static List<List<MiniRule>> minify(Style style) { List<List<MiniRule>> ftStyles = new ArrayList<List<MiniRule>>(); for (FeatureTypeStyle ftStyle : style.featureTypeStyles()) { List<MiniRule> rules = new ArrayList<MiniRule>(); for (Rule rule : ftStyle.rules()) { List<PointSymbolizer> pointSymbolizers = new ArrayList<PointSymbolizer>(); for (Symbolizer symbolizer : rule.symbolizers()) { if (symbolizer instanceof PointSymbolizer) { pointSymbolizers.add((PointSymbolizer) symbolizer); } } if (!pointSymbolizers.isEmpty()) rules.add(new MiniRule(rule.getFilter(), rule.isElseFilter(), pointSymbolizers)); } if (!rules.isEmpty()) { ftStyles.add(rules); } } return ftStyles; }
private void twoFeatureTypeStyles() { // twoFeatureTypeStyles start StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(); FilterFactory2 filterFactory = CommonFactoryFinder.getFilterFactory2(); Style style = styleFactory.getDefaultStyle(); // Feature type style 1 FeatureTypeStyle fts = styleFactory.createFeatureTypeStyle(); fts.featureTypeNames().add(new NameImpl("feature-type-1")); style.featureTypeStyles().add(fts); // Feature type style 2 FeatureTypeStyle fts2 = styleFactory.createFeatureTypeStyle(); fts2.featureTypeNames().add(new NameImpl("feature-type-2")); // creating the rule 1 Rule rule1 = styleFactory.createRule(); rule1.setName("rule1"); Filter aFilter = filterFactory.id(Collections.singleton(filterFactory.featureId("FID"))); rule1.setFilter(aFilter); fts2.rules().add(rule1); // creating the rule 2 Rule rule2 = styleFactory.createRule(); rule2.setIsElseFilter(true); rule2.setName("rule2"); fts2.rules().add(rule2); style.featureTypeStyles().add(fts2); // twoFeatureTypeStyles end }
/** * Filters the rules of <code>featureTypeStyle</code> returnting only those that apply to <code> * feature</code>. * * <p>This method returns rules for which: * * <ol> * <li><code>rule.getFilter()</code> matches <code>feature</code>, or: * <li>the rule defines an "ElseFilter", and the feature matches no other rules. * </ol> * * This method returns an empty array in the case of which no rules match. * * @param featureTypeStyle The feature type style containing the rules. * @param feature The feature being filtered against. */ public static Rule[] filterRules( FeatureTypeStyle featureTypeStyle, SimpleFeature feature, double scaleDenominator) { Rule[] rules = featureTypeStyle.getRules(); if ((rules == null) || (rules.length == 0)) { return new Rule[0]; } ArrayList filtered = new ArrayList(rules.length); // process the rules, keep track of the need to apply an else filters boolean match = false; boolean hasElseFilter = false; for (int i = 0; i < rules.length; i++) { Rule rule = rules[i]; LOGGER.finer(new StringBuffer("Applying rule: ").append(rule.toString()).toString()); // does this rule have an else filter if (rule.hasElseFilter()) { hasElseFilter = true; continue; } // is this rule within scale? if (!isWithInScale(rule, scaleDenominator)) { continue; } // does this rule have a filter which applies to the feature Filter filter = rule.getFilter(); if ((filter == null) || filter.evaluate(feature)) { match = true; filtered.add(rule); } } // if no rules mached the feautre, re-run through the rules applying // any else filters if (!match && hasElseFilter) { // loop through again and apply all the else rules for (int i = 0; i < rules.length; i++) { Rule rule = rules[i]; // is this rule within scale? if (!isWithInScale(rule, scaleDenominator)) { continue; } if (rule.hasElseFilter()) { filtered.add(rule); } } } return (Rule[]) filtered.toArray(new Rule[filtered.size()]); }
/** * Summarizes, when possible, the rule filters into one. * * @param rules * @param originalFiter * @param scaleDenominator The actual scale denominator, or a value <= 0 if no scale denominator * checks have to be performed * @return */ private static Filter summarizeRuleFilters(List[] rules, double scaleDenominator) { if (rules[RULES].size() == 0 && rules[ELSE_RULES].size() > 0) return Filter.EXCLUDE; List filters = new ArrayList(); for (Iterator it = rules[RULES].iterator(); it.hasNext(); ) { Rule rule = (Rule) it.next(); if (scaleDenominator <= 0 || isWithInScale(rule, scaleDenominator)) { // if there is a single rule asking for all filters, we have to // return everything that the original filter returned already if (rule.getFilter() == null || Filter.INCLUDE.equals(rule.getFilter())) return Filter.INCLUDE; else filters.add(rule.getFilter()); } } if (filters.size() > 0) { FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); return ff.or(filters); } else { return Filter.EXCLUDE; } }
private void styleBuilderExample() throws Exception { // styleBuilderExample start // // We are using the GeoTools StyleBuilder that is helpful for quickly making things StyleBuilder builder = new StyleBuilder(); FilterFactory2 ff = builder.getFilterFactory(); // RULE 1 // first rule to draw cities // define a point symbolizer representing a city Graphic city = builder.createGraphic(); city.setSize(ff.literal(10)); city.graphicalSymbols().add(builder.createExternalGraphic("file:city.svg", "svg")); // svg // preferred city.graphicalSymbols().add(builder.createExternalGraphic("file:city.png", "png")); // png next city.graphicalSymbols() .add(builder.createMark(StyleBuilder.MARK_CIRCLE, Color.BLUE, Color.BLACK, 1)); PointSymbolizer pointSymbolizer = builder.createPointSymbolizer(city, "the_geom"); Rule rule1 = builder.createRule(pointSymbolizer); rule1.setName("rule1"); rule1.getDescription().setTitle("City"); rule1.getDescription().setAbstract("Rule for drawing cities"); rule1.setFilter(ff.less(ff.property("POPULATION"), ff.literal(50000))); // // RULE 2 Default Graphic dotGraphic = builder.createGraphic(null, builder.createMark(StyleBuilder.MARK_CIRCLE), null); PointSymbolizer dotSymbolize = builder.createPointSymbolizer(dotGraphic); Rule rule2 = builder.createRule(dotSymbolize); rule2.setIsElseFilter(true); // // define feature type styles used to actually define how features are rendered Rule rules[] = new Rule[] {rule1, rule2}; FeatureTypeStyle featureTypeStyle = builder.createFeatureTypeStyle("Feature", rules); // // create a "user defined" style Style style = builder.createStyle(); style.setName("style"); style.getDescription().setTitle("User Style"); style.getDescription().setAbstract("Definition of Style"); style.featureTypeStyles().add(featureTypeStyle); // styleBuilderExample end }
/** * Returns a sample feature for the given rule, with the following criteria: - if a sample is * given in input is returned in output - if a sample is not given in input, scan the rule * symbolizers to find the one with the max dimensionality, and return a sample for that * dimensionality. * * @param featureType featureType used to create a sample, if none is given as input * @param sample feature sample to be returned as is in output, if defined * @param rule rule containing symbolizers to scan for max dimensionality */ private Feature getSampleFeatureForRule( FeatureType featureType, Feature sample, final Rule rule) { Symbolizer[] symbolizers = rule.getSymbolizers(); // if we don't have a sample as input, we need to create a sampleFeature // looking at the requested symbolizers (we chose the one with the max // dimensionality and create a congruent sample) if (sample == null) { int dimensionality = 1; for (int sIdx = 0; sIdx < symbolizers.length; sIdx++) { final Symbolizer symbolizer = symbolizers[sIdx]; if (LineSymbolizer.class.isAssignableFrom(symbolizer.getClass())) { dimensionality = 2; } if (PolygonSymbolizer.class.isAssignableFrom(symbolizer.getClass())) { dimensionality = 3; } } return createSampleFeature(featureType, dimensionality); } else { return sample; } }
/** * Receives a list of <code>BufferedImages</code> and produces a new one which holds all the * images in <code>imageStack</code> one above the other, handling labels. * * @param imageStack the list of BufferedImages, one for each applicable Rule * @param rules The applicable rules, one for each image in the stack (if not null it's used to * compute labels) * @param request The request. * @param forceLabelsOn true for force labels on also with a single image. * @param forceLabelsOff true for force labels off also with more than one rule. * @return the stack image with all the images on the argument list. * @throws IllegalArgumentException if the list is empty */ private BufferedImage mergeLegends( List<RenderedImage> imageStack, Rule[] rules, GetLegendGraphicRequest req, boolean forceLabelsOn, boolean forceLabelsOff) { Font labelFont = LegendUtils.getLabelFont(req); boolean useAA = LegendUtils.isFontAntiAliasing(req); if (imageStack.size() == 0) { return null; } final BufferedImage finalLegend; if (imageStack.size() == 1 && (!forceLabelsOn || rules == null)) { finalLegend = (BufferedImage) imageStack.get(0); } else { final int imgCount = imageStack.size(); final String[] labels = new String[imgCount]; BufferedImage img = ((BufferedImage) imageStack.get(0)); int totalHeight = 0; int totalWidth = 0; int[] rowHeights = new int[imgCount]; BufferedImage labelsGraphics[] = new BufferedImage[imgCount]; for (int i = 0; i < imgCount; i++) { img = (BufferedImage) imageStack.get(i); if (forceLabelsOff || rules == null) { totalWidth = (int) Math.ceil(Math.max(img.getWidth(), totalWidth)); rowHeights[i] = img.getHeight(); totalHeight += img.getHeight(); } else { Rule rule = rules[i]; // What's the label on this rule? We prefer to use // the 'title' if it's available, but fall-back to 'name' final Description description = rule.getDescription(); Locale locale = req.getLocale(); if (description != null && description.getTitle() != null) { final InternationalString title = description.getTitle(); if (locale != null) { labels[i] = title.toString(locale); } else { labels[i] = title.toString(); } } else if (rule.getName() != null) { labels[i] = rule.getName(); } else { labels[i] = ""; } if (labels[i] != null && labels[i].length() > 0) { final BufferedImage renderedLabel = getRenderedLabel(img, labels[i], req); labelsGraphics[i] = renderedLabel; final Rectangle2D bounds = new Rectangle2D.Double(0, 0, renderedLabel.getWidth(), renderedLabel.getHeight()); totalWidth = (int) Math.ceil(Math.max(img.getWidth() + bounds.getWidth(), totalWidth)); rowHeights[i] = (int) Math.ceil(Math.max(img.getHeight(), bounds.getHeight())); } else { totalWidth = (int) Math.ceil(Math.max(img.getWidth(), totalWidth)); rowHeights[i] = (int) Math.ceil(img.getHeight()); labelsGraphics[i] = null; } totalHeight += rowHeights[i]; } } // buffer the width a bit totalWidth += 2; final boolean transparent = req.isTransparent(); final Color backgroundColor = LegendUtils.getBackgroundColor(req); final Map<RenderingHints.Key, Object> hintsMap = new HashMap<RenderingHints.Key, Object>(); // create the final image finalLegend = ImageUtils.createImage(totalWidth, totalHeight, (IndexColorModel) null, transparent); Graphics2D finalGraphics = ImageUtils.prepareTransparency(transparent, backgroundColor, finalLegend, hintsMap); int topOfRow = 0; for (int i = 0; i < imgCount; i++) { img = (BufferedImage) imageStack.get(i); // draw the image int y = topOfRow; if (img.getHeight() < rowHeights[i]) { // move the image to the center of the row y += (int) ((rowHeights[i] - img.getHeight()) / 2d); } finalGraphics.drawImage(img, 0, y, null); if (forceLabelsOff || rules == null) { topOfRow += rowHeights[i]; continue; } finalGraphics.setFont(labelFont); if (useAA) { finalGraphics.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); } else { finalGraphics.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); } // draw the label if (labels[i] != null && labels[i].length() > 0) { // first create the actual overall label image. final BufferedImage renderedLabel = labelsGraphics[i]; y = topOfRow; if (renderedLabel.getHeight() < rowHeights[i]) { y += (int) ((rowHeights[i] - renderedLabel.getHeight()) / 2d); } finalGraphics.drawImage(renderedLabel, img.getWidth(), y, null); // cleanup renderedLabel.flush(); labelsGraphics[i] = null; } topOfRow += rowHeights[i]; } finalGraphics.dispose(); } return finalLegend; }
Symbolizer[] getSymbolizers(Rule rule) { List<Symbolizer> symbs = new ArrayList<Symbolizer>(); symbs.addAll(Arrays.asList(rule.getSymbolizers())); return symbs.toArray(new Symbolizer[symbs.size()]); }
private void styleFactoryExample() throws Exception { // styleFactoryExample start // // We are using the GeoTools styleFactory that allows access to get/set methods org.geotools.styling.StyleFactory sf = CommonFactoryFinder.getStyleFactory(); FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(); StyledLayerDescriptor sld = sf.createStyledLayerDescriptor(); sld.setName("sld"); sld.setTitle("Example"); sld.setAbstract("Example Style Layer Descriptor"); UserLayer layer = sf.createUserLayer(); layer.setName("layer"); // // define constraint limited what features the sld applies to FeatureTypeConstraint constraint = sf.createFeatureTypeConstraint("Feature", Filter.INCLUDE, null); layer.layerFeatureConstraints().add(constraint); // // create a "user defined" style Style style = sf.createStyle(); style.setName("style"); style.getDescription().setTitle("User Style"); style.getDescription().setAbstract("Definition of Style"); // // define feature type styles used to actually define how features are rendered FeatureTypeStyle featureTypeStyle = sf.createFeatureTypeStyle(); // RULE 1 // first rule to draw cities Rule rule1 = sf.createRule(); rule1.setName("rule1"); rule1.getDescription().setTitle("City"); rule1.getDescription().setAbstract("Rule for drawing cities"); rule1.setFilter(ff.less(ff.property("POPULATION"), ff.literal(50000))); // // create the graphical mark used to represent a city Stroke stroke = sf.stroke(ff.literal("#000000"), null, null, null, null, null, null); Fill fill = sf.fill(null, ff.literal(Color.BLUE), ff.literal(1.0)); // OnLineResource implemented by gt-metadata - so no factory! OnLineResourceImpl svg = new OnLineResourceImpl(new URI("file:city.svg")); svg.freeze(); // freeze to prevent modification at runtime OnLineResourceImpl png = new OnLineResourceImpl(new URI("file:city.png")); png.freeze(); // freeze to prevent modification at runtime // // List of symbols is considered in order with the rendering engine choosing // the first one it can handle. Allowing for svg, png, mark order List<GraphicalSymbol> symbols = new ArrayList<GraphicalSymbol>(); symbols.add(sf.externalGraphic(svg, "svg", null)); // svg preferred symbols.add(sf.externalGraphic(png, "png", null)); // png preferred symbols.add(sf.mark(ff.literal("circle"), fill, stroke)); // simple circle backup plan Expression opacity = null; // use default Expression size = ff.literal(10); Expression rotation = null; // use default AnchorPoint anchor = null; // use default Displacement displacement = null; // use default // define a point symbolizer of a small circle Graphic city = sf.graphic(symbols, opacity, size, rotation, anchor, displacement); PointSymbolizer pointSymbolizer = sf.pointSymbolizer("point", ff.property("the_geom"), null, null, city); rule1.symbolizers().add(pointSymbolizer); featureTypeStyle.rules().add(rule1); // // RULE 2 Default List<GraphicalSymbol> dotSymbols = new ArrayList<GraphicalSymbol>(); dotSymbols.add(sf.mark(ff.literal("circle"), null, null)); Graphic dotGraphic = sf.graphic(dotSymbols, null, ff.literal(3), null, null, null); PointSymbolizer dotSymbolizer = sf.pointSymbolizer("dot", null, null, null, dotGraphic); List<org.opengis.style.Symbolizer> symbolizers = new ArrayList<org.opengis.style.Symbolizer>(); symbolizers.add(dotSymbolizer); Filter other = null; // null will mark this rule as "other" accepting all remaining features Rule rule2 = sf.rule("default", null, null, Double.MIN_VALUE, Double.MAX_VALUE, symbolizers, other); featureTypeStyle.rules().add(rule2); style.featureTypeStyles().add(featureTypeStyle); layer.userStyles().add(style); sld.layers().add(layer); // styleFactoryExample end }
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); } } }
/** * Checks if a rule can be triggered at the current scale level * * @param r The rule * @return true if the scale is compatible with the rule settings */ public static boolean isWithInScale(Rule r, double scaleDenominator) { return ((r.getMinScaleDenominator() - TOLERANCE) <= scaleDenominator) && ((r.getMaxScaleDenominator() + TOLERANCE) > scaleDenominator); }