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 }