Source Code Cross Referenced for DirectionAlongMeridian.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) 


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2007, GeoTools Project Managment Committee (PMC)
005:         *    (C) 2007, Geomatys
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:        package org.geotools.referencing.cs;
018:
019:        // J2SE dependencies
020:        import java.io.Serializable;
021:        import java.util.regex.Matcher;
022:        import java.util.regex.Pattern;
023:
024:        // Geotools dependencies
025:        import org.opengis.referencing.cs.AxisDirection;
026:
027:        /**
028:         * Parses {@linkplain AxisDirection axis direction} of the kind
029:         * "<cite>South along 90 deg East</cite>". Those directions are
030:         * used in the EPSG database for polar stereographic projections.
031:         *
032:         * @version $Id: DirectionAlongMeridian.java 28264 2007-12-05 21:53:08Z desruisseaux $
033:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/cs/DirectionAlongMeridian.java $
034:         * @author Martin Desruisseaux
035:         */
036:        final class DirectionAlongMeridian implements  Comparable, Serializable {
037:            /**
038:             * For cross-version compatibility.
039:             */
040:            private static final long serialVersionUID = 1602711631943838328L;
041:
042:            /**
043:             * For floating point comparaisons.
044:             */
045:            static final double EPS = 1E-10;
046:
047:            /**
048:             * A parser for EPSG axis names. Examples:
049:             *
050:             * "<cite>South along 180 deg</cite>",
051:             * "<cite>South along 90 deg East</cite>"
052:             */
053:            private static final Pattern EPSG = Pattern
054:                    .compile(
055:                            "(\\p{Graph}+)\\s+along\\s+([\\-\\p{Digit}\\.]+)\\s+deg\\s*(\\p{Graph}+)?",
056:                            Pattern.CASE_INSENSITIVE);
057:
058:            /**
059:             * The base directions we are interrested in. Any direction not in
060:             * this group will be rejected by our parser.
061:             */
062:            private static final AxisDirection[] BASE_DIRECTIONS = new AxisDirection[] {
063:                    AxisDirection.NORTH, AxisDirection.SOUTH,
064:                    AxisDirection.EAST, AxisDirection.WEST };
065:
066:            /**
067:             * The direction. Will be created only when first needed.
068:             * 
069:             * @see #getDirection
070:             */
071:            private transient AxisDirection direction;
072:
073:            /**
074:             * The base direction, which must be {@link AxisDirection#NORTH} or
075:             * {@link AxisDirection#SOUTH}.
076:             */
077:            public final AxisDirection baseDirection;
078:
079:            /**
080:             * The meridian, in degrees.
081:             */
082:            public final double meridian;
083:
084:            /**
085:             * Creates a direction.
086:             */
087:            private DirectionAlongMeridian(final AxisDirection baseDirection,
088:                    final double meridian) {
089:                this .baseDirection = baseDirection;
090:                this .meridian = meridian;
091:            }
092:
093:            /**
094:             * Returns the dimension along meridian for the specified axis direction, or {@code null} if
095:             * none.
096:             */
097:            public static DirectionAlongMeridian parse(
098:                    final AxisDirection direction) {
099:                final DirectionAlongMeridian candidate = parse(direction.name());
100:                if (candidate != null) {
101:                    candidate.direction = direction;
102:                }
103:                return candidate;
104:            }
105:
106:            /**
107:             * If the specified name is a direction along some specific meridian,
108:             * returns information about that. Otherwise returns {@code null}.
109:             */
110:            public static DirectionAlongMeridian parse(final String name) {
111:                final Matcher m = EPSG.matcher(name);
112:                if (!m.matches()) {
113:                    // Not the expected pattern.
114:                    return null;
115:                }
116:                String group = m.group(1);
117:                final AxisDirection baseDirection = findDirection(
118:                        BASE_DIRECTIONS, group);
119:                if (baseDirection == null
120:                        || !AxisDirection.NORTH
121:                                .equals(baseDirection.absolute())) {
122:                    // We expected "North" or "South" direction.
123:                    return null;
124:                }
125:                group = m.group(2);
126:                double meridian;
127:                try {
128:                    meridian = Double.parseDouble(group);
129:                } catch (NumberFormatException exception) {
130:                    // Not a legal axis direction. Just ignore the exception,
131:                    // since we are supposed to return 'null' in this situation.
132:                    return null;
133:                }
134:                if (!(meridian >= -180 && meridian <= 180)) {
135:                    // Meridian is NaN or is not in the valid range.
136:                    return null;
137:                }
138:                group = m.group(3);
139:                if (group != null) {
140:                    final AxisDirection sign = findDirection(BASE_DIRECTIONS,
141:                            group);
142:                    final AxisDirection abs = sign.absolute();
143:                    if (sign == null || !AxisDirection.EAST.equals(abs)) {
144:                        // We expected "East" or "West" direction.
145:                        return null;
146:                    }
147:                    if (sign != abs) {
148:                        meridian = -meridian;
149:                    }
150:                }
151:                return new DirectionAlongMeridian(baseDirection, meridian);
152:            }
153:
154:            /**
155:             * Searchs for the specified name in the specified set of directions.
156:             */
157:            private static AxisDirection findDirection(
158:                    final AxisDirection[] values, final String direction) {
159:                for (int i = 0; i < values.length; i++) {
160:                    final AxisDirection candidate = values[i];
161:                    final String name = candidate.name();
162:                    if (direction.equalsIgnoreCase(name)) {
163:                        return candidate;
164:                    }
165:                }
166:                return null;
167:            }
168:
169:            /**
170:             * Searchs for the specified name.
171:             */
172:            static AxisDirection findDirection(String direction) {
173:                final AxisDirection[] values = AxisDirection.values();
174:                AxisDirection candidate = findDirection(values, direction);
175:                if (candidate == null) {
176:                    String modified = direction.replace('-', '_');
177:                    if (modified != direction) {
178:                        direction = modified;
179:                        candidate = findDirection(values, modified);
180:                    }
181:                    if (candidate == null) {
182:                        modified = direction.replace(' ', '_');
183:                        if (modified != direction) {
184:                            candidate = findDirection(values, modified);
185:                        }
186:                    }
187:                }
188:                return candidate;
189:            }
190:
191:            /**
192:             * Returns the axis direction for this object. If a suitable axis direction already exists,
193:             * it will be returned. Otherwise a new one is created and returned.
194:             */
195:            public AxisDirection getDirection() {
196:                if (direction != null) {
197:                    return direction;
198:                }
199:                final String name = toString();
200:                synchronized (AxisDirection.class) {
201:                    /*
202:                     * The calls to  'AxisDirection.values()' and 'findDirection(...)'  should be performed
203:                     * inside the synchronized block, since we try to avoid the creation of many directions
204:                     * for the same name.   Strictly speaking, this synchronization is not suffisient since
205:                     * it doesn't apply to the creation of axis directions from outside this class.  But it
206:                     * okay if this code is the only place where we create axis directions with name of the
207:                     * kind "South among 90�E". This assumption holds for Geotools implementation.
208:                     */
209:                    direction = findDirection(name);
210:                    if (direction == null) {
211:                        direction = AxisDirection.valueOf(name);
212:                    }
213:                }
214:                return direction;
215:            }
216:
217:            /**
218:             * Returns the arithmetic (counterclockwise) angle from this direction to the specified
219:             * direction, in decimal degrees. This method returns a value between -180� and +180�, or
220:             * {@link Double#NaN NaN} if the {@linkplain #baseDirection base directions} don't match.
221:             * A positive angle denote a right-handed system.
222:             * <p>
223:             * Example: the angle from "<cite>North along 90 deg East</cite>" to
224:             * "<cite>North along 0 deg</cite> is 90�.
225:             */
226:            public double getAngle(final DirectionAlongMeridian other) {
227:                if (!baseDirection.equals(other.baseDirection)) {
228:                    return Double.NaN;
229:                }
230:                /*
231:                 * We want the following pair of axis:
232:                 * (NORTH along 90�E, NORTH along 0�)
233:                 * to give a positive angle of 90�
234:                 */
235:                double angle = meridian - other.meridian;
236:                /*
237:                 * Forces to the [-180� .. +180�] range.
238:                 */
239:                if (angle < -180) {
240:                    angle += 360;
241:                } else if (angle > 180) {
242:                    angle -= 360;
243:                }
244:                /*
245:                 * Reverses the sign for axis oriented toward SOUTH,
246:                 * so a positive angle is a right-handed system.
247:                 */
248:                if (!baseDirection.equals(baseDirection.absolute())) {
249:                    angle = -angle;
250:                }
251:                return angle;
252:            }
253:
254:            /**
255:             * Compares this direction with the specified one for order. This method tries to reproduce
256:             * the ordering used for the majority of coordinate systems in the EPSG database, i.e. the
257:             * ordering of a right-handed coordinate system. Examples of ordered pairs that we should
258:             * get (extracted from the EPSG database):
259:             *
260:             * <table>
261:             *   <tr><td>North along 90 deg East,</td>  <td>North along 0 deg</td></tr>
262:             *   <tr><td>North along 75 deg West,</td>  <td>North along 165 deg West</td></tr>
263:             *   <tr><td>South along 90 deg West,</td>  <td>South along 0 deg</td></tr>
264:             *   <tr><td>South along 180 deg,</td>      <td>South along 90 deg West</td></tr>
265:             *   <tr><td>North along 130 deg West</td>  <td>North along 140 deg East</td></tr>
266:             * </table>
267:             */
268:            public int compareTo(final Object object) {
269:                final DirectionAlongMeridian that = (DirectionAlongMeridian) object;
270:                final int c = baseDirection.compareTo(that.baseDirection);
271:                if (c != 0) {
272:                    return c;
273:                }
274:                final double angle = getAngle(that);
275:                if (angle < 0)
276:                    return +1; // Really the opposite sign.
277:                if (angle > 0)
278:                    return -1; // Really the opposite sign.
279:                return 0;
280:            }
281:
282:            /**
283:             * Tests this object for equality with the specified one.
284:             * This method is used mostly for assertions.
285:             */
286:            public boolean equals(final Object object) {
287:                if (object instanceof  DirectionAlongMeridian) {
288:                    final DirectionAlongMeridian that = (DirectionAlongMeridian) object;
289:                    return baseDirection.equals(that.baseDirection)
290:                            && Double.doubleToLongBits(meridian) == Double
291:                                    .doubleToLongBits(that.meridian);
292:                }
293:                return false;
294:            }
295:
296:            /**
297:             * Returns a hash code value, for consistency with {@link #equals}.
298:             */
299:            public int hashCode() {
300:                final long code = Double.doubleToLongBits(meridian);
301:                return (int) serialVersionUID ^ (int) code ^ (int) (code >> 32)
302:                        + 37 * baseDirection.hashCode();
303:            }
304:
305:            /**
306:             * Returns a string representation of this direction, using a syntax matching the one used
307:             * by EPSG. This string representation will be used for creating a new {@link AxisDirection}.
308:             * The generated name should be identical to EPSG name, but we use the generated one anyway
309:             * (rather than the one provided by EPSG) in order to make sure that we create a single
310:             * {@link AxisDirection} for a given direction; we avoid potential differences like lower
311:             * versus upper cases, amount of white space, <cite>etc</cite>.
312:             */
313:            public String toString() {
314:                final StringBuffer buffer = new StringBuffer(baseDirection
315:                        .name());
316:                toLowerCase(buffer, 0);
317:                buffer.append(" along ");
318:                final double md = Math.abs(meridian);
319:                final int mi = (int) md;
320:                if (md == mi) {
321:                    buffer.append(mi);
322:                } else {
323:                    buffer.append(md);
324:                }
325:                buffer.append(" deg");
326:                if (md != 0 && mi != 180) {
327:                    buffer.append(' ');
328:                    final int base = buffer.length();
329:                    final AxisDirection sign = meridian < 0 ? AxisDirection.WEST
330:                            : AxisDirection.EAST;
331:                    buffer.append(sign.name());
332:                    toLowerCase(buffer, base);
333:                }
334:                final String name = buffer.toString();
335:                assert EPSG.matcher(name).matches() : name;
336:                return name;
337:            }
338:
339:            /**
340:             * Changes the buffer content to lower case from {@code base+1} to
341:             * the end of the buffer. For {@link #toString} internal use only.
342:             */
343:            private static void toLowerCase(final StringBuffer buffer,
344:                    final int base) {
345:                for (int i = buffer.length(); --i > base;) {
346:                    buffer
347:                            .setCharAt(i, Character.toLowerCase(buffer
348:                                    .charAt(i)));
349:                }
350:            }
351:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.