/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2014, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.process.spatialstatistics.styler; import java.awt.Color; import java.util.Arrays; import java.util.Collections; import java.util.logging.Logger; import org.geotools.brewer.color.BrewerPalette; import org.geotools.brewer.color.ColorBrewer; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.filter.function.RangedClassifier; import org.geotools.process.spatialstatistics.core.FeatureTypes; import org.geotools.process.spatialstatistics.core.FeatureTypes.SimpleShapeType; import org.geotools.styling.FeatureTypeStyle; import org.geotools.styling.Fill; import org.geotools.styling.Graphic; import org.geotools.styling.LineSymbolizer; import org.geotools.styling.Mark; import org.geotools.styling.PointSymbolizer; import org.geotools.styling.PolygonSymbolizer; import org.geotools.styling.Rule; import org.geotools.styling.SLD; import org.geotools.styling.Stroke; import org.geotools.styling.Style; import org.geotools.styling.Symbolizer; import org.geotools.styling.visitor.DuplicatingStyleVisitor; import org.geotools.util.logging.Logging; import org.opengis.feature.type.GeometryDescriptor; import org.opengis.filter.Filter; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.PropertyName; /** * GraduatedSymbolStyleBuilder * * @author Minpa Lee, MangoSystem * * @source $URL$ */ public class GraduatedSymbolStyleBuilder extends AbstractFeatureStyleBuilder { protected static final Logger LOGGER = Logging.getLogger(GraduatedSymbolStyleBuilder.class); PolygonSymbolizer backgroundSymbol; Symbolizer templateSymbol; String propertyName; String normalProperty; String methodName = "EqualInterval"; int numClasses = 5; float minSize = 2; float maxSize = 24; public PolygonSymbolizer getBackgroundSymbol() { return backgroundSymbol; } public void setBackgroundSymbol(PolygonSymbolizer backgroundSymbol) { this.backgroundSymbol = backgroundSymbol; } public Symbolizer getTemplateSymbol() { return templateSymbol; } public void setTemplateSymbol(Symbolizer templateSymbol) { this.templateSymbol = templateSymbol; } public String getPropertyName() { return propertyName; } public void setPropertyName(String propertyName) { this.propertyName = propertyName; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public int getNumClasses() { return numClasses; } public void setNumClasses(int numClasses) { this.numClasses = numClasses; } public float getMinSize() { return minSize; } public void setMinSize(float minSize) { this.minSize = minSize; } public float getMaxSize() { return maxSize; } public void setMaxSize(float maxSize) { this.maxSize = maxSize; } public void setNormalProperty(String normalProperty) { this.normalProperty = normalProperty; } public String getNormalProperty() { return normalProperty; } private void setDefaultSymbolizer(SimpleFeatureCollection inputFeatures) { GeometryDescriptor geomDesc = inputFeatures.getSchema().getGeometryDescriptor(); String geometryPropertyName = geomDesc.getLocalName(); Class<?> geomBinding = geomDesc.getType().getBinding(); SimpleShapeType shapeType = FeatureTypes.getSimpleShapeType(geomBinding); switch (shapeType) { case POINT: case POLYGON: // default Point Symbolizer Mark mark = sf.getCircleMark(); // createStroke(Expression color, Expression width, Expression opacity) Stroke markStroke = sf.createStroke(ff.literal(Color.WHITE), ff.literal(outlineWidth), ff.literal(outlineOpacity)); mark.setStroke(markStroke); mark.setFill(sf.createFill(ff.literal(Color.RED), ff.literal(fillOpacity))); Graphic graphic = sf.createDefaultGraphic(); graphic.graphicalSymbols().clear(); graphic.graphicalSymbols().add(mark); graphic.setSize(ff.literal(minSize)); this.templateSymbol = sf.createPointSymbolizer(graphic, null); break; case LINESTRING: // Default Line Symbolizer Stroke stroke = sf.createStroke(ff.literal(new Color(0, 112, 255)), ff.literal(lineWidth), ff.literal(outlineOpacity)); this.templateSymbol = sf.createLineSymbolizer(stroke, geometryPropertyName); break; } } public Style createStyle(SimpleFeatureCollection inputFeatures, String propertyName) { return createStyle(inputFeatures, propertyName, "OrRd", false); } public Style createStyle(SimpleFeatureCollection inputFeatures, String propertyName, String brewerPaletteName, boolean reverse) { return createStyle(inputFeatures, propertyName, methodName, numClasses, brewerPaletteName, reverse); } public Style createStyle(SimpleFeatureCollection inputFeatures, String propertyName, String methodName, int numClasses, String brewerPaletteName, boolean reverse) { GeometryDescriptor geomDesc = inputFeatures.getSchema().getGeometryDescriptor(); String geometryPropertyName = geomDesc.getLocalName(); SimpleShapeType shapeType = FeatureTypes.getSimpleShapeType(inputFeatures); if (this.templateSymbol == null) { setDefaultSymbolizer(inputFeatures); } numClasses = numClasses < 3 ? 3 : numClasses; // get classifier RangedClassifier classifier = null; if (normalProperty == null || normalProperty.isEmpty()) { classifier = getClassifier(inputFeatures, propertyName, methodName, numClasses); } else { classifier = getClassifier(inputFeatures, propertyName, normalProperty, methodName, numClasses); } double[] classBreaks = getClassBreaks(classifier); ColorBrewer brewer = ColorBrewer.instance(); BrewerPalette brewerPalette = brewer.getPalette(brewerPaletteName); Color[] colors = brewerPalette.getColors(classBreaks.length - 1); if (reverse) { Collections.reverse(Arrays.asList(colors)); } int step = (int) (maxSize + minSize) / colors.length; FeatureTypeStyle featureTypeStyle = sf.createFeatureTypeStyle(); // add background symbol if (shapeType == SimpleShapeType.POLYGON) { if (backgroundSymbol == null) { Stroke stroke = sf.createStroke(ff.literal(outlineColor), ff.literal(outlineOpacity)); Fill fill = sf.createFill(ff.literal(new Color(234, 234, 234)), ff.literal(fillOpacity)); backgroundSymbol = sf.createPolygonSymbolizer(stroke, fill, geometryPropertyName); } Rule rule = sf.createRule(); rule.setName("Background"); rule.symbolizers().add(backgroundSymbol); featureTypeStyle.rules().add(rule); } DuplicatingStyleVisitor styleVisitor = new DuplicatingStyleVisitor(); PropertyName property = ff.property(propertyName); for (int k = 0, length = classBreaks.length - 2; k <= length; k++) { Expression color = ff.literal(colors[k]); Expression size = ff.literal(minSize + (step * k)); Expression lowerClass = ff.literal(classBreaks[k]); Expression upperClass = ff.literal(classBreaks[k + 1]); Symbolizer symbolizer = null; if (templateSymbol instanceof PointSymbolizer) { PointSymbolizer pointSymbolizer = (PointSymbolizer) templateSymbol; Graphic graphic = pointSymbolizer.getGraphic(); graphic.accept(styleVisitor); Graphic copy = (Graphic) styleVisitor.getCopy(); copy.setSize(size); symbolizer = sf.createPointSymbolizer(copy, geometryPropertyName); SLD.setPointColour((PointSymbolizer) symbolizer, colors[k]); } else { LineSymbolizer lineSymbolizer = (LineSymbolizer) templateSymbol; Stroke stroke = lineSymbolizer.getStroke(); stroke.accept(styleVisitor); Stroke copy = (Stroke) styleVisitor.getCopy(); copy.setWidth(size); copy.setColor(color); symbolizer = sf.createLineSymbolizer(copy, geometryPropertyName); } Filter lower = ff.greaterOrEqual(property, lowerClass); Filter upper = k == length ? ff.lessOrEqual(property, upperClass) : ff.less(property, upperClass); Rule rule = sf.createRule(); rule.setName(classBreaks[k] + " - " + classBreaks[k + 1]); rule.setFilter(ff.and(lower, upper)); rule.symbolizers().add(symbolizer); featureTypeStyle.rules().add(rule); } Style style = sf.createStyle(); style.featureTypeStyles().add(featureTypeStyle); return style; } }