📄 defaultrasterlegendproducer.java
字号:
/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.vfny.geoserver.wms.responses;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.awt.image.IndexColorModel;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.geotools.feature.AttributeType;
import org.geotools.feature.Feature;
import org.geotools.feature.FeatureType;
import org.geotools.feature.IllegalAttributeException;
import org.geotools.geometry.jts.LiteShape2;
import org.geotools.renderer.lite.StyledShapePainter;
import org.geotools.renderer.style.SLDStyleFactory;
import org.geotools.renderer.style.Style2D;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.LineSymbolizer;
import org.geotools.styling.PointSymbolizer;
import org.geotools.styling.PolygonSymbolizer;
import org.geotools.styling.RasterSymbolizer;
import org.geotools.styling.Rule;
import org.geotools.styling.Style;
import org.geotools.styling.Symbolizer;
import org.geotools.styling.TextSymbolizer;
import org.geotools.util.NumberRange;
import org.vfny.geoserver.wms.GetLegendGraphicProducer;
import org.vfny.geoserver.wms.WmsException;
import org.vfny.geoserver.wms.requests.GetLegendGraphicRequest;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Polygon;
/**
* Template {@linkPlain
* org.vfny.geoserver.responses.wms.GetLegendGraphicProducer} based on
* GeoTools' {@link
* http://svn.geotools.org/geotools/trunk/gt/module/main/src/org/geotools/renderer/lite/StyledShapePainter.java
* StyledShapePainter} that produces a BufferedImage with the appropiate
* legend graphic for a given GetLegendGraphic WMS request.
*
* <p>
* It should be enough for a subclass to implement {@linkPlain
* org.vfny.geoserver.responses.wms.GetLegendGraphicProducer#writeTo(OutputStream)}
* and <code>getContentType()</code> in order to encode the BufferedImage
* produced by this class to the appropiate output format.
* </p>
*
* <p>
* This class takes literally the fact that the arguments <code>WIDTH</code>
* and <code>HEIGHT</code> are just <i>hints</i> about the desired dimensions
* of the produced graphic, and the need to produce a legend graphic
* representative enough of the SLD style for which it is being generated.
* Thus, if no <code>RULE</code> parameter was passed and the style has more
* than one applicable Rule for the actual scale factor, there will be
* generated a legend graphic of the specified width, but with as many stacked
* graphics as applicable rules were found, providing by this way a
* representative enough legend.
* </p>
*
* @author Gabriel Roldan, Axios Engineering
* @version $Id: DefaultRasterLegendProducer.java 7746 2007-11-13 15:38:35Z aaime $
*/
public abstract class DefaultRasterLegendProducer implements GetLegendGraphicProducer {
/** shared package's logger */
private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(DefaultRasterLegendProducer.class.getPackage()
.getName());
/** Factory that will resolve symbolizers into rendered styles */
private static final SLDStyleFactory styleFactory = new SLDStyleFactory();
/** Tolerance used to compare doubles for equality */
private static final double TOLERANCE = 1e-6;
/**
* Singleton shape painter to serve all legend requests. We can use a
* single shape painter instance as long as it remains thread safe.
*/
private static final StyledShapePainter shapePainter = new StyledShapePainter(null);
/**
* used to create sample point shapes with LiteShape (not lines nor
* polygons)
*/
private static final GeometryFactory geomFac = new GeometryFactory();
/**
* Default Legend graphics background color
*/
public static final Color BG_COLOR = Color.WHITE;
/**
* Default label color
*/
public static final Color FONT_COLOR = Color.BLACK;
/**
* Image observer to help in creating the stack like legend graphic from
* the images created for each rule
*/
private static final ImageObserver imgObs = new Canvas();
/** padding percentaje factor at both sides of the legend. */
private static final float hpaddingFactor = 0.15f;
/** top & bottom padding percentaje factor for the legend */
private static final float vpaddingFactor = 0.15f;
/** The image produced at <code>produceLegendGraphic</code> */
private BufferedImage legendGraphic;
/**
* set to <code>true</code> when <code>abort()</code> gets called,
* indicates that the rendering of the legend graphic should stop
* gracefully as soon as possible
*/
private boolean renderingStopRequested;
/**
* Just a holder to avoid creating many polygon shapes from inside
* <code>getSampleShape()</code>
*/
private LiteShape2 sampleRect;
/**
* Just a holder to avoid creating many line shapes from inside
* <code>getSampleShape()</code>
*/
private LiteShape2 sampleLine;
/**
* Just a holder to avoid creating many point shapes from inside
* <code>getSampleShape()</code>
*/
private LiteShape2 samplePoint;
/**
* Default constructor. Subclasses may provide its own with a String
* parameter to establish its desired output format, if they support more
* than one (e.g. a JAI based one)
*/
public DefaultRasterLegendProducer() {
super();
}
/**
* Takes a GetLegendGraphicRequest and produces a BufferedImage that then
* can be used by a subclass to encode it to the appropiate output format.
*
* @param request the "parsed" request, where "parsed" means that it's
* values are already validated so this method must not take care
* of verifying the requested layer exists and the like.
*
* @throws WmsException if there are problems creating a "sample" feature
* instance for the FeatureType <code>request</code> returns as
* the required layer (which should not occur).
*/
public void produceLegendGraphic(GetLegendGraphicRequest request)
throws WmsException {
final Feature sampleFeature = createSampleFeature(request.getLayer());
final Style gt2Style = request.getStyle();
final FeatureTypeStyle[] ftStyles = gt2Style.getFeatureTypeStyles();
final double scaleDenominator = request.getScale();
final Rule[] applicableRules;
if (request.getRule() != null) {
applicableRules = new Rule[] { request.getRule() };
} else {
applicableRules = getApplicableRules(ftStyles, scaleDenominator);
}
final NumberRange scaleRange = new NumberRange(scaleDenominator, scaleDenominator);
final int ruleCount = applicableRules.length;
/**
* A legend graphic is produced for each applicable rule. They're being
* held here until the process is done and then painted on a "stack"
* like legend.
*/
final List /*<BufferedImage>*/ legendsStack = new ArrayList(ruleCount);
final int w = request.getWidth();
final int h = request.getHeight();
final Color bgColor = getBackgroundColor(request);
for (int i = 0; i < ruleCount; i++) {
Symbolizer[] symbolizers = applicableRules[i].getSymbolizers();
//BufferedImage image = prepareImage(w, h, request.isTransparent());
final boolean transparent = request.isTransparent();
final RenderedImage image = ImageUtils.createImage(w, h, (IndexColorModel)null, transparent);
final Map hintsMap = new HashMap();
Graphics2D graphics = ImageUtils.prepareTransparency(transparent, bgColor, image, hintsMap);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
for (int sIdx = 0; sIdx < symbolizers.length; sIdx++) {
Symbolizer symbolizer = symbolizers[sIdx];
if (symbolizer instanceof RasterSymbolizer) {
BufferedImage imgShape;
try {
imgShape = ImageIO.read(new URL(request.getHttpServletRequest()
.getRequestURL()
+ "/../data/images/rasterLegend.png"));
} catch (MalformedURLException e) {
LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
throw new WmsException(e);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
throw new WmsException(e);
}
graphics.drawImage(imgShape, 0, 0, w, h, null);
} else {
Style2D style2d = styleFactory.createStyle(sampleFeature, symbolizer, scaleRange);
LiteShape2 shape = getSampleShape(symbolizer, w, h);
if (style2d != null) {
shapePainter.paint(graphics, shape, style2d, scaleDenominator);
}
}
}
legendsStack.add(image);
}
//JD: changd legend behaviour, see GEOS-812
//this.legendGraphic = scaleImage(mergeLegends(legendsStack), request);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -