/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2008 - 2009, Johann Sorel * (C) 2012, Geomatys * * 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.geotoolkit.style; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import java.awt.Color; import java.util.ArrayList; import java.util.List; import javax.measure.Unit; import org.apache.sis.internal.feature.AttributeConvention; import org.geotoolkit.factory.Factory; import org.geotoolkit.factory.FactoryFinder; import org.geotoolkit.factory.Hints; import org.opengis.feature.AttributeType; import org.opengis.feature.FeatureType; import org.opengis.feature.Operation; import org.opengis.feature.PropertyNotFoundException; import org.opengis.feature.PropertyType; import org.opengis.filter.FilterFactory; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.Literal; import org.opengis.style.AnchorPoint; import org.opengis.style.Displacement; import org.opengis.style.Fill; import org.opengis.style.Graphic; import org.opengis.style.GraphicalSymbol; import org.opengis.style.LineSymbolizer; import org.opengis.style.Mark; import org.opengis.style.PointSymbolizer; import org.opengis.style.PolygonSymbolizer; import org.opengis.style.RasterSymbolizer; import org.opengis.style.Stroke; import org.opengis.style.Symbolizer; import org.apache.sis.measure.Units; /** * Random style builder. This is a convini class if you dont need special styles. * This class will provide you simple et good looking styles for your maps. * * @author Johann Sorel * @module */ public class RandomStyleBuilder extends Factory { private static final Literal[] POINT_SHAPES = { StyleConstants.MARK_SQUARE, StyleConstants.MARK_CIRCLE, StyleConstants.MARK_TRIANGLE, StyleConstants.MARK_STAR, StyleConstants.MARK_CROSS, StyleConstants.MARK_X}; private static final int[] SIZES = {8, 10, 12, 14, 16}; private static final int[] WIDTHS = {1, 2}; private static final Color[] COLORS = { Color.BLACK, Color.BLUE, Color.CYAN, Color.DARK_GRAY, Color.GRAY, Color.GREEN.darker(), Color.LIGHT_GRAY, Color.ORANGE, Color.RED, Color.YELLOW.darker() }; private static final MutableStyleFactory SF = (MutableStyleFactory) FactoryFinder.getStyleFactory(new Hints(Hints.STYLE_FACTORY, MutableStyleFactory.class)); private static final FilterFactory FF = FactoryFinder.getFilterFactory(null); private RandomStyleBuilder() {} public static PointSymbolizer createRandomPointSymbolizer() { final Unit uom = Units.POINT; final String geom = StyleConstants.DEFAULT_GEOM; final String name = null; final List<GraphicalSymbol> symbols = new ArrayList<GraphicalSymbol>(); final Fill fill = SF.fill( SF.literal(randomColor()), FF.literal(0.6f) ); final Stroke stroke = SF.stroke(randomColor(), 1); final Mark mark = SF.mark(randomMarkShape(), stroke, fill); symbols.add(mark); final Expression opa = FF.literal(1); final Expression size = FF.literal(randomPointSize()); final Expression rotation = FF.literal(0); final AnchorPoint anchor = SF.anchorPoint(0, 0); final Displacement displacement = SF.displacement(0, 0); final Graphic gra = SF.graphic(symbols,opa,size,rotation,anchor,displacement); return SF.pointSymbolizer(name,geom,StyleConstants.DEFAULT_DESCRIPTION,uom,gra); } public static LineSymbolizer createRandomLineSymbolizer() { final Unit uom = Units.POINT; final String geom = StyleConstants.DEFAULT_GEOM; final String name = null; final Stroke stroke = SF.stroke(randomColor(), 1); final Expression offset = FF.literal(0); return SF.lineSymbolizer(name,geom,StyleConstants.DEFAULT_DESCRIPTION,uom,stroke,offset); } public static PolygonSymbolizer createRandomPolygonSymbolizer() { final Unit uom = Units.POINT; final String geom = StyleConstants.DEFAULT_GEOM; final String name = null; final Fill fill = SF.fill( SF.literal(randomColor()), FF.literal(0.6f) ); final Stroke stroke = SF.stroke(randomColor(), 1); final Displacement displacement = SF.displacement(0, 0); final Expression offset = FF.literal(0); return SF.polygonSymbolizer(name,geom,StyleConstants.DEFAULT_DESCRIPTION,uom,stroke, fill,displacement,offset); } public static MutableStyle createDefaultVectorStyle(final FeatureType typ){ final Symbolizer ps; final PropertyType defAtt; try{ defAtt = typ.getProperty(AttributeConvention.GEOMETRY_PROPERTY.toString()); }catch(PropertyNotFoundException ex){ return SF.style(); } final AttributeType type = (AttributeType) ((Operation)defAtt).getResult(); final Class cla = type.getValueClass(); if (cla.equals(Polygon.class) || cla.equals(MultiPolygon.class)) { ps = SF.polygonSymbolizer(); } else if (cla.equals(LineString.class) || cla.equals(MultiLineString.class)) { ps = SF.lineSymbolizer(); } else if (cla.equals(Point.class) || cla.equals(MultiPoint.class)) { ps = SF.pointSymbolizer(); } else{ //multiple types, create rules final MutableStyle style = SF.style(); final MutableFeatureTypeStyle fts = SF.featureTypeStyle(); final MutableRule rulePoint = SF.rule(StyleConstants.DEFAULT_POINT_SYMBOLIZER); rulePoint.setFilter(FF.or( FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("Point")), FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("MultiPoint")) )); final MutableRule ruleLine = SF.rule(StyleConstants.DEFAULT_LINE_SYMBOLIZER); ruleLine.setFilter(FF.or( FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("LineString")), FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("MultiLineString")) )); final MutableRule rulePolygon = SF.rule(StyleConstants.DEFAULT_POLYGON_SYMBOLIZER); rulePolygon.setFilter(FF.or( FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("Polygon")), FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("MultiPolygon")) )); fts.rules().add(rulePoint); fts.rules().add(ruleLine); fts.rules().add(rulePolygon); style.featureTypeStyles().add(fts); return style; } final MutableStyle style = SF.style(); style.featureTypeStyles().add( SF.featureTypeStyle(ps)); return style; } public static MutableStyle createRandomVectorStyle(final FeatureType typ) { final Symbolizer ps; final PropertyType defAtt; try{ defAtt = typ.getProperty(AttributeConvention.GEOMETRY_PROPERTY.toString()); }catch(PropertyNotFoundException ex){ return SF.style(); } final AttributeType type = (AttributeType) ((Operation)defAtt).getResult(); final Class cla = type.getValueClass(); if (cla.equals(Polygon.class) || cla.equals(MultiPolygon.class)) { ps = createRandomPolygonSymbolizer(); } else if (cla.equals(LineString.class) || cla.equals(MultiLineString.class)) { ps = createRandomLineSymbolizer(); } else if (cla.equals(Point.class) || cla.equals(MultiPoint.class)) { ps = createRandomPointSymbolizer(); } else{ //multiple types, create rules final MutableStyle style = SF.style(); final MutableFeatureTypeStyle fts = SF.featureTypeStyle(); final MutableRule rulePoint = SF.rule(createRandomPointSymbolizer()); rulePoint.setFilter(FF.or( FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("Point")), FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("MultiPoint")) )); final MutableRule ruleLine = SF.rule(createRandomLineSymbolizer()); ruleLine.setFilter(FF.or( FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("LineString")), FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("MultiLineString")) )); final MutableRule rulePolygon = SF.rule(createRandomPolygonSymbolizer()); rulePolygon.setFilter(FF.or( FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("Polygon")), FF.equals(FF.function("geometryType", FF.property(type.getName().toString())), FF.literal("MultiPolygon")) )); fts.rules().add(rulePoint); fts.rules().add(ruleLine); fts.rules().add(rulePolygon); style.featureTypeStyles().add(fts); return style; } final MutableStyle style = SF.style(); style.featureTypeStyles().add( SF.featureTypeStyle(ps)); return style; } public static MutableStyle createDefaultRasterStyle() { final RasterSymbolizer raster = SF.rasterSymbolizer(); return SF.style(new Symbolizer[]{raster}); } /** * @return random point size (8,10,12,14,16) */ public static int randomPointSize() { return SIZES[((int) (Math.random() * SIZES.length))]; } /** * @return random width (1,2) */ public static int randomWidth() { return WIDTHS[((int) (Math.random() * WIDTHS.length))]; } /** * @return random mark literal (circle, square, triangle, ...) */ public static Literal randomMarkShape() { return POINT_SHAPES[((int) (Math.random() * POINT_SHAPES.length))]; } /** * @return random color */ public static Color randomColor() { return COLORS[((int) (Math.random() * COLORS.length))]; } }