/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-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.style; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D.Double; import java.util.logging.Logger; import org.geotools.renderer.style.shape.ExplicitBoundsShape; import org.opengis.feature.Feature; import org.opengis.filter.expression.Expression; /** * The WellKnownMarkFactory is used to hold the knolwedge of how to draw * all the marks hardboiled into the SLD specification (cross, arrow, triangle etc...) * * @author James * * * * @source $URL$ */ public class WellKnownMarkFactory implements MarkFactory { /** The logger for the rendering module. */ private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger( "org.geotools.rendering"); /** Cross general path */ private static Shape cross; /** Star general path */ private static Shape star; /** Triangle general path */ private static Shape triangle; /** Arrow general path */ private static Shape arrow; /** X general path */ private static Shape X; /** hatch path */ static Shape hatch; /** square */ private static Shape square; static { GeneralPath crossPath = new GeneralPath(GeneralPath.WIND_EVEN_ODD); crossPath.moveTo(0.5f, 0.125f); crossPath.lineTo(0.125f, 0.125f); crossPath.lineTo(0.125f, 0.5f); crossPath.lineTo(-0.125f, 0.5f); crossPath.lineTo(-0.125f, 0.125f); crossPath.lineTo(-0.5f, 0.125f); crossPath.lineTo(-0.5f, -0.125f); crossPath.lineTo(-0.125f, -0.125f); crossPath.lineTo(-0.125f, -0.5f); crossPath.lineTo(0.125f, -0.5f); crossPath.lineTo(0.125f, -0.125f); crossPath.lineTo(0.5f, -0.125f); crossPath.lineTo(0.5f, 0.125f); cross = new ExplicitBoundsShape(crossPath); ((ExplicitBoundsShape)cross).setBounds(new Rectangle2D.Double(-.5,.5,1.,1.)); AffineTransform at = new AffineTransform(); at.rotate(Math.PI / 4.0); X = new ExplicitBoundsShape(crossPath.createTransformedShape(at)); ((ExplicitBoundsShape)X).setBounds(new Rectangle2D.Double(-.5,.5,1.,1.)); GeneralPath starPath = new GeneralPath(GeneralPath.WIND_EVEN_ODD); starPath.moveTo(0.191f, 0.0f); starPath.lineTo(0.25f, 0.344f); starPath.lineTo(0.0f, 0.588f); starPath.lineTo(0.346f, 0.638f); starPath.lineTo(0.5f, 0.951f); starPath.lineTo(0.654f, 0.638f); starPath.lineTo(1.0f, 0.588f); // max = 7.887 starPath.lineTo(0.75f, 0.344f); starPath.lineTo(0.89f, 0f); starPath.lineTo(0.5f, 0.162f); starPath.lineTo(0.191f, 0.0f); at = new AffineTransform(); at.translate(-.5, -.5); starPath.transform(at); star = new ExplicitBoundsShape(starPath); ((ExplicitBoundsShape)star).setBounds(new Rectangle2D.Double(-.5,.5,1.,1.)); GeneralPath trianglePath = new GeneralPath(GeneralPath.WIND_EVEN_ODD); trianglePath.moveTo(0f, 1f); trianglePath.lineTo(0.866f, -.5f); trianglePath.lineTo(-0.866f, -.5f); trianglePath.lineTo(0f, 1f); at = new AffineTransform(); at.translate(0, -.25); at.scale(.5, .5); trianglePath.transform(at); triangle = new ExplicitBoundsShape(trianglePath); ((ExplicitBoundsShape)triangle).setBounds(new Rectangle2D.Double(-.5,.5,1.,1.)); GeneralPath arrowPath = new GeneralPath(GeneralPath.WIND_EVEN_ODD); arrowPath.moveTo(0f, -.5f); arrowPath.lineTo(.5f, 0f); arrowPath.lineTo(0f, .5f); arrowPath.lineTo(0f, .1f); arrowPath.lineTo(-.5f, .1f); arrowPath.lineTo(-.5f, -.1f); arrowPath.lineTo(0f, -.1f); arrowPath.lineTo(0f, -.5f); arrow = new ExplicitBoundsShape(arrowPath); ((ExplicitBoundsShape)arrow).setBounds(new Rectangle2D.Double(-.5,.5,1.,1.)); GeneralPath hatchPath = new GeneralPath(GeneralPath.WIND_EVEN_ODD); hatchPath.moveTo(.55f,.57f); hatchPath.lineTo(.52f,.57f); hatchPath.lineTo(-.57f,-.52f); hatchPath.lineTo(-.57f,-.57f); hatchPath.lineTo(-.52f, -.57f); hatchPath.lineTo(.57f, .52f); hatchPath.lineTo(.57f,.57f); hatchPath.moveTo(.57f,-.49f); hatchPath.lineTo(.49f, -.57f); hatchPath.lineTo(.57f,-.57f); hatchPath.lineTo(.57f,-.49f); hatchPath.moveTo(-.57f,.5f); hatchPath.lineTo(-.5f, .57f); hatchPath.lineTo(-.57f,.57f); hatchPath.lineTo(-.57f,.5f); hatch = new ExplicitBoundsShape(hatchPath); ((ExplicitBoundsShape)hatch).setBounds(new Rectangle2D.Double(-.5,.5,1.,1.)); square = new Double(-.5, -.5, 1., 1.); } public Shape getShape(Graphics2D graphics, Expression symbolUrl, Feature feature) throws Exception { // cannot handle a null url if(symbolUrl == null) return null; String wellKnownName = symbolUrl.evaluate(feature, String.class); LOGGER.finer("fetching mark of name " + wellKnownName); if (wellKnownName.equalsIgnoreCase("cross")) { LOGGER.finer("returning cross"); return cross; } if (wellKnownName.equalsIgnoreCase("circle")) { LOGGER.finer("returning circle"); return new java.awt.geom.Ellipse2D.Double(-.5, -.5, 1., 1.); } if (wellKnownName.equalsIgnoreCase("triangle")) { LOGGER.finer("returning triangle"); return triangle; } if (wellKnownName.equalsIgnoreCase("X")) { LOGGER.finer("returning X"); return X; } if (wellKnownName.equalsIgnoreCase("star")) { LOGGER.finer("returning star"); return star; } if (wellKnownName.equalsIgnoreCase("arrow")) { LOGGER.finer("returning arrow"); return arrow; } if (wellKnownName.equalsIgnoreCase("hatch")) { LOGGER.finer("returning hatch"); return hatch; } if (wellKnownName.equalsIgnoreCase("square")) { LOGGER.finer("returning square"); return square; } // failing that return a square? LOGGER.finer("Could not find the symbol, returning null"); return null; } }