Source Code Cross Referenced for DefaultGeodeticDatum.java in  » GIS » GeoTools-2.4.1 » org » geotools » referencing » datum » 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.datum 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2003-2006, GeoTools Project Managment Committee (PMC)
005:         *    (C) 2001, Institut de Recherche pour le Développement
006:         *   
007:         *    This library is free software; you can redistribute it and/or
008:         *    modify it under the terms of the GNU Lesser General Public
009:         *    License as published by the Free Software Foundation;
010:         *    version 2.1 of the License.
011:         *
012:         *    This library is distributed in the hope that it will be useful,
013:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015:         *    Lesser General Public License for more details.
016:         *
017:         *    This package contains documentation from OpenGIS specifications.
018:         *    OpenGIS consortium's work is fully acknowledged here.
019:         */
020:        package org.geotools.referencing.datum;
021:
022:        // J2SE dependencies
023:        import java.util.Arrays;
024:        import java.util.Collections;
025:        import java.util.HashMap;
026:        import java.util.HashSet;
027:        import java.util.LinkedHashSet;
028:        import java.util.Map;
029:        import java.util.Set;
030:
031:        // OpenGIS dependencies
032:        import org.opengis.referencing.ReferenceIdentifier;
033:        import org.opengis.referencing.datum.Datum;
034:        import org.opengis.referencing.datum.Ellipsoid;
035:        import org.opengis.referencing.datum.PrimeMeridian;
036:        import org.opengis.referencing.datum.GeodeticDatum;
037:        import org.opengis.referencing.operation.Matrix;
038:
039:        // Geotools dependencies
040:        import org.geotools.metadata.iso.citation.Citations;
041:        import org.geotools.referencing.operation.matrix.XMatrix;
042:        import org.geotools.referencing.AbstractIdentifiedObject;
043:        import org.geotools.referencing.NamedIdentifier;
044:        import org.geotools.referencing.wkt.Formatter;
045:
046:        /**
047:         * Defines the location and precise orientation in 3-dimensional space of a defined ellipsoid
048:         * (or sphere) that approximates the shape of the earth. Used also for Cartesian coordinate
049:         * system centered in this ellipsoid (or sphere).
050:         *
051:         * @since 2.1
052:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/datum/DefaultGeodeticDatum.java $
053:         * @version $Id: DefaultGeodeticDatum.java 25262 2007-04-23 21:11:16Z desruisseaux $
054:         * @author Martin Desruisseaux
055:         *
056:         * @see Ellipsoid
057:         * @see PrimeMeridian
058:         */
059:        public class DefaultGeodeticDatum extends AbstractDatum implements 
060:                GeodeticDatum {
061:            /**
062:             * Serial number for interoperability with different versions.
063:             */
064:            private static final long serialVersionUID = 8832100095648302943L;
065:
066:            /**
067:             * The default WGS 1984 datum.
068:             */
069:            public static final DefaultGeodeticDatum WGS84;
070:            static {
071:                final ReferenceIdentifier[] identifiers = {
072:                        new NamedIdentifier(Citations.OGC, "WGS84"),
073:                        new NamedIdentifier(Citations.ORACLE, "WGS 84"),
074:                        new NamedIdentifier(null, "WGS_84"),
075:                        new NamedIdentifier(null, "WGS 1984"),
076:                        new NamedIdentifier(Citations.EPSG, "WGS_1984"),
077:                        new NamedIdentifier(Citations.ESRI, "D_WGS_1984"),
078:                        new NamedIdentifier(Citations.EPSG,
079:                                "World Geodetic System 1984") };
080:                final Map properties = new HashMap(4);
081:                properties.put(NAME_KEY, identifiers[0]);
082:                properties.put(ALIAS_KEY, identifiers);
083:                WGS84 = new DefaultGeodeticDatum(properties,
084:                        DefaultEllipsoid.WGS84, DefaultPrimeMeridian.GREENWICH);
085:            }
086:
087:            /**
088:             * The <code>{@value #BURSA_WOLF_KEY}</code> property for
089:             * {@linkplain #getAffineTransform datum shifts}.
090:             */
091:            public static final String BURSA_WOLF_KEY = "bursaWolf";
092:
093:            /**
094:             * The ellipsoid.
095:             */
096:            private final Ellipsoid ellipsoid;
097:
098:            /**
099:             * The prime meridian.
100:             */
101:            private final PrimeMeridian primeMeridian;
102:
103:            /**
104:             * Bursa Wolf parameters for datum shifts, or {@code null} if none.
105:             */
106:            private final BursaWolfParameters[] bursaWolf;
107:
108:            /**
109:             * Constructs a new datum with the same values than the specified one.
110:             * This copy constructor provides a way to wrap an arbitrary implementation into a
111:             * Geotools one or a user-defined one (as a subclass), usually in order to leverage
112:             * some implementation-specific API. This constructor performs a shallow copy,
113:             * i.e. the properties are not cloned.
114:             *
115:             * @since 2.2
116:             */
117:            public DefaultGeodeticDatum(final GeodeticDatum datum) {
118:                super (datum);
119:                ellipsoid = datum.getEllipsoid();
120:                primeMeridian = datum.getPrimeMeridian();
121:                bursaWolf = (datum instanceof  DefaultGeodeticDatum) ? ((DefaultGeodeticDatum) datum).bursaWolf
122:                        : null;
123:            }
124:
125:            /**
126:             * Constructs a geodetic datum from a name.
127:             *
128:             * @param name          The datum name.
129:             * @param ellipsoid     The ellipsoid.
130:             * @param primeMeridian The prime meridian.
131:             */
132:            public DefaultGeodeticDatum(final String name,
133:                    final Ellipsoid ellipsoid, final PrimeMeridian primeMeridian) {
134:                this (Collections.singletonMap(NAME_KEY, name), ellipsoid,
135:                        primeMeridian);
136:            }
137:
138:            /**
139:             * Constructs a geodetic datum from a set of properties. The properties map is given
140:             * unchanged to the {@linkplain AbstractDatum#AbstractDatum(Map) super-class constructor}.
141:             * Additionally, the following properties are understood by this construtor:
142:             * <p>
143:             * <table border='1'>
144:             *   <tr bgcolor="#CCCCFF" class="TableHeadingColor">
145:             *     <th nowrap>Property name</th>
146:             *     <th nowrap>Value type</th>
147:             *     <th nowrap>Value given to</th>
148:             *   </tr>
149:             *   <tr>
150:             *     <td nowrap>&nbsp;{@link #BURSA_WOLF_KEY "bursaWolf"}&nbsp;</td>
151:             *     <td nowrap>&nbsp;{@link BursaWolfParameters} or an array of those&nbsp;</td>
152:             *     <td nowrap>&nbsp;{@link #getBursaWolfParameters}</td>
153:             *   </tr>
154:             * </table>
155:             *
156:             * @param properties    Set of properties. Should contains at least <code>"name"</code>.
157:             * @param ellipsoid     The ellipsoid.
158:             * @param primeMeridian The prime meridian.
159:             */
160:            public DefaultGeodeticDatum(final Map properties,
161:                    final Ellipsoid ellipsoid, final PrimeMeridian primeMeridian) {
162:                super (properties);
163:                this .ellipsoid = ellipsoid;
164:                this .primeMeridian = primeMeridian;
165:                ensureNonNull("ellipsoid", ellipsoid);
166:                ensureNonNull("primeMeridian", primeMeridian);
167:                BursaWolfParameters[] bursaWolf;
168:                final Object object = properties.get(BURSA_WOLF_KEY);
169:                if (object instanceof  BursaWolfParameters) {
170:                    bursaWolf = new BursaWolfParameters[] { (BursaWolfParameters) ((BursaWolfParameters) object)
171:                            .clone() };
172:                } else {
173:                    bursaWolf = (BursaWolfParameters[]) object;
174:                    if (bursaWolf != null) {
175:                        if (bursaWolf.length == 0) {
176:                            bursaWolf = null;
177:                        } else {
178:                            final Set s = new LinkedHashSet();
179:                            for (int i = 0; i < bursaWolf.length; i++) {
180:                                s.add((BursaWolfParameters) bursaWolf[i]
181:                                        .clone());
182:                            }
183:                            bursaWolf = (BursaWolfParameters[]) s
184:                                    .toArray(new BursaWolfParameters[s.size()]);
185:                        }
186:                    }
187:                }
188:                this .bursaWolf = bursaWolf;
189:            }
190:
191:            /**
192:             * Returns the ellipsoid.
193:             */
194:            public Ellipsoid getEllipsoid() {
195:                return ellipsoid;
196:            }
197:
198:            /**
199:             * Returns the prime meridian.
200:             */
201:            public PrimeMeridian getPrimeMeridian() {
202:                return primeMeridian;
203:            }
204:
205:            /**
206:             * Returns all Bursa Wolf parameters specified in the {@code properties} map at
207:             * construction time.
208:             *
209:             * @since 2.4
210:             */
211:            public BursaWolfParameters[] getBursaWolfParameters() {
212:                if (bursaWolf != null) {
213:                    return (BursaWolfParameters[]) bursaWolf.clone();
214:                }
215:                return new BursaWolfParameters[0];
216:            }
217:
218:            /**
219:             * Returns Bursa Wolf parameters for a datum shift toward the specified target, or {@code null}
220:             * if none. This method search only for Bursa-Wolf parameters explicitly specified in the
221:             * {@code properties} map at construction time. This method doesn't try to infer a set of
222:             * parameters from indirect informations. For example it doesn't try to inverse the parameters
223:             * specified in the {@code target} datum if none were found in this datum. If such an elaborated
224:             * search is wanted, use {@link #getAffineTransform} instead.
225:             */
226:            public BursaWolfParameters getBursaWolfParameters(
227:                    final GeodeticDatum target) {
228:                if (bursaWolf != null) {
229:                    for (int i = 0; i < bursaWolf.length; i++) {
230:                        final BursaWolfParameters candidate = bursaWolf[i];
231:                        if (equals(target, candidate.targetDatum, false)) {
232:                            return (BursaWolfParameters) candidate.clone();
233:                        }
234:                    }
235:                }
236:                return null;
237:            }
238:
239:            /**
240:             * Returns a matrix that can be used to define a transformation to the specified datum.
241:             * If no transformation path is found, then this method returns {@code null}.
242:             *
243:             * @param  source The source datum.
244:             * @param  target The target datum.
245:             * @return An affine transform from {@code source} to {@code target}, or {@code null} if none.
246:             *
247:             * @see BursaWolfParameters#getAffineTransform
248:             */
249:            public static Matrix getAffineTransform(final GeodeticDatum source,
250:                    final GeodeticDatum target) {
251:                return getAffineTransform(source, target, null);
252:            }
253:
254:            /**
255:             * Returns a matrix that can be used to define a transformation to the specified datum.
256:             * If no transformation path is found, then this method returns {@code null}.
257:             *
258:             * @param  source The source datum.
259:             * @param  target The target datum.
260:             * @param  exclusion The set of datum to exclude from the search, or {@code null}.
261:             *         This is used in order to avoid never-ending recursivity.
262:             * @return An affine transform from {@code source} to {@code target}, or {@code null} if none.
263:             *
264:             * @see BursaWolfParameters#getAffineTransform
265:             */
266:            private static XMatrix getAffineTransform(
267:                    final GeodeticDatum source, final GeodeticDatum target,
268:                    Set exclusion) {
269:                ensureNonNull("source", source);
270:                ensureNonNull("target", target);
271:                if (source instanceof  DefaultGeodeticDatum) {
272:                    final BursaWolfParameters[] bursaWolf = ((DefaultGeodeticDatum) source).bursaWolf;
273:                    if (bursaWolf != null) {
274:                        for (int i = 0; i < bursaWolf.length; i++) {
275:                            final BursaWolfParameters transformation = bursaWolf[i];
276:                            if (equals(target, transformation.targetDatum,
277:                                    false)) {
278:                                return transformation.getAffineTransform();
279:                            }
280:                        }
281:                    }
282:                }
283:                /*
284:                 * No transformation found to the specified target datum.
285:                 * Search if a transform exists in the opposite direction.
286:                 */
287:                if (target instanceof  DefaultGeodeticDatum) {
288:                    final BursaWolfParameters[] bursaWolf = ((DefaultGeodeticDatum) target).bursaWolf;
289:                    if (bursaWolf != null) {
290:                        for (int i = 0; i < bursaWolf.length; i++) {
291:                            final BursaWolfParameters transformation = bursaWolf[i];
292:                            if (equals(source, transformation.targetDatum,
293:                                    false)) {
294:                                final XMatrix matrix = transformation
295:                                        .getAffineTransform();
296:                                matrix.invert();
297:                                return matrix;
298:                            }
299:                        }
300:                    }
301:                }
302:                /*
303:                 * No direct tranformation found. Search for a path through some intermediate datum.
304:                 * First, search if there is some BursaWolfParameters for the same target in both
305:                 * 'source' and 'target' datum. If such an intermediate is found, ask for a path
306:                 * as below:
307:                 *
308:                 *    source   -->   [common datum]   -->   target
309:                 */
310:                if (source instanceof  DefaultGeodeticDatum
311:                        && target instanceof  DefaultGeodeticDatum) {
312:                    final BursaWolfParameters[] sourceParam = ((DefaultGeodeticDatum) source).bursaWolf;
313:                    final BursaWolfParameters[] targetParam = ((DefaultGeodeticDatum) target).bursaWolf;
314:                    if (sourceParam != null && targetParam != null) {
315:                        GeodeticDatum sourceStep;
316:                        GeodeticDatum targetStep;
317:                        for (int i = 0; i < sourceParam.length; i++) {
318:                            sourceStep = sourceParam[i].targetDatum;
319:                            for (int j = 0; j < targetParam.length; j++) {
320:                                targetStep = targetParam[j].targetDatum;
321:                                if (equals(sourceStep, targetStep, false)) {
322:                                    final XMatrix step1, step2;
323:                                    if (exclusion == null) {
324:                                        exclusion = new HashSet();
325:                                    }
326:                                    if (exclusion.add(source)) {
327:                                        if (exclusion.add(target)) {
328:                                            step1 = getAffineTransform(source,
329:                                                    sourceStep, exclusion);
330:                                            if (step1 != null) {
331:                                                step2 = getAffineTransform(
332:                                                        targetStep, target,
333:                                                        exclusion);
334:                                                if (step2 != null) {
335:                                                    /*
336:                                                     * Note: XMatrix.multiply(XMatrix) is equivalent to
337:                                                     *       AffineTransform.concatenate(...): First
338:                                                     *       transform by the supplied transform and
339:                                                     *       then transform the result by the original
340:                                                     *       transform.
341:                                                     */
342:                                                    step2.multiply(step1);
343:                                                    return step2;
344:                                                }
345:                                            }
346:                                            exclusion.remove(target);
347:                                        }
348:                                        exclusion.remove(source);
349:                                    }
350:                                }
351:                            }
352:                        }
353:                    }
354:                }
355:                return null;
356:            }
357:
358:            /**
359:             * Returns {@code true} if the specified object is equals (at least on
360:             * computation purpose) to the {@link #WGS84} datum. This method may conservatively
361:             * returns {@code false} if the specified datum is uncertain (for example
362:             * because it come from an other implementation).
363:             */
364:            public static boolean isWGS84(final Datum datum) {
365:                if (datum instanceof  AbstractIdentifiedObject) {
366:                    return WGS84
367:                            .equals((AbstractIdentifiedObject) datum, false);
368:                }
369:                // Maybe the specified object has its own test...
370:                return datum != null && datum.equals(WGS84);
371:            }
372:
373:            /**
374:             * Compare this datum with the specified object for equality.
375:             *
376:             * @param  object The object to compare to {@code this}.
377:             * @param  compareMetadata {@code true} for performing a strict comparaison, or
378:             *         {@code false} for comparing only properties relevant to transformations.
379:             * @return {@code true} if both objects are equal.
380:             */
381:            public boolean equals(final AbstractIdentifiedObject object,
382:                    final boolean compareMetadata) {
383:                if (object == this ) {
384:                    return true; // Slight optimization.
385:                }
386:                if (super .equals(object, compareMetadata)) {
387:                    final DefaultGeodeticDatum that = (DefaultGeodeticDatum) object;
388:                    if (equals(this .ellipsoid, that.ellipsoid, compareMetadata)
389:                            && equals(this .primeMeridian, that.primeMeridian,
390:                                    compareMetadata)) {
391:                        /*
392:                         * HACK: We do not consider Bursa Wolf parameters as a non-metadata field.
393:                         *       This is needed in order to get equalsIgnoreMetadata(...) to returns
394:                         *       'true' when comparing the WGS84 constant in this class with a WKT
395:                         *       DATUM element with a TOWGS84[0,0,0,0,0,0,0] element. Furthermore,
396:                         *       the Bursa Wolf parameters are not part of ISO 19111 specification.
397:                         *       We don't want two CRS to be considered as different because one has
398:                         *       more of those transformation informations (which is nice, but doesn't
399:                         *       change the CRS itself).
400:                         */
401:                        return !compareMetadata
402:                                || Arrays
403:                                        .equals(this .bursaWolf, that.bursaWolf);
404:                    }
405:                }
406:                return false;
407:            }
408:
409:            /**
410:             * Returns a hash value for this geodetic datum. {@linkplain #getName Name},
411:             * {@linkplain #getRemarks remarks} and the like are not taken in account. In
412:             * other words, two geodetic datums will return the same hash value if they
413:             * are equal in the sense of
414:             * <code>{@link #equals equals}(AbstractIdentifiedObject, <strong>false</strong>)</code>.
415:             *
416:             * @return The hash code value. This value doesn't need to be the same
417:             *         in past or future versions of this class.
418:             */
419:            public int hashCode() {
420:                int code = (int) serialVersionUID
421:                        ^ 37
422:                        * (super .hashCode() ^ 37 * (ellipsoid.hashCode() ^ 37 * (primeMeridian
423:                                .hashCode())));
424:                return code;
425:            }
426:
427:            /**
428:             * Format the inner part of a
429:             * <A HREF="http://geoapi.sourceforge.net/snapshot/javadoc/org/opengis/referencing/doc-files/WKT.html"><cite>Well
430:             * Known Text</cite> (WKT)</A> element.
431:             *
432:             * @param  formatter The formatter to use.
433:             * @return The WKT element name, which is "DATUM"
434:             */
435:            protected String formatWKT(final Formatter formatter) {
436:                // Do NOT invokes the super-class method, because
437:                // horizontal datum do not write the datum type.
438:                formatter.append(ellipsoid);
439:                if (bursaWolf != null) {
440:                    for (int i = 0; i < bursaWolf.length; i++) {
441:                        final BursaWolfParameters transformation = bursaWolf[i];
442:                        if (isWGS84(transformation.targetDatum)) {
443:                            formatter.append(transformation);
444:                            break;
445:                        }
446:                    }
447:                }
448:                return "DATUM";
449:            }
450:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.