001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/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: 25061 $ $Date: 2010-06-24 15:44:25 +0200 (Do, 24 Jun 2010) $ 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 double accuracy = 0.000001; 062 063 private final int 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( x, 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( x, y, 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( 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 = 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 this.accuracy = 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 point; 251 } 252 }