001 //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/model/spatialschema/PositionImpl.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.model.spatialschema;
037
038 import java.io.Serializable;
039 import java.util.Arrays;
040
041 import javax.vecmath.Point3d;
042
043 /**
044 * A sequence of decimals numbers which when written on a width are a sequence of coordinate positions. The width is
045 * derived from the CRS or coordinate dimension of the container.
046 *
047 * <p>
048 * -----------------------------------------------------------------------
049 * </p>
050 *
051 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
052 * @author last edited by: $Author: apoth $
053 * @version $Revision: 30154 $ $Date: 2011-03-24 16:41:18 +0100 (Thu, 24 Mar 2011) $
054 */
055 public class PositionImpl implements Position, Serializable {
056 /** Use serialVersionUID for interoperability. */
057 private final static long serialVersionUID = -3780255674921824356L;
058
059 private final Point3d point;
060
061 private static float accuracy = 0.000001f;
062
063 private final byte dimension;
064
065 /**
066 * constructor. initializes a point to the coordinate 0/0
067 */
068 protected PositionImpl() {
069 point = new Point3d();
070 dimension = 3;
071 }
072
073 /**
074 * constructor
075 *
076 * @param x
077 * x-value of the point
078 * @param y
079 * y-value of the point
080 */
081 protected PositionImpl( double x, double y ) {
082 point = new Point3d( (double)x, (double)y, Double.NaN );
083 dimension = 2;
084 }
085
086 /**
087 * constructor
088 *
089 * @param x
090 * x-value of the point
091 * @param y
092 * y-value of the point
093 * @param z
094 * z-value of the point
095 */
096 protected PositionImpl( double x, double y, double z ) {
097 point = new Point3d( (double)x, (double)y, (double)z );
098 if ( Double.isNaN( z ) ) {
099 dimension = 2;
100 } else {
101 dimension = 3;
102 }
103 }
104
105 /**
106 * constructor.
107 *
108 * @param coords
109 * the Coordinates from which the position is build.
110 */
111 protected PositionImpl( double[] coords ) {
112 if ( coords == null || coords.length < 2 || coords.length > 3 ) {
113 if ( coords == null ) {
114 throw new NullPointerException( "The given coordinate array does not denote a valid Position." );
115 }
116 throw new IllegalArgumentException( "The given coordinate array does not denote a valid Position: "
117 + Arrays.toString( coords ) );
118
119 }
120 if ( coords.length == 3 && !Double.isNaN( coords[2] ) ) {
121 dimension = 3;
122 } else {
123 if ( coords.length == 2 ) {
124 coords = new double[] { coords[0], coords[1], Double.NaN };
125 }
126 dimension = 2;
127 }
128 point = new Point3d( new Point3d(coords) );
129 }
130
131 /**
132 * Constructor from another Point3d
133 *
134 * @param other
135 * the Coordinates from which the position is build if <code>null</code> the default values 0,0,0 with
136 * a dim of 3 is assumed.
137 */
138 protected PositionImpl( final Point3d other ) {
139 if ( other != null ) {
140 dimension = (byte)( Double.isNaN( other.z ) ? 2 : 3);
141 point = new Point3d( other );
142 } else {
143 dimension = 3;
144 point = new Point3d();
145 }
146 }
147
148 /**
149 * @return the coordinate dimension of the position
150 */
151 public int getCoordinateDimension() {
152 return dimension;
153 }
154
155 /**
156 * @return a shallow copy of the geometry.
157 */
158 @Override
159 public Object clone() {
160 return new PositionImpl( (Point3d) point.clone() );
161 }
162
163 /**
164 * @return the x-value of this point
165 */
166 public double getX() {
167 return point.x;
168 }
169
170 /**
171 * @return the y-value of this point
172 */
173 public double getY() {
174 return point.y;
175 }
176
177 /**
178 * @return the z-value of this point, if dimension is 2, this value will be Double.NaN
179 */
180 public double getZ() {
181 return point.z;
182 }
183
184 /**
185 * @return the position as a array the first field contains the x- the second field the y-value etc.
186 *
187 * NOTE: The returned array always has a length of 3, regardless of the dimension. This is due to a limitation in
188 * the coordinate transformation package (proj4), which expects coordinates to have 3 dimensions.
189 */
190 public double[] getAsArray() {
191 return new double[] { point.x, point.y, point.z };
192 }
193
194 /**
195 * translate the point by the submitted values.
196 *
197 * @param d
198 */
199 public void translate( double[] d ) {
200 if ( d != null && d.length >= 2 ) {
201 point.x += d[0];
202 point.y += d[1];
203 if ( dimension == 3 ) {
204 if ( d.length == 3 ) {
205 point.z += d[2];
206 }
207 }
208 }
209 }
210
211 @Override
212 public boolean equals( Object other ) {
213 if ( other != null && other instanceof Position ) {
214 final Position that = (Position) other;
215 return dimension == that.getCoordinateDimension() && Math.abs( point.x - that.getX() ) <= accuracy
216 && Math.abs( point.y - that.getY() ) <= accuracy
217 && ( ( dimension == 3 ) ? Math.abs( point.z - that.getZ() ) <= accuracy : true );
218 }
219 return false;
220 }
221
222 /**
223 * @return the accuracy the position is defined. The accuracy is measured in values of the CRS the positions
224 * coordinates are stored
225 */
226 public double getAccuracy() {
227 return accuracy;
228 }
229
230 /**
231 * @param accuracy
232 */
233 public void setAccuracy( double accuracy ) {
234 PositionImpl.accuracy = (float)accuracy;
235 }
236
237 @Override
238 public String toString() {
239 StringBuilder ret = new StringBuilder( "Position: " );
240 ret.append( point.x ).append( " " );
241 ret.append( point.y );
242 if ( dimension == 3 ) {
243 ret.append( " " );
244 ret.append( point.z );
245 }
246 return ret.toString();
247 }
248
249 public final Point3d getAsPoint3d() {
250 return new Point3d( point );
251 }
252 }