001: //$HeadURL: $
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:
039: package org.deegree.crs.components;
040:
041: import org.deegree.crs.Identifiable;
042: import org.deegree.crs.projections.ProjectionUtils;
043:
044: /**
045: * The <code>Ellipsoid</code> class hold all parameters which are necessary to define an Ellipsoid. Every Ellipsoid
046: * has a semi-major-axis and one of inverse_flattening, eccentricity or semi-minor-axis.
047: *
048: * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
049: *
050: * @author last edited by: $Author:$
051: *
052: * @version $Revision:$, $Date:$
053: *
054: */
055:
056: public class Ellipsoid extends Identifiable {
057:
058: /**
059: * WGS 1984 ellipsoid. This ellipsoid is used in the GPS system and is the "default" Ellipsoid.
060: */
061: public static final Ellipsoid WGS84 = new Ellipsoid(6378137.0,
062: Unit.METRE, 298.257223563, "EPSG:7030", "WGS84_Ellipsoid");
063:
064: /**
065: * the larger one of the two (semi)axis of an ellipsoid
066: */
067: private final double semiMajorAxis;
068:
069: /**
070: * the smaller one of the two (semi)axis of an ellipsoid
071: */
072: private final double semiMinorAxis;
073:
074: /**
075: * the units of the axis
076: */
077: private final Unit units;
078:
079: /**
080: * Flattening f is dependent on both the semi-major axis a and the semi-minor axis b. f = (a - b) / a
081: */
082: private final double flattening;
083:
084: /**
085: * Flattening f is normally given as 1/... value therefore an inverse is often given.
086: */
087: private final double inverseFlattening;
088:
089: /**
090: * The ellipsoid may also be defined by its semi-major axis a and eccentricity e, which is given by: e*e = 2f - f*f
091: */
092: private final double eccentricity;
093:
094: /**
095: * The ellipsoid may also be defined by its semi-major axis a and eccentricity e, which is given by: e*e = 2f - f*f,
096: * this is it's squared value.
097: */
098: private final double squaredEccentricity;
099:
100: /**
101: * @param units
102: * @param semiMajorAxis
103: * @param semiMinorAxis
104: * @param identifiers
105: * @param names
106: * @param versions
107: * @param descriptions
108: * @param areasOfUse
109: */
110: public Ellipsoid(Unit units, double semiMajorAxis,
111: double semiMinorAxis, String[] identifiers, String[] names,
112: String[] versions, String[] descriptions,
113: String[] areasOfUse) {
114: super (identifiers, names, versions, descriptions, areasOfUse);
115: this .units = units;
116: this .semiMajorAxis = semiMajorAxis;
117: this .semiMinorAxis = semiMinorAxis;
118: flattening = (semiMajorAxis - semiMinorAxis) / semiMajorAxis;
119: if (Math.abs(flattening) > 0.00001) {
120: inverseFlattening = 1. / flattening;
121: } else {
122: inverseFlattening = 0;
123: }
124: this .squaredEccentricity = calcSquaredEccentricity(flattening);
125: this .eccentricity = Math.sqrt(squaredEccentricity);
126: }
127:
128: /**
129: * @param units
130: * @param semiMajorAxis
131: * @param semiMinorAxis
132: * @param identifier
133: * @param name
134: * @param version
135: * @param description
136: * @param areaOfUse
137: */
138: public Ellipsoid(Unit units, double semiMajorAxis,
139: double semiMinorAxis, String identifier, String name,
140: String version, String description, String areaOfUse) {
141: this (units, semiMajorAxis, semiMinorAxis,
142: new String[] { identifier }, new String[] { name },
143: new String[] { version }, new String[] { description },
144: new String[] { areaOfUse });
145: }
146:
147: /**
148: * @param units
149: * @param semiMajorAxis
150: * @param semiMinorAxis
151: * @param identifiers
152: */
153: public Ellipsoid(Unit units, double semiMajorAxis,
154: double semiMinorAxis, String[] identifiers) {
155: this (units, semiMajorAxis, semiMinorAxis, identifiers, null,
156: null, null, null);
157: }
158:
159: /**
160: * @param units
161: * @param semiMajorAxis
162: * @param semiMinorAxis
163: * @param identifier
164: * @param name
165: */
166: public Ellipsoid(Unit units, double semiMajorAxis,
167: double semiMinorAxis, String identifier, String name) {
168: this (units, semiMajorAxis, semiMinorAxis,
169: new String[] { identifier }, new String[] { name },
170: null, null, null);
171: }
172:
173: /**
174: * @param semiMajorAxis
175: * @param units
176: * @param inverseFlattening
177: * @param identifiers
178: * @param names
179: * @param versions
180: * @param descriptions
181: * @param areasOfUse
182: */
183: public Ellipsoid(double semiMajorAxis, Unit units,
184: double inverseFlattening, String[] identifiers,
185: String[] names, String[] versions, String[] descriptions,
186: String[] areasOfUse) {
187: super (identifiers, names, versions, descriptions, areasOfUse);
188: this .units = units;
189: this .semiMajorAxis = semiMajorAxis;
190: this .inverseFlattening = inverseFlattening;
191: if (Math.abs(this .inverseFlattening) > 0.00001) {
192: flattening = 1. / this .inverseFlattening;
193: } else {
194: flattening = 0;
195: }
196: this .squaredEccentricity = calcSquaredEccentricity(this .flattening);
197: eccentricity = Math.sqrt(squaredEccentricity);
198: this .semiMinorAxis = this .semiMajorAxis
199: - (flattening * this .semiMajorAxis);
200: }
201:
202: /**
203: * @param semiMajorAxis
204: * @param units
205: * @param inverseFlattening
206: * @param identifier
207: * @param name
208: * @param version
209: * @param description
210: * @param areaOfUse
211: */
212: public Ellipsoid(double semiMajorAxis, Unit units,
213: double inverseFlattening, String identifier, String name,
214: String version, String description, String areaOfUse) {
215: this (semiMajorAxis, units, inverseFlattening,
216: new String[] { identifier }, new String[] { name },
217: new String[] { version }, new String[] { description },
218: new String[] { areaOfUse });
219: }
220:
221: /**
222: * @param semiMajorAxis
223: * @param units
224: * @param inverseFlattening
225: * @param identifiers
226: */
227: public Ellipsoid(double semiMajorAxis, Unit units,
228: double inverseFlattening, String[] identifiers) {
229: this (semiMajorAxis, units, inverseFlattening, identifiers,
230: null, null, null, null);
231: }
232:
233: /**
234: * @param semiMajorAxis
235: * @param units
236: * @param inverseFlattening
237: * @param identifier
238: * @param name
239: */
240: public Ellipsoid(double semiMajorAxis, Unit units,
241: double inverseFlattening, String identifier, String name) {
242: this (semiMajorAxis, units, inverseFlattening,
243: new String[] { identifier }, new String[] { name },
244: null, null, null);
245: }
246:
247: /**
248: * @param semiMajorAxis
249: * @param eccentricity
250: * @param units
251: * @param identifiers
252: * @param names
253: * @param versions
254: * @param descriptions
255: * @param areasOfUse
256: */
257: public Ellipsoid(double semiMajorAxis, double eccentricity,
258: Unit units, String[] identifiers, String[] names,
259: String[] versions, String[] descriptions,
260: String[] areasOfUse) {
261: super (identifiers, names, versions, descriptions, areasOfUse);
262: this .units = units;
263: this .semiMajorAxis = semiMajorAxis;
264: this .eccentricity = eccentricity;
265: this .squaredEccentricity = this .eccentricity
266: * this .eccentricity;
267: this .flattening = calcFlattening(eccentricity);
268: if (Math.abs(flattening) > 0.00001) {
269: this .inverseFlattening = 1d / flattening;
270: } else {
271: this .inverseFlattening = 0;
272: }
273: this .semiMinorAxis = this .semiMajorAxis
274: - (flattening * this .semiMajorAxis);
275: }
276:
277: /**
278: * @param semiMajorAxis
279: * @param eccentricity
280: * @param units
281: * @param identifier
282: * @param name
283: * @param version
284: * @param description
285: * @param areaOfUse
286: */
287: public Ellipsoid(double semiMajorAxis, double eccentricity,
288: Unit units, String identifier, String name, String version,
289: String description, String areaOfUse) {
290: this (semiMajorAxis, eccentricity, units,
291: new String[] { identifier }, new String[] { name },
292: new String[] { version }, new String[] { description },
293: new String[] { areaOfUse });
294: }
295:
296: /**
297: * @param semiMajorAxis
298: * @param eccentricity
299: * @param units
300: * @param identifiers
301: */
302: public Ellipsoid(double semiMajorAxis, double eccentricity,
303: Unit units, String[] identifiers) {
304: this (semiMajorAxis, eccentricity, units, identifiers, null,
305: null, null, null);
306: }
307:
308: /**
309: * @param semiMajorAxis
310: * @param eccentricity
311: * @param units
312: * @param identifier
313: * @param name
314: */
315: public Ellipsoid(double semiMajorAxis, double eccentricity,
316: Unit units, String identifier, String name) {
317: this (semiMajorAxis, eccentricity, units,
318: new String[] { identifier }, new String[] { name },
319: null, null, null);
320: }
321:
322: /**
323: * @return the eccentricity.
324: */
325: public final double getEccentricity() {
326: return eccentricity;
327: }
328:
329: /**
330: * @return the squared eccentricity of the ellipsoid-
331: */
332: public final double getSquaredEccentricity() {
333: return squaredEccentricity;
334: }
335:
336: /**
337: * @return the flattening.
338: */
339: public final double getFlattening() {
340: return flattening;
341: }
342:
343: /**
344: * @return the inverseFlattening.
345: */
346: public final double getInverseFlattening() {
347: return inverseFlattening;
348: }
349:
350: /**
351: * @return the semiMajorAxis.
352: */
353: public final double getSemiMajorAxis() {
354: return semiMajorAxis;
355: }
356:
357: /**
358: * @return the semiMinorAxis.
359: */
360: public final double getSemiMinorAxis() {
361: return semiMinorAxis;
362: }
363:
364: /**
365: * @return the units.
366: */
367: public final Unit getUnits() {
368: return units;
369: }
370:
371: /**
372: * @param other
373: * another ellipsoid
374: * @return true if the other ellipsoid != null and its units, semi-major-axis and eccentricity are the same.
375: */
376: @Override
377: public boolean equals(Object other) {
378: if (other != null && other instanceof Ellipsoid) {
379: final Ellipsoid that = (Ellipsoid) other;
380: return this .units.equals(that.units)
381: && (Math.abs(this .semiMajorAxis
382: - that.semiMajorAxis) < ProjectionUtils.EPS11)
383: && (Math.abs(this .eccentricity - that.eccentricity) < ProjectionUtils.EPS11)
384: && super .equals(that);
385: }
386: return false;
387: }
388:
389: /**
390: * Calc the eccentricity from the flattening
391: *
392: * @param flattening
393: * given.
394: * @return the squared eccentricity which is given by e^2 = 2*f - f*f.
395: */
396: private double calcSquaredEccentricity(double flattening) {
397: return (2. * flattening) - (flattening * flattening);
398: }
399:
400: /**
401: * calcs the flattening of an ellispoid using the eccentricity.
402: *
403: * @param eccentricity
404: * given
405: * @return 1-sqrt( 1- e^2) or 0 if e^1 > 1
406: */
407: private double calcFlattening(double eccentricity) {
408: if (eccentricity * eccentricity > 1) {
409: return 0;
410: }
411: return 1 - Math.sqrt((1 - eccentricity * eccentricity));
412: }
413:
414: @Override
415: public String toString() {
416: StringBuilder sb = new StringBuilder(super .toString());
417: sb.append(", - Units: ").append(units);
418: sb.append(", - semi-major-axis(a): ").append(semiMajorAxis);
419: sb.append(", - semi-minor-axis(b): ").append(semiMinorAxis);
420: sb.append(", - inverse-flattening: ").append(inverseFlattening);
421: sb.append(", - eccentricity: ").append(eccentricity);
422: return sb.toString();
423: }
424:
425: /**
426: * Implementation as proposed by Joshua Block in Effective Java (Addison-Wesley 2001), which supplies an even
427: * distribution and is relatively fast. It is created from field <b>f</b> as follows:
428: * <ul>
429: * <li>boolean -- code = (f ? 0 : 1)</li>
430: * <li>byte, char, short, int -- code = (int)f </li>
431: * <li>long -- code = (int)(f ^ (f >>>32))</li>
432: * <li>float -- code = Float.floatToIntBits(f);</li>
433: * <li>double -- long l = Double.doubleToLongBits(f); code = (int)(l ^ (l >>> 32))</li>
434: * <li>all Objects, (where equals( ) calls equals( ) for this field) -- code = f.hashCode( )</li>
435: * <li>Array -- Apply above rules to each element</li>
436: * </ul>
437: * <p>
438: * Combining the hash code(s) computed above: result = 37 * result + code;
439: * </p>
440: *
441: * @return (int) ( result >>> 32 ) ^ (int) result;
442: *
443: * @see java.lang.Object#hashCode()
444: */
445: @Override
446: public int hashCode() {
447: // the 2nd millionth prime, :-)
448: long code = 32452843;
449: if (units != null) {
450: code = code * 37 + units.hashCode();
451: }
452: long tmp = Double.doubleToLongBits(semiMinorAxis);
453: code = code * 37 + (int) (tmp ^ (tmp >>> 32));
454:
455: tmp = Double.doubleToLongBits(eccentricity);
456: code = code * 37 + (int) (tmp ^ (tmp >>> 32));
457:
458: return (int) (code >>> 32) ^ (int) code;
459: }
460: }
|