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


0001:        /*
0002:         *    GeoTools - OpenSource mapping toolkit
0003:         *    http://geotools.org
0004:         *    (C) 2003-2006, GeoTools Project Managment Committee (PMC)
0005:         *    (C) 2001, Institut de Recherche pour le Développement
0006:         *   
0007:         *    This library is free software; you can redistribute it and/or
0008:         *    modify it under the terms of the GNU Lesser General Public
0009:         *    License as published by the Free Software Foundation;
0010:         *    version 2.1 of the License.
0011:         *
0012:         *    This library is distributed in the hope that it will be useful,
0013:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0014:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015:         *    Lesser General Public License for more details.
0016:         *
0017:         *    This package contains documentation from OpenGIS specifications.
0018:         *    OpenGIS consortium's work is fully acknowledged here.
0019:         */
0020:        package org.geotools.referencing.cs;
0021:
0022:        // J2SE dependencies and extensions
0023:        import java.util.Collections;
0024:        import java.util.HashMap;
0025:        import java.util.Locale;
0026:        import java.util.Map;
0027:        import java.util.NoSuchElementException;
0028:        import javax.units.Converter;
0029:        import javax.units.NonSI;
0030:        import javax.units.SI;
0031:        import javax.units.Unit;
0032:
0033:        // OpenGIS dependencies
0034:        import org.opengis.referencing.cs.AxisDirection;
0035:        import org.opengis.referencing.cs.CoordinateSystemAxis;
0036:        import org.opengis.referencing.cs.RangeMeaning;
0037:        import org.opengis.util.InternationalString;
0038:
0039:        // Geotools dependencies
0040:        import org.geotools.referencing.AbstractIdentifiedObject;
0041:        import org.geotools.referencing.wkt.Formatter;
0042:        import org.geotools.resources.Utilities;
0043:        import org.geotools.resources.i18n.Errors;
0044:        import org.geotools.resources.i18n.ErrorKeys;
0045:        import org.geotools.resources.i18n.Vocabulary;
0046:        import org.geotools.resources.i18n.VocabularyKeys;
0047:        import org.geotools.util.SimpleInternationalString;
0048:        import org.geotools.util.NameFactory;
0049:
0050:        /**
0051:         * Definition of a coordinate system axis. This is used to label axes, and indicate the orientation.
0052:         * See {@linkplain org.opengis.referencing.cs#AxisNames axis name constraints}.
0053:         * <p>
0054:         * In some case, the axis name is constrained by ISO 19111 depending on the
0055:         * {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem coordinate reference system}
0056:         * type. These constraints are identified in the javadoc by "<cite>ISO 19111 name is...</cite>"
0057:         * sentences. This constraint works in two directions; for example the names
0058:         * "<cite>geodetic latitude</cite>" and "<cite>geodetic longitude</cite>" shall be used to
0059:         * designate the coordinate axis names associated with a
0060:         * {@linkplain org.opengis.referencing.crs.GeographicCRS geographic coordinate reference system}.
0061:         * Conversely, these names shall not be used in any other context.
0062:         *
0063:         * @since 2.1
0064:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/cs/DefaultCoordinateSystemAxis.java $
0065:         * @version $Id: DefaultCoordinateSystemAxis.java 25778 2007-06-08 08:46:34Z desruisseaux $
0066:         * @author Martin Desruisseaux
0067:         *
0068:         * @see AbstractCS
0069:         * @see Unit
0070:         */
0071:        public class DefaultCoordinateSystemAxis extends
0072:                AbstractIdentifiedObject implements  CoordinateSystemAxis {
0073:            /**
0074:             * Serial number for interoperability with different versions.
0075:             */
0076:            private static final long serialVersionUID = -7883614853277827689L;
0077:
0078:            /**
0079:             * Number of directions from "North", "North-North-East", "North-East", etc.
0080:             * This is verified by {@code DefaultCoordinateSystemAxisTest.testCompass}.
0081:             */
0082:            static final int COMPASS_DIRECTION_COUNT = 16;
0083:
0084:            /**
0085:             * Number of items in {@link #PREDEFINED}. Should be considered
0086:             * as a constant after the class initialisation is completed.
0087:             */
0088:            private static int PREDEFINED_COUNT = 0;
0089:
0090:            /**
0091:             * The list of predefined constants declared in this class,
0092:             * in declaration order. This order matter.
0093:             */
0094:            private static final DefaultCoordinateSystemAxis[] PREDEFINED = new DefaultCoordinateSystemAxis[26];
0095:
0096:            /**
0097:             * Default axis info for geodetic longitudes in a
0098:             * {@linkplain org.opengis.referencing.crs.GeographicCRS geographic CRS}.
0099:             *
0100:             * Increasing ordinates values go {@linkplain AxisDirection#EAST East}
0101:             * and units are {@linkplain NonSI#DEGREE_ANGLE decimal degrees}.
0102:             *
0103:             * The ISO 19111 name is "<cite>geodetic longitude</cite>" and the abbreviation is "&lambda;"
0104:             * (lambda).
0105:             * 
0106:             * This axis is usually part of a {@link #GEODETIC_LONGITUDE}, {@link #GEODETIC_LATITUDE},
0107:             * {@link #ELLIPSOIDAL_HEIGHT} set.
0108:             *
0109:             * @see #LONGITUDE
0110:             * @see #SPHERICAL_LONGITUDE
0111:             * @see #GEODETIC_LATITUDE
0112:             */
0113:            public static final DefaultCoordinateSystemAxis GEODETIC_LONGITUDE = new DefaultCoordinateSystemAxis(
0114:                    VocabularyKeys.GEODETIC_LONGITUDE, "\u03BB",
0115:                    AxisDirection.EAST, NonSI.DEGREE_ANGLE);
0116:
0117:            /**
0118:             * Default axis info for geodetic latitudes in a
0119:             * {@linkplain org.opengis.referencing.crs.GeographicCRS geographic CRS}.
0120:             *
0121:             * Increasing ordinates values go {@linkplain AxisDirection#NORTH North}
0122:             * and units are {@linkplain NonSI#DEGREE_ANGLE decimal degrees}.
0123:             *
0124:             * The ISO 19111 name is "<cite>geodetic latitude</cite>" and the abbreviation is "&phi;" (phi).
0125:             * 
0126:             * This axis is usually part of a {@link #GEODETIC_LONGITUDE}, {@link #GEODETIC_LATITUDE},
0127:             * {@link #ELLIPSOIDAL_HEIGHT} set.
0128:             *
0129:             * @see #LATITUDE
0130:             * @see #SPHERICAL_LATITUDE
0131:             * @see #GEODETIC_LONGITUDE
0132:             */
0133:            public static final DefaultCoordinateSystemAxis GEODETIC_LATITUDE = new DefaultCoordinateSystemAxis(
0134:                    VocabularyKeys.GEODETIC_LATITUDE, "\u03C6",
0135:                    AxisDirection.NORTH, NonSI.DEGREE_ANGLE);
0136:
0137:            /**
0138:             * Default axis info for longitudes.
0139:             *
0140:             * Increasing ordinates values go {@linkplain AxisDirection#EAST East}
0141:             * and units are {@linkplain NonSI#DEGREE_ANGLE decimal degrees}.
0142:             *
0143:             * The abbreviation is "&lambda;" (lambda).
0144:             *
0145:             * This axis is usually part of a {@link #LONGITUDE}, {@link #LATITUDE}, {@link #ALTITUDE} set.
0146:             *
0147:             * @see #GEODETIC_LONGITUDE
0148:             * @see #SPHERICAL_LONGITUDE
0149:             * @see #LATITUDE
0150:             */
0151:            public static final DefaultCoordinateSystemAxis LONGITUDE = new DefaultCoordinateSystemAxis(
0152:                    VocabularyKeys.LONGITUDE, "\u03BB", AxisDirection.EAST,
0153:                    NonSI.DEGREE_ANGLE);
0154:
0155:            /**
0156:             * Default axis info for latitudes.
0157:             *
0158:             * Increasing ordinates values go {@linkplain AxisDirection#NORTH North}
0159:             * and units are {@linkplain NonSI#DEGREE_ANGLE decimal degrees}.
0160:             *
0161:             * The abbreviation is "&phi;" (phi).
0162:             * 
0163:             * This axis is usually part of a {@link #LONGITUDE}, {@link #LATITUDE}, {@link #ALTITUDE} set.
0164:             *
0165:             * @see #GEODETIC_LATITUDE
0166:             * @see #SPHERICAL_LATITUDE
0167:             * @see #LONGITUDE
0168:             */
0169:            public static final DefaultCoordinateSystemAxis LATITUDE = new DefaultCoordinateSystemAxis(
0170:                    VocabularyKeys.LATITUDE, "\u03C6", AxisDirection.NORTH,
0171:                    NonSI.DEGREE_ANGLE);
0172:
0173:            /**
0174:             * The default axis for height values above the ellipsoid in a
0175:             * {@linkplain org.opengis.referencing.crs.GeographicCRS geographic CRS}.
0176:             *
0177:             * Increasing ordinates values go {@linkplain AxisDirection#UP up}
0178:             * and units are {@linkplain SI#METER metres}.
0179:             *
0180:             * The ISO 19111 name is "<cite>ellipsoidal heigt</cite>" and the abbreviation is lower case
0181:             * "<var>h</var>".
0182:             * 
0183:             * This axis is usually part of a {@link #GEODETIC_LONGITUDE}, {@link #GEODETIC_LATITUDE},
0184:             * {@link #ELLIPSOIDAL_HEIGHT} set.
0185:             *
0186:             * @see #ALTITUDE
0187:             * @see #GEOCENTRIC_RADIUS
0188:             * @see #GRAVITY_RELATED_HEIGHT
0189:             * @see #DEPTH
0190:             */
0191:            public static final DefaultCoordinateSystemAxis ELLIPSOIDAL_HEIGHT = new DefaultCoordinateSystemAxis(
0192:                    VocabularyKeys.ELLIPSOIDAL_HEIGHT, "h", AxisDirection.UP,
0193:                    SI.METER);
0194:
0195:            /**
0196:             * The default axis for height values measured from gravity.
0197:             *
0198:             * Increasing ordinates values go {@linkplain AxisDirection#UP up}
0199:             * and units are {@linkplain SI#METER metres}.
0200:             *
0201:             * The ISO 19111 name is "<cite>gravity-related height</cite>" and the abbreviation is lower
0202:             * case "<var>h</var>".
0203:             *
0204:             * @see #ALTITUDE
0205:             * @see #ELLIPSOIDAL_HEIGHT
0206:             * @see #GEOCENTRIC_RADIUS
0207:             * @see #DEPTH
0208:             */
0209:            public static final DefaultCoordinateSystemAxis GRAVITY_RELATED_HEIGHT = new DefaultCoordinateSystemAxis(
0210:                    VocabularyKeys.GRAVITY_RELATED_HEIGHT, "h",
0211:                    AxisDirection.UP, SI.METER);
0212:
0213:            /**
0214:             * The default axis for altitude values.
0215:             *
0216:             * Increasing ordinates values go {@linkplain AxisDirection#UP up}
0217:             * and units are {@linkplain SI#METER metres}.
0218:             *
0219:             * The abbreviation is lower case "<var>h</var>".
0220:             * 
0221:             * This axis is usually part of a {@link #LONGITUDE}, {@link #LATITUDE}, {@link #ALTITUDE} set.
0222:             *
0223:             * @see #ELLIPSOIDAL_HEIGHT
0224:             * @see #GEOCENTRIC_RADIUS
0225:             * @see #GRAVITY_RELATED_HEIGHT
0226:             * @see #DEPTH
0227:             */
0228:            public static final DefaultCoordinateSystemAxis ALTITUDE = new DefaultCoordinateSystemAxis(
0229:                    VocabularyKeys.ALTITUDE, "h", AxisDirection.UP, SI.METER);
0230:
0231:            /**
0232:             * The default axis for depth.
0233:             *
0234:             * Increasing ordinates values go {@linkplain AxisDirection#DOWN down}
0235:             * and units are {@linkplain SI#METER metres}.
0236:             *
0237:             * The ISO 19111 name is "<cite>depth</cite>".
0238:             *
0239:             * @see #ALTITUDE
0240:             * @see #ELLIPSOIDAL_HEIGHT
0241:             * @see #GEOCENTRIC_RADIUS
0242:             * @see #GRAVITY_RELATED_HEIGHT
0243:             */
0244:            public static final DefaultCoordinateSystemAxis DEPTH = new DefaultCoordinateSystemAxis(
0245:                    VocabularyKeys.DEPTH, "d", AxisDirection.DOWN, SI.METER);
0246:            static {
0247:                ALTITUDE.opposite = DEPTH;
0248:                DEPTH.opposite = ALTITUDE;
0249:            }
0250:
0251:            /**
0252:             * Default axis info for radius in a
0253:             * {@linkplain org.opengis.referencing.crs.GeocentricCRS geocentric CRS} using
0254:             * {@linkplain org.opengis.referencing.cs.SphericalCS spherical CS}.
0255:             *
0256:             * Increasing ordinates values go {@linkplain AxisDirection#UP up}
0257:             * and units are {@linkplain SI#METER metres}.
0258:             *
0259:             * The ISO 19111 name is "<cite>geocentric radius</cite>" and the abbreviation is lower case
0260:             * "<var>r</var>".
0261:             * 
0262:             * This axis is usually part of a {@link #SPHERICAL_LONGITUDE}, {@link #SPHERICAL_LATITUDE},
0263:             * {@link #GEOCENTRIC_RADIUS} set.
0264:             *
0265:             * @see #ALTITUDE
0266:             * @see #ELLIPSOIDAL_HEIGHT
0267:             * @see #GRAVITY_RELATED_HEIGHT
0268:             * @see #DEPTH
0269:             */
0270:            public static final DefaultCoordinateSystemAxis GEOCENTRIC_RADIUS = new DefaultCoordinateSystemAxis(
0271:                    VocabularyKeys.GEOCENTRIC_RADIUS, "r", AxisDirection.UP,
0272:                    SI.METER);
0273:
0274:            /**
0275:             * Default axis info for longitudes in a
0276:             * {@linkplain org.opengis.referencing.crs.GeocentricCRS geocentric CRS} using
0277:             * {@linkplain org.opengis.referencing.crs.SphericalCS spherical CS}.
0278:             *
0279:             * Increasing ordinates values go {@linkplain AxisDirection#EAST East}
0280:             * and units are {@linkplain NonSI#DEGREE_ANGLE decimal degrees}.
0281:             *
0282:             * The ISO 19111 name is "<cite>spherical longitude</cite>" and the abbreviation is "&Omega;"
0283:             * (omega).
0284:             *
0285:             * This axis is usually part of a {@link #SPHERICAL_LONGITUDE}, {@link #SPHERICAL_LATITUDE},
0286:             * {@link #GEOCENTRIC_RADIUS} set.
0287:             *
0288:             * @see #LONGITUDE
0289:             * @see #GEODETIC_LONGITUDE
0290:             * @see #SPHERICAL_LATITUDE
0291:             */
0292:            public static final DefaultCoordinateSystemAxis SPHERICAL_LONGITUDE = new DefaultCoordinateSystemAxis(
0293:                    VocabularyKeys.SPHERICAL_LONGITUDE, "\u03A9",
0294:                    AxisDirection.EAST, NonSI.DEGREE_ANGLE);
0295:
0296:            /**
0297:             * Default axis info for latitudes in a
0298:             * {@linkplain org.opengis.referencing.crs.GeocentricCRS geocentric CRS} using
0299:             * {@linkplain org.opengis.referencing.cs.SphericalCS spherical CS}.
0300:             *
0301:             * Increasing ordinates values go {@linkplain AxisDirection#NORTH North}
0302:             * and units are {@linkplain NonSI#DEGREE_ANGLE decimal degrees}.
0303:             *
0304:             * The ISO 19111 name is "<cite>spherical latitude</cite>" and the abbreviation is "&Theta;"
0305:             * (theta).
0306:             * 
0307:             * This axis is usually part of a {@link #SPHERICAL_LONGITUDE}, {@link #SPHERICAL_LATITUDE},
0308:             * {@link #GEOCENTRIC_RADIUS} set.
0309:             *
0310:             * @see #LATITUDE
0311:             * @see #GEODETIC_LATITUDE
0312:             * @see #SPHERICAL_LONGITUDE
0313:             */
0314:            public static final DefaultCoordinateSystemAxis SPHERICAL_LATITUDE = new DefaultCoordinateSystemAxis(
0315:                    VocabularyKeys.SPHERICAL_LATITUDE, "\u03B8",
0316:                    AxisDirection.NORTH, NonSI.DEGREE_ANGLE);
0317:
0318:            /**
0319:             * Default axis info for <var>x</var> values in a
0320:             * {@linkplain org.opengis.referencing.cs.CartesianCS cartesian CS}.
0321:             *
0322:             * Increasing ordinates values go {@linkplain AxisDirection#EAST East}
0323:             * and units are {@linkplain SI#METER metres}.
0324:             *
0325:             * The abbreviation is lower case "<var>x</var>".
0326:             * 
0327:             * This axis is usually part of a {@link #X}, {@link #Y}, {@link #Z} set.
0328:             *
0329:             * @see #EASTING
0330:             * @see #WESTING
0331:             * @see #GEOCENTRIC_X
0332:             * @see #DISPLAY_X
0333:             * @see #COLUMN
0334:             */
0335:            public static final DefaultCoordinateSystemAxis X = new DefaultCoordinateSystemAxis(
0336:                    -1, "x", AxisDirection.EAST, SI.METER);
0337:
0338:            /**
0339:             * Default axis info for <var>y</var> values in a
0340:             * {@linkplain org.opengis.referencing.cs.CartesianCS cartesian CS}.
0341:             *
0342:             * Increasing ordinates values go {@linkplain AxisDirection#NORTH North}
0343:             * and units are {@linkplain SI#METER metres}.
0344:             *
0345:             * The abbreviation is lower case "<var>y</var>".
0346:             * 
0347:             * This axis is usually part of a {@link #X}, {@link #Y}, {@link #Z} set.
0348:             *
0349:             * @see #NORTHING
0350:             * @see #SOUTHING
0351:             * @see #GEOCENTRIC_Y
0352:             * @see #DISPLAY_Y
0353:             * @see #ROW
0354:             */
0355:            public static final DefaultCoordinateSystemAxis Y = new DefaultCoordinateSystemAxis(
0356:                    -1, "y", AxisDirection.NORTH, SI.METER);
0357:
0358:            /**
0359:             * Default axis info for <var>z</var> values in a
0360:             * {@linkplain org.opengis.referencing.cs.CartesianCS cartesian CS}.
0361:             *
0362:             * Increasing ordinates values go {@linkplain AxisDirection#UP up}
0363:             * and units are {@linkplain SI#METER metres}.
0364:             *
0365:             * The abbreviation is lower case "<var>z</var>".
0366:             * 
0367:             * This axis is usually part of a {@link #X}, {@link #Y}, {@link #Z} set.
0368:             */
0369:            public static final DefaultCoordinateSystemAxis Z = new DefaultCoordinateSystemAxis(
0370:                    -1, "z", AxisDirection.UP, SI.METER);
0371:
0372:            /**
0373:             * Default axis info for <var>x</var> values in a
0374:             * {@linkplain org.opengis.referencing.crs.GeocentricCRS geocentric CRS} using
0375:             * {@linkplain org.opengis.referencing.cs.CartesianCS cartesian CS}.
0376:             *
0377:             * Increasing ordinates values go toward prime meridian
0378:             * and units are {@linkplain SI#METER metres}.
0379:             *
0380:             * The ISO 19111 name is "<cite>geocentric X</cite>" and the abbreviation is upper case
0381:             * "<var>X</var>".
0382:             * 
0383:             * This axis is usually part of a {@link #GEOCENTRIC_X}, {@link #GEOCENTRIC_Y},
0384:             * {@link #GEOCENTRIC_Z} set.
0385:             */
0386:            public static final DefaultCoordinateSystemAxis GEOCENTRIC_X = new DefaultCoordinateSystemAxis(
0387:                    VocabularyKeys.GEOCENTRIC_X, "X", AxisDirection.OTHER,
0388:                    SI.METER);
0389:
0390:            /**
0391:             * Default axis info for <var>y</var> values in a
0392:             * {@linkplain org.opengis.referencing.crs.GeocentricCRS geocentric CRS} using
0393:             * {@linkplain org.opengis.referencing.cs.CartesianCS cartesian CS}.
0394:             *
0395:             * Increasing ordinates values go {@linkplain AxisDirection#EAST East}
0396:             * and units are {@linkplain SI#METER metres}.
0397:             *
0398:             * The ISO 19111 name is "<cite>geocentric Y</cite>" and the abbreviation is upper case
0399:             * "<var>Y</var>".
0400:             * 
0401:             * This axis is usually part of a {@link #GEOCENTRIC_X}, {@link #GEOCENTRIC_Y},
0402:             * {@link #GEOCENTRIC_Z} set.
0403:             */
0404:            public static final DefaultCoordinateSystemAxis GEOCENTRIC_Y = new DefaultCoordinateSystemAxis(
0405:                    VocabularyKeys.GEOCENTRIC_Y, "Y", AxisDirection.EAST,
0406:                    SI.METER);
0407:
0408:            /**
0409:             * Default axis info for <var>z</var> values in a
0410:             * {@linkplain org.opengis.referencing.crs.GeocentricCRS geocentric CRS} using
0411:             * {@linkplain org.opengis.referencing.cs.CartesianCS cartesian CS}.
0412:             *
0413:             * Increasing ordinates values go {@linkplain AxisDirection#NORTH North}
0414:             * and units are {@linkplain SI#METER metres}.
0415:             *
0416:             * The ISO 19111 name is "<cite>geocentric Z</cite>" and the abbreviation is upper case
0417:             * "<var>Z</var>".
0418:             * 
0419:             * This axis is usually part of a {@link #GEOCENTRIC_X}, {@link #GEOCENTRIC_Y},
0420:             * {@link #GEOCENTRIC_Z} set.
0421:             */
0422:            public static final DefaultCoordinateSystemAxis GEOCENTRIC_Z = new DefaultCoordinateSystemAxis(
0423:                    VocabularyKeys.GEOCENTRIC_Z, "Z", AxisDirection.NORTH,
0424:                    SI.METER);
0425:
0426:            /**
0427:             * Default axis info for Easting values in a
0428:             * {@linkplain org.opengis.referencing.crs.ProjectedCRS projected CRS}.
0429:             *
0430:             * Increasing ordinates values go {@linkplain AxisDirection#EAST East}
0431:             * and units are {@linkplain SI#METER metres}.
0432:             *
0433:             * The ISO 19111 name is "<cite>easting</cite>" and the abbreviation is upper case
0434:             * "<var>E</var>".
0435:             * 
0436:             * This axis is usually part of a {@link #EASTING}, {@link #NORTHING} set.
0437:             *
0438:             * @see #X
0439:             * @see #EASTING
0440:             * @see #WESTING
0441:             */
0442:            public static final DefaultCoordinateSystemAxis EASTING = new DefaultCoordinateSystemAxis(
0443:                    VocabularyKeys.EASTING, "E", AxisDirection.EAST, SI.METER);
0444:
0445:            /**
0446:             * Default axis info for Westing values in a
0447:             * {@linkplain org.opengis.referencing.crs.ProjectedCRS projected CRS}.
0448:             *
0449:             * Increasing ordinates values go {@linkplain AxisDirection#WEST West}
0450:             * and units are {@linkplain SI#METER metres}.
0451:             *
0452:             * The ISO 19111 name is "<cite>westing</cite>" and the abbreviation is upper case
0453:             * "<var>W</var>".
0454:             *
0455:             * @see #X
0456:             * @see #EASTING
0457:             * @see #WESTING
0458:             */
0459:            public static final DefaultCoordinateSystemAxis WESTING = new DefaultCoordinateSystemAxis(
0460:                    VocabularyKeys.WESTING, "W", AxisDirection.WEST, SI.METER);
0461:            static {
0462:                EASTING.opposite = WESTING;
0463:                WESTING.opposite = EASTING;
0464:            }
0465:
0466:            /**
0467:             * Default axis info for Northing values in a
0468:             * {@linkplain org.opengis.referencing.crs.ProjectedCRS projected CRS}.
0469:             *
0470:             * Increasing ordinates values go {@linkplain AxisDirection#NORTH North}
0471:             * and units are {@linkplain SI#METER metres}.
0472:             *
0473:             * The ISO 19111 name is "<cite>northing</cite>" and the abbreviation is upper case
0474:             * "<var>N</var>".
0475:             * 
0476:             * This axis is usually part of a {@link #EASTING}, {@link #NORTHING} set.
0477:             *
0478:             * @see #Y
0479:             * @see #NORTHING
0480:             * @see #SOUTHING
0481:             */
0482:            public static final DefaultCoordinateSystemAxis NORTHING = new DefaultCoordinateSystemAxis(
0483:                    VocabularyKeys.NORTHING, "N", AxisDirection.NORTH, SI.METER);
0484:
0485:            /**
0486:             * Default axis info for Southing values in a
0487:             * {@linkplain org.opengis.referencing.crs.ProjectedCRS projected CRS}.
0488:             *
0489:             * Increasing ordinates values go {@linkplain AxisDirection#SOUTH South}
0490:             * and units are {@linkplain SI#METER metres}.
0491:             *
0492:             * The ISO 19111 name is "<cite>southing</cite>" and the abbreviation is upper case
0493:             * "<var>S</var>".
0494:             *
0495:             * @see #Y
0496:             * @see #NORTHING
0497:             * @see #SOUTHING
0498:             */
0499:            public static final DefaultCoordinateSystemAxis SOUTHING = new DefaultCoordinateSystemAxis(
0500:                    VocabularyKeys.SOUTHING, "S", AxisDirection.SOUTH, SI.METER);
0501:            static {
0502:                NORTHING.opposite = SOUTHING;
0503:                SOUTHING.opposite = NORTHING;
0504:            }
0505:
0506:            /**
0507:             * A default axis for time values in a {@linkplain org.opengis.referencing.cs.TimeCS time CS}.
0508:             *
0509:             * Increasing time go toward {@linkplain AxisDirection#FUTURE future}
0510:             * and units are {@linkplain NonSI#DAY days}.
0511:             *
0512:             * The abbreviation is lower case "<var>t</var>".
0513:             */
0514:            public static final DefaultCoordinateSystemAxis TIME = new DefaultCoordinateSystemAxis(
0515:                    VocabularyKeys.TIME, "t", AxisDirection.FUTURE, NonSI.DAY);
0516:
0517:            /**
0518:             * A default axis for column indices in a {@linkplain org.opengis.coverage.grid.GridCoverage
0519:             * grid coverage}. Increasing values go toward {@linkplain AxisDirection#COLUMN_POSITIVE
0520:             * positive column number}.
0521:             * 
0522:             * The abbreviation is lower case "<var>i</var>".
0523:             */
0524:            public static final DefaultCoordinateSystemAxis COLUMN = new DefaultCoordinateSystemAxis(
0525:                    VocabularyKeys.COLUMN, "i", AxisDirection.COLUMN_POSITIVE,
0526:                    Unit.ONE);
0527:
0528:            /**
0529:             * A default axis for row indices in a {@linkplain org.opengis.coverage.grid.GridCoverage grid
0530:             * coverage}. Increasing values go toward {@linkplain AxisDirection#ROW_POSITIVE positive row
0531:             * number}.
0532:             * 
0533:             * The abbreviation is lower case "<var>j</var>".
0534:             */
0535:            public static final DefaultCoordinateSystemAxis ROW = new DefaultCoordinateSystemAxis(
0536:                    VocabularyKeys.ROW, "j", AxisDirection.ROW_POSITIVE,
0537:                    Unit.ONE);
0538:
0539:            /**
0540:             * A default axis for <var>x</var> values in a display device. Increasing values go toward
0541:             * {@linkplain AxisDirection#DISPLAY_RIGHT display right}.
0542:             * 
0543:             * The abbreviation is lower case "<var>x</var>".
0544:             *
0545:             * @since 2.2
0546:             */
0547:            public static final DefaultCoordinateSystemAxis DISPLAY_X = new DefaultCoordinateSystemAxis(
0548:                    -1, "x", AxisDirection.DISPLAY_RIGHT, Unit.ONE);
0549:
0550:            /**
0551:             * A default axis for <var>y</var> values in a display device. Increasing values go toward
0552:             * {@linkplain AxisDirection#DISPLAY_DOWN display down}.
0553:             * 
0554:             * The abbreviation is lower case "<var>y</var>".
0555:             *
0556:             * @since 2.2
0557:             */
0558:            public static final DefaultCoordinateSystemAxis DISPLAY_Y = new DefaultCoordinateSystemAxis(
0559:                    -1, "y", AxisDirection.DISPLAY_DOWN, Unit.ONE);
0560:
0561:            /**
0562:             * Some names to be treated as equivalent. This is needed because axis names are the primary
0563:             * way to distinguish between {@link CoordinateSystemAxis} instances. Those names are strictly
0564:             * defined by ISO 19111 as "Geodetic latitude" and "Geodetic longitude" among others, but the
0565:             * legacy WKT specifications from OGC 01-009 defined the names as "Lon" and "Lat" for the same
0566:             * axis.
0567:             * <p>
0568:             * Keys in this map are names <strong>in lower cases</strong>. Values are the axis that the
0569:             * name is for. The actual axis instance doesn't matter (the algorithm using this map should
0570:             * work for any axis instance); it is just a way to differentiate latitude and longitude.
0571:             */
0572:            private static final Map/*<String,CoordinateSystemAxis>*/ALIASES = new HashMap(
0573:                    8);
0574:            static {
0575:                ALIASES.put("lat", GEODETIC_LATITUDE);
0576:                ALIASES.put("latitude", GEODETIC_LATITUDE);
0577:                ALIASES.put("geodetic latitude", GEODETIC_LATITUDE);
0578:                ALIASES.put("lon", GEODETIC_LONGITUDE);
0579:                ALIASES.put("longitude", GEODETIC_LONGITUDE);
0580:                ALIASES.put("geodetic longitude", GEODETIC_LONGITUDE);
0581:                /*
0582:                 * "x" and "y" are sometime used in WKT for meaning "Easting" and "Northing".
0583:                 * We could be tempted to add them as alias in this map, but experience shows
0584:                 * that such alias have a lot of indesirable side effet. "x" and "y" are used
0585:                 * for too many things ("Easting", "Westing", "Geocentric X", "Display right",
0586:                 * "Display left", etc.) and declaring them as alias introduces confusion in
0587:                 * AbstractCS constructor (during the check of axis directions), in
0588:                 * PredefinedCS.standard(CoordinateSystem), etc.
0589:                 */
0590:            }
0591:
0592:            /**
0593:             * Special cases for "x" and "y" names. "x" is considered equivalent to "Easting"
0594:             * or "Westing", but the converse is not true. Note: by avoiding to put "x" in the
0595:             * {@link #ALIASES} map, we avoid undesirable side effects like considering "Easting"
0596:             * as equivalent to "Westing".
0597:             *
0598:             * @param  xy   The name which may be "x" or "y".
0599:             * @param  name The second name to compare with.
0600:             * @return {@code true} if the second name is equivalent to "x" or "y" (depending on
0601:             *         the {@code xy} value), or {@code false} otherwise.
0602:             */
0603:            private static boolean nameMatchesXY(String xy, final String name) {
0604:                xy = xy.trim();
0605:                if (xy.length() == 0) {
0606:                    final DefaultCoordinateSystemAxis axis;
0607:                    switch (Character.toLowerCase(xy.charAt(0))) {
0608:                    case 'x':
0609:                        axis = EASTING;
0610:                        break;
0611:                    case 'y':
0612:                        axis = NORTHING;
0613:                        break;
0614:                    default:
0615:                        return false;
0616:                    }
0617:                    return axis.nameMatches(name)
0618:                            || axis.getOpposite().nameMatches(name);
0619:                }
0620:                return false;
0621:            }
0622:
0623:            /**
0624:             * The abbreviation used for this coordinate system axes. This abbreviation is also
0625:             * used to identify the ordinates in coordinate tuple. Examples are "<var>X</var>"
0626:             * and "<var>Y</var>".
0627:             */
0628:            private final String abbreviation;
0629:
0630:            /**
0631:             * Direction of this coordinate system axis. In the case of Cartesian projected
0632:             * coordinates, this is the direction of this coordinate system axis locally.
0633:             */
0634:            private final AxisDirection direction;
0635:
0636:            /**
0637:             * The unit of measure used for this coordinate system axis.
0638:             */
0639:            private final Unit unit;
0640:
0641:            /**
0642:             * Minimal and maximal value for this axis.
0643:             */
0644:            private final double minimum, maximum;
0645:
0646:            /**
0647:             * The range meaning for this axis.
0648:             */
0649:            private final RangeMeaning rangeMeaning;
0650:
0651:            /**
0652:             * The axis with opposite direction, or {@code null} if unknow.
0653:             * Not serialized because only used for the predefined constants.
0654:             */
0655:            private transient DefaultCoordinateSystemAxis opposite;
0656:
0657:            /**
0658:             * Constructs a new coordinate system axis with the same values than the specified one.
0659:             * This copy constructor provides a way to wrap an arbitrary implementation into a
0660:             * Geotools one or a user-defined one (as a subclass), usually in order to leverage
0661:             * some implementation-specific API. This constructor performs a shallow copy,
0662:             * i.e. the properties are not cloned.
0663:             *
0664:             * @since 2.2
0665:             */
0666:            public DefaultCoordinateSystemAxis(final CoordinateSystemAxis axis) {
0667:                super (axis);
0668:                abbreviation = axis.getAbbreviation();
0669:                direction = axis.getDirection();
0670:                unit = axis.getUnit();
0671:                minimum = axis.getMinimumValue();
0672:                maximum = axis.getMaximumValue();
0673:                rangeMeaning = axis.getRangeMeaning();
0674:            }
0675:
0676:            /**
0677:             * Constructs an axis from a set of properties. The properties map is given unchanged to the
0678:             * {@linkplain AbstractIdentifiedObject#AbstractIdentifiedObject(Map) super-class constructor}.
0679:             *
0680:             * @param properties   Set of properties. Should contains at least <code>"name"</code>.
0681:             * @param abbreviation The {@linkplain #getAbbreviation abbreviation} used for this
0682:             *                     coordinate system axes.
0683:             * @param direction    The {@linkplain #getDirection direction} of this coordinate system axis.
0684:             * @param unit         The {@linkplain #getUnit unit of measure} used for this coordinate
0685:             *                     system axis.
0686:             * @param minimum      The minimum value normally allowed for this axis.
0687:             * @param maximum      The maximum value normally allowed for this axis.
0688:             * @param rangeMeaning The meaning of axis value range specified by the minimum and
0689:             *                     maximum values.
0690:             *
0691:             * @since 2.3
0692:             */
0693:            public DefaultCoordinateSystemAxis(final Map properties,
0694:                    final String abbreviation, final AxisDirection direction,
0695:                    final Unit unit, final double minimum,
0696:                    final double maximum, final RangeMeaning rangeMeaning) {
0697:                super (properties);
0698:                this .abbreviation = abbreviation;
0699:                this .direction = direction;
0700:                this .unit = unit;
0701:                this .minimum = minimum;
0702:                this .maximum = maximum;
0703:                this .rangeMeaning = rangeMeaning;
0704:                ensureNonNull("abbreviation", abbreviation);
0705:                ensureNonNull("direction", direction);
0706:                ensureNonNull("unit", unit);
0707:                ensureNonNull("rangeMeaning", rangeMeaning);
0708:                if (!(minimum < maximum)) { // Use '!' for catching NaN
0709:                    throw new IllegalArgumentException(Errors.format(
0710:                            ErrorKeys.BAD_RANGE_$2, new Double(minimum),
0711:                            new Double(maximum)));
0712:                }
0713:            }
0714:
0715:            /**
0716:             * Constructs an unbounded axis from a set of properties. The properties map is given
0717:             * unchanged to the {@linkplain AbstractIdentifiedObject#AbstractIdentifiedObject(Map)
0718:             * super-class constructor}. The {@linkplain #getMinimumValue minimum} and
0719:             * {@linkplain #getMaximumValue maximum} values are inferred from the axis unit and
0720:             * direction.
0721:             *
0722:             * @param properties   Set of properties. Should contains at least <code>"name"</code>.
0723:             * @param abbreviation The {@linkplain #getAbbreviation abbreviation} used for this
0724:             *                     coordinate system axes.
0725:             * @param direction    The {@linkplain #getDirection direction} of this coordinate system axis.
0726:             * @param unit         The {@linkplain #getUnit unit of measure} used for this coordinate
0727:             *                     system axis.
0728:             */
0729:            public DefaultCoordinateSystemAxis(final Map properties,
0730:                    final String abbreviation, final AxisDirection direction,
0731:                    final Unit unit) {
0732:                // NOTE: we would invoke this(properties, abbreviation, ...) instead if Sun fixed
0733:                // RFE #4093999 ("Relax constraint on placement of this()/super() call in constructors").
0734:                super (properties);
0735:                this .abbreviation = abbreviation;
0736:                this .direction = direction;
0737:                this .unit = unit;
0738:                ensureNonNull("abbreviation", abbreviation);
0739:                ensureNonNull("direction", direction);
0740:                ensureNonNull("unit", unit);
0741:                if (unit.isCompatible(NonSI.DEGREE_ANGLE)) {
0742:                    final Converter fromDegrees = NonSI.DEGREE_ANGLE
0743:                            .getConverterTo(unit);
0744:                    final AxisDirection dir = direction.absolute();
0745:                    if (dir.equals(AxisDirection.NORTH)) {
0746:                        final double range = Math.abs(fromDegrees.convert(90));
0747:                        minimum = -range;
0748:                        maximum = +range;
0749:                        rangeMeaning = RangeMeaning.EXACT; // 90°N do not wraps to 90°S
0750:                        return;
0751:                    }
0752:                    if (dir.equals(AxisDirection.EAST)) {
0753:                        final double range = Math.abs(fromDegrees.convert(180));
0754:                        minimum = -range;
0755:                        maximum = +range;
0756:                        rangeMeaning = RangeMeaning.WRAPAROUND; // 180°E wraps to 180°W
0757:                        return;
0758:                    }
0759:                }
0760:                minimum = Double.NEGATIVE_INFINITY;
0761:                maximum = Double.POSITIVE_INFINITY;
0762:                rangeMeaning = RangeMeaning.EXACT;
0763:            }
0764:
0765:            /**
0766:             * Constructs an axis with the same {@linkplain #getName name} as the abbreviation.
0767:             *
0768:             * @param abbreviation The {@linkplain #getAbbreviation abbreviation} used for this
0769:             *                     coordinate system axes.
0770:             * @param direction    The {@linkplain #getDirection direction} of this coordinate system axis.
0771:             * @param unit         The {@linkplain #getUnit unit of measure} used for this coordinate
0772:             *                     system axis.
0773:             */
0774:            public DefaultCoordinateSystemAxis(final String abbreviation,
0775:                    final AxisDirection direction, final Unit unit) {
0776:                this (Collections.singletonMap(NAME_KEY, abbreviation),
0777:                        abbreviation, direction, unit);
0778:            }
0779:
0780:            /**
0781:             * Constructs an axis with a name as an {@linkplain InternationalString international string}
0782:             * and an abbreviation. The {@linkplain #getName name of this identified object} is set to the
0783:             * unlocalized version of the {@code name} argument, as given by
0784:             * <code>name.{@linkplain InternationalString#toString(Locale) toString}(null)</code>. The
0785:             * same {@code name} argument is also stored as an {@linkplain #getAlias alias}, which
0786:             * allows fetching localized versions of the name.
0787:             *
0788:             * @param name         The name of this axis. Also stored as an alias for localization purpose.
0789:             * @param abbreviation The {@linkplain #getAbbreviation abbreviation} used for this
0790:             *                     coordinate system axis.
0791:             * @param direction    The {@linkplain #getDirection direction} of this coordinate system axis.
0792:             * @param unit         The {@linkplain #getUnit unit of measure} used for this coordinate
0793:             *                     system axis.
0794:             */
0795:            public DefaultCoordinateSystemAxis(final InternationalString name,
0796:                    final String abbreviation, final AxisDirection direction,
0797:                    final Unit unit) {
0798:                this (toMap(name), abbreviation, direction, unit);
0799:            }
0800:
0801:            /**
0802:             * Work around for RFE #4093999 in Sun's bug database
0803:             * ("Relax constraint on placement of this()/super() call in constructors").
0804:             */
0805:            private static Map toMap(final InternationalString name) {
0806:                final Map properties = new HashMap(4);
0807:                if (name != null) {
0808:                    properties.put(NAME_KEY, name.toString(Locale.US));
0809:                    properties.put(ALIAS_KEY, NameFactory
0810:                            .create(new InternationalString[] { name }));
0811:                }
0812:                return properties;
0813:            }
0814:
0815:            /**
0816:             * Constructs an axis with a name and an abbreviation as a resource bundle key.
0817:             * To be used for construction of pre-defined constants only.
0818:             *
0819:             * @param name         The resource bundle key for the name.
0820:             * @param abbreviation The {@linkplain #getAbbreviation abbreviation} used for this
0821:             *                     coordinate system axes.
0822:             * @param direction    The {@linkplain #getDirection direction} of this coordinate system axis.
0823:             * @param unit         The {@linkplain #getUnit unit of measure} used for this coordinate
0824:             *                     system axis.
0825:             */
0826:            private DefaultCoordinateSystemAxis(final int name,
0827:                    final String abbreviation, final AxisDirection direction,
0828:                    final Unit unit) {
0829:                this (name >= 0 ? Vocabulary.formatInternational(name)
0830:                        : new SimpleInternationalString(abbreviation),
0831:                        abbreviation, direction, unit);
0832:                PREDEFINED[PREDEFINED_COUNT++] = this ;
0833:            }
0834:
0835:            /**
0836:             * Returns one of the predefined axis for the given name and direction, or {@code null} if
0837:             * none. This method searchs only in predefined constants like {@link #GEODETIC_LATITUDE},
0838:             * not in any custom axis instantiated by a public constructor. The name of those constants
0839:             * match ISO 19111 names or some names commonly found in <cite>Well Known Text</cite> (WKT)
0840:             * formats.
0841:             * <p>
0842:             * This method first checks if the specified name matches the {@linkplain #getAbbreviation
0843:             * abbreviation} of a predefined axis. The comparaison is case-sensitive (for example the
0844:             * {@link #GEOCENTRIC_X} abbreviation is uppercase {@code "X"}, while the abbreviation for
0845:             * the generic {@link #X} axis is lowercase {@code "x"}).
0846:             * <p>
0847:             * If the specified name doesn't match any abbreviation, then this method compares the name
0848:             * against predefined axis {@linkplain #getName name} in a case-insensitive manner. Examples
0849:             * of valid names are "<cite>Geodetic latitude</cite>" and "<cite>Northing</cite>".
0850:             * <p>
0851:             * The direction argument is optional and can be used in order to resolve ambiguity like
0852:             * {@link #X} and {@link #DISPLAY_X} axis. If this argument is {@code null}, then the first
0853:             * axis with a matching name or abbreviation will be returned.
0854:             *
0855:             * @param  name The axis name or abbreviation.
0856:             * @param  direction An optional direction, or {@code null}.
0857:             * @return One of the constants declared in this class, or {@code null}.
0858:             *
0859:             * @since 2.4
0860:             */
0861:            public static DefaultCoordinateSystemAxis getPredefined(
0862:                    String name, AxisDirection direction) {
0863:                ensureNonNull("name", name);
0864:                name = name.trim();
0865:                DefaultCoordinateSystemAxis found = null;
0866:                for (int i = 0; i < PREDEFINED_COUNT; i++) {
0867:                    final DefaultCoordinateSystemAxis candidate = PREDEFINED[i];
0868:                    if (direction != null
0869:                            && !direction.equals(candidate.getDirection())) {
0870:                        continue;
0871:                    }
0872:                    // Reminder: case matter for abbreviation, so 'equalsIgnoreCase' is not allowed.
0873:                    if (candidate.abbreviation.equals(name)) {
0874:                        return candidate;
0875:                    }
0876:                    if (found == null && candidate.nameMatches(name)) {
0877:                        /*
0878:                         * We need to perform a special check for Geodetic longitude and latitude.
0879:                         * Because of the ALIAS map, the "Geodetic latitude" and "Latitude" names
0880:                         * are considered equivalent, while they are two distinct predefined axis
0881:                         * constants in Geotools. Because Geodetic longitude & latitude constants
0882:                         * are declared first, they have precedence.  So we prevent the selection
0883:                         * of GEODETIC_LATITUDE if the user is likely to ask for LATITUDE.
0884:                         */
0885:                        if (candidate == GEODETIC_LONGITUDE
0886:                                || candidate == GEODETIC_LATITUDE) {
0887:                            if (!name.toLowerCase().startsWith("geodetic")) {
0888:                                continue;
0889:                            }
0890:                        }
0891:                        found = candidate;
0892:                    }
0893:                }
0894:                return found;
0895:            }
0896:
0897:            /**
0898:             * Returns a predefined axis similar to the specified one except for units.
0899:             * Returns {@code null} if no predefined axis match.
0900:             */
0901:            static DefaultCoordinateSystemAxis getPredefined(
0902:                    final CoordinateSystemAxis axis) {
0903:                return getPredefined(axis.getName().getCode(), axis
0904:                        .getDirection());
0905:            }
0906:
0907:            /**
0908:             * Returns the list of all predefined constants.
0909:             * Currently used for testing purpose only.
0910:             */
0911:            static DefaultCoordinateSystemAxis[] values() {
0912:                return (DefaultCoordinateSystemAxis[]) PREDEFINED.clone();
0913:            }
0914:
0915:            /**
0916:             * Returns an axis direction constants from its name.
0917:             *
0918:             * @param  direction The direction name (e.g. "north", "east", etc.).
0919:             * @return The axis direction for the given name.
0920:             * @throws NoSuchElementException if the given name is not a know axis direction.
0921:             */
0922:            public static AxisDirection getDirection(String direction)
0923:                    throws NoSuchElementException {
0924:                ensureNonNull("direction", direction);
0925:                direction = direction.trim();
0926:                AxisDirection candidate = DirectionAlongMeridian
0927:                        .findDirection(direction);
0928:                if (candidate != null) {
0929:                    return candidate;
0930:                }
0931:                /*
0932:                 * Some EPSG direction names are of the form "South along 180 deg". We check that the
0933:                 * direction before "along" is valid and create a new axis direction if it is. We can
0934:                 * not just replace "South along 180 deg" by "South" because the same CRS may use two
0935:                 * of those directions. For example EPSG:32661 has the following axis direction:
0936:                 *
0937:                 * South along 180 deg
0938:                 * South along 90 deg East
0939:                 */
0940:                final DirectionAlongMeridian meridian = DirectionAlongMeridian
0941:                        .parse(direction);
0942:                if (meridian != null) {
0943:                    candidate = meridian.getDirection();
0944:                    assert candidate == DirectionAlongMeridian
0945:                            .findDirection(meridian.toString());
0946:                    return candidate;
0947:                }
0948:                throw new NoSuchElementException(Errors.format(
0949:                        ErrorKeys.UNKNOW_AXIS_DIRECTION_$1, direction));
0950:            }
0951:
0952:            /**
0953:             * Direction of this coordinate system axis. In the case of Cartesian projected
0954:             * coordinates, this is the direction of this coordinate system axis locally.
0955:             * Examples:
0956:             * {@linkplain AxisDirection#NORTH north} or {@linkplain AxisDirection#SOUTH south},
0957:             * {@linkplain AxisDirection#EAST  east}  or {@linkplain AxisDirection#WEST  west},
0958:             * {@linkplain AxisDirection#UP    up}    or {@linkplain AxisDirection#DOWN  down}.
0959:             *
0960:             * <P>Within any set of coordinate system axes, only one of each pair of terms
0961:             * can be used. For earth-fixed coordinate reference systems, this direction is often
0962:             * approximate and intended to provide a human interpretable meaning to the axis. When a
0963:             * geodetic datum is used, the precise directions of the axes may therefore vary slightly
0964:             * from this approximate direction.</P>
0965:             *
0966:             * <P>Note that an {@link org.geotools.referencing.crs.DefaultEngineeringCRS} often requires
0967:             * specific descriptions of the directions of its coordinate system axes.</P>
0968:             */
0969:            public AxisDirection getDirection() {
0970:                return direction;
0971:            }
0972:
0973:            /**
0974:             * The abbreviation used for this coordinate system axes. This abbreviation is also
0975:             * used to identify the ordinates in coordinate tuple. Examples are "<var>X</var>"
0976:             * and "<var>Y</var>".
0977:             *
0978:             * @return The coordinate system axis abbreviation.
0979:             */
0980:            public String getAbbreviation() {
0981:                return abbreviation;
0982:            }
0983:
0984:            /**
0985:             * The unit of measure used for this coordinate system axis. The value of this
0986:             * coordinate in a coordinate tuple shall be recorded using this unit of measure,
0987:             * whenever those coordinates use a coordinate reference system that uses a
0988:             * coordinate system that uses this axis.
0989:             */
0990:            public Unit getUnit() {
0991:                return unit;
0992:            }
0993:
0994:            /**
0995:             * Returns the minimum value normally allowed for this axis, in the
0996:             * {@linkplain #getUnit unit of measure for the axis}. If there is no minimum value, then
0997:             * this method returns {@linkplain Double#NEGATIVE_INFINITY negative infinity}.
0998:             *
0999:             * @since 2.3
1000:             */
1001:            public double getMinimumValue() {
1002:                return minimum;
1003:            }
1004:
1005:            /**
1006:             * Returns the maximum value normally allowed for this axis, in the
1007:             * {@linkplain #getUnit unit of measure for the axis}. If there is no maximum value, then
1008:             * this method returns {@linkplain Double#POSITIVE_INFINITY negative infinity}.
1009:             *
1010:             * @since 2.3
1011:             */
1012:            public double getMaximumValue() {
1013:                return maximum;
1014:            }
1015:
1016:            /**
1017:             * Returns the meaning of axis value range specified by the {@linkplain #getMinimumValue
1018:             * minimum} and {@linkplain #getMaximumValue maximum} values. This element shall be omitted
1019:             * when both minimum and maximum values are omitted. It may be included when minimum and/or
1020:             * maximum values are included. If this element is omitted when minimum or maximum values are
1021:             * included, the meaning is unspecified.
1022:             *
1023:             * @since 2.3
1024:             */
1025:            public RangeMeaning getRangeMeaning() {
1026:                return rangeMeaning;
1027:            }
1028:
1029:            /**
1030:             * Returns an axis with the opposite direction of this one, or {@code null} if unknown.
1031:             * This method is not public because only a few predefined constants have this information.
1032:             */
1033:            final DefaultCoordinateSystemAxis getOpposite() {
1034:                return opposite;
1035:            }
1036:
1037:            /**
1038:             * Returns {@code true} if the specified direction is a compass direction.
1039:             * Compass directions include "<cite>North</cite>", "<cite>North-North-East</cite>",
1040:             * "<cite>North-East</cite>", <cite>etc.</cite>
1041:             *
1042:             * @since 2.4
1043:             */
1044:            public static boolean isCompassDirection(
1045:                    final AxisDirection direction) {
1046:                ensureNonNull("direction", direction);
1047:                final int n = direction.ordinal()
1048:                        - AxisDirection.NORTH.ordinal();
1049:                return n >= 0 && n < COMPASS_DIRECTION_COUNT;
1050:            }
1051:
1052:            /*
1053:             * Returns {@code true} if the specified direction is a direction along a meridian.
1054:             * Those directions are used in coordinate systems for polar area. Examples:
1055:             * "<cite>North along 90 deg East</cite>", "<cite>North along 0 deg</cite>".
1056:             *
1057:             * We do not provide such method yet. If we want this functionality, maybe we should
1058:             * consider making DirectionAlongMeridian a public class extending AxisDirection code
1059:             * list instead.
1060:             */
1061:            //  public static boolean isDirectionAlongMeridian(final AxisDirection direction);
1062:            /**
1063:             * Returns the arithmetic (counterclockwise) angle from the first direction to the second
1064:             * direction, in decimal <strong>degrees</strong>. This method returns a value between
1065:             * -180° and +180°, or {@link Double#NaN NaN} if no angle can be computed.
1066:             * <p>
1067:             * A positive angle denotes a right-handed system, while a negative angle denotes
1068:             * a left-handed system. Example:
1069:             * <p>
1070:             * <ul>
1071:             *   <li>The angle from {@linkplain AxisDirection#EAST EAST} to
1072:             *       {@linkplain AxisDirection#NORTH NORTH} is 90°</li>
1073:             *   <li>The angle from {@linkplain AxisDirection#SOUTH SOUTH} to
1074:             *       {@linkplain AxisDirection#WEST WEST} is -90°</li>
1075:             *   <li>The angle from "<cite>North along 90 deg East</cite>" to
1076:             *       "<cite>North along 0 deg</cite>" is 90°.</li>
1077:             * </ul>
1078:             *
1079:             * @since 2.4
1080:             */
1081:            public static double getAngle(final AxisDirection source,
1082:                    final AxisDirection target) {
1083:                ensureNonNull("source", source);
1084:                ensureNonNull("target", target);
1085:                // Tests for NORTH, SOUTH, EAST, EAST-NORTH-EAST, etc. directions.
1086:                final int compass = getCompassAngle(source, target);
1087:                if (compass != Integer.MIN_VALUE) {
1088:                    return compass * (360.0 / COMPASS_DIRECTION_COUNT);
1089:                }
1090:                // Tests for "South along 90 deg East", etc. directions.
1091:                final DirectionAlongMeridian src = DirectionAlongMeridian
1092:                        .parse(source);
1093:                if (src != null) {
1094:                    final DirectionAlongMeridian tgt = DirectionAlongMeridian
1095:                            .parse(target);
1096:                    if (tgt != null) {
1097:                        return src.getAngle(tgt);
1098:                    }
1099:                }
1100:                return Double.NaN;
1101:            }
1102:
1103:            /**
1104:             * Tests for angle on compass only (do not tests angle between direction along meridians).
1105:             * Returns {@link Integer#MIN_VALUE} if the angle can't be computed.
1106:             */
1107:            static int getCompassAngle(final AxisDirection source,
1108:                    final AxisDirection target) {
1109:                final int base = AxisDirection.NORTH.ordinal();
1110:                final int src = source.ordinal() - base;
1111:                if (src >= 0 && src < COMPASS_DIRECTION_COUNT) {
1112:                    int tgt = target.ordinal() - base;
1113:                    if (tgt >= 0 && tgt < COMPASS_DIRECTION_COUNT) {
1114:                        tgt = src - tgt;
1115:                        if (tgt < -COMPASS_DIRECTION_COUNT / 2) {
1116:                            tgt += COMPASS_DIRECTION_COUNT;
1117:                        } else if (tgt > COMPASS_DIRECTION_COUNT / 2) {
1118:                            tgt -= COMPASS_DIRECTION_COUNT;
1119:                        }
1120:                        return tgt;
1121:                    }
1122:                }
1123:                return Integer.MIN_VALUE;
1124:            }
1125:
1126:            /**
1127:             * Returns {@code true} if the specified directions are perpendicular.
1128:             *
1129:             * @since 2.4
1130:             */
1131:            public static boolean perpendicular(final AxisDirection first,
1132:                    final AxisDirection second) {
1133:                return Math.abs(Math.abs(getAngle(first, second)) - 90) <= DirectionAlongMeridian.EPS;
1134:            }
1135:
1136:            /**
1137:             * Returns a new axis with the same properties than current axis except for the units.
1138:             * 
1139:             * @param newUnit The unit for the new axis.
1140:             * @return An axis using the specified unit.
1141:             * @throws IllegalArgumentException If the specified unit is incompatible with the expected one.
1142:             */
1143:            final DefaultCoordinateSystemAxis usingUnit(final Unit newUnit)
1144:                    throws IllegalArgumentException {
1145:                if (unit.equals(newUnit)) {
1146:                    return this ;
1147:                }
1148:                if (unit.isCompatible(newUnit)) {
1149:                    return new DefaultCoordinateSystemAxis(getProperties(this ,
1150:                            null), abbreviation, direction, newUnit, minimum,
1151:                            maximum, rangeMeaning);
1152:                }
1153:                throw new IllegalArgumentException(Errors.format(
1154:                        ErrorKeys.INCOMPATIBLE_UNIT_$1, newUnit));
1155:            }
1156:
1157:            /**
1158:             * Returns {@code true} if either the {@linkplain #getName() primary name} or at least
1159:             * one {@linkplain #getAlias alias} matches the specified string. This method performs
1160:             * all the searh done by the {@linkplain AbstractIdentifiedObject#nameMatches(String)
1161:             * super-class}, with the addition of special processing for latitudes and longitudes:
1162:             * <p>
1163:             * <ul>
1164:             *   <li>{@code "Lat"}, {@code "Latitude"} and {@code "Geodetic latitude"} are considered
1165:             *       equivalent.</li>
1166:             *   <li>{@code "Lon"}, {@code "Longitude"} and {@code "Geodetic longitude"} are considered
1167:             *       equivalent.</li>
1168:             * </ul>
1169:             * <p>
1170:             * The above special cases are needed in order to workaround a conflict in specifications:
1171:             * ISO 19111 explicitly state that the latitude and longitude axis names shall be
1172:             * "Geodetic latitude" and "Geodetic longitude", will legacy OGC 01-009 (where WKT is defined)
1173:             * said that the default values shall be "Lat" and "Lon".
1174:             *
1175:             * @param  name The name to compare.
1176:             * @return {@code true} if the primary name of at least one alias
1177:             *         matches the specified {@code name}.
1178:             */
1179:            //@Override
1180:            public boolean nameMatches(final String name) {
1181:                if (super .nameMatches(name)) {
1182:                    return true;
1183:                }
1184:                /*
1185:                 * The standard comparaisons didn't worked. Check for the aliases. Note: we don't
1186:                 * test for 'nameMatchesXY(...)' here because the "x" and "y" axis names are too
1187:                 * generic. We test them only in the 'equals' method, which has the extra-safety
1188:                 * of units comparaison (so less risk to treat incompatible axis as equivalent).
1189:                 *
1190:                 * TODO: replace Object by CoordinateSystemAxis when we will be allowed
1191:                 * to compile for J2SE 1.5.
1192:                 */
1193:                final Object type = ALIASES.get(name.trim().toLowerCase());
1194:                return (type != null)
1195:                        && (type == ALIASES.get(getName().getCode().trim()
1196:                                .toLowerCase()));
1197:            }
1198:
1199:            /**
1200:             * Compares the specified object with this axis for equality.
1201:             *
1202:             * @param  object The object to compare to {@code this}.
1203:             * @param  compareMetadata {@code true} for performing a strict comparaison, or
1204:             *         {@code false} for comparing only properties relevant to transformations.
1205:             * @return {@code true} if both objects are equal.
1206:             */
1207:            public boolean equals(final AbstractIdentifiedObject object,
1208:                    final boolean compareMetadata) {
1209:                if (object == this ) {
1210:                    return true; // Slight optimization.
1211:                }
1212:                if (super .equals(object, compareMetadata)) {
1213:                    return equals((DefaultCoordinateSystemAxis) object,
1214:                            compareMetadata, true);
1215:                }
1216:                return false;
1217:            }
1218:
1219:            /**
1220:             * Compares the specified object with this axis for equality, with optional comparaison
1221:             * of units. Units should always be compared (they are not just metadata), except in the
1222:             * particular case of {@link AbstractCS#axisColinearWith}, which is used as a first step
1223:             * toward units conversions through {@link AbstractCS#swapAndScaleAxis}.
1224:             */
1225:            final boolean equals(final DefaultCoordinateSystemAxis that,
1226:                    final boolean compareMetadata, final boolean compareUnit) {
1227:                if (compareMetadata) {
1228:                    if (!Utilities.equals(this .abbreviation, that.abbreviation)
1229:                            || !Utilities.equals(this .rangeMeaning,
1230:                                    that.rangeMeaning)
1231:                            || Double.doubleToLongBits(minimum) != Double
1232:                                    .doubleToLongBits(that.minimum)
1233:                            || Double.doubleToLongBits(maximum) != Double
1234:                                    .doubleToLongBits(that.maximum)) {
1235:                        return false;
1236:                    }
1237:                } else {
1238:                    /*
1239:                     * Checking the abbreviation is not suffisient. For example the polar angle and the
1240:                     * spherical latitude have the same abbreviation (theta).  Geotools extensions like
1241:                     * "Longitude" (in addition of ISO 19111 "Geodetic longitude") bring more potential
1242:                     * confusion. Furthermore, not all implementors will use the greek letters (even if
1243:                     * they are part of ISO 19111).    For example most CRS in WKT format use the "Lat"
1244:                     * abbreviation instead of the greek letter phi. For comparaisons without metadata,
1245:                     * we ignore the unreliable abbreviation and check the axis name instead. These
1246:                     * names are constrained by ISO 19111 specification (see class javadoc), so they
1247:                     * should be reliable enough.
1248:                     *
1249:                     * Note: there is no need to execute this block if 'compareMetadata' is true,
1250:                     *       because in this case a stricter check has already been performed by
1251:                     *       the 'equals' method in the superclass.
1252:                     */
1253:                    final String thatName = that.getName().getCode();
1254:                    if (!nameMatches(thatName)) {
1255:                        // The above test checked for special cases ("Lat" / "Lon" aliases, etc.).
1256:                        // The next line may not, but is tested anyway in case the user overrided
1257:                        // the 'that.nameMatches(...)' method.
1258:                        final String this Name = getName().getCode();
1259:                        if (!nameMatches(that, this Name)) {
1260:                            // For the needs of AbstractCS.axisColinearWith(...), we must stop here.
1261:                            // In addition it may be safer to not test 'nameMatchesXY' when we don't
1262:                            // have the extra-safety of units comparaison, because "x" and "y" names
1263:                            // are too generic.
1264:                            if (!compareUnit) {
1265:                                return false;
1266:                            }
1267:                            // Last chance: check for the special case of "x" and "y" axis names.
1268:                            if (!nameMatchesXY(thatName, this Name)
1269:                                    && !nameMatchesXY(this Name, thatName)) {
1270:                                return false;
1271:                            }
1272:                        }
1273:                    }
1274:                }
1275:                return Utilities.equals(this .direction, that.direction)
1276:                        && (!compareUnit || Utilities.equals(this .unit,
1277:                                that.unit));
1278:            }
1279:
1280:            /**
1281:             * Returns a hash value for this axis. This value doesn't need to be the same
1282:             * in past or future versions of this class.
1283:             */
1284:            public int hashCode() {
1285:                int code = (int) serialVersionUID;
1286:                code = code * 37 + abbreviation.hashCode();
1287:                code = code * 37 + direction.hashCode();
1288:                code = code * 37 + unit.hashCode();
1289:                return code;
1290:            }
1291:
1292:            /**
1293:             * Format the inner part of a
1294:             * <A HREF="http://geoapi.sourceforge.net/snapshot/javadoc/org/opengis/referencing/doc-files/WKT.html"><cite>Well
1295:             * Known Text</cite> (WKT)</A> element. WKT is returned by the {@link #toString toString} method
1296:             * and looks like <code>AXIS["name",NORTH]</code>.
1297:             *
1298:             * @param  formatter The formatter to use.
1299:             * @return The WKT element name, which is "AXIS".
1300:             */
1301:            protected String formatWKT(final Formatter formatter) {
1302:                formatter.append(direction);
1303:                return "AXIS";
1304:            }
1305:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.