001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/graphics/sld/PointPlacement.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 package org.deegree.graphics.sld; 037 038 import org.deegree.framework.log.ILogger; 039 import org.deegree.framework.log.LoggerFactory; 040 import org.deegree.framework.xml.Marshallable; 041 import org.deegree.model.feature.Feature; 042 import org.deegree.model.filterencoding.FilterEvaluationException; 043 import org.deegree.model.filterencoding.PropertyName; 044 045 /** 046 * Incarnation of a sld:PointPlacement-element. For a PointPlacement, the anchor point of the label 047 * and a linear displacement from the point can be specified, to allow a graphic symbol to be 048 * plotted directly at the point. This might be useful to label a city, for example. For a 049 * LinePlacement, a perpendicular offset can be specified, to allow the line itself to be plotted 050 * also. This might be useful for labelling a road or a river, for example. 051 * <p> 052 * 053 * 054 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 055 * @author last edited by: $Author: mschneider $ 056 * 057 * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18 Jun 2009) $ 058 */ 059 public class PointPlacement implements Marshallable { 060 061 private static final ILogger LOG = LoggerFactory.getLogger( PointPlacement.class ); 062 063 private ParameterValueType rotation = null; 064 065 private ParameterValueType[] anchorPoint = null; 066 067 private ParameterValueType[] displacement = null; 068 069 // should the placement be optimized? 070 private boolean auto = false; 071 072 /** 073 * package protected default constructor 074 * 075 */ 076 PointPlacement() { 077 //again nothing. 078 } 079 080 /** 081 * Creates a new PointPlacement object. 082 * 083 * @param anchorPoint 084 * @param displacement 085 * @param rotation 086 * @param auto 087 */ 088 public PointPlacement( ParameterValueType[] anchorPoint, ParameterValueType[] displacement, 089 ParameterValueType rotation, boolean auto ) { 090 this.anchorPoint = anchorPoint; 091 this.displacement = displacement; 092 this.rotation = rotation; 093 this.auto = auto; 094 } 095 096 /** 097 * returns the anchor points (x and y) as array of 098 * 099 * @see ParameterValueType 100 * @return anchor point as 101 * @see ParameterValueType 102 */ 103 public ParameterValueType[] getAnchorPoint() { 104 return anchorPoint; 105 } 106 107 /** 108 * returns the displacements (x and y) as array of 109 * 110 * @see ParameterValueType 111 * @return displacements (x and y) as array of 112 * @see ParameterValueType 113 */ 114 public ParameterValueType[] getDisplacement() { 115 return displacement; 116 } 117 118 /** 119 * returns the rotation of ParameterValueType 120 * @return the rotation 121 */ 122 public ParameterValueType getRotation() { 123 return rotation; 124 } 125 126 /** 127 * The AnchorPoint element of a PointPlacement gives the location inside of a label to use for 128 * anchoring the label to the main-geometry point. 129 * <p> 130 * </p> 131 * The coordinates are given as two floating-point numbers in the AnchorPointX and AnchorPointY 132 * elements each with values between 0.0 and 1.0 inclusive. The bounding box of the label to be 133 * rendered is considered to be in a coorindate space from 0.0 (lower-left corner) to 1.0 134 * (upper-right corner), and the anchor position is specified as a point in this space. The 135 * default point is X=0, Y=0.5, which is at the middle height of the left-hand side of the 136 * label. A system may choose different anchor points to de-conflict labels. 137 * <p> 138 * 139 * @param feature 140 * specifies the <tt>Feature</tt> to be used for evaluation of the underlying 141 * 'sld:ParameterValueType' 142 * @return 2 double values: x ([0]) and y ([0]) 143 * @throws FilterEvaluationException 144 * if the evaluation fails 145 */ 146 public double[] getAnchorPoint( Feature feature ) 147 throws FilterEvaluationException { 148 double[] anchorPointVal = { 0.0, 0.5 }; 149 150 if ( anchorPoint != null ) { 151 anchorPointVal[0] = Double.parseDouble( anchorPoint[0].evaluate( feature ) ); 152 anchorPointVal[1] = Double.parseDouble( anchorPoint[1].evaluate( feature ) ); 153 } 154 155 return anchorPointVal; 156 } 157 158 /** 159 * @see PointPlacement#getAnchorPoint(Feature) 160 * <p> 161 * @param anchorPoint 162 * anchorPoint for the PointPlacement 163 */ 164 public void setAnchorPoint( double[] anchorPoint ) { 165 ParameterValueType pvt = null; 166 ParameterValueType[] pvtArray = new ParameterValueType[anchorPoint.length]; 167 for ( int i = 0; i < anchorPoint.length; i++ ) { 168 pvt = StyleFactory.createParameterValueType( "" + anchorPoint[i] ); 169 pvtArray[i] = pvt; 170 } 171 this.anchorPoint = pvtArray; 172 } 173 174 /** 175 * The Displacement element of a PointPlacement gives the X and Y displacements from the 176 * main-geometry point to render a text label. 177 * <p> 178 * </p> 179 * This will often be used to avoid over-plotting a graphic symbol marking a city or some such 180 * feature. The displacements are in units of pixels above and to the right of the point. A 181 * system may reflect this displacement about the X and/or Y axes to de-conflict labels. The 182 * default displacement is X=0, Y=0. 183 * <p> 184 * 185 * @param feature 186 * specifies the <tt>Feature</tt> to be used for evaluation of the underlying 187 * 'sld:ParameterValueType' 188 * @return 2 double values: x ([0]) and y ([0]) 189 * @throws FilterEvaluationException 190 * if the evaluation fails* 191 */ 192 public double[] getDisplacement( Feature feature ) 193 throws FilterEvaluationException { 194 double[] displacementVal = { 0.0, 0.0 }; 195 196 if ( displacement != null ) { 197 displacementVal[0] = Double.parseDouble( displacement[0].evaluate( feature ) ); 198 displacementVal[1] = Double.parseDouble( displacement[1].evaluate( feature ) ); 199 } 200 201 return displacementVal; 202 } 203 204 /** 205 * @see PointPlacement#getDisplacement(Feature) 206 * <p> 207 * @param displacement 208 */ 209 public void setDisplacement( double[] displacement ) { 210 ParameterValueType pvt = null; 211 ParameterValueType[] pvtArray = new ParameterValueType[displacement.length]; 212 for ( int i = 0; i < displacement.length; i++ ) { 213 pvt = StyleFactory.createParameterValueType( "" + displacement[i] ); 214 pvtArray[i] = pvt; 215 } 216 this.displacement = pvtArray; 217 } 218 219 /** 220 * The Rotation of a PointPlacement gives the clockwise rotation of the label in degrees from 221 * the normal direction for a font (left-to-right for Latin- derived human languages at least). 222 * <p> 223 * 224 * @param feature 225 * specifies the <tt>Feature</tt> to be used for evaluation of the underlying 226 * 'sld:ParameterValueType' 227 * @return double value describing the rotation parameter 228 * @throws FilterEvaluationException 229 * if the evaluation fails* 230 */ 231 public double getRotation( Feature feature ) 232 throws FilterEvaluationException { 233 double rot = 0.0; 234 235 if ( rotation != null ) { 236 String tmp = rotation.evaluate( feature ); 237 if ( tmp != null ) { 238 try { 239 rot = Double.parseDouble( tmp ); 240 } catch ( NumberFormatException e ) { 241 LOG.logInfo( "could not parse rotation value as float, use 0° as default: ", tmp ); 242 } 243 } 244 } 245 246 return rot; 247 } 248 249 250 /** 251 * Returns the property name of the rotation if available 252 * 253 * @return the property name or null, if no property name is set 254 */ 255 public PropertyName getRotationPropertyName() { 256 if ( rotation != null ) { 257 Object[] o = rotation.getComponents(); 258 for ( int i = 0; i < o.length; i++ ) { 259 if ( o[i] instanceof PropertyName ) { 260 return (PropertyName) o[i]; 261 } 262 } 263 } 264 return null; 265 } 266 267 /** 268 * @see PointPlacement#getRotation(Feature) 269 * @param rotation 270 * the rotation to be set for the PointPlacement 271 */ 272 public void setRotation( double rotation ) { 273 ParameterValueType pvt = null; 274 pvt = StyleFactory.createParameterValueType( "" + rotation ); 275 this.rotation = pvt; 276 } 277 278 /** 279 * Returns whether the placement should be optimized or not. 280 * <p> 281 * 282 * @return true, if it should be optimized 283 * 284 */ 285 public boolean isAuto() { 286 return auto; 287 } 288 289 /** 290 * <p> 291 * 292 * @param auto 293 * 294 */ 295 public void setAuto( boolean auto ) { 296 this.auto = auto; 297 } 298 299 /** 300 * exports the content of the PointPlacement as XML formated String 301 * 302 * @return xml representation of the PointPlacement 303 */ 304 public String exportAsXML() { 305 306 StringBuffer sb = new StringBuffer( 1000 ); 307 sb.append( "<PointPlacement" ); 308 if ( auto ) { 309 sb.append( " auto='true'" ); 310 } 311 sb.append( ">" ); 312 if ( anchorPoint != null && anchorPoint.length > 1 ) { 313 sb.append( "<AnchorPoint>" ).append( "<AnchorPointX>" ); 314 sb.append( ( (Marshallable) anchorPoint[0] ).exportAsXML() ); 315 sb.append( "</AnchorPointX>" ).append( "<AnchorPointY>" ); 316 sb.append( ( (Marshallable) anchorPoint[1] ).exportAsXML() ); 317 sb.append( "</AnchorPointY>" ).append( "</AnchorPoint>" ); 318 } 319 if ( displacement != null && displacement.length > 1 ) { 320 sb.append( "<Displacement>" ).append( "<DisplacementX>" ); 321 sb.append( ( (Marshallable) displacement[0] ).exportAsXML() ); 322 sb.append( "</DisplacementX>" ).append( "<DisplacementY>" ); 323 sb.append( ( (Marshallable) displacement[1] ).exportAsXML() ); 324 sb.append( "</DisplacementY>" ).append( "</Displacement>" ); 325 } 326 if ( rotation != null ) { 327 sb.append( "<Rotation>" ); 328 sb.append( ( (Marshallable) rotation ).exportAsXML() ); 329 sb.append( "</Rotation>" ); 330 } 331 332 sb.append( "</PointPlacement>" ); 333 334 return sb.toString(); 335 } 336 }