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