Source Code Cross Referenced for GeocentricTransform.java in  » GIS » GeoTools-2.4.1 » org » geotools » referencing » operation » transform » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » GeoTools 2.4.1 » org.geotools.referencing.operation.transform 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *   
005:         *   (C) 2003-2006, Geotools Project Managment Committee (PMC)
006:         *   (C) 2001, Institut de Recherche pour le Développement
007:         *
008:         *    This library is free software; you can redistribute it and/or
009:         *    modify it under the terms of the GNU Lesser General Public
010:         *    License as published by the Free Software Foundation; either
011:         *    version 2.1 of the License, or (at your option) any later version.
012:         *
013:         *    This library is distributed in the hope that it will be useful,
014:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
015:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
016:         *    Lesser General Public License for more details.
017:         *
018:         *    This package contains documentation from OpenGIS specifications.
019:         *    OpenGIS consortium's work is fully acknowledged here.
020:         */
021:        package org.geotools.referencing.operation.transform;
022:
023:        // J2SE dependencies and extensions
024:        import java.io.IOException;
025:        import java.io.ObjectInputStream;
026:        import java.io.Serializable;
027:        import java.util.Collections;
028:        import javax.units.Converter;
029:        import javax.units.SI;
030:        import javax.units.Unit;
031:
032:        // OpenGIS dependencies
033:        import org.opengis.parameter.ParameterDescriptor;
034:        import org.opengis.parameter.ParameterDescriptorGroup;
035:        import org.opengis.parameter.ParameterNotFoundException;
036:        import org.opengis.parameter.ParameterValue;
037:        import org.opengis.parameter.ParameterValueGroup;
038:        import org.opengis.referencing.datum.Ellipsoid;
039:        import org.opengis.referencing.operation.Conversion;
040:        import org.opengis.referencing.operation.MathTransform;
041:        import org.opengis.referencing.operation.OperationMethod;
042:
043:        // Geotools dependencies
044:        import org.geotools.metadata.iso.citation.Citations;
045:        import org.geotools.parameter.DefaultParameterDescriptor;
046:        import org.geotools.parameter.FloatParameter;
047:        import org.geotools.referencing.NamedIdentifier;
048:        import org.geotools.referencing.operation.MathTransformProvider;
049:        import org.geotools.resources.i18n.VocabularyKeys;
050:        import org.geotools.resources.i18n.Vocabulary;
051:        import org.geotools.resources.i18n.ErrorKeys;
052:        import org.geotools.resources.i18n.Errors;
053:
054:        /**
055:         * Transforms three dimensional {@linkplain org.geotools.referencing.crs.DefaultGeographicCRS
056:         * geographic} points to {@linkplain org.geotools.referencing.crs.DefaultGeocentricCRS geocentric}
057:         * coordinate points. Input points must be longitudes, latitudes and heights above the ellipsoid.
058:         *
059:         * @since 2.0
060:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/GeocentricTransform.java $
061:         * @version $Id: GeocentricTransform.java 24384 2007-02-14 00:23:05Z desruisseaux $
062:         * @author Frank Warmerdam
063:         * @author Martin Desruisseaux
064:         */
065:        public class GeocentricTransform extends AbstractMathTransform
066:                implements  Serializable {
067:            /**
068:             * Serial number for interoperability with different versions.
069:             */
070:            private static final long serialVersionUID = -3352045463953828140L;
071:
072:            /**
073:             * Maximal error tolerance in metres during assertions, in metres. If assertions
074:             * are enabled (JDK 1.4 only), then every coordinates transformed with
075:             * {@link #inverseTransform} will be transformed again with {@link #mathTransform}.
076:             * If the distance between the resulting position and the original position
077:             * is greater than {@code MAX_ERROR}, then a {@link AssertionError} is thrown.
078:             */
079:            private static final double MAX_ERROR = 0.01;
080:
081:            /**
082:             * Cosine of 67.5 decimal degrees.
083:             */
084:            private static final double COS_67P5 = 0.38268343236508977;
085:
086:            /**
087:             * Toms region 1 constant.
088:             */
089:            private static final double AD_C = 1.0026000;
090:
091:            /**
092:             * Semi-major axis of ellipsoid in meters.
093:             */
094:            private final double a;
095:
096:            /**
097:             * Semi-minor axis of ellipsoid in meters.
098:             */
099:            private final double b;
100:
101:            /**
102:             * Square of semi-major axis (<var>a</var>˛).
103:             */
104:            private final double a2;
105:
106:            /**
107:             * Square of semi-minor axis (<var>b</var>˛).
108:             */
109:            private final double b2;
110:
111:            /**
112:             * Eccentricity squared.
113:             */
114:            private final double e2;
115:
116:            /**
117:             * 2nd eccentricity squared.
118:             */
119:            private final double ep2;
120:
121:            /**
122:             * {@code true} if geographic coordinates include an ellipsoidal
123:             * height (i.e. are 3-D), or {@code false} if they are strictly 2-D.
124:             */
125:            private final boolean hasHeight;
126:
127:            /**
128:             * The inverse of this transform. Will be created only when needed.
129:             */
130:            private transient MathTransform inverse;
131:
132:            /**
133:             * Constructs a transform from the specified ellipsoid.
134:             *
135:             * @param ellipsoid The ellipsoid.
136:             * @param hasHeight {@code true} if geographic coordinates
137:             *                  include an ellipsoidal height (i.e. are 3-D),
138:             *                  or {@code false} if they are only 2-D.
139:             */
140:            public GeocentricTransform(final Ellipsoid ellipsoid,
141:                    final boolean hasHeight) {
142:                this (ellipsoid.getSemiMajorAxis(),
143:                        ellipsoid.getSemiMinorAxis(), ellipsoid.getAxisUnit(),
144:                        hasHeight);
145:            }
146:
147:            /**
148:             * Constructs a transform from the specified parameters.
149:             *
150:             * @param semiMajor The semi-major axis length.
151:             * @param semiMinor The semi-minor axis length.
152:             * @param units     The axis units.
153:             * @param hasHeight {@code true} if geographic coordinates
154:             *                  include an ellipsoidal height (i.e. are 3-D),
155:             *                  or {@code false} if they are only 2-D.
156:             */
157:            public GeocentricTransform(final double semiMajor,
158:                    final double semiMinor, final Unit units,
159:                    final boolean hasHeight) {
160:                this .hasHeight = hasHeight;
161:                final Converter converter = units.getConverterTo(SI.METER);
162:                a = converter.convert(semiMajor);
163:                b = converter.convert(semiMinor);
164:                a2 = a * a;
165:                b2 = b * b;
166:                e2 = (a2 - b2) / a2;
167:                ep2 = (a2 - b2) / b2;
168:                checkArgument("a", a, Double.MAX_VALUE);
169:                checkArgument("b", b, a);
170:            }
171:
172:            /**
173:             * Checks an argument value. The argument must be greater
174:             * than 0 and finite, otherwise an exception is thrown.
175:             *
176:             * @param name  The argument name.
177:             * @param value The argument value.
178:             * @param max   The maximal legal argument value.
179:             */
180:            private static void checkArgument(final String name,
181:                    final double value, final double max)
182:                    throws IllegalArgumentException {
183:                if (!(value >= 0 && value <= max)) {
184:                    // Use '!' in order to trap NaN
185:                    throw new IllegalArgumentException(Errors.format(
186:                            ErrorKeys.ILLEGAL_ARGUMENT_$2, name, new Double(
187:                                    value)));
188:                }
189:            }
190:
191:            /**
192:             * Returns the parameter descriptors for this math transform.
193:             */
194:            public ParameterDescriptorGroup getParameterDescriptors() {
195:                return Provider.PARAMETERS;
196:            }
197:
198:            /**
199:             * Returns the parameter values for this math transform.
200:             *
201:             * @return A copy of the parameter values for this math transform.
202:             */
203:            public ParameterValueGroup getParameterValues() {
204:                return getParameterValues(getParameterDescriptors());
205:            }
206:
207:            /**
208:             * Returns the parameter values using the specified descriptor.
209:             *
210:             * @param  descriptor The parameter descriptor.
211:             * @return A copy of the parameter values for this math transform.
212:             */
213:            private ParameterValueGroup getParameterValues(
214:                    final ParameterDescriptorGroup descriptor) {
215:                final ParameterValue[] parameters = new ParameterValue[hasHeight ? 2
216:                        : 3];
217:                int index = 0;
218:                if (!hasHeight) {
219:                    final ParameterValue p = new org.geotools.parameter.Parameter(
220:                            Provider.DIM);
221:                    p.setValue(2);
222:                    parameters[index++] = p;
223:                }
224:                parameters[index++] = new FloatParameter(Provider.SEMI_MAJOR, a);
225:                parameters[index++] = new FloatParameter(Provider.SEMI_MINOR, b);
226:                return new org.geotools.parameter.ParameterGroup(descriptor,
227:                        parameters);
228:            }
229:
230:            /**
231:             * Gets the dimension of input points, which is 2 or 3.
232:             */
233:            public int getSourceDimensions() {
234:                return hasHeight ? 3 : 2;
235:            }
236:
237:            /**
238:             * Gets the dimension of output points, which is 3.
239:             */
240:            public final int getTargetDimensions() {
241:                return 3;
242:            }
243:
244:            /**
245:             * Converts geodetic coordinates (longitude, latitude, height) to geocentric
246:             * coordinates (x, y, z) according to the current ellipsoid parameters.
247:             */
248:            public void transform(double[] srcPts, int srcOff, double[] dstPts,
249:                    int dstOff, int numPts) {
250:                transform(srcPts, srcOff, dstPts, dstOff, numPts, false);
251:            }
252:
253:            /**
254:             * Implementation of geodetic to geocentric conversion. This implementation allows the caller
255:             * to use height in computation. This is used for assertion with {@link #checkTransform}.
256:             */
257:            private void transform(double[] srcPts, int srcOff,
258:                    final double[] dstPts, int dstOff, int numPts,
259:                    boolean hasHeight) {
260:                final int dimSource = getSourceDimensions();
261:                hasHeight |= (dimSource >= 3);
262:                if (srcPts == dstPts
263:                        && needCopy(srcOff, dimSource, dstOff, 3, numPts)) {
264:                    // Source and destination arrays overlaps: copy in a temporary buffer.
265:                    final double[] old = srcPts;
266:                    srcPts = new double[numPts * (hasHeight ? 3 : 2)];
267:                    System.arraycopy(old, srcOff, srcPts, 0, srcPts.length);
268:                    srcOff = 0;
269:                }
270:                while (--numPts >= 0) {
271:                    final double L = Math.toRadians(srcPts[srcOff++]); // Longitude
272:                    final double P = Math.toRadians(srcPts[srcOff++]); // Latitude
273:                    final double h = hasHeight ? srcPts[srcOff++] : 0; // Height above the ellipsoid (m)
274:
275:                    final double cosLat = Math.cos(P);
276:                    final double sinLat = Math.sin(P);
277:                    final double rn = a / Math.sqrt(1 - e2 * (sinLat * sinLat));
278:
279:                    dstPts[dstOff++] = (rn + h) * cosLat * Math.cos(L); // X: Toward prime meridian
280:                    dstPts[dstOff++] = (rn + h) * cosLat * Math.sin(L); // Y: Toward East
281:                    dstPts[dstOff++] = (rn * (1 - e2) + h) * sinLat; // Z: Toward North
282:                }
283:            }
284:
285:            /**
286:             * Converts geodetic coordinates (longitude, latitude, height) to geocentric
287:             * coordinates (x, y, z) according to the current ellipsoid parameters.
288:             */
289:            public void transform(float[] srcPts, int srcOff,
290:                    final float[] dstPts, int dstOff, int numPts) {
291:                final int dimSource = getSourceDimensions();
292:                final boolean hasHeight = (dimSource >= 3);
293:                if (srcPts == dstPts
294:                        && needCopy(srcOff, dimSource, dstOff, 3, numPts)) {
295:                    // Source and destination arrays overlaps: copy in a temporary buffer.
296:                    final float[] old = srcPts;
297:                    srcPts = new float[numPts * dimSource];
298:                    System.arraycopy(old, srcOff, srcPts, 0, srcPts.length);
299:                    srcOff = 0;
300:                }
301:                while (--numPts >= 0) {
302:                    final double L = Math.toRadians(srcPts[srcOff++]); // Longitude
303:                    final double P = Math.toRadians(srcPts[srcOff++]); // Latitude
304:                    final double h = hasHeight ? srcPts[srcOff++] : 0; // Height above the ellipsoid (m)
305:
306:                    final double cosLat = Math.cos(P);
307:                    final double sinLat = Math.sin(P);
308:                    final double rn = a / Math.sqrt(1 - e2 * (sinLat * sinLat));
309:
310:                    dstPts[dstOff++] = (float) ((rn + h) * cosLat * Math.cos(L)); // X: Toward prime meridian
311:                    dstPts[dstOff++] = (float) ((rn + h) * cosLat * Math.sin(L)); // Y: Toward East
312:                    dstPts[dstOff++] = (float) ((rn * (1 - e2) + h) * sinLat); // Z: Toward North
313:                }
314:            }
315:
316:            /**
317:             * Converts geocentric coordinates (x, y, z) to geodetic coordinates
318:             * (longitude, latitude, height), according to the current ellipsoid
319:             * parameters. The method used here is derived from "An Improved
320:             * Algorithm for Geocentric to Geodetic Coordinate Conversion", by
321:             * Ralph Toms, Feb 1996.
322:             */
323:            public void inverseTransform(double[] srcPts, int srcOff,
324:                    final double[] dstPts, int dstOff, final int numPts) {
325:                final int dimTarget = getSourceDimensions();
326:                if (srcPts == dstPts
327:                        && needCopy(srcOff, 3, dstOff, dimTarget, numPts)) {
328:                    // Source and destination arrays overlaps: copy in a temporary buffer.
329:                    final double[] old = srcPts;
330:                    srcPts = new double[numPts * 3];
331:                    System.arraycopy(old, srcOff, srcPts, 0, srcPts.length);
332:                    srcOff = 0;
333:                }
334:                inverseTransform(null, srcPts, srcOff, null, dstPts, dstOff,
335:                        numPts, dimTarget);
336:            }
337:
338:            /**
339:             * Converts geocentric coordinates (x, y, z) to geodetic coordinates
340:             * (longitude, latitude, height), according to the current ellipsoid
341:             * parameters. The method used here is derived from "An Improved
342:             * Algorithm for Geocentric to Geodetic Coordinate Conversion", by
343:             * Ralph Toms, Feb 1996.
344:             */
345:            public void inverseTransform(float[] srcPts, int srcOff,
346:                    final float[] dstPts, int dstOff, final int numPts) {
347:                final int dimTarget = getSourceDimensions();
348:                if (srcPts == dstPts
349:                        && needCopy(srcOff, 3, dstOff, dimTarget, numPts)) {
350:                    // Source and destination arrays overlaps: copy in a temporary buffer.
351:                    final float[] old = srcPts;
352:                    srcPts = new float[numPts * 3];
353:                    System.arraycopy(old, srcOff, srcPts, 0, srcPts.length);
354:                    srcOff = 0;
355:                }
356:                inverseTransform(srcPts, null, srcOff, dstPts, null, dstOff,
357:                        numPts, dimTarget);
358:            }
359:
360:            /**
361:             * Implementation of the inverse transformation.
362:             */
363:            private void inverseTransform(final float[] srcPts1,
364:                    final double[] srcPts2, int srcOff, final float[] dstPts1,
365:                    final double[] dstPts2, int dstOff, int numPts,
366:                    final int dimTarget) {
367:                final boolean hasHeight = (dimTarget >= 3);
368:                boolean computeHeight = hasHeight;
369:                assert (computeHeight = true) == true; // Force computeHeight to true if assertions are enabled.
370:                while (--numPts >= 0) {
371:                    final double x, y, z;
372:                    if (srcPts2 != null) {
373:                        x = srcPts2[srcOff++]; // Toward prime meridian
374:                        y = srcPts2[srcOff++]; // Toward East
375:                        z = srcPts2[srcOff++]; // Toward North
376:                    } else {
377:                        x = srcPts1[srcOff++]; // Toward prime meridian
378:                        y = srcPts1[srcOff++]; // Toward East
379:                        z = srcPts1[srcOff++]; // Toward North
380:                    }
381:                    // Note: The Java version of 'atan2' work correctly for x==0.
382:                    //       No need for special handling like in the C version.
383:                    //       No special handling neither for latitude. Formulas
384:                    //       below are generic enough, considering that 'atan'
385:                    //       work correctly with infinities (1/0).
386:
387:                    // Note: Variable names follow the notation used in Toms, Feb 1996
388:                    final double W2 = x * x + y * y; // square of distance from Z axis
389:                    final double W = Math.sqrt(W2); // distance from Z axis
390:                    final double T0 = z * AD_C; // initial estimate of vertical component
391:                    final double S0 = Math.sqrt(T0 * T0 + W2); // initial estimate of horizontal component
392:                    final double sin_B0 = T0 / S0; // sin(B0), B0 is estimate of Bowring aux variable
393:                    final double cos_B0 = W / S0; // cos(B0)
394:                    final double sin3_B0 = sin_B0 * sin_B0 * sin_B0; // cube of sin(B0)
395:                    final double T1 = z + b * ep2 * sin3_B0; // corrected estimate of vertical component
396:                    final double sum = W - a * e2 * (cos_B0 * cos_B0 * cos_B0); // numerator of cos(phi1)
397:                    final double S1 = Math.sqrt(T1 * T1 + sum * sum); // corrected estimate of horizontal component
398:                    final double sin_p1 = T1 / S1; // sin(phi1), phi1 is estimated latitude
399:                    final double cos_p1 = sum / S1; // cos(phi1)
400:
401:                    final double longitude = Math.toDegrees(Math.atan2(y, x));
402:                    final double latitude = Math.toDegrees(Math.atan(sin_p1
403:                            / cos_p1));
404:                    final double height;
405:
406:                    if (dstPts2 != null) {
407:                        dstPts2[dstOff++] = longitude;
408:                        dstPts2[dstOff++] = latitude;
409:                    } else {
410:                        dstPts1[dstOff++] = (float) longitude;
411:                        dstPts1[dstOff++] = (float) latitude;
412:                    }
413:                    if (computeHeight) {
414:                        final double rn = a
415:                                / Math.sqrt(1 - e2 * (sin_p1 * sin_p1)); // Earth radius at location
416:                        if (cos_p1 >= +COS_67P5)
417:                            height = W / +cos_p1 - rn;
418:                        else if (cos_p1 <= -COS_67P5)
419:                            height = W / -cos_p1 - rn;
420:                        else
421:                            height = z / sin_p1 + rn * (e2 - 1.0);
422:                        if (hasHeight) {
423:                            if (dstPts2 != null) {
424:                                dstPts2[dstOff++] = height;
425:                            } else {
426:                                dstPts1[dstOff++] = (float) height;
427:                            }
428:                        }
429:                        // If assertion are enabled, then transform the
430:                        // result and compare it with the input array.
431:                        double distance;
432:                        assert MAX_ERROR > (distance = checkTransform(new double[] {
433:                                x, y, z, longitude, latitude, height })) : distance;
434:                    }
435:                }
436:            }
437:
438:            /**
439:             * Transform the last half if the specified array and returns
440:             * the distance with the first half. Array {@code points}
441:             * must have a length of 6.
442:             */
443:            private double checkTransform(final double[] points) {
444:                transform(points, 3, points, 3, 1, true);
445:                final double dx = points[0] - points[3];
446:                final double dy = points[1] - points[4];
447:                final double dz = points[2] - points[5];
448:                return Math.sqrt(dx * dx + dy * dy + dz * dz);
449:            }
450:
451:            /**
452:             * Returns the inverse of this transform.
453:             */
454:            public MathTransform inverse() {
455:                if (inverse == null) {
456:                    // No need to synchronize; this is not a big deal if this object is created twice.
457:                    inverse = new Inverse();
458:                }
459:                return inverse;
460:            }
461:
462:            /**
463:             * Returns a hash value for this transform.
464:             */
465:            public int hashCode() {
466:                final long code = Double.doubleToLongBits(a)
467:                        + 37
468:                        * (Double.doubleToLongBits(b) + 37 * (Double
469:                                .doubleToLongBits(a2) + 37 * (Double
470:                                .doubleToLongBits(b2) + 37 * (Double
471:                                .doubleToLongBits(e2) + 37 * (Double
472:                                .doubleToLongBits(ep2))))));
473:                return (int) code ^ (int) (code >>> 32)
474:                        ^ (int) serialVersionUID;
475:            }
476:
477:            /**
478:             * Compares the specified object with this math transform for equality.
479:             */
480:            public boolean equals(final Object object) {
481:                if (object == this ) {
482:                    // Slight optimization
483:                    return true;
484:                }
485:                if (super .equals(object)) {
486:                    final GeocentricTransform that = (GeocentricTransform) object;
487:                    return Double.doubleToLongBits(this .a) == Double
488:                            .doubleToLongBits(that.a)
489:                            && Double.doubleToLongBits(this .b) == Double
490:                                    .doubleToLongBits(that.b)
491:                            && Double.doubleToLongBits(this .a2) == Double
492:                                    .doubleToLongBits(that.a2)
493:                            && Double.doubleToLongBits(this .b2) == Double
494:                                    .doubleToLongBits(that.b2)
495:                            && Double.doubleToLongBits(this .e2) == Double
496:                                    .doubleToLongBits(that.e2)
497:                            && Double.doubleToLongBits(this .ep2) == Double
498:                                    .doubleToLongBits(that.ep2)
499:                            && this .hasHeight == that.hasHeight;
500:                }
501:                return false;
502:            }
503:
504:            /**
505:             * Inverse of a geocentric transform.
506:             *
507:             * @version $Id: GeocentricTransform.java 24384 2007-02-14 00:23:05Z desruisseaux $
508:             * @author Martin Desruisseaux
509:             */
510:            private final class Inverse extends AbstractMathTransform.Inverse
511:                    implements  Serializable {
512:                /**
513:                 * Serial number for interoperability with different versions.
514:                 */
515:                private static final long serialVersionUID = 6942084702259211803L;
516:
517:                /**
518:                 * Default constructor.
519:                 */
520:                public Inverse() {
521:                    GeocentricTransform.this .super ();
522:                }
523:
524:                /**
525:                 * Returns the parameter descriptors for this math transform.
526:                 */
527:                public ParameterDescriptorGroup getParameterDescriptors() {
528:                    return ProviderInverse.PARAMETERS;
529:                }
530:
531:                /**
532:                 * Returns the parameter values for this math transform.
533:                 *
534:                 * @return A copy of the parameter values for this math transform.
535:                 */
536:                public ParameterValueGroup getParameterValues() {
537:                    return GeocentricTransform.this 
538:                            .getParameterValues(getParameterDescriptors());
539:                }
540:
541:                /**
542:                 * Inverse transform an array of points.
543:                 */
544:                public void transform(final double[] source,
545:                        final int srcOffset, final double[] dest,
546:                        final int dstOffset, final int length) {
547:                    GeocentricTransform.this .inverseTransform(source,
548:                            srcOffset, dest, dstOffset, length);
549:                }
550:
551:                /**
552:                 * Inverse transform an array of points.
553:                 */
554:                public void transform(final float[] source,
555:                        final int srcOffset, final float[] dest,
556:                        final int dstOffset, final int length) {
557:                    GeocentricTransform.this .inverseTransform(source,
558:                            srcOffset, dest, dstOffset, length);
559:                }
560:
561:                /**
562:                 * Restore reference to this object after deserialization.
563:                 */
564:                private void readObject(ObjectInputStream in)
565:                        throws IOException, ClassNotFoundException {
566:                    in.defaultReadObject();
567:                    GeocentricTransform.this .inverse = this ;
568:                }
569:            }
570:
571:            /**
572:             * The provider for {@link GeocentricTransform}. This provider will constructs transforms
573:             * from {@linkplain org.geotools.referencing.crs.DefaultGeographicCRS geographic} to
574:             * {@linkplain org.geotools.referencing.crs.DefaultGeocentricCRS geocentric} coordinate
575:             * reference systems.
576:             *
577:             * @version $Id: GeocentricTransform.java 24384 2007-02-14 00:23:05Z desruisseaux $
578:             * @author Martin Desruisseaux
579:             */
580:            public static class Provider extends MathTransformProvider {
581:                /**
582:                 * Serial number for interoperability with different versions.
583:                 */
584:                private static final long serialVersionUID = 7043216580786030251L;
585:
586:                /**
587:                 * The operation parameter descriptor for the "semi_major" parameter value.
588:                 * Valid values range from 0 to infinity.
589:                 */
590:                public static final ParameterDescriptor SEMI_MAJOR = createDescriptor(
591:                        new NamedIdentifier[] {
592:                                new NamedIdentifier(Citations.OGC, "semi_major"),
593:                                new NamedIdentifier(Citations.EPSG,
594:                                        "semi-major axis") //epsg does not specifically define this parameter
595:                        }, Double.NaN, 0, Double.POSITIVE_INFINITY, SI.METER);
596:
597:                /**
598:                 * The operation parameter descriptor for the "semi_minor" parameter value.
599:                 * Valid values range from 0 to infinity.
600:                 */
601:                public static final ParameterDescriptor SEMI_MINOR = createDescriptor(
602:                        new NamedIdentifier[] {
603:                                new NamedIdentifier(Citations.OGC, "semi_minor"),
604:                                new NamedIdentifier(Citations.EPSG,
605:                                        "semi-minor axis") //epsg does not specifically define this parameter
606:                        }, Double.NaN, 0, Double.POSITIVE_INFINITY, SI.METER);
607:
608:                /**
609:                 * The number of geographic dimension (2 or 3). This is a Geotools-specific argument.
610:                 * The default value is 3, which is the value implied in OGC's WKT.
611:                 */
612:                static final ParameterDescriptor DIM = new DefaultParameterDescriptor(
613:                        Collections.singletonMap(NAME_KEY, new NamedIdentifier(
614:                                Citations.GEOTOOLS, "dim")), 3, 2, 3, false);
615:
616:                /**
617:                 * The parameters group.
618:                 */
619:                static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(
620:                        "Ellipsoid_To_Geocentric", // OGC name
621:                        "Geographic/geocentric conversions", // EPSG name
622:                        "9602", // EPSG identifier
623:                        VocabularyKeys.GEOCENTRIC_TRANSFORM); // Geotools name
624:
625:                /**
626:                 * Constructs the parameters group.
627:                 */
628:                static ParameterDescriptorGroup createDescriptorGroup(
629:                        final String ogc, final String epsgName,
630:                        final String epsgCode, final int geotools) {
631:                    return createDescriptorGroup(new NamedIdentifier[] {
632:                            new NamedIdentifier(Citations.OGC, ogc),
633:                            new NamedIdentifier(Citations.EPSG, epsgName),
634:                            new NamedIdentifier(Citations.EPSG, epsgCode),
635:                            new NamedIdentifier(Citations.GEOTOOLS, Vocabulary
636:                                    .formatInternational(geotools)) },
637:                            new ParameterDescriptor[] { SEMI_MAJOR, SEMI_MINOR,
638:                                    DIM });
639:                }
640:
641:                /**
642:                 * The provider for the 2D case. Will be constructed when first needed.
643:                 */
644:                transient Provider noHeight;
645:
646:                /**
647:                 * Constructs a provider with default parameters.
648:                 */
649:                public Provider() {
650:                    super (3, 3, PARAMETERS);
651:                }
652:
653:                /**
654:                 * Constructs a provider from a set of parameters.
655:                 *
656:                 * @param sourceDimensions Number of dimensions in the source CRS of this operation method.
657:                 * @param targetDimensions Number of dimensions in the target CRS of this operation method.
658:                 * @param parameters The set of parameters (never {@code null}).
659:                 */
660:                Provider(final int sourceDimensions,
661:                        final int targetDimensions,
662:                        final ParameterDescriptorGroup parameters) {
663:                    super (sourceDimensions, targetDimensions, parameters);
664:                }
665:
666:                /**
667:                 * Returns the operation type.
668:                 */
669:                public Class getOperationType() {
670:                    return Conversion.class;
671:                }
672:
673:                /**
674:                 * Creates a transform from the specified group of parameter values.
675:                 *
676:                 * @param  values The group of parameter values.
677:                 * @return The created math transform.
678:                 * @throws ParameterNotFoundException if a required parameter was not found.
679:                 */
680:                protected MathTransform createMathTransform(
681:                        final ParameterValueGroup values)
682:                        throws ParameterNotFoundException {
683:                    final int dimGeographic = intValue(DIM, values);
684:                    final double semiMajor = doubleValue(SEMI_MAJOR, values);
685:                    final double semiMinor = doubleValue(SEMI_MINOR, values);
686:                    final boolean hasHeight = (dimGeographic != 2); // Value may be 0, which default as 3.
687:                    MathTransform transform = new GeocentricTransform(
688:                            semiMajor, semiMinor, SI.METER, hasHeight);
689:                    if (!hasHeight) {
690:                        if (noHeight == null) {
691:                            noHeight = new Provider(2, 3, PARAMETERS);
692:                        }
693:                        transform = new Delegate(transform, noHeight);
694:                    }
695:                    return transform;
696:                }
697:            }
698:
699:            /**
700:             * The provider for inverse of {@link GeocentricTransform}. This provider will construct
701:             * transforms from {@linkplain org.geotools.referencing.crs.DefaultGeocentricCRS geocentric}
702:             * to {@linkplain org.geotools.referencing.crs.DefaultGeographicCRS geographic} coordinate
703:             * reference systems.
704:             *
705:             * @version $Id: GeocentricTransform.java 24384 2007-02-14 00:23:05Z desruisseaux $
706:             * @author Martin Desruisseaux
707:             */
708:            public static class ProviderInverse extends Provider {
709:                /**
710:                 * Serial number for interoperability with different versions.
711:                 */
712:                private static final long serialVersionUID = -7356791540110076789L;
713:
714:                /**
715:                 * The parameters group.
716:                 *
717:                 * @todo The EPSG code seems to be the same than for the direct transform.
718:                 */
719:                static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(
720:                        "Geocentric_To_Ellipsoid", // OGC name
721:                        "Geographic/geocentric conversions", // EPSG name
722:                        "9602", // EPSG identifier
723:                        VocabularyKeys.GEOCENTRIC_TRANSFORM); // Geotools name
724:
725:                /**
726:                 * Creates a provider.
727:                 */
728:                public ProviderInverse() {
729:                    super (3, 3, PARAMETERS);
730:                }
731:
732:                /**
733:                 * Constructs a provider from a set of parameters.
734:                 *
735:                 * @param sourceDimensions Number of dimensions in the source CRS of this operation method.
736:                 * @param targetDimensions Number of dimensions in the target CRS of this operation method.
737:                 * @param parameters The set of parameters (never {@code null}).
738:                 */
739:                ProviderInverse(final int sourceDimensions,
740:                        final int targetDimensions,
741:                        final ParameterDescriptorGroup parameters) {
742:                    super (sourceDimensions, targetDimensions, parameters);
743:                }
744:
745:                /**
746:                 * Creates a transform from the specified group of parameter values.
747:                 *
748:                 * @param  values The group of parameter values.
749:                 * @return The created math transform.
750:                 * @throws ParameterNotFoundException if a required parameter was not found.
751:                 */
752:                public MathTransform createMathTransform(
753:                        final ParameterValueGroup values)
754:                        throws ParameterNotFoundException {
755:                    final int dimGeographic = intValue(DIM, values);
756:                    final double semiMajor = doubleValue(SEMI_MAJOR, values);
757:                    final double semiMinor = doubleValue(SEMI_MINOR, values);
758:                    final boolean hasHeight = (dimGeographic != 2); // Value may be 0, which default as 3.
759:                    MathTransform transform = new GeocentricTransform(
760:                            semiMajor, semiMinor, SI.METER, hasHeight)
761:                            .inverse();
762:                    if (!hasHeight) {
763:                        if (noHeight == null) {
764:                            noHeight = new ProviderInverse(3, 2, PARAMETERS);
765:                        }
766:                        transform = new Delegate(transform, noHeight);
767:                    }
768:                    return transform;
769:                }
770:            }
771:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.