Source Code Cross Referenced for PolarStereographic.java in  » GIS » GeoTools-2.4.1 » org » geotools » referencing » operation » projection » 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.projection 
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:         *   (C) 2000, Frank Warmerdam
008:         *   (C) 1999, Fisheries and Oceans Canada
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:         *
015:         *    This library is distributed in the hope that it will be useful,
016:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
017:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
018:         *    Lesser General Public License for more details.
019:         *
020:         *    This package contains formulas from the PROJ package of USGS.
021:         *    USGS's work is fully acknowledged here. This derived work has
022:         *    been relicensed under LGPL with Frank Warmerdam's permission.
023:         */
024:        package org.geotools.referencing.operation.projection;
025:
026:        // J2SE dependencies and extensions
027:        import java.awt.geom.Point2D;
028:        import java.util.Collection;
029:        import javax.units.NonSI;
030:
031:        // OpenGIS dependencies
032:        import org.opengis.parameter.ParameterValueGroup;
033:        import org.opengis.parameter.ParameterDescriptor;
034:        import org.opengis.parameter.ParameterDescriptorGroup;
035:        import org.opengis.parameter.ParameterNotFoundException;
036:        import org.opengis.parameter.ParameterValueGroup;
037:        import org.opengis.referencing.operation.MathTransform;
038:
039:        // Geotools dependencies
040:        import org.geotools.resources.i18n.Errors;
041:        import org.geotools.resources.i18n.ErrorKeys;
042:        import org.geotools.referencing.NamedIdentifier;
043:        import org.geotools.metadata.iso.citation.Citations;
044:
045:        /**
046:         * The polar case of the {@linkplain Stereographic stereographic} projection.
047:         * This default implementation uses USGS equation (i.e. iteration) for computing
048:         * the {@linkplain #inverseTransformNormalized inverse transform}.
049:         *
050:         * @since 2.4
051:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/projection/PolarStereographic.java $
052:         * @version $Id: PolarStereographic.java 25778 2007-06-08 08:46:34Z desruisseaux $
053:         * @author André Gosselin
054:         * @author Martin Desruisseaux
055:         * @author Rueben Schulz
056:         */
057:        public class PolarStereographic extends Stereographic {
058:            /**
059:             * Maximum number of iterations for iterative computations.
060:             */
061:            private static final int MAXIMUM_ITERATIONS = 15;
062:
063:            /**
064:             * Difference allowed in iterative computations.
065:             */
066:            private static final double ITERATION_TOLERANCE = 1E-10;
067:
068:            /**
069:             * Maximum difference allowed when comparing real numbers.
070:             */
071:            private static final double EPSILON = 1E-8;
072:
073:            /**
074:             * A constant used in the transformations.
075:             * This is <strong>not</strong> equal to the {@link #scaleFactor}.
076:             */
077:            private final double k0;
078:
079:            /**
080:             * Latitude of true scale, in radians (a.k.a. {@code "standard_parallel_1").
081:             */
082:            final double standardParallel;
083:
084:            /**
085:             * {@code true} if this projection is for the south pole, or {@code false}
086:             * if it is for the north pole.
087:             */
088:            final boolean southPole;
089:
090:            /**
091:             * {@code true} if {@link #southPole} was forced, or {@code false} if it was auto-detected.
092:             */
093:            private final boolean poleForced;
094:
095:            /**
096:             * Constructs a polar stereographic projection.
097:             *
098:             * @param  parameters The group of parameter values.
099:             * @param  descriptor The expected parameter descriptor.
100:             * @param  forceSouthPole Forces projection to North pole if {@link Boolean#FALSE},
101:             *         to South pole if {@link Boolean#TRUE}, or do not force (i.e. detect
102:             *         from other parameter values) if {@code null}.
103:             * @throws ParameterNotFoundException if a required parameter was not found.
104:             */
105:            PolarStereographic(final ParameterValueGroup parameters,
106:                    final ParameterDescriptorGroup descriptor,
107:                    final Boolean forceSouthPole)
108:                    throws ParameterNotFoundException {
109:                super (parameters, descriptor);
110:                /*
111:                 * Get "standard_parallel_1" parameter value. This parameter should be mutually exclusive
112:                 * with "latitude_of_origin", but this is not a strict requirement for this constructor.
113:                 *
114:                 *   +-----------------------------------+--------------------+-------------+
115:                 *   | Projection                        | Parameter          | Force pole  |
116:                 *   | --------------------------------- | ------------------ | ----------- |
117:                 *   | Polar Stereographic (variant A)   | Latitude of origin | auto detect |
118:                 *   | Polar Stereographic (variant B)   | Standard Parallel  | auto detect |
119:                 *   | Stereographic North Pole          | Standard Parallel  | North pole  |
120:                 *   | Stereographic South Pole          | Standard Parallel  | South pole  |
121:                 *   +-----------------------------------+--------------------+-------------+
122:                 *
123:                 * "Standard Parallel" (a.k.a. "Latitude true scale") default to 90°N for every cases
124:                 * (including Polar A, but it is meanless in this case), except for "Stereographic South
125:                 * Pole" where it default to 90°S.
126:                 */
127:                final ParameterDescriptor trueScaleDescriptor = Boolean.TRUE
128:                        .equals(forceSouthPole) ? ProviderSouth.STANDARD_PARALLEL
129:                        : ProviderNorth.STANDARD_PARALLEL;
130:                final Collection expected = descriptor.descriptors();
131:                double latitudeTrueScale;
132:                if (isExpectedParameter(expected, trueScaleDescriptor)) {
133:                    // Any cases except Polar A
134:                    latitudeTrueScale = doubleValue(expected,
135:                            trueScaleDescriptor, parameters);
136:                } else {
137:                    // Polar A case
138:                    latitudeTrueScale = (latitudeOfOrigin < 0) ? -Math.PI / 2
139:                            : Math.PI / 2;
140:                }
141:                ensureLatitudeInRange(trueScaleDescriptor, latitudeTrueScale,
142:                        true);
143:                /*
144:                 * Forces the "standard_parallel_1" to the appropriate hemisphere,
145:                 * and forces the "latitude_of_origin" to ±90°.
146:                 */
147:                poleForced = (forceSouthPole != null);
148:                if (poleForced) {
149:                    southPole = forceSouthPole.booleanValue();
150:                    latitudeTrueScale = Math.abs(latitudeTrueScale);
151:                    if (southPole) {
152:                        latitudeTrueScale = -latitudeTrueScale;
153:                    }
154:                } else {
155:                    southPole = (latitudeTrueScale < 0);
156:                }
157:                this .latitudeOfOrigin = (southPole) ? -(Math.PI / 2)
158:                        : +(Math.PI / 2);
159:                this .standardParallel = latitudeTrueScale; // May be anything in [-90 .. +90] range.
160:                /*
161:                 * Computes coefficients.
162:                 */
163:                latitudeTrueScale = Math.abs(latitudeTrueScale);
164:                if (Math.abs(latitudeTrueScale - Math.PI / 2) >= EPSILON) {
165:                    final double t = Math.sin(latitudeTrueScale);
166:                    k0 = msfn(t, Math.cos(latitudeTrueScale))
167:                            / tsfn(latitudeTrueScale, t); // Derives from (21-32 and 21-33)
168:                } else {
169:                    // True scale at pole (part of (21-33))
170:                    k0 = 2.0 / Math.sqrt(Math.pow(1 + excentricity,
171:                            1 + excentricity)
172:                            * Math.pow(1 - excentricity, 1 - excentricity));
173:                }
174:            }
175:
176:            /**
177:             * Transforms the specified (<var>&lambda;</var>,<var>&phi;</var>) coordinates
178:             * (units in radians) and stores the result in {@code ptDst} (linear distance
179:             * on a unit sphere).
180:             */
181:            protected Point2D transformNormalized(double x, double y,
182:                    Point2D ptDst) throws ProjectionException {
183:                final double sinlat = Math.sin(y);
184:                final double coslon = Math.cos(x);
185:                final double sinlon = Math.sin(x);
186:                if (southPole) {
187:                    final double rho = k0 * tsfn(-y, -sinlat);
188:                    x = rho * sinlon;
189:                    y = rho * coslon;
190:                } else {
191:                    final double rho = k0 * tsfn(y, sinlat);
192:                    x = rho * sinlon;
193:                    y = -rho * coslon;
194:                }
195:
196:                if (ptDst != null) {
197:                    ptDst.setLocation(x, y);
198:                    return ptDst;
199:                }
200:                return new Point2D.Double(x, y);
201:            }
202:
203:            /**
204:             * Transforms the specified (<var>x</var>,<var>y</var>) coordinates (units in radians)
205:             * and stores the result in {@code ptDst} (linear distance on a unit sphere).
206:             */
207:            protected Point2D inverseTransformNormalized(double x, double y,
208:                    Point2D ptDst) throws ProjectionException {
209:                final double rho = Math.sqrt(x * x + y * y);
210:                if (southPole) {
211:                    y = -y;
212:                }
213:                /*
214:                 * Compute latitude using iterative technique.
215:                 */
216:                final double t = rho / k0;
217:                final double halfe = excentricity / 2.0;
218:                double phi0 = 0;
219:                for (int i = MAXIMUM_ITERATIONS;;) {
220:                    final double esinphi = excentricity * Math.sin(phi0);
221:                    final double phi = (Math.PI / 2)
222:                            - 2.0
223:                            * Math.atan(t
224:                                    * Math.pow((1 - esinphi) / (1 + esinphi),
225:                                            halfe));
226:                    if (Math.abs(phi - phi0) < ITERATION_TOLERANCE) {
227:                        x = (Math.abs(rho) < EPSILON) ? 0.0 : Math.atan2(x, -y);
228:                        y = (southPole) ? -phi : phi;
229:                        break;
230:                    }
231:                    phi0 = phi;
232:                    if (--i < 0) {
233:                        throw new ProjectionException(Errors
234:                                .format(ErrorKeys.NO_CONVERGENCE));
235:                    }
236:                }
237:
238:                if (ptDst != null) {
239:                    ptDst.setLocation(x, y);
240:                    return ptDst;
241:                }
242:                return new Point2D.Double(x, y);
243:            }
244:
245:            /**
246:             * {@inheritDoc}
247:             */
248:            public ParameterValueGroup getParameterValues() {
249:                final ParameterDescriptor trueScaleDescriptor = poleForced ? (southPole ? ProviderSouth.STANDARD_PARALLEL
250:                        : // forced = true,  south = true
251:                        ProviderNorth.STANDARD_PARALLEL)
252:                        : // forced = true,  south = false
253:                        ProviderB.STANDARD_PARALLEL; // forced = false
254:                final ParameterValueGroup values = super .getParameterValues();
255:                final Collection expected = getParameterDescriptors()
256:                        .descriptors();
257:                set(expected, trueScaleDescriptor, values, standardParallel);
258:                return values;
259:            }
260:
261:            /**
262:             * Returns a hash value for this map projection.
263:             */
264:            public int hashCode() {
265:                final long code = Double.doubleToLongBits(k0);
266:                return ((int) code ^ (int) (code >>> 32)) + 37
267:                        * super .hashCode();
268:            }
269:
270:            /**
271:             * Compares the specified object with this map projection for equality.
272:             */
273:            public boolean equals(final Object object) {
274:                if (object == this ) {
275:                    // Slight optimization
276:                    return true;
277:                }
278:                if (super .equals(object)) {
279:                    final PolarStereographic that = (PolarStereographic) object;
280:                    return this .southPole == that.southPole
281:                            && equals(this .k0, that.k0)
282:                            && equals(this .standardParallel,
283:                                    that.standardParallel);
284:                }
285:                return false;
286:            }
287:
288:            /**
289:             * Provides the transform equations for the spherical case of the polar
290:             * stereographic projection.
291:             *
292:             * @version $Id: PolarStereographic.java 25778 2007-06-08 08:46:34Z desruisseaux $
293:             * @author Martin Desruisseaux
294:             * @author Rueben Schulz
295:             */
296:            static final class Spherical extends PolarStereographic {
297:                /**
298:                 * A constant used in the transformations. This constant hides the {@code k0}
299:                 * constant from the ellipsoidal case. The spherical and ellipsoidal {@code k0}
300:                 * are not computed in the same way, and we preserve the ellipsoidal {@code k0}
301:                 * in {@link Stereographic} in order to allow assertions to work.
302:                 */
303:                private final double k0;
304:
305:                /**
306:                 * Constructs a spherical stereographic projection.
307:                 *
308:                 * @param  parameters The group of parameter values.
309:                 * @param  descriptor The expected parameter descriptor.
310:                 * @param  forceSouthPole For projection to North pole if {@link Boolean#FALSE},
311:                 *         to South pole if {@link Boolean#TRUE}, or do not force (i.e. detect
312:                 *         from other parameter values) if {@code null}.
313:                 * @throws ParameterNotFoundException if a required parameter was not found.
314:                 */
315:                Spherical(final ParameterValueGroup parameters,
316:                        final ParameterDescriptorGroup descriptor,
317:                        final Boolean forceSouthPole)
318:                        throws ParameterNotFoundException {
319:                    super (parameters, descriptor, forceSouthPole);
320:                    ensureSpherical();
321:                    final double phi = Math.abs(standardParallel);
322:                    if (Math.abs(phi - Math.PI / 2) >= EPSILON) {
323:                        k0 = 1 + Math.sin(phi); // derived from (21-7) and (21-11)
324:                    } else {
325:                        k0 = 2;
326:                    }
327:                }
328:
329:                /**
330:                 * Transforms the specified (<var>&lambda;</var>,<var>&phi;</var>) coordinates
331:                 * (units in radians) and stores the result in {@code ptDst} (linear distance
332:                 * on a unit sphere).
333:                 */
334:                protected Point2D transformNormalized(double x, double y,
335:                        Point2D ptDst) throws ProjectionException {
336:                    //Compute using ellipsoidal formulas, for comparaison later.
337:                    assert (ptDst = super .transformNormalized(x, y, ptDst)) != null;
338:
339:                    final double coslat = Math.cos(y);
340:                    final double sinlat = Math.sin(y);
341:                    final double coslon = Math.cos(x);
342:                    final double sinlon = Math.sin(x);
343:
344:                    if (southPole) {
345:                        if (Math.abs(1 - sinlat) < EPSILON) {
346:                            throw new ProjectionException(
347:                                    Errors
348:                                            .format(ErrorKeys.VALUE_TEND_TOWARD_INFINITY));
349:                        }
350:                        // (21-12)
351:                        final double f = k0 * coslat / (1 - sinlat); // == tan (pi/4 + phi/2)
352:                        x = f * sinlon; // (21-9)
353:                        y = f * coslon; // (21-10)
354:                    } else {
355:                        if (Math.abs(1 + sinlat) < EPSILON) {
356:                            throw new ProjectionException(
357:                                    Errors
358:                                            .format(ErrorKeys.VALUE_TEND_TOWARD_INFINITY));
359:                        }
360:                        // (21-8)
361:                        final double f = k0 * coslat / (1 + sinlat); // == tan (pi/4 - phi/2)
362:                        x = f * sinlon; // (21-5)
363:                        y = -f * coslon; // (21-6)
364:                    }
365:
366:                    assert checkTransform(x, y, ptDst);
367:                    if (ptDst != null) {
368:                        ptDst.setLocation(x, y);
369:                        return ptDst;
370:                    }
371:                    return new Point2D.Double(x, y);
372:                }
373:
374:                /**
375:                 * Transforms the specified (<var>x</var>,<var>y</var>) coordinates (units in radians)
376:                 * and stores the result in {@code ptDst} (linear distance on a unit sphere).
377:                 */
378:                protected Point2D inverseTransformNormalized(double x,
379:                        double y, Point2D ptDst) throws ProjectionException {
380:                    // Compute using ellipsoidal formulas, for comparaison later.
381:                    assert (ptDst = super .inverseTransformNormalized(x, y,
382:                            ptDst)) != null;
383:
384:                    final double rho = Math.sqrt(x * x + y * y);
385:
386:                    if (!southPole) {
387:                        y = -y;
388:                    }
389:                    // (20-17) call atan2(x,y) to properly deal with y==0
390:                    x = (Math.abs(x) < EPSILON && Math.abs(y) < EPSILON) ? 0.0
391:                            : Math.atan2(x, y);
392:                    if (Math.abs(rho) < EPSILON) {
393:                        y = latitudeOfOrigin;
394:                    } else {
395:                        final double c = 2.0 * Math.atan(rho / k0);
396:                        final double cosc = Math.cos(c);
397:                        y = (southPole) ? Math.asin(-cosc) : Math.asin(cosc);
398:                        // (20-14) with phi1=90
399:                    }
400:
401:                    assert checkInverseTransform(x, y, ptDst);
402:                    if (ptDst != null) {
403:                        ptDst.setLocation(x, y);
404:                        return ptDst;
405:                    }
406:                    return new Point2D.Double(x, y);
407:                }
408:            }
409:
410:            /**
411:             * Overides {@link PolarStereographic} to use the a series for the
412:             * {@link #inverseTransformNormalized inverseTransformNormalized(...)}
413:             * method. This is the equation specified by the EPSG. Allows for a 
414:             * {@code "latitude_true_scale"} parameter to be used, but this
415:             * parameter is not listed by the EPSG and is not given as a parameter
416:             * by the provider.
417:             * <p>
418:             * Compared to the default {@link PolarStereographic} implementation, the series
419:             * implementation is a little bit faster at the expense of a little bit less
420:             * accuracy. The default {@link PolarStereographic} implementation
421:             * is a derivated work of Proj4, and is therefor better tested.
422:             *
423:             * @version $Id: PolarStereographic.java 25778 2007-06-08 08:46:34Z desruisseaux $
424:             * @author Rueben Schulz
425:             */
426:            static final class Series extends PolarStereographic {
427:                /**
428:                 * Constants used for the inverse polar series
429:                 */
430:                private final double A, B;
431:
432:                /**
433:                 * Constants used for the inverse polar series
434:                 */
435:                private double C, D;
436:
437:                /**
438:                 * A constant used in the transformations. This constant hides the {@code k0}
439:                 * constant from the USGS case. The EPSG and USGS {@code k0} are not computed
440:                 * in the same way, and we preserve the USGS {@code k0} in order to allow
441:                 * assertions to work.
442:                 */
443:                private final double k0;
444:
445:                /**
446:                 * Constructs a polar stereographic projection (seires inverse equations).
447:                 *
448:                 * @param  parameters The group of parameter values.
449:                 * @param  descriptor The expected parameter descriptor.
450:                 * @param  forceSouthPole For projection to North pole if {@link Boolean#FALSE},
451:                 *         to South pole if {@link Boolean#TRUE}, or do not force (i.e. detect
452:                 *         from other parameter values) if {@code null}.
453:                 * @throws ParameterNotFoundException if a required parameter was not found.
454:                 */
455:                Series(final ParameterValueGroup parameters,
456:                        final ParameterDescriptorGroup descriptor,
457:                        final Boolean forceSouthPole)
458:                        throws ParameterNotFoundException {
459:                    super (parameters, descriptor, forceSouthPole);
460:                    // See Snyde P. 19, "Computation of Series"
461:                    final double e4 = excentricitySquared * excentricitySquared;
462:                    final double e6 = e4 * excentricitySquared;
463:                    final double e8 = e4 * e4;
464:                    C = 7.0 / 120.0 * e6 + 81.0 / 1120.0 * e8;
465:                    D = 4279.0 / 161280.0 * e8;
466:                    A = excentricitySquared / 2.0 + 5.0 / 24.0 * e4 + e6 / 12.0
467:                            + 13.0 / 360.0 * e8 - C;
468:                    B = 2.0
469:                            * (7.0 / 48.0 * e4 + 29.0 / 240.0 * e6 + 811.0 / 11520.0 * e8)
470:                            - 4.0 * D;
471:                    C *= 4.0;
472:                    D *= 8.0;
473:
474:                    final double latTrueScale = Math.abs(standardParallel);
475:                    if (Math.abs(latTrueScale - Math.PI / 2) >= EPSILON) {
476:                        final double t = Math.sin(latTrueScale);
477:                        k0 = msfn(t, Math.cos(latTrueScale))
478:                                * Math.sqrt(Math.pow(1 + excentricity,
479:                                        1 + excentricity)
480:                                        * Math.pow(1 - excentricity,
481:                                                1 - excentricity))
482:                                / (2.0 * tsfn(latTrueScale, t));
483:                    } else {
484:                        k0 = 1.0;
485:                    }
486:                }
487:
488:                /**
489:                 * Transforms the specified (<var>x</var>,<var>y</var>) coordinates
490:                 * and stores the result in {@code ptDst}.
491:                 */
492:                protected Point2D inverseTransformNormalized(double x,
493:                        double y, Point2D ptDst) throws ProjectionException {
494:                    // Compute using iteration formulas, for comparaison later.
495:                    assert (ptDst = super .inverseTransformNormalized(x, y,
496:                            ptDst)) != null;
497:
498:                    final double rho = Math.sqrt(x * x + y * y);
499:                    if (southPole) {
500:                        y = -y;
501:                    }
502:                    // The series form
503:                    final double t = (rho / k0)
504:                            * Math.sqrt(Math.pow(1 + excentricity,
505:                                    1 + excentricity)
506:                                    * Math.pow(1 - excentricity,
507:                                            1 - excentricity)) / 2;
508:                    final double chi = Math.PI / 2 - 2 * Math.atan(t);
509:
510:                    x = (Math.abs(rho) < EPSILON) ? 0.0 : Math.atan2(x, -y);
511:
512:                    // See Snyde P. 19, "Computation of Series"
513:                    final double sin2chi = Math.sin(2.0 * chi);
514:                    final double cos2chi = Math.cos(2.0 * chi);
515:                    y = chi + sin2chi
516:                            * (A + cos2chi * (B + cos2chi * (C + D * cos2chi)));
517:                    y = (southPole) ? -y : y;
518:
519:                    assert checkInverseTransform(x, y, ptDst);
520:                    if (ptDst != null) {
521:                        ptDst.setLocation(x, y);
522:                        return ptDst;
523:                    }
524:                    return new Point2D.Double(x, y);
525:                }
526:            }
527:
528:            //////////////////////////////////////////////////////////////////////////////////////////
529:            //////////////////////////////////////////////////////////////////////////////////////////
530:            ////////                                                                          ////////
531:            ////////                                 PROVIDERS                                ////////
532:            ////////                                                                          ////////
533:            //////////////////////////////////////////////////////////////////////////////////////////
534:            //////////////////////////////////////////////////////////////////////////////////////////
535:
536:            /**
537:             * The {@linkplain org.geotools.referencing.operation.MathTransformProvider math transform
538:             * provider} for a {@linkplain PolarStereographic Polar Stereographic} projection. This
539:             * provider uses the series equations for the inverse elliptical calculations.
540:             *
541:             * @since 2.4
542:             * @version $Id: PolarStereographic.java 25778 2007-06-08 08:46:34Z desruisseaux $
543:             * @author Rueben Schulz
544:             *
545:             * @see org.geotools.referencing.operation.DefaultMathTransformFactory
546:             */
547:            public static final class ProviderA extends Stereographic.Provider {
548:                /**
549:                 * The parameters group.
550:                 */
551:                static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(
552:                        new NamedIdentifier[] {
553:                                new NamedIdentifier(Citations.OGC,
554:                                        "Polar_Stereographic"),
555:                                new NamedIdentifier(Citations.EPSG,
556:                                        "Polar Stereographic (variant A)"),
557:                                new NamedIdentifier(Citations.EPSG, "9810"),
558:                                new NamedIdentifier(Citations.GEOTIFF,
559:                                        "CT_PolarStereographic"),
560:                                new NamedIdentifier(Citations.GEOTOOLS,
561:                                        Provider.NAME) },
562:                        new ParameterDescriptor[] { SEMI_MAJOR, SEMI_MINOR,
563:                                CENTRAL_MERIDIAN, LATITUDE_OF_ORIGIN,
564:                                SCALE_FACTOR, FALSE_EASTING, FALSE_NORTHING });
565:
566:                /**
567:                 * Constructs a new provider. 
568:                 */
569:                public ProviderA() {
570:                    super (PARAMETERS);
571:                }
572:
573:                /**
574:                 * Creates a transform from the specified group of parameter values.
575:                 *
576:                 * @param  parameters The group of parameter values.
577:                 * @return The created math transform.
578:                 * @throws ParameterNotFoundException if a required parameter was not found.
579:                 */
580:                public MathTransform createMathTransform(
581:                        final ParameterValueGroup parameters)
582:                        throws ParameterNotFoundException {
583:                    if (isSpherical(parameters)) {
584:                        return new PolarStereographic.Spherical(parameters,
585:                                PARAMETERS, null);
586:                    } else {
587:                        return new PolarStereographic.Series(parameters,
588:                                PARAMETERS, null);
589:                    }
590:                }
591:            }
592:
593:            /**
594:             * The {@linkplain org.geotools.referencing.operation.MathTransformProvider math transform
595:             * provider} for a {@linkplain PolarStereographic Polar Stereographic} (Variant B)
596:             * projection. This provider includes a "Standard_Parallel_1" parameter and determines
597:             * the hemisphere of the projection from the Standard_Parallel_1 value. It also uses the
598:             * series equations for the inverse elliptical calculations.
599:             *
600:             * @since 2.4
601:             * @version $Id: PolarStereographic.java 25778 2007-06-08 08:46:34Z desruisseaux $
602:             * @author Rueben Schulz
603:             *
604:             * @see org.geotools.referencing.operation.DefaultMathTransformFactory
605:             */
606:            public static final class ProviderB extends Stereographic.Provider {
607:                /**
608:                 * The operation parameter descriptor for the {@code standardParallel}
609:                 * parameter value. Valid values range is from -90 to 90°. The default
610:                 * value is 90°N.
611:                 */
612:                public static final ParameterDescriptor STANDARD_PARALLEL = ProviderNorth.STANDARD_PARALLEL;
613:
614:                /**
615:                 * The parameters group.
616:                 */
617:                static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(
618:                        new NamedIdentifier[] {
619:                                new NamedIdentifier(Citations.EPSG,
620:                                        "Polar Stereographic (variant B)"),
621:                                new NamedIdentifier(Citations.EPSG, "9829"),
622:                                new NamedIdentifier(Citations.GEOTOOLS,
623:                                        Provider.NAME) },
624:                        new ParameterDescriptor[] { SEMI_MAJOR, SEMI_MINOR,
625:                                CENTRAL_MERIDIAN, STANDARD_PARALLEL,
626:                                FALSE_EASTING, FALSE_NORTHING });
627:
628:                /**
629:                 * Constructs a new provider. 
630:                 */
631:                public ProviderB() {
632:                    super (PARAMETERS);
633:                }
634:
635:                /**
636:                 * Creates a transform from the specified group of parameter values.
637:                 *
638:                 * @param  parameters The group of parameter values.
639:                 * @return The created math transform.
640:                 * @throws ParameterNotFoundException if a required parameter was not found.
641:                 */
642:                public MathTransform createMathTransform(
643:                        final ParameterValueGroup parameters)
644:                        throws ParameterNotFoundException {
645:                    if (isSpherical(parameters)) {
646:                        return new PolarStereographic.Spherical(parameters,
647:                                PARAMETERS, null);
648:                    } else {
649:                        return new PolarStereographic.Series(parameters,
650:                                PARAMETERS, null);
651:                    }
652:                }
653:            }
654:
655:            /**
656:             * The {@linkplain org.geotools.referencing.operation.MathTransformProvider math transform
657:             * provider} for a {@linkplain PolarStereographic North Polar Stereographic} projection.
658:             * This provider sets the "latitude_of_origin" parameter to +90.0 degrees and uses the
659:             * iterative equations for the inverse elliptical calculations.
660:             *
661:             * @since 2.4
662:             * @version $Id: PolarStereographic.java 25778 2007-06-08 08:46:34Z desruisseaux $
663:             * @author Rueben Schulz
664:             *
665:             * @see org.geotools.referencing.operation.DefaultMathTransformFactory
666:             */
667:            public static final class ProviderNorth extends
668:                    Stereographic.Provider {
669:                /**
670:                 * The operation parameter descriptor for the {@code standardParallel}
671:                 * parameter value. Valid values range is from -90 to 90°. The default
672:                 * value is 90°N.
673:                 */
674:                public static final ParameterDescriptor STANDARD_PARALLEL = createDescriptor(
675:                        new NamedIdentifier[] {
676:                                new NamedIdentifier(Citations.ESRI,
677:                                        "standard_parallel_1"),
678:                                new NamedIdentifier(Citations.EPSG,
679:                                        "Latitude of standard parallel") }, 90,
680:                        -90, 90, NonSI.DEGREE_ANGLE);
681:
682:                /**
683:                 * The parameters group.
684:                 */
685:                static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(
686:                        new NamedIdentifier[] {
687:                                new NamedIdentifier(Citations.ESRI,
688:                                        "Stereographic_North_Pole"),
689:                                new NamedIdentifier(Citations.GEOTOOLS,
690:                                        Provider.NAME) },
691:                        new ParameterDescriptor[] { SEMI_MAJOR, SEMI_MINOR,
692:                                CENTRAL_MERIDIAN, STANDARD_PARALLEL,
693:                                SCALE_FACTOR, FALSE_EASTING, FALSE_NORTHING });
694:
695:                /**
696:                 * Constructs a new provider. 
697:                 */
698:                public ProviderNorth() {
699:                    super (PARAMETERS);
700:                }
701:
702:                /**
703:                 * Creates a transform from the specified group of parameter values.
704:                 *
705:                 * @param  parameters The group of parameter values.
706:                 * @return The created math transform.
707:                 * @throws ParameterNotFoundException if a required parameter was not found.
708:                 */
709:                public MathTransform createMathTransform(
710:                        final ParameterValueGroup parameters)
711:                        throws ParameterNotFoundException {
712:                    if (isSpherical(parameters)) {
713:                        return new PolarStereographic.Spherical(parameters,
714:                                PARAMETERS, Boolean.FALSE);
715:                    } else {
716:                        return new PolarStereographic(parameters, PARAMETERS,
717:                                Boolean.FALSE);
718:                    }
719:                }
720:            }
721:
722:            /**
723:             * The {@linkplain org.geotools.referencing.operation.MathTransformProvider math transform
724:             * provider} for a {@linkplain PolarStereographic South Polar Stereographic} projection.
725:             * This provider sets the "latitude_of_origin" parameter to -90.0 degrees and uses the
726:             * iterative equations for the inverse elliptical calculations.
727:             *
728:             * @since 2.4
729:             * @version $Id: PolarStereographic.java 25778 2007-06-08 08:46:34Z desruisseaux $
730:             * @author Rueben Schulz
731:             *
732:             * @see org.geotools.referencing.operation.DefaultMathTransformFactory
733:             */
734:            public static final class ProviderSouth extends
735:                    Stereographic.Provider {
736:                /**
737:                 * The operation parameter descriptor for the {@code standardParallel}
738:                 * parameter value. Valid values range is from -90 to 90°. The default
739:                 * value is 90°S.
740:                 */
741:                public static final ParameterDescriptor STANDARD_PARALLEL = createDescriptor(
742:                        new NamedIdentifier[] {
743:                                new NamedIdentifier(Citations.ESRI,
744:                                        "standard_parallel_1"),
745:                                new NamedIdentifier(Citations.EPSG,
746:                                        "Latitude of standard parallel") },
747:                        -90, -90, 90, NonSI.DEGREE_ANGLE);
748:
749:                /**
750:                 * The parameters group.
751:                 */
752:                static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(
753:                        new NamedIdentifier[] {
754:                                new NamedIdentifier(Citations.ESRI,
755:                                        "Stereographic_South_Pole"),
756:                                new NamedIdentifier(Citations.GEOTOOLS,
757:                                        Provider.NAME) },
758:                        new ParameterDescriptor[] { SEMI_MAJOR, SEMI_MINOR,
759:                                CENTRAL_MERIDIAN, STANDARD_PARALLEL,
760:                                SCALE_FACTOR, FALSE_EASTING, FALSE_NORTHING });
761:
762:                /**
763:                 * Constructs a new provider. 
764:                 */
765:                public ProviderSouth() {
766:                    super (PARAMETERS);
767:                }
768:
769:                /**
770:                 * Creates a transform from the specified group of parameter values.
771:                 *
772:                 * @param  parameters The group of parameter values.
773:                 * @return The created math transform.
774:                 * @throws ParameterNotFoundException if a required parameter was not found.
775:                 */
776:                public MathTransform createMathTransform(
777:                        final ParameterValueGroup parameters)
778:                        throws ParameterNotFoundException {
779:                    if (isSpherical(parameters)) {
780:                        return new PolarStereographic.Spherical(parameters,
781:                                PARAMETERS, Boolean.TRUE);
782:                    } else {
783:                        return new PolarStereographic(parameters, PARAMETERS,
784:                                Boolean.TRUE);
785:                    }
786:                }
787:            }
788:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.