/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2004-2008, 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.renderer.lite; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import org.geotools.styling.ExternalGraphic; import org.geotools.styling.Graphic; import org.opengis.filter.FilterFactory2; import org.opengis.filter.expression.Expression; /** * * @author jfc173 * * @source $URL$ */ public class CustomGlyphRenderer implements GlyphRenderer { private GlyphPropertiesList list = new GlyphPropertiesList(); private boolean maxFound = false; private int maxBarHeight = 0; /** Creates a new instance of CustomGlyphRenderer */ public CustomGlyphRenderer() { FilterFactory2 factory = (FilterFactory2) org.geotools.factory.CommonFactoryFinder .getFilterFactory(null); list.addProperty("radius", Expression.class, factory.literal(50)); list.addProperty("circle color", Expression.class, factory.literal("#000066")); list.addProperty("bar height", Expression.class, factory.literal(150)); list.addProperty("bar color", Expression.class, factory.literal("#000000")); list.addProperty("bar uncertainty", Expression.class, factory.literal(50)); list.addProperty("bar uncertainty width", Expression.class, factory.literal(5)); list.addProperty("bar uncertainty color", Expression.class, factory.literal("#999999")); list.addProperty("pointer length", Expression.class, factory.literal(100)); list.addProperty("pointer color", Expression.class, factory.literal("#FF0000")); list.addProperty("pointer direction", Expression.class, factory.literal(21)); list.addProperty("wedge width", Expression.class, factory.literal(25)); list.addProperty("wedge color", Expression.class, factory.literal("#9999FF")); } public boolean canRender(String format) { return format.equalsIgnoreCase("image/hack"); } public List getFormats() { Vector ret = new Vector(); ret.add("image/hack"); return ret; } public String getGlyphName(){ return "exploded clock"; //I think Alan called it this once, so here it sticks. } public GlyphPropertiesList getGlyphProperties(){ return list; } //Is this really necessary, since the values in the properties list can be set? public void setGlyphProperties(GlyphPropertiesList gpl){ list = gpl; } /** * djb -- addd "height" which is ignored as per API change * @param graphic * @param eg * @param feature * @param height */ public BufferedImage render(Graphic graphic, ExternalGraphic eg, Object feature, int height) { Map props = eg.getCustomProperties(); Set propNames = props.keySet(); Iterator it = propNames.iterator(); while (it.hasNext()) { String nextName = (String) it.next(); if (list.hasProperty(nextName)) { list.setPropertyValue(nextName, props.get(nextName)); } else { //DO I WANT TO THROW AN EXCEPTION OR ADD THE NEW PROPERTY TO THE LIST OR DO NOTHING? System.out.println("Tried to set the property " + nextName + " to a glyph that does not have this property."); } } //Change this to get values from list. int radius = 50; Expression e = (Expression) list.getPropertyValue("radius"); if (e != null){ radius = ((Number) e.evaluate(feature)).intValue(); } Color circleColor = Color.BLUE.darker(); e = (Expression) list.getPropertyValue("circle color"); if (e != null){ circleColor = Color.decode((String) e.evaluate(feature)); } int barHeight = 150; e = (Expression) list.getPropertyValue("bar height"); if (e != null){ barHeight = ((Number) e.evaluate(feature)).intValue(); } Color barColor = Color.BLACK; e = (Expression) list.getPropertyValue("bar color"); if (e != null){ barColor = Color.decode((String) e.evaluate(feature)); } int barUncertainty = 50; e = (Expression) list.getPropertyValue("bar uncertainty"); if (e != null){ barUncertainty = ((Number) e.evaluate(feature)).intValue(); } int barUncWidth = 5; e = (Expression) list.getPropertyValue("bar uncertainty width"); if (e != null){ barUncWidth = ((Number) e.evaluate(feature)).intValue(); } Color barUncColor = Color.GRAY; e = (Expression) list.getPropertyValue("bar uncertainty color"); if (e != null){ barUncColor = Color.decode((String) e.evaluate(feature)); } int pointerDirection = 21; e = (Expression) list.getPropertyValue("pointer direction"); if (e != null){ pointerDirection = ((Number) e.evaluate(feature)).intValue(); } Color pointerColor = Color.RED; e = (Expression) list.getPropertyValue("pointer color"); if (e != null){ pointerColor = Color.decode((String) e.evaluate(feature)); } int pointerLength = 100; e = (Expression) list.getPropertyValue("pointer length"); if (e != null){ pointerLength = ((Number) e.evaluate(feature)).intValue(); } int wedgeWidth = 25; e = (Expression) list.getPropertyValue("wedge width"); if (e != null){ wedgeWidth = ((Number) e.evaluate(feature)).intValue(); } Color wedgeColor = Color.BLUE; e = (Expression) list.getPropertyValue("wedge color"); if (e != null){ wedgeColor = Color.decode((String) e.evaluate(feature)); } int circleCenterX, circleCenterY, imageHeight, imageWidth; BufferedImage image; Graphics2D imageGraphic; //calculate maximum value of barHeight + barUncertainty & use that instead of "barHeight + barUncertainty" Expression tempExp = (Expression) list.getPropertyValue("bar height"); int temp1 = 0; if (tempExp != null){ temp1 = ((Number) tempExp.evaluate(feature)).intValue(); } tempExp = (Expression) list.getPropertyValue("bar uncertainty"); int temp2 = 0; if (tempExp != null){ temp2 = ((Number) tempExp.evaluate(feature)).intValue(); } if (temp1 + temp2 > maxBarHeight){ maxBarHeight = temp1 + temp2; } //chorner: feature.getParent is no more... is this needed? // if (!maxFound){ // maxFound = true; // SimpleFeatureCollection fc = feature.getParent(); // SimpleFeatureIterator features = fc.features(); // while (features.hasNext()){ // Feature next = features.next(); // Expression tempExp = (Expression) list.getPropertyValue("bar height"); // int temp1 = 0; // if (tempExp != null){ // temp1 = ((Number) tempExp.evaluate(next)).intValue(); // } // tempExp = (Expression) list.getPropertyValue("bar uncertainty"); // int temp2 = 0; // if (tempExp != null){ // temp2 = ((Number) tempExp.evaluate(next)).intValue(); // } // if (temp1 + temp2 > maxBarHeight){ // maxBarHeight = temp1 + temp2; // } // } // } circleCenterX = Math.max(pointerLength, radius); circleCenterY = Math.max(maxBarHeight, Math.max(pointerLength, radius)); imageHeight = Math.max(radius * 2, Math.max(radius + pointerLength, Math.max(radius + maxBarHeight, pointerLength + maxBarHeight))); imageWidth = Math.max(radius * 2, pointerLength * 2); image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB); pointerLength = Math.max(pointerLength, radius); imageGraphic = image.createGraphics(); imageGraphic.setColor(circleColor); imageGraphic.fillOval(circleCenterX - radius, circleCenterY - radius, radius * 2, radius * 2); imageGraphic.setColor(wedgeColor); imageGraphic.fillArc(circleCenterX - radius, circleCenterY - radius, radius * 2, radius * 2, calculateWedgeAngle(pointerDirection, wedgeWidth), wedgeWidth * 2); imageGraphic.setColor(barUncColor); imageGraphic.fillRect(circleCenterX - barUncWidth, circleCenterY - barHeight - barUncertainty, barUncWidth * 2, barUncertainty * 2); //pointer int[] endPoint = calculateEndOfPointer(circleCenterX, circleCenterY, pointerLength, pointerDirection); imageGraphic.setStroke(new java.awt.BasicStroke(3)); imageGraphic.setColor(pointerColor); imageGraphic.draw(new java.awt.geom.Line2D.Double(circleCenterX, circleCenterY, endPoint[0], endPoint[1])); //bar imageGraphic.setStroke(new java.awt.BasicStroke(3)); imageGraphic.setColor(barColor); imageGraphic.draw(new java.awt.geom.Line2D.Double(circleCenterX, circleCenterY, circleCenterX, circleCenterY - barHeight)); imageGraphic.dispose(); return image; } private int calculateWedgeAngle(int pointerDirection, int wedgeWidth){ return 450 - (pointerDirection + wedgeWidth); } private int[] calculateEndOfPointer(int circleCenterX, int circleCenterY, int pointerLength, int pointerDirection){ int x = circleCenterX + (int) Math.round(pointerLength * Math.cos(Math.toRadians(pointerDirection - 90))); int y = circleCenterY + (int) Math.round(pointerLength * Math.sin(Math.toRadians(pointerDirection - 90))); return new int[]{x, y}; } }