001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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 }