001: //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/trunk/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: mschneider $
063: *
064: * @version $Revision: 10547 $, $Date: 2008-03-11 01:40:28 -0700 (Tue, 11 Mar 2008) $
065: */
066: public class PointPlacement implements Marshallable {
067:
068: private static final ILogger LOG = LoggerFactory
069: .getLogger(PointPlacement.class);
070:
071: private ParameterValueType rotation = null;
072:
073: private ParameterValueType[] anchorPoint = null;
074:
075: private ParameterValueType[] displacement = null;
076:
077: // should the placement be optimized?
078: private boolean auto = false;
079:
080: /**
081: * package protected default constructor
082: *
083: */
084: PointPlacement() {
085:
086: }
087:
088: /**
089: * Creates a new PointPlacement object.
090: *
091: * @param anchorPoint
092: * @param displacement
093: * @param rotation
094: */
095: public PointPlacement(ParameterValueType[] anchorPoint,
096: ParameterValueType[] displacement,
097: ParameterValueType rotation, boolean auto) {
098: this .anchorPoint = anchorPoint;
099: this .displacement = displacement;
100: this .rotation = rotation;
101: this .auto = auto;
102: }
103:
104: /**
105: * returns the anchor points (x and y) as array of
106: *
107: * @see ParameterValueType
108: * @return anchor point as
109: * @see ParameterValueType
110: */
111: public ParameterValueType[] getAnchorPoint() {
112: return anchorPoint;
113: }
114:
115: /**
116: * returns the displacements (x and y) as array of
117: *
118: * @see ParameterValueType
119: * @return displacements (x and y) as array of
120: * @see ParameterValueType
121: */
122: public ParameterValueType[] getDisplacement() {
123: return displacement;
124: }
125:
126: /**
127: * returns the rotation of
128: *
129: * @see ParameterValueType
130: * @return
131: */
132: public ParameterValueType getRotation() {
133: return rotation;
134: }
135:
136: /**
137: * The AnchorPoint element of a PointPlacement gives the location inside of a label to use for
138: * anchoring the label to the main-geometry point.
139: * <p>
140: * </p>
141: * The coordinates are given as two floating-point numbers in the AnchorPointX and AnchorPointY
142: * elements each with values between 0.0 and 1.0 inclusive. The bounding box of the label to be
143: * rendered is considered to be in a coorindate space from 0.0 (lower-left corner) to 1.0
144: * (upper-right corner), and the anchor position is specified as a point in this space. The
145: * default point is X=0, Y=0.5, which is at the middle height of the left-hand side of the
146: * label. A system may choose different anchor points to de-conflict labels.
147: * <p>
148: *
149: * @param feature
150: * specifies the <tt>Feature</tt> to be used for evaluation of the underlying
151: * 'sld:ParameterValueType'
152: * @return 2 double values: x ([0]) and y ([0])
153: * @throws FilterEvaluationException
154: * if the evaluation fails
155: */
156: public double[] getAnchorPoint(Feature feature)
157: throws FilterEvaluationException {
158: double[] anchorPointVal = { 0.0, 0.5 };
159:
160: if (anchorPoint != null) {
161: anchorPointVal[0] = Double.parseDouble(anchorPoint[0]
162: .evaluate(feature));
163: anchorPointVal[1] = Double.parseDouble(anchorPoint[1]
164: .evaluate(feature));
165: }
166:
167: return anchorPointVal;
168: }
169:
170: /**
171: * @see PointPlacement#getAnchorPoint(Feature)
172: * <p>
173: * @param anchorPoint
174: * anchorPoint for the PointPlacement
175: */
176: public void setAnchorPoint(double[] anchorPoint) {
177: ParameterValueType pvt = null;
178: ParameterValueType[] pvtArray = new ParameterValueType[anchorPoint.length];
179: for (int i = 0; i < anchorPoint.length; i++) {
180: pvt = StyleFactory.createParameterValueType(""
181: + anchorPoint[i]);
182: pvtArray[i] = pvt;
183: }
184: this .anchorPoint = pvtArray;
185: }
186:
187: /**
188: * The Displacement element of a PointPlacement gives the X and Y displacements from the
189: * main-geometry point to render a text label.
190: * <p>
191: * </p>
192: * This will often be used to avoid over-plotting a graphic symbol marking a city or some such
193: * feature. The displacements are in units of pixels above and to the right of the point. A
194: * system may reflect this displacement about the X and/or Y axes to de-conflict labels. The
195: * default displacement is X=0, Y=0.
196: * <p>
197: *
198: * @param feature
199: * specifies the <tt>Feature</tt> to be used for evaluation of the underlying
200: * 'sld:ParameterValueType'
201: * @return 2 double values: x ([0]) and y ([0])
202: * @throws FilterEvaluationException
203: * if the evaluation fails*
204: */
205: public double[] getDisplacement(Feature feature)
206: throws FilterEvaluationException {
207: double[] displacementVal = { 0.0, 0.0 };
208:
209: if (displacement != null) {
210: displacementVal[0] = Double.parseDouble(displacement[0]
211: .evaluate(feature));
212: displacementVal[1] = Double.parseDouble(displacement[1]
213: .evaluate(feature));
214: }
215:
216: return displacementVal;
217: }
218:
219: /**
220: * @see PointPlacement#getDisplacement(Feature)
221: * <p>
222: * @param displacement
223: */
224: public void setDisplacement(double[] displacement) {
225: ParameterValueType pvt = null;
226: ParameterValueType[] pvtArray = new ParameterValueType[displacement.length];
227: for (int i = 0; i < displacement.length; i++) {
228: pvt = StyleFactory.createParameterValueType(""
229: + displacement[i]);
230: pvtArray[i] = pvt;
231: }
232: this .displacement = pvtArray;
233: }
234:
235: /**
236: * The Rotation of a PointPlacement gives the clockwise rotation of the label in degrees from
237: * the normal direction for a font (left-to-right for Latin- derived human languages at least).
238: * <p>
239: *
240: * @param feature
241: * specifies the <tt>Feature</tt> to be used for evaluation of the underlying
242: * 'sld:ParameterValueType'
243: * @return double value describing the rotation parameter
244: * @throws FilterEvaluationException
245: * if the evaluation fails*
246: */
247: public double getRotation(Feature feature)
248: throws FilterEvaluationException {
249: double rot = 0.0;
250:
251: if (rotation != null) {
252: String tmp = rotation.evaluate(feature);
253: if (tmp != null) {
254: try {
255: rot = Double.parseDouble(tmp);
256: } catch (NumberFormatException e) {
257: LOG
258: .logInfo(
259: "could not parse rotation value as float, use 0° as default: ",
260: tmp);
261: }
262: }
263: }
264:
265: return rot;
266: }
267:
268: /**
269: * @see PointPlacement#getRotation(Feature)
270: * @param rotation
271: * the rotation to be set for the PointPlacement
272: */
273: public void setRotation(double rotation) {
274: ParameterValueType pvt = null;
275: pvt = StyleFactory.createParameterValueType("" + rotation);
276: this .rotation = pvt;
277: }
278:
279: /**
280: * Returns whether the placement should be optimized or not.
281: * <p>
282: *
283: * @return true, if it should be optimized
284: *
285: */
286: public boolean isAuto() {
287: return auto;
288: }
289:
290: /**
291: * <p>
292: *
293: * @param auto
294: *
295: */
296: public void setAuto(boolean auto) {
297: this .auto = auto;
298: }
299:
300: /**
301: * exports the content of the PointPlacement as XML formated String
302: *
303: * @return xml representation of the PointPlacement
304: */
305: public String exportAsXML() {
306:
307: StringBuffer sb = new StringBuffer(1000);
308: sb.append("<PointPlacement");
309: if (auto) {
310: sb.append(" auto='true'");
311: }
312: sb.append(">");
313: if (anchorPoint != null && anchorPoint.length > 1) {
314: sb.append("<AnchorPoint>").append("<AnchorPointX>");
315: sb.append(((Marshallable) anchorPoint[0]).exportAsXML());
316: sb.append("</AnchorPointX>").append("<AnchorPointY>");
317: sb.append(((Marshallable) anchorPoint[1]).exportAsXML());
318: sb.append("</AnchorPointY>").append("</AnchorPoint>");
319: }
320: if (displacement != null && displacement.length > 1) {
321: sb.append("<Displacement>").append("<DisplacementX>");
322: sb.append(((Marshallable) displacement[0]).exportAsXML());
323: sb.append("</DisplacementX>").append("<DisplacementY>");
324: sb.append(((Marshallable) displacement[1]).exportAsXML());
325: sb.append("</DisplacementY>").append("</Displacement>");
326: }
327: if (rotation != null) {
328: sb.append("<Rotation>");
329: sb.append(((Marshallable) rotation).exportAsXML());
330: sb.append("</Rotation>");
331: }
332:
333: sb.append("</PointPlacement>");
334:
335: return sb.toString();
336: }
337: }
|