001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/crs/src/org/deegree/model/csct/cs/WGS84ConversionInfo.java $
002 /*---------------- FILE HEADER ------------------------------------------
003 This file is part of deegree.
004 Copyright (C) 2001-2008 by:
005 Department of Geography, University of Bonn
006 http://www.giub.uni-bonn.de/deegree/
007 lat/lon GmbH
008 http://www.lat-lon.de
009
010 This library is free software; you can redistribute it and/or
011 modify it under the terms of the GNU Lesser General Public
012 License as published by the Free Software Foundation; either
013 version 2.1 of the License, or (at your option) any later version.
014 This library is distributed in the hope that it will be useful,
015 but WITHOUT ANY WARRANTY; without even the implied warranty of
016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017 Lesser General Public License for more details.
018 You should have received a copy of the GNU Lesser General Public
019 License along with this library; if not, write to the Free Software
020 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021 Contact:
022
023 Andreas Poth
024 lat/lon GmbH
025 Aennchenstr. 19
026 53177 Bonn
027 Germany
028 E-Mail: poth@lat-lon.de
029
030 Prof. Dr. Klaus Greve
031 Department of Geography
032 University of Bonn
033 Meckenheimer Allee 166
034 53115 Bonn
035 Germany
036 E-Mail: greve@giub.uni-bonn.de
037 ---------------------------------------------------------------------------*/
038 package org.deegree.crs.transformations;
039
040 import javax.vecmath.Matrix4d;
041
042 import org.deegree.crs.Identifiable;
043 import org.deegree.crs.projections.ProjectionUtils;
044
045 /**
046 * Parameters for a geographic transformation into WGS84. The Bursa Wolf parameters should be applied to geocentric
047 * coordinates, where the X axis points towards the Greenwich Prime Meridian, the Y axis points East, and the Z axis
048 * points North.
049 *
050 *
051 * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
052 *
053 * @author last edited by: $Author:$
054 *
055 * @version $Revision:$, $Date:$
056 *
057 */
058 public class WGS84ConversionInfo extends Identifiable {
059
060 /** Bursa Wolf shift in meters. */
061 public double dx;
062
063 /** Bursa Wolf shift in meters. */
064 public double dy;
065
066 /** Bursa Wolf shift in meters. */
067 public double dz;
068
069 /** Bursa Wolf rotation in arc seconds, which is 1/3600 of a degree. */
070 public double ex;
071
072 /** Bursa Wolf rotation in arc seconds. */
073 public double ey;
074
075 /** Bursa Wolf rotation in arc seconds. */
076 public double ez;
077
078 /** Bursa Wolf scaling in parts per million. */
079 public double ppm;
080
081 /**
082 * Construct a conversion info with all parameters set to 0;
083 *
084 * @param identifier
085 */
086 public WGS84ConversionInfo( String identifier ) {
087 this( new String[]{identifier} );
088 }
089
090 /**
091 * Construct a conversion info with all parameters set to 0;
092 *
093 * @param identifiers
094 */
095 public WGS84ConversionInfo( String[] identifiers ) {
096 super( identifiers );
097 }
098
099 /**
100 * Construct a conversion info with all parameters set to 0;
101 *
102 * @param identifiers
103 * @param names
104 * @param versions
105 * @param descriptions
106 * @param areasOfUse
107 */
108 public WGS84ConversionInfo( String[] identifiers, String[] names, String[] versions, String[] descriptions, String[] areasOfUse ) {
109 super( identifiers, names, versions, descriptions, areasOfUse );
110
111 }
112
113 /**
114 * @param dx
115 * Bursa Wolf shift in meters.
116 * @param dy
117 * Bursa Wolf shift in meters.
118 * @param dz
119 * Bursa Wolf shift in meters.
120 * @param ex
121 * Bursa Wolf rotation in arc seconds.
122 * @param ey
123 * Bursa Wolf rotation in arc seconds.
124 * @param ez
125 * Bursa Wolf rotation in arc seconds.
126 * @param ppm
127 * Bursa Wolf scaling in parts per million.
128 * @param identifiers
129 * @param names
130 * @param versions
131 * @param descriptions
132 * @param areaOfUses
133 */
134 public WGS84ConversionInfo( double dx, double dy, double dz, double ex, double ey, double ez, double ppm,
135 String[] identifiers, String[] names, String[] versions, String[] descriptions, String[] areaOfUses ) {
136 super( identifiers, names, versions, descriptions, areaOfUses );
137 this.dx = dx;
138 this.dy = dy;
139 this.dz = dz;
140 this.ex = ex;
141 this.ey = ey;
142 this.ez = ez;
143 this.ppm = ppm;
144 }
145
146 /**
147 * @param dx
148 * Bursa Wolf shift in meters.
149 * @param dy
150 * Bursa Wolf shift in meters.
151 * @param dz
152 * Bursa Wolf shift in meters.
153 * @param ex
154 * Bursa Wolf rotation in arc seconds.
155 * @param ey
156 * Bursa Wolf rotation in arc seconds.
157 * @param ez
158 * Bursa Wolf rotation in arc seconds.
159 * @param ppm
160 * Bursa Wolf scaling in parts per million.
161 * @param identifier
162 * @param name
163 * @param version
164 * @param description
165 * @param areaOfUse
166 */
167 public WGS84ConversionInfo( double dx, double dy, double dz, double ex, double ey, double ez, double ppm,
168 String identifier, String name, String version, String description, String areaOfUse ) {
169 this( dx, dy, dz, ex, ey, ez, ppm, new String[]{identifier}, new String[]{name}, new String[]{version}, new String[]{description}, new String[]{areaOfUse} );
170 }
171
172 /**
173 * @param dx
174 * Bursa Wolf shift in meters.
175 * @param dy
176 * Bursa Wolf shift in meters.
177 * @param dz
178 * Bursa Wolf shift in meters.
179 * @param ex
180 * Bursa Wolf rotation in arc seconds.
181 * @param ey
182 * Bursa Wolf rotation in arc seconds.
183 * @param ez
184 * Bursa Wolf rotation in arc seconds.
185 * @param ppm
186 * Bursa Wolf scaling in parts per million.
187 * @param identifiers
188 */
189 public WGS84ConversionInfo( double dx, double dy, double dz, double ex, double ey, double ez, double ppm,
190 String[] identifiers ) {
191 this( dx, dy, dz, ex, ey, ez, ppm, identifiers, null, null, null, null );
192 }
193
194 /**
195 * @param dx
196 * Bursa Wolf shift in meters.
197 * @param dy
198 * Bursa Wolf shift in meters.
199 * @param dz
200 * Bursa Wolf shift in meters.
201 * @param ex
202 * Bursa Wolf rotation in arc seconds.
203 * @param ey
204 * Bursa Wolf rotation in arc seconds.
205 * @param ez
206 * Bursa Wolf rotation in arc seconds.
207 * @param ppm
208 * Bursa Wolf scaling in parts per million.
209 * @param identifier
210 */
211 public WGS84ConversionInfo( double dx, double dy, double dz, double ex, double ey, double ez, double ppm,
212 String identifier) {
213 this( dx, dy, dz, ex, ey, ez, ppm, new String[]{identifier});
214 }
215
216 /**
217 * @param dx
218 * Bursa Wolf shift in meters.
219 * @param dy
220 * Bursa Wolf shift in meters.
221 * @param dz
222 * Bursa Wolf shift in meters.
223 * @param ex
224 * Bursa Wolf rotation in arc seconds.
225 * @param ey
226 * Bursa Wolf rotation in arc seconds.
227 * @param ez
228 * Bursa Wolf rotation in arc seconds.
229 * @param ppm
230 * Bursa Wolf scaling in parts per million.
231 * @param identifiable object containing all relevant id.
232 */
233 public WGS84ConversionInfo( double dx, double dy, double dz, double ex, double ey, double ez, double ppm, Identifiable identifiable ) {
234 super( identifiable );
235 this.dx = dx;
236 this.dy = dy;
237 this.dz = dz;
238 this.ex = ex;
239 this.ey = ey;
240 this.ez = ez;
241 this.ppm = ppm;
242 }
243
244 /**
245 * Returns an affine tranformation also known as the "Helmert" transformation. The matrix representation of this
246 * transformation (also known as "Bursa Wolf" formula) is as follows:
247 *
248 * <blockquote>
249 *
250 * <pre>
251 * S = 1 + {@link #ppm}/1000000
252 *
253 * [ X ] [ S -{@link #ez}*S +{@link #ey}*S {@link #dx} ] [ X ]
254 * [ Y ] = [ +{@link #ez}*S S -{@link #ex}*S {@link #dy} ] [ Y ]
255 * [ Z ] [ -{@link #ey}*S +{@link #ex}*S S {@link #dz} ] [ Z ]
256 * [ 1 ] [ 0 0 0 1 ] [ 1 ]
257 * </pre>
258 *
259 * </blockquote>
260 *
261 * This affine transform can be applied to transform <code>geocentric</code> coordinates from one datum into
262 * <code>geocentric</code> coordinates of an other datum. see <a
263 * href="http://www.posc.org/Epicentre.2_2/DataModel/ExamplesofUsage/eu_cs35.html#CS3523_helmert">
264 * http://www.posc.org/Epicentre.2_2/DataModel/ExamplesofUsage/eu_cs35.html</a> for more information.
265 *
266 * @return the affine "Helmert" transformation as a Matrix4d.
267 */
268 public Matrix4d getAsAffineTransform() {
269 // Note: (ex, ey, ez) is a rotation in arc seconds. We need to convert it into radians (the R factor in RS).
270 final double S = 1 + ( ppm * 1E-6 );
271 final double RS = ( Math.PI / ( 180. * 3600. ) ) * S;
272 return new Matrix4d( S,
273 -ez * RS,
274 +ey * RS,
275 dx,
276 +ez * RS,
277 S,
278 -ex * RS,
279 dy,
280 -ey * RS,
281 +ex * RS,
282 S,
283 dz,
284 0,
285 0,
286 0,
287 1. );
288 }
289
290 @Override
291 public boolean equals( final Object object ) {
292 if ( object != null && object instanceof WGS84ConversionInfo ) {
293 final WGS84ConversionInfo that = (WGS84ConversionInfo) object;
294 return Math.abs( this.dx - that.dx ) < ProjectionUtils.EPS11 && Math.abs( this.dy - that.dy ) < ProjectionUtils.EPS11
295 && Math.abs( this.dz - that.dz ) < ProjectionUtils.EPS11
296 && Math.abs( this.ex - that.ex ) < ProjectionUtils.EPS11
297 && Math.abs( this.ey - that.ey ) < ProjectionUtils.EPS11
298 && Math.abs( this.ez - that.ez ) < ProjectionUtils.EPS11
299 && Math.abs( this.ppm - that.ppm ) < ProjectionUtils.EPS11;
300
301 }
302 return false;
303 }
304
305 /**
306 * Returns the Well Know Text (WKT) for this object. The WKT is part of OpenGIS's specification and looks like
307 * <code>TOWGS84[dx, dy, dz, ex, ey, ez, ppm]</code>.
308 *
309 * @return the Well Know Text (WKT) for this object.
310 */
311 @Override
312 public String toString() {
313 final StringBuffer buffer = new StringBuffer( "[\"" );
314 buffer.append( dx );
315 buffer.append( ", " );
316 buffer.append( dy );
317 buffer.append( ", " );
318 buffer.append( dz );
319 buffer.append( ", " );
320 buffer.append( ex );
321 buffer.append( ", " );
322 buffer.append( ey );
323 buffer.append( ", " );
324 buffer.append( ez );
325 buffer.append( ", " );
326 buffer.append( ppm );
327 buffer.append( ']' );
328 return buffer.toString();
329 }
330
331 /**
332 * Implementation as proposed by Joshua Block in Effective Java (Addison-Wesley 2001), which supplies an even
333 * distribution and is relatively fast. It is created from field <b>f</b> as follows:
334 * <ul>
335 * <li>boolean -- code = (f ? 0 : 1)</li>
336 * <li>byte, char, short, int -- code = (int)f </li>
337 * <li>long -- code = (int)(f ^ (f >>>32))</li>
338 * <li>float -- code = Float.floatToIntBits(f);</li>
339 * <li>double -- long l = Double.doubleToLongBits(f); code = (int)(l ^ (l >>> 32))</li>
340 * <li>all Objects, (where equals( ) calls equals( ) for this field) -- code = f.hashCode( )</li>
341 * <li>Array -- Apply above rules to each element</li>
342 * </ul>
343 * <p>
344 * Combining the hash code(s) computed above: result = 37 * result + code;
345 * </p>
346 *
347 * @return (int) ( result >>> 32 ) ^ (int) result;
348 *
349 * @see java.lang.Object#hashCode()
350 */
351 @Override
352 public int hashCode() {
353 // the 2nd millionth prime, :-)
354 long code = 32452843;
355 long tmp = Double.doubleToLongBits( dx );
356 code = code * 37 + (int)( tmp ^ (tmp >>> 32 ));
357
358 tmp = Double.doubleToLongBits( dy );
359 code = code * 37 + (int)( tmp ^ (tmp >>> 32 ));
360
361 tmp = Double.doubleToLongBits( dz );
362 code = code * 37 + (int)( tmp ^ (tmp >>> 32 ));
363
364 tmp = Double.doubleToLongBits( ex );
365 code = code * 37 + (int)( tmp ^ (tmp >>> 32 ));
366
367 tmp = Double.doubleToLongBits( ey );
368 code = code * 37 + (int)( tmp ^ (tmp >>> 32 ));
369
370 tmp = Double.doubleToLongBits( ez );
371 code = code * 37 + (int)( tmp ^ (tmp >>> 32 ));
372
373 tmp = Double.doubleToLongBits( ppm );
374 code = code * 37 + (int)( tmp ^ (tmp >>> 32 ));
375 return (int) ( code >>> 32 ) ^ (int) code;
376 }
377 }